[project @ 2004-01-05 12:11:42 by simonpj]
[ghc-hetmet.git] / ghc / compiler / rename / RnNames.lhs
index 527a673..62cb2db 100644 (file)
@@ -6,7 +6,8 @@
 \begin{code}
 module RnNames (
        rnImports, importsFromLocalDecls, exportsFromAvail,
-       reportUnusedNames, mkModDeps, exportsToAvails
+       reportUnusedNames, reportDeprecations, 
+       mkModDeps, exportsToAvails
     ) where
 
 #include "HsVersions.h"
@@ -564,9 +565,8 @@ type ExportAccum    -- The type of the accumulating parameter of
                        -- the main worker function in exportsFromAvail
      = ([ModuleName],          -- 'module M's seen so far
        ExportOccMap,           -- Tracks exported occurrence names
-       AvailEnv)               -- The accumulated exported stuff, kept in an env
-                               --   so we can common-up related AvailInfos
-emptyExportAccum = ([], emptyOccEnv, emptyAvailEnv) 
+       NameSet)                -- The accumulated exported stuff
+emptyExportAccum = ([], emptyOccEnv, emptyNameSet) 
 
 type ExportOccMap = OccEnv (Name, IE RdrName)
        -- Tracks what a particular exported OccName
@@ -577,7 +577,7 @@ type ExportOccMap = OccEnv (Name, IE RdrName)
 
 exportsFromAvail :: Bool  -- False => no 'module M(..) where' header at all
                 -> Maybe [Located (IE RdrName)] -- Nothing => no explicit export list
-                -> RnM Avails
+                -> RnM NameSet
        -- Complains if two distinct exports have same OccName
         -- Warns about identical exports.
        -- Complains about exports items not in scope
@@ -600,33 +600,27 @@ exportsFromAvail explicit_mod exports
        exports_from_avail real_exports rdr_env imports }
 
 
-exports_from_avail Nothing rdr_env
-                  imports@(ImportAvails { imp_env = entity_avail_env })
+exports_from_avail Nothing rdr_env imports
  =     -- Export all locally-defined things
        -- We do this by filtering the global RdrEnv,
-       -- keeping only things that are (a) qualified,
-       -- (b) locally defined, (c) a 'main' name
-       -- Then we look up in the entity-avail-env
-   return [ lookupAvailEnv entity_avail_env name
-         | gre <- globalRdrEnvElts rdr_env,
-           isLocalGRE gre,
-           let name = gre_name gre,
-           isNothing (nameParent_maybe name)   -- Main things only
-         ]
+       -- keeping only things that are locally-defined
+   return (mkNameSet [ gre_name gre 
+                    | gre <- globalRdrEnvElts rdr_env,
+                      isLocalGRE gre ])
 
 exports_from_avail (Just export_items) rdr_env
                   (ImportAvails { imp_qual = mod_avail_env, 
                                   imp_env  = entity_avail_env }) 
   = foldlM (exports_from_litem) emptyExportAccum
-           export_items                        `thenM` \ (_, _, export_avail_map) ->
-    returnM (nameEnvElts export_avail_map)
+           export_items                        `thenM` \ (_, _, exports) ->
+    returnM exports
 
   where
     exports_from_litem :: ExportAccum -> Located (IE RdrName) -> RnM ExportAccum
     exports_from_litem acc = addLocM (exports_from_item acc)
 
     exports_from_item :: ExportAccum -> IE RdrName -> RnM ExportAccum
