+reportUnusedNames :: ModuleName -> [Module]
+ -> GlobalRdrEnv -> AvailEnv
+ -> 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
+
+ -- Now, a use of C implies a use of T,
+ -- if C was brought into scope by T(..) or T(C)
+ really_used_names = used_names `unionNameSets`
+ mkNameSet [ availName parent_avail
+ | sub_name <- nameSetToList used_names
+ , isValOcc (getOccName sub_name)
+
+ -- Usually, every used name will appear in avail_env, but there
+ -- is one time when it doesn't: tuples and other built in syntax. When you
+ -- write (a,b) that gives rise to a *use* of "(,)", so that the
+ -- instances will get pulled in, but the tycon "(,)" isn't actually
+ -- in scope. Hence the isValOcc filter.
+ --
+ -- Also, (-x) gives rise to an implicit use of 'negate'; similarly,
+ -- 3.5 gives rise to an implcit use of :%
+ -- hence the isUserImportedName filter on the warning
+
+ , let parent_avail
+ = case lookupNameEnv avail_env sub_name of
+ Just avail -> avail
+ Nothing -> WARN( isUserImportedName sub_name,
+ text "reportUnusedName: not in avail_env" <+>
+ ppr sub_name )
+ Avail sub_name
+
+ , case parent_avail of { AvailTC _ _ -> True; other -> False }
+ ]
+
+ defined_names, defined_but_not_used :: [(Name,Provenance)]
+ defined_names = concat (rdrEnvElts gbl_env)
+ defined_but_not_used = filter not_used defined_names
+ not_used name = not (name `elemNameSet` really_used_names)
+
+ -- Filter out the ones only defined implicitly
+ bad_locals :: [Name]
+ bad_locals = [n | (n,LocalDef) <- defined_but_not_used]
+
+ bad_imp_names :: [(Name,Provenance)]
+ bad_imp_names = [(n,p) | (n,p@(UserImport mod _ True)) <- defined_but_not_used,
+ not (module_unused mod)]
+
+ deprec_used deprec_env = [ (n,txt)
+ | n <- nameSetToList mentioned_names,
+ 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: Consider
+ -- module This
+ -- import M ()
+ --
+ -- The import M() is not *necessarily* redundant, even if
+ -- we suck in no instance decls from M (e.g. it contains
+ -- no instance decls, or This contains no code). 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. Sigh.
+ -- There's really no good way to detect this, so the error message
+ -- in RnEnv.warnUnusedModules is weakened instead
+ inst_mods = [m | InstD (InstDecl _ _ _ (Just dfun) _) <- imported_decls,
+ let m = nameModule dfun,
+ m `elem` direct_import_mods
+ ]
+
+ minimal_imports :: FiniteMap Module AvailEnv
+ 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 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]
+ 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)),
+ moduleName m /= pRELUDE_Name]
+
+ module_unused :: Module -> Bool
+ module_unused mod = mod `elem` unused_imp_mods
+
+ in
+ warnUnusedModules unused_imp_mods `thenRn_`
+ warnUnusedLocalBinds bad_locals `thenRn_`
+ warnUnusedImports bad_imp_names `thenRn_`
+ printMinimalImports mod_name minimal_imports `thenRn_`
+ getIfacesRn `thenRn` \ ifaces ->
+ doptRn Opt_WarnDeprecations `thenRn` \ warn_drs ->
+ (if warn_drs
+ then mapRn_ warnDeprec (deprec_used (iDeprecs ifaces))
+ else returnRn ())
+
+-- ToDo: deal with original imports with 'qualified' and 'as M' clauses
+printMinimalImports mod_name imps
+ = doptRn Opt_D_dump_minimal_imports `thenRn` \ dump_minimal ->
+ printMinimalImports_wrk dump_minimal mod_name imps
+
+printMinimalImports_wrk dump_minimal mod_name imps
+ | not dump_minimal
+ = returnRn ()
+ | otherwise
+ = mapRn to_ies (fmToList imps) `thenRn` \ mod_ies ->
+ ioToRnM (do { h <- openFile filename WriteMode ;
+ printForUser h (vcat (map ppr_mod_ie mod_ies))
+ }) `thenRn_`
+ returnRn ()