combine_globals ns_old ns_new -- ns_new is often short
= foldr add ns_old ns_new
where
- add n ns | all (no_conflict n) ns_old = map choose ns -- Eliminate duplicates
- | otherwise = n:ns
+ add n ns | any (is_duplicate n) ns_old = map choose ns -- Eliminate duplicates
+ | otherwise = n:ns
where
choose n' | n==n' && better_provenance n n' = n
| otherwise = n'
(NonLocalDef (UserImport _ _ _ ) _, NonLocalDef ImplicitImport _) -> True
other -> False
-no_conflict :: Name -> Name -> Bool
-no_conflict n1 n2 | isLocallyDefined n1 && isLocallyDefined n2 = False
- | otherwise = n1 == n2
- -- We complain of a conflict if one RdrName maps to two different Names,
- -- OR if one RdrName maps to the same *locally-defined* Name. The latter
- -- case is to catch two separate, local definitions of the same thing.
+is_duplicate :: Name -> Name -> Bool
+is_duplicate n1 n2 | isLocallyDefined n1 && isLocallyDefined n2 = False
+ | otherwise = n1 == n2
+ -- We treat two bindings of a locally-defined name as a duplicate,
+ -- because they might be two separate, local defns and we want to report
+ -- and error for that, *not* eliminate a duplicate.
+
+ -- On the other hand, if you import the same name from two different
+ -- import statements, we *do* want to eliminate the duplicate, not report
+ -- an error.
--
-- If a module imports itself then there might be a local defn and an imported
-- defn of the same name; in this case the names will compare as equal, but
-- LOAD IT INTO Ifaces
-- First set the module
- setModuleRn load_mod $
-- 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 ->
+ setModuleRn load_mod $ -- First set the module name of the module being loaded,
+ -- so that unqualified occurrences in the interface file
+ -- get the right qualifer
foldlRn loadDecl (iDecls ifaces) rd_decls `thenRn` \ new_decls ->
foldlRn loadFixDecl (iFixes ifaces) rd_decls `thenRn` \ new_fixities ->
- mapRn loadExport exports `thenRn` \ avails_s ->
foldlRn loadInstDecl insts rd_insts `thenRn` \ new_insts ->
+
+ mapRn (loadExport this_mod) exports `thenRn` \ avails_s ->
let
mod_details = (new_hif, mod_vers, concat avails_s)
returnRn new_ifaces
}}
-loadExport :: ExportItem -> RnMG [AvailInfo]
-loadExport (mod, entities)
+loadExport :: Module -> ExportItem -> RnMG [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 entities
where
new_name occ = newImportedGlobalName mod occ