-    exports_from_item acc@(mods, occs, avails) ie@(IEModuleContents mod)
+    exports_from_item acc@(mods, occs, exports) ie@(IEModuleContents mod)
        | mod `elem` mods       -- Duplicate export of M
        = do { warn_dup_exports <- doptM Opt_WarnDuplicateExports ;
               warnIf warn_dup_exports (dupModuleExport mod) ;
@@ -639,23 +633,19 @@ exports_from_avail (Just export_items) rdr_env
 
            Just avail_env
                -> let
-                       mod_avails = [ filtered_avail
-                                    | avail <- availEnvElts avail_env,
-                                      let mb_avail = filter_unqual rdr_env avail,
-                                      isJust mb_avail,
-                                      let Just filtered_avail = mb_avail]
-                                               
-                       avails' = foldl addAvail avails mod_avails
+                       new_exports = [ name | avail <- availEnvElts avail_env,
+                                              name  <- availNames avail,
+                                              inScopeUnqual rdr_env name ]
                   in
+
                -- This check_occs not only finds conflicts between this item
                -- and others, but also internally within this item.  That is,
                -- if 'M.x' is in scope in several ways, we'll have several
                -- members of mod_avails with the same OccName.
+                  check_occs ie occs new_exports       `thenM` \ occs' ->
+                  returnM (mod:mods, occs', addListToNameSet exports new_exports)
 
-                  foldlM (check_occs ie) occs mod_avails       `thenM` \ occs' ->
-                  returnM (mod:mods, occs', avails')
-
-    exports_from_item acc@(mods, occs, avails) ie
+    exports_from_item acc@(mods, occs, exports) ie
        = lookupGlobalOccRn (ieName ie)                 `thenM` \ name -> 
          if isUnboundName name then
                returnM acc     -- Avoid error cascade
@@ -674,41 +664,34 @@ exports_from_avail (Just export_items) rdr_env
            Just export_avail ->        
 
                -- Phew!  It's OK!  Now to check the occurrence stuff!
-         checkForDodgyExport ie avail                          `thenM_`
-          check_occs ie occs export_avail                      `thenM` \ occs' ->
-         returnM (mods, occs', addAvail avails export_avail)
+       
+         let 
+             new_exports = availNames export_avail 
+         in
+         checkForDodgyExport ie new_exports            `thenM_`
+          check_occs ie occs new_exports               `thenM` \ occs' ->
+         returnM (mods, occs', addListToNameSet exports new_exports)
          }
 
 
 -------------------------------
-filter_unqual :: GlobalRdrEnv -> AvailInfo -> Maybe AvailInfo
--- Filter the Avail by what's in scope unqualified
-filter_unqual env (Avail n)
-  | in_scope env n = Just (Avail n)
-  | otherwise     = Nothing
-filter_unqual env (AvailTC n ns)
-  | not (null ns') = Just (AvailTC n ns')
-  | otherwise     = Nothing
-  where
-    ns' = filter (in_scope env) ns
-
-in_scope :: GlobalRdrEnv -> Name -> Bool
+inScopeUnqual :: GlobalRdrEnv -> Name -> Bool
 -- Checks whether the Name is in scope unqualified, 
 -- regardless of whether it's ambiguous or not
-in_scope env n = any unQualOK (lookupGRE_Name env n)
+inScopeUnqual env n = any unQualOK (lookupGRE_Name env n)
 
 -------------------------------
-checkForDodgyExport :: IE RdrName -> AvailInfo -> RnM ()
-checkForDodgyExport (IEThingAll tc) (AvailTC _ [n]) = addWarn (dodgyExportWarn tc)
+checkForDodgyExport :: IE RdrName -> [Name] -> RnM ()
+checkForDodgyExport (IEThingAll tc) [n] = addWarn (dodgyExportWarn tc)
   -- This occurs when you import T(..), but
   -- only export T abstractly.  The single [n]
   -- in the AvailTC is the type or class itself
 checkForDodgyExport _ _ = return ()
 
 -------------------------------
-check_occs :: IE RdrName -> ExportOccMap -> AvailInfo -> RnM ExportOccMap
-check_occs ie occs avail 
-  = foldlM check occs (availNames avail)
+check_occs :: IE RdrName -> ExportOccMap -> [Name] -> RnM ExportOccMap
+check_occs ie occs names
+  = foldlM check occs names
   where
     check occs name
       = case lookupOccEnv occs name_occ of
@@ -730,15 +713,68 @@ check_occs ie occs avail
 
 %*********************************************************
 %*                                                      *
-\subsection{Unused names}
+               Deprecations
+%*                                                      *
+%*********************************************************
+
+\begin{code}
+reportDeprecations :: TcGblEnv -> RnM ()
+reportDeprecations tcg_env
+  = ifOptM Opt_WarnDeprecations        $
+    do { hpt <- getHpt
+       ; eps <- getEps
+       ; mapM_ (check hpt (eps_PIT eps)) all_gres }
+  where
+    used_names = findUses (tcg_dus tcg_env) emptyNameSet
+    all_gres   = globalRdrEnvElts (tcg_rdr_env tcg_env)
+
+    check hpt pit (GRE {gre_name = name, gre_prov = Imported (imp_spec:_) _})
+      | name `elemNameSet` used_names
+      ,        Just deprec_txt <- lookupDeprec hpt pit name
+      = addSrcSpan (is_loc imp_spec) $
+       addWarn (sep [ptext SLIT("Deprecated use of") <+> 
+                       text (occNameFlavour (nameOccName name)) <+> 
+                       quotes (ppr name),
+                     (parens imp_msg),
+                     (ppr deprec_txt) ])
+       where
+         name_mod = nameModuleName name
+         imp_mod  = is_mod imp_spec
+         imp_msg  = ptext SLIT("imported from") <+> ppr imp_mod <> extra
+         extra | imp_mod == name_mod = empty
+               | otherwise = ptext SLIT(", but defined in") <+> ppr name_mod
+
+    check hpt pit ok_gre = returnM ()  -- Local, or not used, or not deprectated
+           -- The Imported pattern-match: don't deprecate locally defined names
+           -- For a start, we may be exporting a deprecated thing
+           -- Also we may use a deprecated thing in the defn of another
+           -- deprecated things.  We may even use a deprecated thing in
+           -- the defn of a non-deprecated thing, when changing a module's 
+           -- interface
+
+lookupDeprec :: HomePackageTable -> PackageIfaceTable 
+            -> Name -> Maybe DeprecTxt
+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)   
+               -- By now all the interfaces should have been loaded
+
+gre_is_used :: NameSet -> GlobalRdrElt -> Bool
+gre_is_used used_names gre = gre_name gre `elemNameSet` used_names
+\end{code}
+
+%*********************************************************
+%*                                                      *
+               Unused names
 %*                                                      *
 %*********************************************************
 
 \begin{code}
 reportUnusedNames :: TcGblEnv -> RnM ()
 reportUnusedNames gbl_env 
-  = do { warnDeprecations     defined_and_used
-       ; warnUnusedTopBinds   unused_locals
+  = do { warnUnusedTopBinds   unused_locals
        ; warnUnusedModules    unused_imp_mods
        ; warnUnusedImports    unused_imports   
        ; warnDuplicateImports dup_imps
@@ -759,8 +795,8 @@ reportUnusedNames gbl_env
        -- are both [GRE]; that's why we need defined_and_used
        -- rather than just all_used_names
     defined_and_used, defined_but_not_used :: [GlobalRdrElt]
-    (defined_and_used, defined_but_not_used) = partition is_used defined_names
-    is_used gre = gre_name gre `elemNameSet` all_used_names
+    (defined_and_used, defined_but_not_used) 
+       = partition (gre_is_used all_used_names) defined_names
     
        -- Find the duplicate imports
     dup_imps = filter is_dup defined_and_used
@@ -854,47 +890,6 @@ reportUnusedNames gbl_env
     module_unused :: ModuleName -> Bool
     module_unused mod = mod `elem` unused_imp_mods
 
-                     
----------------------
-warnDeprecations :: [GlobalRdrElt] -> RnM ()
-warnDeprecations used_gres
-  = ifOptM Opt_WarnDeprecations        $
-    do { hpt <- getHpt
-       ; eps <- getEps
-       ; mapM_ (check hpt (eps_PIT eps)) used_gres }
-  where
-    check hpt pit (GRE {gre_name = name, gre_prov = Imported (imp_spec:_) _})
-      | Just deprec_txt <- lookupDeprec hpt pit name
-      = addSrcSpan (is_loc imp_spec) $
-       addWarn (sep [ptext SLIT("Deprecated use of") <+> 
-                       text (occNameFlavour (nameOccName name)) <+> 
-                       quotes (ppr name),
-                     (parens imp_msg),
-                     (ppr deprec_txt) ])
-       where
-         name_mod = nameModuleName name
-         imp_mod  = is_mod imp_spec
-         imp_msg  = ptext SLIT("imported from") <+> ppr imp_mod <> extra
-         extra | imp_mod == name_mod = empty
-               | otherwise = ptext SLIT(", but defined in") <+> ppr name_mod
-
-    check hpt pit ok_gre = returnM ()  -- Local, or not deprectated
-           -- The Imported pattern-match: don't deprecate locally defined names
-           -- For a start, we may be exporting a deprecated thing
-           -- Also we may use a deprecated thing in the defn of another
-           -- deprecated things.  We may even use a deprecated thing in
-           -- the defn of a non-deprecated thing, when changing a module's 
-           -- interface
-
-lookupDeprec :: HomePackageTable -> PackageIfaceTable 
-            -> Name -> Maybe DeprecTxt
-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)   
-               -- By now all the interfaces should have been loaded
-
 ---------------------
 warnDuplicateImports :: [GlobalRdrElt] -> RnM ()
 warnDuplicateImports gres