diff --git a/ghc/compiler/rename/Rename.lhs b/ghc/compiler/rename/Rename.lhs index 58adc32f1decdcdb54bee72a28b97523e5905a2b..73df99f9db971c7b8e55d45035d29a3c5948317b 100644 --- a/ghc/compiler/rename/Rename.lhs +++ b/ghc/compiler/rename/Rename.lhs @@ -26,7 +26,8 @@ import RnIfaces ( getImportedInstDecls, importDecl, mkImportExportInfo, getInte getImportedRules, loadHomeInterface, getSlurped, removeContext, loadBuiltinRules, getDeferredDecls, ImportDeclResult(..) ) -import RnEnv ( availName, availsToNameSet, unitAvailEnv, availEnvElts, plusAvailEnv, +import RnEnv ( availName, availsToNameSet, + emptyAvailEnv, unitAvailEnv, availEnvElts, plusAvailEnv, warnUnusedImports, warnUnusedLocalBinds, warnUnusedModules, lookupImplicitOccsRn, pprAvail, unknownNameErr, FreeVars, plusFVs, plusFV, unitFV, emptyFVs, isEmptyFVs, addOneFV @@ -54,7 +55,9 @@ import Type ( namesOfType, funTyCon ) import ErrUtils ( printErrorsAndWarnings, dumpIfSet, ghcExit ) import BasicTypes ( Version, initialVersion ) import Bag ( isEmptyBag, bagToList ) -import FiniteMap ( FiniteMap, eltsFM, fmToList, emptyFM, lookupFM, addToFM_C ) +import FiniteMap ( FiniteMap, eltsFM, fmToList, emptyFM, lookupFM, + addToFM_C, elemFM, addToFM + ) import UniqSupply ( UniqSupply ) import UniqFM ( lookupUFM ) import SrcLoc ( noSrcLoc ) @@ -192,7 +195,8 @@ rename this_mod@(HsModule mod_name vers exports imports local_decls mod_deprec l -- REPORT UNUSED NAMES, AND DEBUG DUMP reportUnusedNames mod_name direct_import_mods gbl_env global_avail_env - export_avails source_fvs `thenRn_` + export_avails source_fvs + rn_imp_decls `thenRn_` returnRn (Just result, dump_action) } where @@ -654,10 +658,12 @@ rnDeprecs gbl_env mod_deprec decls \begin{code} reportUnusedNames :: ModuleName -> [ModuleName] -> GlobalRdrEnv -> AvailEnv - -> Avails -> NameSet -> RnMG () + -> Avails -> NameSet -> [RenamedHsDecl] + -> RnMG () reportUnusedNames mod_name direct_import_mods gbl_env avail_env export_avails mentioned_names + imported_decls = let used_names = mentioned_names `unionNameSets` availsToNameSet export_avails @@ -682,7 +688,8 @@ reportUnusedNames mod_name direct_import_mods = case lookupNameEnv avail_env sub_name of Just avail -> avail Nothing -> WARN( isUserImportedName sub_name, - text "reportUnusedName: not in avail_env" <+> ppr sub_name ) + text "reportUnusedName: not in avail_env" <+> + ppr sub_name ) Avail sub_name , case parent_avail of { AvailTC _ _ -> True; other -> False } @@ -702,12 +709,35 @@ reportUnusedNames mod_name direct_import_mods not (isLocallyDefined n), Just txt <- [lookupNameEnv deprec_env n] ] + -- inst_mods are directly-imported modules that + -- contain instance decl(s) that the renamer decided to suck in + -- It's not necessarily redundant to import such modules. + -- NOTE: import M () is not necessarily redundant, even if + -- we suck in no instance decls from M (e.g. it contains + -- no instance decls). It may be that we import M solely to + -- ensure that M's orphan instance decls (or those in its imports) + -- are visible to people who import this module. Sigh. There's + -- really no good way to detect this, so the error message is weakened + inst_mods = [m | InstD (InstDecl _ _ _ dfun _) <- imported_decls, + let m = moduleName (nameModule dfun), + m `elem` direct_import_mods + ] + 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 (moduleName m) - (unitAvailEnv (mk_avail n)) + minimal_imports0 = emptyFM + minimal_imports1 = foldNameSet add_name minimal_imports0 really_used_names + minimal_imports = foldr add_inst_mod minimal_imports1 inst_mods + + add_name n acc = case maybeUserImportedFrom n of + Nothing -> acc + Just m -> addToFM_C plusAvailEnv acc (moduleName m) + (unitAvailEnv (mk_avail n)) + add_inst_mod m acc + | m `elemFM` acc = acc -- We import something already + | otherwise = addToFM acc m emptyAvailEnv + -- Add an empty collection of imports for a module + -- from which we have sucked only instance decls + mk_avail n = case lookupNameEnv avail_env n of Just (AvailTC m _) | n==m -> AvailTC n [n] | otherwise -> AvailTC m [n,m] diff --git a/ghc/compiler/rename/RnEnv.lhs b/ghc/compiler/rename/RnEnv.lhs index 05ec12accc92672b9547ae2746bc6c1604417402..6bdb45bcb1df1f37e137ce5faec2d8a7c26260d4 100644 --- a/ghc/compiler/rename/RnEnv.lhs +++ b/ghc/compiler/rename/RnEnv.lhs @@ -763,8 +763,10 @@ warnUnusedModules mods | not opt_WarnUnusedImports = returnRn () | otherwise = mapRn_ (addWarnRn . unused_mod) mods where - unused_mod m = ptext SLIT("Module") <+> quotes (pprModuleName m) <+> - text "is imported, but nothing from it is used" + unused_mod m = vcat [ptext SLIT("Module") <+> quotes (pprModuleName m) <+> + text "is imported, but nothing from it is used", + parens (ptext SLIT("except perhaps to re-export instances visible in") <+> + quotes (pprModuleName m))] warnUnusedLocalBinds, warnUnusedImports, warnUnusedMatches :: [Name] -> RnM d () warnUnusedImports names diff --git a/ghc/compiler/rename/RnIfaces.lhs b/ghc/compiler/rename/RnIfaces.lhs index 71221cee80137334a69aa8f536624a617d8b42be..f1f51bc4304d8ba09f95f42c79d5a0c7b5c7e9b2 100644 --- a/ghc/compiler/rename/RnIfaces.lhs +++ b/ghc/compiler/rename/RnIfaces.lhs @@ -364,9 +364,9 @@ loadFixDecl mod_name sig@(FixitySig rdr_name fixity loc) ----------------------------------------------------- loadInstDecl :: Module - -> Bag GatedDecl + -> IfaceInsts -> RdrNameInstDecl - -> RnM d (Bag GatedDecl) + -> RnM d IfaceInsts loadInstDecl mod insts decl@(InstDecl inst_ty binds uprags dfun_name src_loc) = -- Find out what type constructors and classes are "gates" for the diff --git a/ghc/compiler/rename/RnMonad.lhs b/ghc/compiler/rename/RnMonad.lhs index 950fe4849ada4f352509ccad75d2a7a51465167d..1756133f3ef072d00a389026dfb0d86da48fb68b 100644 --- a/ghc/compiler/rename/RnMonad.lhs +++ b/ghc/compiler/rename/RnMonad.lhs @@ -314,21 +314,19 @@ data Ifaces = Ifaces { -- This is used to generate the "usage" information for this module. -- Subset of the previous field. - iInsts :: Bag GatedDecl, + iInsts :: IfaceInsts, -- The as-yet un-slurped instance decls; this bag is depleted when we -- slurp an instance decl so that we don't slurp the same one twice. -- Each is 'gated' by the names that must be available before -- this instance decl is needed. iRules :: IfaceRules, - -- Similar to instance decls, except that we track the version number of the - -- rules we import from each module - -- [We keep just one rule-version number for each module] - -- The Bool is True if we import any rules at all from that module + -- Similar to instance decls, only for rules iDeprecs :: DeprecationEnv } +type IfaceInsts = Bag GatedDecl type IfaceRules = Bag GatedDecl type GatedDecl = (NameSet, (Module, RdrNameHsDecl)) diff --git a/ghc/compiler/typecheck/TcEnv.lhs b/ghc/compiler/typecheck/TcEnv.lhs index d07c219b46a3b68edea43328b7396224305db889..953d7fffab52496884605e1bc0bfdc946cc4fae4 100644 --- a/ghc/compiler/typecheck/TcEnv.lhs +++ b/ghc/compiler/typecheck/TcEnv.lhs @@ -61,7 +61,9 @@ import BasicTypes ( Arity ) import IdInfo ( vanillaIdInfo ) import Name ( Name, OccName, nameOccName, getSrcLoc, maybeWiredInTyConName, maybeWiredInIdName, isLocallyDefined, - NamedThing(..) + NamedThing(..), + NameEnv, emptyNameEnv, addToNameEnv, + extendNameEnv, lookupNameEnv, nameEnvElts ) import Unique ( pprUnique10, Unique, Uniquable(..) ) import FiniteMap ( lookupFM, addToFM ) @@ -147,14 +149,12 @@ data TcEnv = TcEnv -- ...why mutable? see notes with tcGetGlobalTyVars -- Includes the in-scope tyvars -type NameEnv val = UniqFM val -- Keyed by Names - type UsageEnv = NameEnv UVar type TypeEnv = NameEnv (TcKind, TcTyThing) type ValueEnv = NameEnv Id valueEnvIds :: ValueEnv -> [Id] -valueEnvIds ve = eltsUFM ve +valueEnvIds ve = nameEnvElts ve data TcTyThing = ATyVar TcTyVar -- Mutable only so that the kind can be mutable -- if the kind is mutable, the tyvar must be so that @@ -165,11 +165,11 @@ data TcTyThing = ATyVar TcTyVar -- Mutable only so that the kind can be mutable initEnv :: TcRef TcTyVarSet -> TcEnv -initEnv mut = TcEnv emptyUFM emptyUFM emptyUFM (emptyVarSet, mut) +initEnv mut = TcEnv emptyNameEnv emptyNameEnv emptyNameEnv (emptyVarSet, mut) -getEnvClasses (TcEnv _ te _ _) = [cl | (_, AClass cl _) <- eltsUFM te] +getEnvClasses (TcEnv _ te _ _) = [cl | (_, AClass cl _) <- nameEnvElts te] -getEnvTyCons (TcEnv _ te _ _) = catMaybes (map get_tc (eltsUFM te)) +getEnvTyCons (TcEnv _ te _ _) = catMaybes (map get_tc (nameEnvElts te)) where get_tc (_, ADataTyCon tc) = Just tc get_tc (_, ASynTyCon tc _) = Just tc @@ -193,7 +193,7 @@ Extending the usage environment. tcExtendUVarEnv :: Name -> UVar -> TcM s r -> TcM s r tcExtendUVarEnv uv_name uv scope = tcGetEnv `thenNF_Tc` \ (TcEnv ue te ve gtvs) -> - tcSetEnv (TcEnv (addToUFM ue uv_name uv) te ve gtvs) scope + tcSetEnv (TcEnv (addToNameEnv ue uv_name uv) te ve gtvs) scope \end{code} Looking up in the environments. @@ -202,7 +202,7 @@ Looking up in the environments. tcLookupUVar :: Name -> NF_TcM s UVar tcLookupUVar uv_name = tcGetEnv `thenNF_Tc` \ (TcEnv ue te ve gtvs) -> - case lookupUFM ue uv_name of + case lookupNameEnv ue uv_name of Just uv -> returnNF_Tc uv Nothing -> failWithTc (uvNameOutOfScope uv_name) \end{code} @@ -221,7 +221,7 @@ tcExtendTyVarEnv tyvars scope extend_list = [ (getName tv, (kindToTcKind (tyVarKind tv), ATyVar tv)) | tv <- tyvars ] - te' = addListToUFM te extend_list + te' = extendNameEnv te extend_list new_tv_set = mkVarSet tyvars in_scope_tvs' = in_scope_tvs `unionVarSet` new_tv_set in @@ -244,7 +244,7 @@ tcExtendTyVarEnvForMeths :: [TyVar] -> [TcTyVar] -> TcM s r -> TcM s r tcExtendTyVarEnvForMeths sig_tyvars inst_tyvars thing_inside = tcGetEnv `thenNF_Tc` \ (TcEnv ue te ve gtvs) -> let - te' = addListToUFM te stuff + te' = extendNameEnv te stuff in tcSetEnv (TcEnv ue te' ve gtvs) thing_inside where @@ -297,7 +297,7 @@ tcExtendTypeEnv bindings scope -- Not for tyvars; use tcExtendTyVarEnv tcGetEnv `thenNF_Tc` \ (TcEnv ue te ve gtvs) -> let - te' = addListToUFM te bindings + te' = extendNameEnv te bindings in tcSetEnv (TcEnv ue te' ve gtvs) scope \end{code} @@ -309,7 +309,7 @@ Looking up in the environments. tcLookupTy :: Name -> NF_TcM s (TcKind, TcTyThing) tcLookupTy name = tcGetEnv `thenNF_Tc` \ (TcEnv ue te ve gtvs) -> - case lookupUFM te name of { + case lookupNameEnv te name of { Just thing -> returnNF_Tc thing ; Nothing -> @@ -368,7 +368,7 @@ tcExtendLocalValEnv names_w_ids scope = tcGetEnv `thenNF_Tc` \ (TcEnv ue te ve (in_scope_tvs,gtvs)) -> tcReadMutVar gtvs `thenNF_Tc` \ global_tvs -> let - ve' = addListToUFM ve names_w_ids + ve' = extendNameEnv ve names_w_ids extra_global_tyvars = tyVarsOfTypes (map (idType . snd) names_w_ids) in tc_extend_gtvs gtvs extra_global_tyvars `thenNF_Tc` \ gtvs' -> @@ -391,7 +391,7 @@ tcLookupValueMaybe name = case maybeWiredInIdName name of Just id -> returnNF_Tc (Just id) Nothing -> tcGetEnv `thenNF_Tc` \ (TcEnv ue te ve gtvs) -> - returnNF_Tc (lookupUFM ve name) + returnNF_Tc (lookupNameEnv ve name) tcLookupValueByKey :: Unique -> NF_TcM s Id -- Panics if not found tcLookupValueByKey key @@ -424,7 +424,7 @@ explicitLookupValue :: ValueEnv -> Name -> Maybe Id explicitLookupValue ve name = case maybeWiredInIdName name of Just id -> Just id - Nothing -> lookupUFM ve name + Nothing -> lookupNameEnv ve name -- Extract the IdInfo from an IfaceSig imported from an interface file tcAddImportedIdInfo :: ValueEnv -> Id -> Id