+\begin{code}
+loadHomeInterface :: SDoc -> Name -> RnM d Ifaces
+loadHomeInterface doc_str name
+ = loadInterface doc_str (moduleName (nameModule name)) ImportBySystem
+
+loadOrphanModules :: [ModuleName] -> RnM d ()
+loadOrphanModules mods
+ | null mods = returnRn ()
+ | otherwise = traceRn (text "Loading orphan modules:" <+>
+ fsep (map pprModuleName mods)) `thenRn_`
+ mapRn_ load mods `thenRn_`
+ returnRn ()
+ where
+ load mod = loadInterface (mk_doc mod) mod ImportBySystem
+ mk_doc mod = pprModuleName mod <+> ptext SLIT("is a orphan-instance module")
+
+
+loadInterface :: SDoc -> ModuleName -> WhereFrom -> RnM d Ifaces
+loadInterface doc mod from
+ = tryLoadInterface doc mod from `thenRn` \ (ifaces, maybe_err) ->
+ case maybe_err of
+ Nothing -> returnRn ifaces
+ Just err -> failWithRn ifaces err
+
+tryLoadInterface :: SDoc -> ModuleName -> WhereFrom -> RnM d (Ifaces, Maybe Message)
+ -- Returns (Just err) if an error happened
+ -- Guarantees to return with iImpModInfo m --> (... Just cts)
+ -- (If the load fails, we plug in a vanilla placeholder
+tryLoadInterface doc_str mod_name from
+ = getIfacesRn `thenRn` \ ifaces ->
+ let
+ mod_map = iImpModInfo ifaces
+ mod_info = lookupFM mod_map mod_name
+
+ hi_boot_file = case from of {
+ ImportByUser -> False ; -- Not hi-boot
+ ImportByUserSource -> True ; -- hi-boot
+ ImportBySystem ->
+ case mod_info of
+ Just (_, is_boot, _) -> is_boot
+
+ Nothing -> False
+ -- We're importing a module we know absolutely
+ -- nothing about, so we assume it's from
+ -- another package, where we aren't doing
+ -- dependency tracking. So it won't be a hi-boot file.
+ }
+ redundant_source_import
+ = case (from, mod_info) of
+ (ImportByUserSource, Just (_,False,_)) -> True
+ other -> False
+ in
+ -- CHECK WHETHER WE HAVE IT ALREADY
+ case mod_info of {
+ Just (_, _, Just _)
+ -> -- We're read it already so don't re-read it
+ returnRn (ifaces, Nothing) ;
+
+ _ ->
+
+ -- Issue a warning for a redundant {- SOURCE -} import
+ -- NB that we arrange to read all the ordinary imports before
+ -- any of the {- SOURCE -} imports
+ warnCheckRn (not redundant_source_import)
+ (warnRedundantSourceImport mod_name) `thenRn_`
+
+ -- READ THE MODULE IN
+ findAndReadIface doc_str mod_name hi_boot_file `thenRn` \ read_result ->
+ case read_result of {
+ Left err -> -- Not found, so add an empty export env to the Ifaces map
+ -- so that we don't look again
+ let
+ mod = mkVanillaModule mod_name
+ new_mod_map = addToFM mod_map mod_name (False, False, Just (mod, 0, 0, 0, from, []))
+ new_ifaces = ifaces { iImpModInfo = new_mod_map }
+ in
+ setIfacesRn new_ifaces `thenRn_`
+ returnRn (new_ifaces, Just err) ;
+
+ -- Found and parsed!
+ Right iface ->
+
+ -- LOAD IT INTO Ifaces
+
+ -- NB: *first* we do loadDecl, so that the provenance of all the locally-defined
+ --- names is done correctly (notably, whether this is an .hi file or .hi-boot file).
+ -- If we do loadExport first the wrong info gets into the cache (unless we
+ -- explicitly tag each export which seems a bit of a bore)
+
+ getModuleRn `thenRn` \ this_mod_nm ->
+ let
+ mod = pi_mod iface
+ in
+ -- Sanity check. If we're system-importing a module we know nothing at all
+ -- about, it should be from a different package to this one
+ WARN( not (maybeToBool mod_info) &&
+ case from of { ImportBySystem -> True; other -> False } &&
+ isLocalModule mod,
+ ppr mod )
+ foldlRn (loadDecl mod) (iDecls ifaces) (pi_decls iface) `thenRn` \ new_decls ->
+ foldlRn (loadInstDecl mod) (iInsts ifaces) (pi_insts iface) `thenRn` \ new_insts ->
+ loadRules mod (iRules ifaces) (pi_rules iface) `thenRn` \ new_rules ->
+ loadFixDecls mod_name (iFixes ifaces) (pi_fixity iface) `thenRn` \ new_fixities ->
+ foldlRn (loadDeprec mod) (iDeprecs ifaces) (pi_deprecs iface) `thenRn` \ new_deprecs ->
+ mapRn (loadExport this_mod_nm) (pi_exports iface) `thenRn` \ avails_s ->
+ let
+ -- For an explicit user import, add to mod_map info about
+ -- the things the imported module depends on, extracted
+ -- from its usage info.
+ mod_map1 = case from of
+ ImportByUser -> addModDeps mod (pi_usages iface) mod_map
+ other -> mod_map
+
+ -- Now add info about this module
+ mod_map2 = addToFM mod_map1 mod_name mod_details
+ cts = (pi_mod iface, pi_vers iface,
+ fst (pi_fixity iface), fst (pi_rules iface),
+ from, concat avails_s)
+ mod_details = (pi_orphan iface, hi_boot_file, Just cts)
+
+ new_ifaces = ifaces { iImpModInfo = mod_map2,
+ iDecls = new_decls,
+ iFixes = new_fixities,
+ iInsts = new_insts,
+ iRules = new_rules,
+ iDeprecs = new_deprecs }
+ in
+ setIfacesRn new_ifaces `thenRn_`
+ returnRn (new_ifaces, Nothing)
+ }}
+
+-----------------------------------------------------
+-- Adding module dependencies from the
+-- import decls in the interface file
+-----------------------------------------------------
+
+addModDeps :: Module -> [ImportVersion a]
+ -> ImportedModuleInfo -> ImportedModuleInfo
+-- (addModDeps M ivs deps)
+-- We are importing module M, and M.hi contains 'import' decls given by ivs
+addModDeps mod new_deps mod_deps
+ = foldr add mod_deps filtered_new_deps
+ where
+ -- Don't record dependencies when importing a module from another package
+ -- Except for its descendents which contain orphans,
+ -- and in that case, forget about the boot indicator
+ filtered_new_deps
+ | isLocalModule mod = [ (imp_mod, (has_orphans, is_boot, Nothing))
+ | (imp_mod, has_orphans, is_boot, _) <- new_deps
+ ]
+ | otherwise = [ (imp_mod, (True, False, Nothing))
+ | (imp_mod, has_orphans, _, _) <- new_deps,
+ has_orphans
+ ]
+ add (imp_mod, dep) deps = addToFM_C combine deps imp_mod dep
+
+ combine old@(_, old_is_boot, cts) new
+ | maybeToBool cts || not old_is_boot = old -- Keep the old info if it's already loaded
+ -- or if it's a non-boot pending load
+ | otherwise = new -- Otherwise pick new info
+
+
+-----------------------------------------------------
+-- Loading the export list
+-----------------------------------------------------
+
+loadExport :: ModuleName -> ExportItem -> RnM d [AvailInfo]
+loadExport this_mod (mod, entities)
+ | mod == this_mod = returnRn []
+ -- If the module exports anything defined in this module, just ignore it.
+ -- Reason: otherwise it looks as if there are two local definition sites
+ -- for the thing, and an error gets reported. Easiest thing is just to
+ -- filter them out up front. This situation only arises if a module
+ -- imports itself, or another module that imported it. (Necessarily,
+ -- this invoves a loop.) Consequence: if you say
+ -- module A where
+ -- import B( AType )
+ -- type AType = ...
+ --
+ -- module B( AType ) where
+ -- import {-# SOURCE #-} A( AType )
+ --
+ -- then you'll get a 'B does not export AType' message. A bit bogus
+ -- but it's a bogus thing to do!
+
+ | otherwise
+ = mapRn (load_entity mod) entities
+ where
+ new_name mod occ = mkImportedGlobalName mod occ