diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bdae0ee5e85b8b1da6a52f9438ac62a635f2efc..972b159c6d2729b7b3364d7bee86018da16e90a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,11 @@ Change log for curry-frontend Under development ================= - * Type synonyms in typed expressions are now desugared - fixes #921 + * Added warnings for top-level functions without type signatures - fixes #769 + + * Moved pretty-printing of types from Checks.TypeCheck to Base.CurryTypes + + * Type synonyms in typed expressions are now desugared - fixes #921 * Declaration of operator precedence is now optional in infix operator declarations diff --git a/src/Checks/WarnCheck.hs b/src/Checks/WarnCheck.hs index c3f4bbf0b1ca3b419fdec0cc4ee96108d746a432..7f30589f8a7c5479d64e75d02288378c078443e8 100644 --- a/src/Checks/WarnCheck.hs +++ b/src/Checks/WarnCheck.hs @@ -28,6 +28,7 @@ import Curry.Base.Pretty import Curry.Syntax import Curry.Syntax.Pretty (ppPattern, ppExpr, ppIdent) +import Base.CurryTypes (ppTypeScheme) import Base.Messages (Message, posMessage, internalError) import qualified Base.ScopeEnv as SE ( ScopeEnv, new, beginScope, endScopeUp, insert, lookup, level, modify @@ -36,7 +37,7 @@ import qualified Base.ScopeEnv as SE import Base.Types import Env.ModuleAlias import Env.TypeConstructor (TCEnv, TypeInfo (..), lookupTC, qualLookupTC) -import Env.Value (ValueEnv, ValueInfo (..), qualLookupValue) +import Env.Value (ValueEnv, ValueInfo (..), lookupValue, qualLookupValue) import CompilerOpts @@ -54,6 +55,7 @@ warnCheck opts aEnv valEnv tcEnv (Module _ mid es is ds) checkExports es checkImports is checkDeclGroup ds + checkMissingTypeSignatures ds type ScopeEnv = SE.ScopeEnv QualIdent IdInfo @@ -415,6 +417,32 @@ checkOverlappingAlts (alt : alts) = warnFor WarnOverlapping $ do eqPattern _ _ = False +-- ----------------------------------------------------------------------------- +-- Check for missing type signatures +-- ----------------------------------------------------------------------------- + +-- check if a type signature was specified for every top-level function +-- declaration +-- for external function declarations this check is already performed +-- during syntax checking + +checkMissingTypeSignatures :: [Decl] -> WCM () +checkMissingTypeSignatures decls = do + let tys = [t | TypeSig _ ts _ <- decls, t <- ts] + missingTys = [f | FunctionDecl _ f _ <- decls, f `notElem` tys] + unless (null missingTys) $ do + mid <- getModuleIdent + tyScs <- mapM getTyScheme missingTys + mapM_ report $ zipWith (warnMissingTypeSignature mid) missingTys tyScs + +getTyScheme :: Ident -> WCM TypeScheme +getTyScheme q = do + tyEnv <- gets valueEnv + return $ case lookupValue q tyEnv of + [Value _ _ tys] -> tys + _ -> internalError $ + "Checks.WarnCheck.getTyScheme: " ++ show q + -- ----------------------------------------------------------------------------- -- Check for non-exhaustive patterns -- ----------------------------------------------------------------------------- @@ -858,6 +886,11 @@ typeId = qualify . flip renameIdent 1 -- Warnings messages -- --------------------------------------------------------------------------- +warnMissingTypeSignature :: ModuleIdent -> Ident -> TypeScheme -> Message +warnMissingTypeSignature mid i tys = posMessage i $ hsep (map text + ["Top-level binding with no type signature:", showIdent i, "::"]) + <+> ppTypeScheme mid tys + warnMultiplyImportedModule :: ModuleIdent -> Message warnMultiplyImportedModule mid = posMessage mid $ hsep $ map text ["Module", moduleName mid, "is imported more than once"] diff --git a/test/CheckSignature.curry b/test/CheckSignature.curry new file mode 100644 index 0000000000000000000000000000000000000000..06da0a99da998a04e9eaf52bb695e89e0d044832 --- /dev/null +++ b/test/CheckSignature.curry @@ -0,0 +1,7 @@ +--hw :: String +hw = "Hello World" + +f x = tail x + where + answer = 42 + inc i = i + 1 \ No newline at end of file