@@ -19,7 +19,7 @@
1919
2020module Language.PureScript.Linter (lint, module L) where
2121
22−import Data.List (mapAccumL, nub)
22+import Data.List (mapAccumL, nub, (\\))
2323import Data.Maybe (mapMaybe)
2424import Data.Monoid
2525
@@ -60,7 +60,7 @@ lint (Module _ _ mn ds _) = censor (onErrorMessages (ErrorInModule mn)) $ mapM_
6060
6161 f' :: Declaration -> MultipleErrors
6262 f' (PositionedDeclaration pos _ dec) = onErrorMessages (PositionedError pos) (f' dec)
63− f' dec = f dec <> checkShadowedTypeVars dec
63+ f' dec = f dec <> checkTypeVars dec
6464
6565 in tell (f' d)
6666 where
@@ -90,17 +90,27 @@ lint (Module _ _ mn ds _) = censor (onErrorMessages (ErrorInModule mn)) $ mapM_
9090 bindName :: S.Set Ident -> Ident -> (S.Set Ident, MultipleErrors)
9191 bindName = bind ShadowedName
9292
93− checkShadowedTypeVars :: Declaration -> MultipleErrors
94− checkShadowedTypeVars d =
95− let (f, _, _, _, _) = accumTypes go in f d
93+ checkTypeVars :: Declaration -> MultipleErrors
94+ checkTypeVars d =
95+ let (checkShadow, _, _, _, _) = accumTypes (everythingWithContextOnTypes S.empty mempty mappend step)
96+ (checkUnused, _, _, _, _) = accumTypes findUnused
97+ in checkShadow d <> checkUnused d
9698 where
97− go :: Type -> MultipleErrors
98− go = everythingWithContextOnTypes S.empty mempty mappend step
9999 step :: S.Set String -> Type -> (S.Set String, MultipleErrors)
100100 step s (ForAll tv _ _) = bindVar s tv
101101 step s _ = (s, mempty)
102102 bindVar :: S.Set String -> String -> (S.Set String, MultipleErrors)
103103 bindVar = bind ShadowedTypeVar
104+ findUnused :: Type -> MultipleErrors
105+ findUnused ty =
106+ let used = usedTypeVariables ty
107+ declared = everythingOnTypes (++) go ty
108+ unused = nub declared \\ nub used
109+ in foldl (<>) mempty $ map (errorMessage . UnusedTypeVar) unused
110+ where
111+ go :: Type -> [String]
112+ go (ForAll tv _ _) = [tv]
113+ go _ = []
104114
105115 bind :: (Ord a) => (a -> SimpleErrorMessage) -> S.Set a -> a -> (S.Set a, MultipleErrors)
106116 bind mkError s name | name `S.member` s = (s, errorMessage (mkError name))