+%*********************************************************
+%* *
+\subsection{Instance declarations are handled specially}
+%* *
+%*********************************************************
+
+\begin{code}
+getImportedInstDecls :: RnMG [(Module,RdrNameInstDecl)]
+getImportedInstDecls
+ = -- First load any special-instance modules that aren't aready loaded
+ getSpecialInstModules `thenRn` \ inst_mods ->
+ mapRn_ load_it inst_mods `thenRn_`
+
+ -- Now we're ready to grab the instance declarations
+ -- Find the un-gated ones and return them,
+ -- removing them from the bag kept in Ifaces
+ getIfacesRn `thenRn` \ ifaces ->
+ let
+ (insts, tycls_names) = iDefInsts ifaces
+
+ -- An instance decl is ungated if all its gates have been slurped
+ select_ungated :: IfaceInst -- A gated inst decl
+
+ -> ([(Module, RdrNameInstDecl)], [IfaceInst]) -- Accumulator
+
+ -> ([(Module, RdrNameInstDecl)], -- The ungated ones
+ [IfaceInst]) -- Still gated, but with
+ -- depeleted gates
+ select_ungated (decl,gates) (ungated_decls, gated_decls)
+ | isEmptyNameSet remaining_gates
+ = (decl : ungated_decls, gated_decls)
+ | otherwise
+ = (ungated_decls, (decl, remaining_gates) : gated_decls)
+ where
+ remaining_gates = gates `minusNameSet` tycls_names
+
+ (un_gated_insts, still_gated_insts) = foldrBag select_ungated ([], []) insts
+
+ new_ifaces = ifaces {iDefInsts = (listToBag still_gated_insts, tycls_names)}
+ -- NB: don't throw away tycls_names;
+ -- we may comre across more instance decls
+ in
+ traceRn (sep [text "getInstDecls:", fsep (map ppr (nameSetToList tycls_names))]) `thenRn_`
+ setIfacesRn new_ifaces `thenRn_`
+ returnRn un_gated_insts
+ where
+ load_it mod = loadInterface (doc_str mod) mod
+ doc_str mod = sep [pprModule mod, ptext SLIT("is a special-instance module")]
+
+
+getSpecialInstModules :: RnMG [Module]
+getSpecialInstModules
+ = getIfacesRn `thenRn` \ ifaces ->
+ returnRn (iInstMods ifaces)
+
+getImportedFixities :: GlobalRdrEnv -> RnMG FixityEnv
+ -- Get all imported fixities
+ -- We first make sure that all the home modules
+ -- of all in-scope variables are loaded.
+getImportedFixities gbl_env
+ = let
+ home_modules = [ nameModule name | names <- rdrEnvElts gbl_env,
+ name <- names,
+ not (isLocallyDefined name)
+ ]
+ in
+ mapRn_ load (nub home_modules) `thenRn_`
+
+ -- Now we can snaffle the fixity env
+ getIfacesRn `thenRn` \ ifaces ->
+ returnRn (iFixes ifaces)
+ where
+ load mod = loadInterface doc_str mod
+ where
+ doc_str = ptext SLIT("Need fixities from") <+> ppr mod
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Keeping track of what we've slurped, and version numbers}
+%* *
+%*********************************************************
+
+getImportVersions figures out what the "usage information" for this moudule is;
+that is, what it must record in its interface file as the things it uses.
+It records:
+ - anything reachable from its body code
+ - any module exported with a "module Foo".
+
+Why the latter? Because if Foo changes then this module's export list
+will change, so we must recompile this module at least as far as
+making a new interface file --- but in practice that means complete
+recompilation.
+
+What about this?
+ module A( f, g ) where module B( f ) where
+ import B( f ) f = h 3
+ g = ... h = ...
+
+Should we record B.f in A's usages? In fact we don't. Certainly, if
+anything about B.f changes than anyone who imports A should be recompiled;
+they'll get an early exit if they don't use B.f. However, even if B.f
+doesn't change at all, B.h may do so, and this change may not be reflected
+in f's version number. So there are two things going on when compiling module A:
+
+1. Are A.o and A.hi correct? Then we can bale out early.
+2. Should modules that import A be recompiled?
+
+For (1) it is slightly harmful to record B.f in A's usages, because a change in
+B.f's version will provoke full recompilation of A, producing an identical A.o,
+and A.hi differing only in its usage-version of B.f (which isn't used by any importer).
+
+For (2), because of the tricky B.h question above, we ensure that A.hi is touched
+(even if identical to its previous version) if A's recompilation was triggered by
+an imported .hi file date change. Given that, there's no need to record B.f in
+A's usages.
+
+On the other hand, if A exports "module B" then we *do* count module B among
+A's usages, because we must recompile A to ensure that A.hi changes appropriately.
+
+\begin{code}
+getImportVersions :: Module -- Name of this module
+ -> Maybe [IE any] -- Export list for this module
+ -> RnMG (VersionInfo Name) -- Version info for these names
+
+getImportVersions this_mod exports
+ = getIfacesRn `thenRn` \ ifaces ->
+ let
+ mod_map = iModMap ifaces
+ imp_names = iVSlurp ifaces
+
+ -- mv_map groups together all the things imported from a particular module.
+ mv_map, mv_map_mod :: FiniteMap Module (WhatsImported Name)
+
+ mv_map_mod = foldl add_mod emptyFM export_mods
+ -- mv_map_mod records all the modules that have a "module M"
+ -- in this module's export list with an "Everything"
+
+ mv_map = foldl add_mv mv_map_mod imp_names
+ -- mv_map adds the version numbers of things exported individually
+
+ mk_version_info (mod, local_versions)
+ = case lookupFM mod_map mod of
+ Just (hif, version, _) -> (mod, version, local_versions)
+ in
+ returnRn (map mk_version_info (fmToList mv_map))
+ where
+ export_mods = case exports of
+ Nothing -> []
+ Just es -> [mod | IEModuleContents mod <- es, mod /= this_mod]
+
+ add_mv mv_map v@(name, version)
+ = addToFM_C add_item mv_map mod (Specifically [v])
+ where
+ mod = nameModule name
+
+ add_item Everything _ = Everything
+ add_item (Specifically xs) _ = Specifically (v:xs)
+
+ add_mod mv_map mod = addToFM mv_map mod Everything
+\end{code}
+
+\begin{code}
+checkSlurped name
+ = getIfacesRn `thenRn` \ ifaces ->
+ returnRn (name `elemNameSet` iSlurp ifaces)
+
+getSlurpedNames :: RnMG NameSet
+getSlurpedNames
+ = getIfacesRn `thenRn` \ ifaces ->
+ returnRn (iSlurp ifaces)
+
+recordSlurp maybe_version necessity avail
+ = {- traceRn (hsep [text "Record slurp:", pprAvail avail,
+ -- NB PprForDebug prints export flag, which is too
+ -- strict; it's a knot-tied thing in RnNames
+ case necessity of {Compulsory -> text "comp"; Optional -> text "opt" } ]) `thenRn_`
+ -}
+ getIfacesRn `thenRn` \ ifaces ->
+ let
+ Ifaces { iSlurp = slurped_names,
+ iVSlurp = imp_names,
+ iDefInsts = (insts, tycls_names) } = ifaces
+
+ new_slurped_names = addAvailToNameSet slurped_names avail
+
+ new_imp_names = case maybe_version of
+ Just version -> (availName avail, version) : imp_names
+ Nothing -> imp_names
+
+ -- Add to the names that will let in instance declarations;
+ -- but only (a) if it's a type/class
+ -- (b) if it's compulsory (unless the test flag opt_PruneInstDecls is off)
+ new_tycls_names = case avail of
+ AvailTC tc _ | not opt_PruneInstDecls ||
+ case necessity of {Optional -> False; Compulsory -> True }
+ -> tycls_names `addOneToNameSet` tc
+ otherwise -> tycls_names
+
+ new_ifaces = ifaces { iSlurp = new_slurped_names,
+ iVSlurp = new_imp_names,
+ iDefInsts = (insts, new_tycls_names) }
+ in
+ setIfacesRn new_ifaces
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Getting binders out of a declaration}
+%* *
+%*********************************************************
+
+@getDeclBinders@ returns the names for a @RdrNameHsDecl@.
+It's used for both source code (from @availsFromDecl@) and interface files
+(from @loadDecl@).
+
+It doesn't deal with source-code specific things: ValD, DefD. They
+are handled by the sourc-code specific stuff in RnNames.
+