[project @ 2004-08-17 15:23:47 by simonpj]
[ghc-hetmet.git] / ghc / compiler / rename / RnNames.lhs
index 7be2214..9e15a4b 100644 (file)
@@ -29,7 +29,7 @@ import Module         ( Module, ModuleName, moduleName, mkPackageModule,
                          moduleNameUserString, isHomeModule,
                          unitModuleEnvByName, unitModuleEnv, 
                          lookupModuleEnvByName, moduleEnvElts )
-import Name            ( Name, nameSrcLoc, nameOccName, nameModuleName,
+import Name            ( Name, nameSrcLoc, nameOccName, nameModuleName, isWiredInName,
                          nameParent, nameParent_maybe, isExternalName, nameModule )
 import NameSet
 import NameEnv
@@ -50,10 +50,10 @@ import RdrName              ( RdrName, rdrNameOcc, setRdrNameSpace,
 import Outputable
 import Maybes          ( isJust, isNothing, catMaybes, mapCatMaybes, seqMaybe )
 import SrcLoc          ( noSrcLoc, Located(..), mkGeneralSrcSpan,
-                         unLoc, noLoc )
+                         unLoc, noLoc, srcLocSpan, SrcSpan )
 import BasicTypes      ( DeprecTxt )
 import ListSetOps      ( removeDups )
-import Util            ( sortLt, notNull, isSingleton )
+import Util            ( sortLe, notNull, isSingleton )
 import List            ( partition )
 import IO              ( openFile, IOMode(..) )
 \end{code}
@@ -71,32 +71,32 @@ rnImports :: [LImportDecl RdrName]
          -> RnM (GlobalRdrEnv, ImportAvails)
 
 rnImports imports
-  =            -- PROCESS IMPORT DECLS
+  = do {       -- PROCESS IMPORT DECLS
                -- Do the non {- SOURCE -} ones first, so that we get a helpful
                -- warning for {- SOURCE -} ones that are unnecessary
-       getModule                               `thenM` \ this_mod ->
-       doptM Opt_NoImplicitPrelude             `thenM` \ opt_no_prelude -> 
-       let
-         all_imports        = mk_prel_imports this_mod opt_no_prelude ++ imports
-         (source, ordinary) = partition is_source_import all_imports
-         is_source_import (L _ (ImportDecl _ is_boot _ _ _)) = is_boot
-
-         get_imports = importsFromImportDecl this_mod
-       in
-       mappM get_imports ordinary      `thenM` \ stuff1 ->
-       mappM get_imports source        `thenM` \ stuff2 ->
+         this_mod <- getModule
+       ; opt_no_prelude <- doptM Opt_NoImplicitPrelude
+       ; let
+           all_imports      = mk_prel_imports this_mod opt_no_prelude ++ imports
+           (source, ordinary) = partition is_source_import all_imports
+           is_source_import (L _ (ImportDecl _ is_boot _ _ _)) = is_boot
+
+           get_imports = importsFromImportDecl this_mod
+
+       ; stuff1 <- mappM get_imports ordinary
+       ; stuff2 <- mappM get_imports source
 
                -- COMBINE RESULTS
-       let
+       ; let
            (imp_gbl_envs, imp_avails) = unzip (stuff1 ++ stuff2)
            gbl_env :: GlobalRdrEnv
            gbl_env = foldr plusGlobalRdrEnv emptyGlobalRdrEnv imp_gbl_envs
 
            all_avails :: ImportAvails
            all_avails = foldr plusImportAvails emptyImportAvails imp_avails
-       in
+
                -- ALL DONE
-       returnM (gbl_env, all_avails)
+       ; return (gbl_env, all_avails) }
   where
        -- NB: opt_NoImplicitPrelude is slightly different to import Prelude ();
        -- because the former doesn't even look at Prelude.hi for instance 
@@ -228,7 +228,7 @@ importsFromImportDecl this_mod
        imports   = ImportAvails { 
                        imp_qual     = unitModuleEnvByName qual_mod_name avail_env,
                        imp_env      = avail_env,
-                       imp_mods     = unitModuleEnv imp_mod (imp_mod, import_all),
+                       imp_mods     = unitModuleEnv imp_mod (imp_mod, import_all, loc),
                        imp_orphs    = orphans,
                        imp_dep_mods = mkModDeps dependent_mods,
                        imp_dep_pkgs = dependent_pkgs }
@@ -305,7 +305,7 @@ importsFromLocalDecls group
        -- The complaint will come out as "Multiple declarations of Foo.f" because
        -- since 'f' is in the env twice, the unQualInScope used by the error-msg
        -- printer returns False.  It seems awkward to fix, unfortunately.
-    mappM_ (addErr . dupDeclErr) dups                  `thenM_` 
+    mappM_ addDupDeclErr dups                  `thenM_` 
 
     doptM Opt_NoImplicitPrelude                `thenM` \ implicit_prelude ->
     let
@@ -405,33 +405,37 @@ filterImports :: ModIface
              -> ImportSpec                     -- The span for the entire import decl
              -> Maybe (Bool, [Located (IE RdrName)])   -- Import spec; True => hiding
              -> [AvailInfo]                    -- What's available
-             -> RnM (AvailEnv,                 -- What's imported
-                     GlobalRdrEnv)             -- ...in two forms
+             -> RnM (AvailEnv,                 -- What's imported (qualified or unqualified)
+                     GlobalRdrEnv)             -- Same again, but in GRE form
 
        -- Complains if import spec mentions things that the module doesn't export
         -- Warns/informs if import spec contains duplicates.
+                       
 mkGenericRdrEnv imp_spec avails
   = mkGlobalRdrEnv [ GRE { gre_name = name, gre_prov = Imported [imp_spec] False }
                   | avail <- avails, name <- availNames avail ]
-                       
+
 filterImports iface imp_spec Nothing total_avails
-  = returnM (mkAvailEnv total_avails, mkGenericRdrEnv imp_spec total_avails)
+  = returnM (mkAvailEnv total_avails, 
+            mkGenericRdrEnv imp_spec total_avails)
 
 filterImports iface imp_spec (Just (want_hiding, import_items)) total_avails
-  = mapAndUnzipM (addLocM get_item) import_items       `thenM` \ (avails, gres) ->
+  = mapAndUnzipM (addLocM get_item) import_items       `thenM` \ (avails_s, gres) ->
     let
-       all_avails = foldr plusAvailEnv     emptyAvailEnv     avails
-       rdr_env    = foldr plusGlobalRdrEnv emptyGlobalRdrEnv gres
+       avails = concat avails_s
     in
     if not want_hiding then
-       returnM (all_avails, rdr_env)
+      return (mkAvailEnv avails,
+             foldr plusGlobalRdrEnv emptyGlobalRdrEnv gres)
     else
-    let        -- Hide stuff in all_avails
-          hidden = availsToNameSet (availEnvElts all_avails)
-          keep n = not (n `elemNameSet` hidden)
-          pruned_avails = pruneAvails keep total_avails
-    in
-    returnM (mkAvailEnv pruned_avails, mkGenericRdrEnv imp_spec pruned_avails)
+      let
+       hidden = availsToNameSet avails
+       keep n = not (n `elemNameSet` hidden)
+       pruned_avails = pruneAvails keep total_avails
+      in
+      return (mkAvailEnv pruned_avails,
+             mkGenericRdrEnv imp_spec pruned_avails)
+
   where
     import_fm :: OccEnv AvailInfo
     import_fm = mkOccEnv [ (nameOccName name, avail) 
@@ -442,12 +446,12 @@ filterImports iface imp_spec (Just (want_hiding, import_items)) total_avails
        -- in an import list map to TcOccs, not VarOccs.
 
     bale_out item = addErr (badImportItemErr iface imp_spec item)      `thenM_`
-                   returnM (emptyAvailEnv, emptyGlobalRdrEnv)
+                   returnM ([], emptyGlobalRdrEnv)
 
-    succeed_with :: Bool -> AvailInfo -> RnM (AvailEnv, GlobalRdrEnv)
+    succeed_with :: Bool -> AvailInfo -> RnM ([AvailInfo], GlobalRdrEnv)
     succeed_with all_explicit avail
       = do { loc <- getSrcSpanM
-          ; returnM (unitAvailEnv avail, 
+          ; returnM ([avail], 
                      mkGlobalRdrEnv (map (mk_gre loc) (availNames avail))) }
       where
        mk_gre loc name = GRE { gre_name = name, 
@@ -456,7 +460,7 @@ filterImports iface imp_spec (Just (want_hiding, import_items)) total_avails
        explicit name = all_explicit || name == main_name
        main_name = availName avail
 
-    get_item :: IE RdrName -> RnM (AvailEnv, GlobalRdrEnv)
+    get_item :: IE RdrName -> RnM ([AvailInfo], GlobalRdrEnv)
        -- Empty result for a bad item.
        -- Singleton result is typical case.
        -- Can have two when we are hiding, and mention C which might be
@@ -470,16 +474,17 @@ filterImports iface imp_spec (Just (want_hiding, import_items)) total_avails
          Just avail@(AvailTC _ [n]) ->         -- This occurs when you import T(..), but
                                                -- only export T abstractly.  The single [n]
                                                -- in the AvailTC is the type or class itself
-                                       ifOptM Opt_WarnMisc (addWarn (dodgyImportWarn tc))      `thenM_`
+                                       ifOptM Opt_WarnDodgyImports (addWarn (dodgyImportWarn tc)) `thenM_`
                                        succeed_with False avail
          Just avail                 -> succeed_with False avail
 
     get_item item@(IEThingAbs n)
       | want_hiding    -- hiding( C ) 
-                       -- Here the 'C' can be a data constructor *or* a type/class
+                       -- Here the 'C' can be a data constructor 
+                       -- *or* a type/class, or even both
       = case catMaybes [check_item item, check_item (IEVar data_n)] of
          []     -> bale_out item
-         avails -> returnM (mkAvailEnv avails, emptyGlobalRdrEnv)
+         avails -> returnM (avails, emptyGlobalRdrEnv)
                        -- The GlobalRdrEnv result is irrelevant when hiding
       where
        data_n = setRdrNameSpace n srcDataName
@@ -723,8 +728,7 @@ check_occs ie occs names
 reportDeprecations :: TcGblEnv -> RnM ()
 reportDeprecations tcg_env
   = ifOptM Opt_WarnDeprecations        $
-    do { hpt <- getHpt
-       ; eps <- getEps
+    do { (eps,hpt) <- getEpsAndHpt
        ; mapM_ (check hpt (eps_PIT eps)) all_gres }
   where
     used_names = findUses (tcg_dus tcg_env) emptyNameSet
@@ -760,7 +764,13 @@ lookupDeprec hpt pit n
   = case lookupIface hpt pit (nameModule n) of
        Just iface -> mi_dep_fn iface n `seqMaybe`      -- Bleat if the thing, *or
                      mi_dep_fn iface (nameParent n)    -- its parent*, is deprec'd
-       Nothing    -> pprPanic "lookupDeprec" (ppr n)   
+       Nothing    
+         | isWiredInName n -> Nothing
+               -- We have not necessarily loaded the .hi file for a 
+               -- wired-in name (yet), although we *could*.
+               -- And we never deprecate them
+
+        | otherwise -> pprPanic "lookupDeprec" (ppr n) 
                -- By now all the interfaces should have been loaded
 
 gre_is_used :: NameSet -> GlobalRdrElt -> Bool
@@ -847,8 +857,7 @@ reportUnusedNames gbl_env
        -- We've carefully preserved the provenance so that we can
        -- construct minimal imports that import the name by (one of)
        -- the same route(s) as the programmer originally did.
-    add_name (GRE {gre_name = n, 
-                  gre_prov = Imported imp_specs _}) acc 
+    add_name (GRE {gre_name = n, gre_prov = Imported imp_specs _}) acc 
        = addToFM_C plusAvailEnv acc (is_mod (head imp_specs))
                    (unitAvailEnv (mk_avail n (nameParent_maybe n)))
     add_name other acc 
@@ -859,38 +868,35 @@ reportUnusedNames gbl_env
     mk_avail n Nothing | isTcOcc (nameOccName n) = AvailTC n [n]
                       | otherwise               = Avail n
     
-    add_inst_mod m acc 
-      | m `elemFM` acc = acc   -- We import something already
-      | otherwise      = addToFM acc m emptyAvailEnv
+    add_inst_mod (mod,_,_) acc 
+      | mod_name `elemFM` acc = acc    -- We import something already
+      | otherwise             = addToFM acc mod_name emptyAvailEnv
+      where
+       mod_name = moduleName mod
        -- Add an empty collection of imports for a module
        -- from which we have sucked only instance decls
    
     imports = tcg_imports gbl_env
 
-    direct_import_mods :: [ModuleName]
-    direct_import_mods = map (moduleName . fst) 
-                            (moduleEnvElts (imp_mods imports))
-
-    hasEmptyImpList :: ModuleName -> Bool
-    hasEmptyImpList m = 
-       case lookupModuleEnvByName (imp_mods imports) m of
-        Just (_,Just x) -> not x
-        _ -> False
+    direct_import_mods :: [(Module, Maybe Bool, SrcSpan)]
+       -- See the type of the imp_mods for this triple
+    direct_import_mods = moduleEnvElts (imp_mods imports)
 
     -- unused_imp_mods are the directly-imported modules 
     -- 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]
-    unused_imp_mods = [m | m <- direct_import_mods,
-                      isNothing (lookupFM minimal_imports1 m),
-                      m /= pRELUDE_Name,
-                      not (hasEmptyImpList m)]
-       -- hasEmptyImpList arranges not to complain about
+    unused_imp_mods = [(mod_name,loc) | (mod,imp,loc) <- direct_import_mods,
+                      let mod_name = moduleName mod,
+                      not (mod_name `elemFM` minimal_imports1),
+                      mod_name /= pRELUDE_Name,
+                      imp /= Just False]
+       -- The Just False part is not to complain about
        -- import M (), which is an idiom for importing
        -- instance declarations
     
     module_unused :: ModuleName -> Bool
-    module_unused mod = mod `elem` unused_imp_mods
+    module_unused mod = any (((==) mod) . fst) unused_imp_mods
 
 ---------------------
 warnDuplicateImports :: [GlobalRdrElt] -> RnM ()
@@ -997,12 +1003,18 @@ exportClashErr global_env name1 name2 ie1 ie2
             (gre:_) -> gre
             []      -> pprPanic "exportClashErr" (ppr name)
 
-dupDeclErr (n:ns)
-  = vcat [ptext SLIT("Multiple declarations of") <+> quotes (ppr n),
+addDupDeclErr :: [Name] -> TcRn ()
+addDupDeclErr (n:ns)
+  = addErrAt (srcLocSpan (nameSrcLoc n)) $
+    vcat [ptext SLIT("Multiple declarations of") <+> quotes (ppr n),
+         nest 2 (ptext SLIT("other declarations at:")),
          nest 4 (vcat (map ppr sorted_locs))]
   where
-    sorted_locs = sortLt occ'ed_before (map nameSrcLoc (n:ns))
-    occ'ed_before a b = LT == compare a b
+    sorted_locs = sortLe occ'ed_before (map nameSrcLoc ns)
+    occ'ed_before a b = case compare a b of
+                         LT -> True
+                         EQ -> True
+                         GT -> False
 
 dupExportWarn occ_name ie1 ie2
   = hsep [quotes (ppr occ_name),