[project @ 1999-01-28 14:22:15 by simonpj]
authorsimonpj <unknown>
Thu, 28 Jan 1999 14:22:17 +0000 (14:22 +0000)
committersimonpj <unknown>
Thu, 28 Jan 1999 14:22:17 +0000 (14:22 +0000)
Fix erroneous name-clash report when a module ends up importing itself (eg TcEnv)

ghc/compiler/rename/RnEnv.lhs
ghc/compiler/rename/RnIfaces.lhs
ghc/compiler/rename/RnNames.lhs

index ca8d876..ebe6af2 100644 (file)
@@ -462,8 +462,8 @@ combine_globals :: [Name]   -- Old
 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'
@@ -479,12 +479,16 @@ better_provenance n1 n2
        (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
index 0407764..5010eed 100644 (file)
@@ -203,16 +203,21 @@ loadInterface doc_str load_mod
 
        -- 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)
 
@@ -229,8 +234,26 @@ loadInterface doc_str load_mod
     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
index a0dbf46..926fd59 100644 (file)
@@ -73,6 +73,7 @@ getGlobalNames (HsModule this_mod _ exports imports decls mod_loc)
           rec_unqual_fn = unQualInScope rec_rn_env
        in
        setOmitQualFn rec_unqual_fn             $
+       setModuleRn this_mod                    $
 
                -- PROCESS LOCAL DECLS
                -- Do these *first* so that the correct provenance gets