From c615209582841eb514b50800725d5989d176be13 Mon Sep 17 00:00:00 2001 From: simonpj <unknown> Date: Mon, 22 May 2000 06:56:04 +0000 Subject: [PATCH] [project @ 2000-05-22 06:56:04 by simonpj] *** NO NEED TO MERGE WITH 4.07, BUT POSSIBLE *** Warn about completely unused imported modules (when -fwarn-unused-imports) --- ghc/compiler/rename/Rename.lhs | 54 +++++++++++++++++++++++----------- ghc/compiler/rename/RnEnv.lhs | 9 +++++- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/ghc/compiler/rename/Rename.lhs b/ghc/compiler/rename/Rename.lhs index 3f271942928a..ee176e6af0c1 100644 --- a/ghc/compiler/rename/Rename.lhs +++ b/ghc/compiler/rename/Rename.lhs @@ -24,7 +24,8 @@ import RnIfaces ( getImportedInstDecls, importDecl, getImportVersions, getInter getImportedRules, loadHomeInterface, getSlurped, removeContext ) import RnEnv ( availName, availsToNameSet, unitAvailEnv, availEnvElts, plusAvailEnv, - warnUnusedImports, warnUnusedLocalBinds, lookupImplicitOccRn, pprAvail, + warnUnusedImports, warnUnusedLocalBinds, warnUnusedModules, + lookupImplicitOccRn, pprAvail, FreeVars, plusFVs, plusFV, unitFV, emptyFVs, isEmptyFVs ) import Module ( Module, ModuleName, WhereFrom(..), @@ -46,10 +47,10 @@ import Type ( namesOfType, funTyCon ) import ErrUtils ( printErrorsAndWarnings, dumpIfSet, ghcExit ) import BasicTypes ( NewOrData(..) ) import Bag ( isEmptyBag, bagToList ) -import FiniteMap ( FiniteMap, eltsFM, fmToList, emptyFM, addToFM_C ) +import FiniteMap ( FiniteMap, eltsFM, fmToList, emptyFM, lookupFM, addToFM_C ) import UniqSupply ( UniqSupply ) import UniqFM ( lookupUFM ) -import Maybes ( maybeToBool ) +import Maybes ( maybeToBool, expectJust ) import Outputable import IO ( openFile, IOMode(..) ) \end{code} @@ -146,11 +147,6 @@ rename this_mod@(HsModule mod_name vers _ imports local_decls mod_deprec loc) getImportVersions mod_name export_env `thenRn` \ my_usages -> getNameSupplyRn `thenRn` \ name_supply -> - -- REPORT UNUSED NAMES - reportUnusedNames mod_name gbl_env global_avail_env - export_env - source_fvs `thenRn_` - -- RETURN THE RENAMED MODULE let has_orphans = any isOrphanDecl rn_local_decls @@ -161,7 +157,13 @@ rename this_mod@(HsModule mod_name vers _ imports local_decls mod_deprec loc) mod_deprec loc in - rnDump rn_imp_decls rn_all_decls `thenRn` \ dump_action -> + -- REPORT UNUSED NAMES, AND DEBUG DUMP + reportUnusedNames mod_name direct_import_mods + gbl_env global_avail_env + export_env + source_fvs `thenRn_` + rnDump rn_imp_decls rn_all_decls `thenRn` \ dump_action -> + returnRn (Just (mkThisModule mod_name, renamed_module, (InterfaceDetails has_orphans my_usages export_env deprecs), @@ -528,8 +530,12 @@ getInstDeclGates other = emptyFVs %********************************************************* \begin{code} -reportUnusedNames :: ModuleName -> GlobalRdrEnv -> AvailEnv -> ExportEnv -> NameSet -> RnMG () -reportUnusedNames mod_name gbl_env avail_env (ExportEnv export_avails _ _) mentioned_names +reportUnusedNames :: ModuleName -> [ModuleName] + -> GlobalRdrEnv -> AvailEnv + -> ExportEnv -> NameSet -> RnMG () +reportUnusedNames mod_name direct_import_mods + gbl_env avail_env + (ExportEnv export_avails _ _) mentioned_names = let used_names = mentioned_names `unionNameSets` availsToNameSet export_avails @@ -565,28 +571,42 @@ reportUnusedNames mod_name gbl_env avail_env (ExportEnv export_avails _ _) menti nameSetToList (defined_names `minusNameSet` really_used_names) -- Filter out the ones only defined implicitly - bad_locals = [n | n <- defined_but_not_used, isLocallyDefined n] - bad_imps = [n | n <- defined_but_not_used, isUserImportedExplicitlyName n] + bad_locals = [n | n <- defined_but_not_used, isLocallyDefined n] + bad_imp_names = [n | n <- defined_but_not_used, isUserImportedExplicitlyName n, + not (module_unused n)] deprec_used deprec_env = [ (n,txt) | n <- nameSetToList mentioned_names, not (isLocallyDefined n), Just txt <- [lookupNameEnv deprec_env n] ] - minimal_imports :: FiniteMap Module AvailEnv + minimal_imports :: FiniteMap ModuleName AvailEnv minimal_imports = foldNameSet add emptyFM really_used_names add n acc = case maybeUserImportedFrom n of Nothing -> acc - Just m -> addToFM_C plusAvailEnv acc m + Just m -> addToFM_C plusAvailEnv acc (moduleName m) (unitAvailEnv (mk_avail n)) mk_avail n = case lookupNameEnv avail_env n of Just (AvailTC m _) | n==m -> AvailTC n [n] | otherwise -> AvailTC m [n,m] Just avail -> Avail n Nothing -> pprPanic "mk_avail" (ppr n) + + -- unused_imp_mods are the directly-imported modules + -- that are not mentioned in minimal_imports + unused_imp_mods = [m | m <- direct_import_mods, + not (maybeToBool (lookupFM minimal_imports m))] + + module_unused :: Name -> Bool + -- Name is imported from a module that's completely unused, + -- so don't report stuff about the name (the module covers it) + module_unused n = moduleName (expectJust "module_unused" (maybeUserImportedFrom n)) + `elem` unused_imp_mods + -- module_unused is only called if it's user-imported in + warnUnusedModules unused_imp_mods `thenRn_` warnUnusedLocalBinds bad_locals `thenRn_` - warnUnusedImports bad_imps `thenRn_` + warnUnusedImports bad_imp_names `thenRn_` printMinimalImports mod_name minimal_imports `thenRn_` getIfacesRn `thenRn` \ ifaces -> (if opt_WarnDeprecations @@ -613,7 +633,7 @@ printMinimalImports mod_name imps parens (fsep (punctuate comma (map ppr ies))) to_ies (mod, avail_env) = mapRn to_ie (availEnvElts avail_env) `thenRn` \ ies -> - returnRn (moduleName mod, ies) + returnRn (mod, ies) to_ie :: AvailInfo -> RnMG (IE Name) to_ie (Avail n) = returnRn (IEVar n) diff --git a/ghc/compiler/rename/RnEnv.lhs b/ghc/compiler/rename/RnEnv.lhs index 118267f893a7..7cef968fe5c2 100644 --- a/ghc/compiler/rename/RnEnv.lhs +++ b/ghc/compiler/rename/RnEnv.lhs @@ -763,8 +763,15 @@ mapFvRn f xs = mapRn f xs `thenRn` \ stuff -> \begin{code} -warnUnusedLocalBinds, warnUnusedImports, warnUnusedMatches :: [Name] -> RnM d () +warnUnusedModules :: [ModuleName] -> RnM d () +warnUnusedModules mods + | not opt_WarnUnusedImports = returnRn () + | otherwise = mapRn_ (addWarnRn . unused_mod) mods + where + unused_mod m = ptext SLIT("Module") <+> quotes (ppr m) <+> + ptext SLIT("is imported, but nothing from it is used") +warnUnusedLocalBinds, warnUnusedImports, warnUnusedMatches :: [Name] -> RnM d () warnUnusedImports names | not opt_WarnUnusedImports = returnRn () -- Don't force names unless necessary -- GitLab