git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Warn on unused type variable
3ba23c7Gary Burgess
src/Language/PureScript/Errors.hs+4
@@ -141,6 +141,7 @@ data SimpleErrorMessage
141 | TransitiveExportError DeclarationRef [DeclarationRef]
141 | TransitiveExportError DeclarationRef [DeclarationRef]
142 | ShadowedName Ident
142 | ShadowedName Ident
143 | ShadowedTypeVar String
143 | ShadowedTypeVar String
144+ | UnusedTypeVar String
144 | WildcardInferredType Type
145 | WildcardInferredType Type
145 | NotExhaustivePattern [[Binder]] Bool
146 | NotExhaustivePattern [[Binder]] Bool
146 | OverlappingPattern [[Binder]] Bool
147 | OverlappingPattern [[Binder]] Bool
@@ -268,6 +269,7 @@ errorCode em = case unwrapErrorMessage em of
268 TransitiveExportError{} -> "TransitiveExportError"
269 TransitiveExportError{} -> "TransitiveExportError"
269 ShadowedName{} -> "ShadowedName"
270 ShadowedName{} -> "ShadowedName"
270 ShadowedTypeVar{} -> "ShadowedTypeVar"
271 ShadowedTypeVar{} -> "ShadowedTypeVar"
272+ UnusedTypeVar{} -> "UnusedTypeVar"
271 WildcardInferredType{} -> "WildcardInferredType"
273 WildcardInferredType{} -> "WildcardInferredType"
272 NotExhaustivePattern{} -> "NotExhaustivePattern"
274 NotExhaustivePattern{} -> "NotExhaustivePattern"
273 OverlappingPattern{} -> "OverlappingPattern"
275 OverlappingPattern{} -> "OverlappingPattern"
@@ -633,6 +635,8 @@ prettyPrintSingleError full level e = prettyPrintErrorMessage <$> onTypesInError
633 line $ "Name '" ++ showIdent nm ++ "' was shadowed"
635 line $ "Name '" ++ showIdent nm ++ "' was shadowed"
634 goSimple (ShadowedTypeVar tv) =
636 goSimple (ShadowedTypeVar tv) =
635 line $ "Type variable '" ++ tv ++ "' was shadowed"
637 line $ "Type variable '" ++ tv ++ "' was shadowed"
638+ goSimple (UnusedTypeVar tv) =
639+ line $ "Type variable '" ++ tv ++ "' was declared but not used"
636 goSimple (ClassOperator className opName) =
640 goSimple (ClassOperator className opName) =
637 paras [ line $ "Class '" ++ runProperName className ++ "' declares operator " ++ showIdent opName ++ "."
641 paras [ line $ "Class '" ++ runProperName className ++ "' declares operator " ++ showIdent opName ++ "."
638 , indent $ line "This may be disallowed in the future - consider declaring a named member in the class and making the operator an alias:"
642 , indent $ line "This may be disallowed in the future - consider declaring a named member in the class and making the operator an alias:"
src/Language/PureScript/Linter.hs+17−7
@@ -19,7 +19,7 @@
19
19
20module Language.PureScript.Linter (lint, module L) where
20module Language.PureScript.Linter (lint, module L) where
21
21
22−import Data.List (mapAccumL, nub)
22+import Data.List (mapAccumL, nub, (\\))
23import Data.Maybe (mapMaybe)
23import Data.Maybe (mapMaybe)
24import Data.Monoid
24import Data.Monoid
25
25
@@ -60,7 +60,7 @@ lint (Module _ _ mn ds _) = censor (onErrorMessages (ErrorInModule mn)) $ mapM_
60
60
61 f' :: Declaration -> MultipleErrors
61 f' :: Declaration -> MultipleErrors
62 f' (PositionedDeclaration pos _ dec) = onErrorMessages (PositionedError pos) (f' dec)
62 f' (PositionedDeclaration pos _ dec) = onErrorMessages (PositionedError pos) (f' dec)
63− f' dec = f dec <> checkShadowedTypeVars dec
63+ f' dec = f dec <> checkTypeVars dec
64
64
65 in tell (f' d)
65 in tell (f' d)
66 where
66 where
@@ -90,17 +90,27 @@ lint (Module _ _ mn ds _) = censor (onErrorMessages (ErrorInModule mn)) $ mapM_
90 bindName :: S.Set Ident -> Ident -> (S.Set Ident, MultipleErrors)
90 bindName :: S.Set Ident -> Ident -> (S.Set Ident, MultipleErrors)
91 bindName = bind ShadowedName
91 bindName = bind ShadowedName
92
92
93− checkShadowedTypeVars :: Declaration -> MultipleErrors
93+ checkTypeVars :: Declaration -> MultipleErrors
94− checkShadowedTypeVars d =
94+ checkTypeVars d =
95− let (f, _, _, _, _) = accumTypes go in f d
95+ let (checkShadow, _, _, _, _) = accumTypes (everythingWithContextOnTypes S.empty mempty mappend step)
96+ (checkUnused, _, _, _, _) = accumTypes findUnused
97+ in checkShadow d <> checkUnused d
96 where
98 where
97− go :: Type -> MultipleErrors
98− go = everythingWithContextOnTypes S.empty mempty mappend step
99 step :: S.Set String -> Type -> (S.Set String, MultipleErrors)
99 step :: S.Set String -> Type -> (S.Set String, MultipleErrors)
100 step s (ForAll tv _ _) = bindVar s tv
100 step s (ForAll tv _ _) = bindVar s tv
101 step s _ = (s, mempty)
101 step s _ = (s, mempty)
102 bindVar :: S.Set String -> String -> (S.Set String, MultipleErrors)
102 bindVar :: S.Set String -> String -> (S.Set String, MultipleErrors)
103 bindVar = bind ShadowedTypeVar
103 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 _ = []
104
114
105 bind :: (Ord a) => (a -> SimpleErrorMessage) -> S.Set a -> a -> (S.Set a, MultipleErrors)
115 bind :: (Ord a) => (a -> SimpleErrorMessage) -> S.Set a -> a -> (S.Set a, MultipleErrors)
106 bind mkError s name | name `S.member` s = (s, errorMessage (mkError name))
116 bind mkError s name | name `S.member` s = (s, errorMessage (mkError name))