import CmdLineOpts ( DynFlag(..) )
import HsSyn ( IE(..), ieName, ImportDecl(..), LImportDecl,
- ForeignDecl(..), HsGroup(..),
- collectGroupBinders, tyClDeclNames
+ ForeignDecl(..), HsGroup(..), HsBindGroup(..),
+ Sig(..), collectGroupBinders, tyClDeclNames
)
import RnEnv
import IfaceEnv ( lookupOrig, newGlobalBinder )
IfaceExport, HomePackageTable, PackageIfaceTable,
availNames, unQualInScope,
Deprecs(..), ModIface(..), Dependencies(..),
- lookupIface, ExternalPackageState(..),
- IfacePackage(..)
+ lookupIface, ExternalPackageState(..)
)
+import Packages ( PackageIdH(..) )
import RdrName ( RdrName, rdrNameOcc, setRdrNameSpace,
GlobalRdrEnv, mkGlobalRdrEnv, GlobalRdrElt(..),
emptyGlobalRdrEnv, plusGlobalRdrEnv, globalRdrEnvElts,
(dependent_mods, dependent_pkgs)
= case mi_package iface of
- ThisPackage ->
+ HomePackage ->
-- Imported module is from the home package
-- Take its dependent modules and add imp_mod itself
-- Take its dependent packages unchanged
-- check. See LoadIface.loadHiBootInterface
((imp_mod_name, want_boot) : dep_mods deps, dep_pkgs deps)
- ExternalPackage pkg ->
+ ExtPackage pkg ->
-- Imported module is from another package
-- Dump the dependent modules
-- Add the package imp_mod comes from to the dependent packages
-- ensures that the subordinate names record their parent;
-- and that in turn ensures that the GlobalRdrEnv
-- has the correct parent for all the names in its range.
- -- For imported things, we only suck in the binding site later, if ever.
+ -- For imported things, we may only suck in the interface later, if ever.
-- Reason for all this:
-- Suppose module M exports type A.T, and constructor A.MkT
-- Then, we know that A.MkT is a subordinate name of A.T,
-- an export indicator because they are all implicitly exported.
mappM new_tc tycl_decls `thenM` \ tc_avails ->
- mappM new_simple (for_hs_bndrs ++ val_hs_bndrs) `thenM` \ simple_avails ->
- returnM (tc_avails ++ simple_avails)
+
+ -- In a hs-boot file, the value binders come from the
+ -- *signatures*, and there should be no foreign binders
+ tcIsHsBoot `thenM` \ is_hs_boot ->
+ let val_bndrs | is_hs_boot = sig_hs_bndrs
+ | otherwise = for_hs_bndrs ++ val_hs_bndrs
+ in
+ mappM new_simple val_bndrs `thenM` \ names ->
+
+ returnM (tc_avails ++ map Avail names)
where
- new_simple rdr_name = newTopSrcBinder mod Nothing rdr_name `thenM` \ name ->
- returnM (Avail name)
+ new_simple rdr_name = newTopSrcBinder mod Nothing rdr_name
+ sig_hs_bndrs = [nm | HsBindGroup _ lsigs _ <- val_decls,
+ L _ (Sig nm _) <- lsigs]
val_hs_bndrs = collectGroupBinders val_decls
for_hs_bndrs = [nm | L _ (ForeignImport nm _ _ _) <- foreign_decls]
%*********************************************************
\begin{code}
-reportUnusedNames :: TcGblEnv -> RnM ()
-reportUnusedNames gbl_env
+reportUnusedNames :: Maybe [Located (IE RdrName)] -- Export list
+ -> TcGblEnv -> RnM ()
+reportUnusedNames export_decls gbl_env
= do { warnUnusedTopBinds unused_locals
; warnUnusedModules unused_imp_mods
; warnUnusedImports unused_imports
-- To figure out the minimal set of imports, start with the things
-- that are in scope (i.e. in gbl_env). Then just combine them
-- into a bunch of avails, so they are properly grouped
+ --
+ -- BUG WARNING: this does not deal properly with qualified imports!
minimal_imports :: FiniteMap Module AvailEnv
- minimal_imports0 = emptyFM
+ minimal_imports0 = foldr add_expall emptyFM expall_mods
minimal_imports1 = foldr add_name minimal_imports0 defined_and_used
minimal_imports = foldr add_inst_mod minimal_imports1 direct_import_mods
-- The last line makes sure that we retain all direct imports
add_name other acc
= acc
+ -- Modules mentioned as 'module M' in the export list
+ expall_mods = case export_decls of
+ Nothing -> []
+ Just es -> [m | L _ (IEModuleContents m) <- es]
+
+ -- This is really bogus. The idea is that if we see 'module M' in
+ -- the export list we must retain the import decls that drive it
+ -- If we aren't careful we might see
+ -- module A( module M ) where
+ -- import M
+ -- import N
+ -- and suppose that N exports everything that M does. Then we
+ -- must not drop the import of M even though N brings it all into
+ -- scope.
+ --
+ -- BUG WARNING: 'module M' exports aside, what if M.x is mentioned?!
+ --
+ -- The reason that add_expall is bogus is that it doesn't take
+ -- qualified imports into account. But it's an improvement.
+ add_expall mod acc = addToFM_C plusAvailEnv acc mod emptyAvailEnv
+
-- n is the name of the thing, p is the name of its parent
mk_avail n (Just p) = AvailTC p [p,n]
mk_avail n Nothing | isTcOcc (nameOccName n) = AvailTC n [n]
-- that are not mentioned in minimal_imports1
-- [Note: not 'minimal_imports', because that includes directly-imported
-- modules even if we use nothing from them; see notes above]
+ --
+ -- BUG WARNING: does not deal correctly with multiple imports of the same module
+ -- becuase direct_import_mods has only one entry per module
unused_imp_mods = [(mod,loc) | (mod,imp,loc) <- direct_import_mods,
not (mod `elemFM` minimal_imports1),
mod /= pRELUDE,