[project @ 1999-07-05 15:30:25 by simonpj]
[ghc-hetmet.git] / ghc / compiler / rename / Rename.lhs
index bc01d7c..ca22b19 100644 (file)
@@ -22,17 +22,17 @@ import RnMonad
 import RnNames         ( getGlobalNames )
 import RnSource                ( rnSourceDecls, rnDecl )
 import RnIfaces                ( getImportedInstDecls, importDecl, getImportVersions,
-                         getImportedRules, loadHomeInterface, getSlurped
+                         getImportedRules, loadHomeInterface, getSlurped, removeContext
                        )
 import RnEnv           ( availName, availNames, availsToNameSet, 
-                         warnUnusedTopNames, mapFvRn,
+                         warnUnusedTopNames, mapFvRn, lookupImplicitOccRn,
                          FreeVars, plusFVs, plusFV, unitFV, emptyFVs, isEmptyFVs
                        )
 import Module           ( Module, ModuleName, pprModule, mkSearchPath, mkThisModule )
 import Name            ( Name, isLocallyDefined,
                          NamedThing(..), ImportReason(..), Provenance(..),
                          pprOccName, nameOccName,
-                         getNameProvenance, occNameUserString, 
+                         getNameProvenance, 
                          maybeWiredInTyConName, maybeWiredInIdName, isWiredInName
                        )
 import Id              ( idType )
@@ -42,7 +42,7 @@ import RdrName                ( RdrName )
 import NameSet
 import PrelMods                ( mAIN_Name, pREL_MAIN_Name )
 import TysWiredIn      ( unitTyCon, intTyCon, doubleTyCon, boolTyCon )
-import PrelInfo                ( ioTyCon_NAME, thinAirIdNames )
+import PrelInfo                ( ioTyCon_NAME, numClass_RDR, thinAirIdNames, derivingOccurrences )
 import Type            ( namesOfType, funTyCon )
 import ErrUtils                ( pprBagOfErrors, pprBagOfWarnings,
                          doIfSet, dumpIfSet, ghcExit
@@ -51,6 +51,7 @@ import BasicTypes     ( NewOrData(..) )
 import Bag             ( isEmptyBag, bagToList )
 import FiniteMap       ( fmToList, delListFromFM, addToFM, sizeFM, eltsFM )
 import UniqSupply      ( UniqSupply )
+import UniqFM          ( lookupUFM )
 import Util            ( equivClasses )
 import Maybes          ( maybeToBool )
 import Outputable
@@ -119,8 +120,9 @@ rename this_mod@(HsModule mod_name vers exports imports local_decls loc)
     )                                  `thenRn` \ (rn_local_decls, source_fvs) ->
 
        -- SLURP IN ALL THE NEEDED DECLARATIONS
+    implicitFVs mod_name rn_local_decls        `thenRn` \ implicit_fvs -> 
     let
-       real_source_fvs = implicitFVs mod_name `plusFV` source_fvs
+       real_source_fvs = implicit_fvs `plusFV` source_fvs
                -- It's important to do the "plus" this way round, so that
                -- when compiling the prelude, locally-defined (), Bool, etc
                -- override the implicit ones. 
@@ -169,10 +171,13 @@ rename this_mod@(HsModule mod_name vers exports imports local_decls loc)
 mentioned explicitly, but which might be needed by the type checker.
 
 \begin{code}
-implicitFVs mod_name
-  = implicit_main              `plusFV` 
-    mkNameSet default_tys      `plusFV`
-    mkNameSet thinAirIdNames
+implicitFVs mod_name decls
+  = mapRn lookupImplicitOccRn implicit_occs    `thenRn` \ implicit_names ->
+    returnRn (implicit_main            `plusFV` 
+             mkNameSet default_tys     `plusFV`
+             mkNameSet thinAirIdNames  `plusFV`
+             mkNameSet implicit_names)
+    
   where
        -- Add occurrences for Int, Double, and (), because they
        -- are the types to which ambigious type variables may be defaulted by
@@ -188,11 +193,30 @@ implicitFVs mod_name
     implicit_main |  mod_name == mAIN_Name
                  || mod_name == pREL_MAIN_Name = unitFV ioTyCon_NAME
                  |  otherwise                  = emptyFVs
+
+       -- Now add extra "occurrences" for things that
+       -- the deriving mechanism, or defaulting, will later need in order to
+       -- generate code
+    implicit_occs = foldr ((++) . get) [] decls
+
+    get (DefD _) = [numClass_RDR]
+    get (TyClD (TyData _ _ _ _ _ (Just deriv_classes) _ _))
+       = concat (map get_deriv deriv_classes)
+    get other = []
+
+    get_deriv cls = case lookupUFM derivingOccurrences cls of
+                       Nothing   -> []
+                       Just occs -> occs
 \end{code}
 
 \begin{code}
 isOrphanDecl (InstD (InstDecl inst_ty _ _ _ _))
-  = not (foldNameSet ((||) . isLocallyDefined) False (extractHsTyNames inst_ty))
+  = not (foldNameSet ((||) . isLocallyDefined) False (extractHsTyNames (removeContext inst_ty)))
+       -- The 'removeContext' is because of
+       --      instance Foo a => Baz T where ...
+       -- The decl is an orphan if Baz and T are both not locally defined,
+       --      even if Foo *is* locally defined
+
 isOrphanDecl (RuleD (RuleDecl _ _ _ lhs _ _))
   = check lhs
   where
@@ -213,26 +237,55 @@ isOrphanDecl other = False
 -------------------------------------------------------
 slurpImpDecls source_fvs
   = traceRn (text "slurpImp" <+> fsep (map ppr (nameSetToList source_fvs))) `thenRn_`
-       -- The current slurped-set records all local things
-    getSlurped                                 `thenRn` \ local_binders ->
 
-    slurpSourceRefs source_fvs                 `thenRn` \ (decls1, needed1, wired_in) ->
-    let
-       inst_gates1 = foldr (plusFV . getWiredInGates)     source_fvs  wired_in
-       inst_gates2 = foldr (plusFV . getGates source_fvs) inst_gates1 decls1
-    in
-       -- Do this first slurpDecls before the getImportedInstDecls,
-       -- so that the home modules of all the inst_gates will be sure to be loaded
-    slurpDecls decls1 needed1                  `thenRn` \ (decls2, needed2) -> 
-    mapRn_ (load_home local_binders) wired_in  `thenRn_`
+       -- The current slurped-set records all local things
+    getSlurped                                 `thenRn` \ source_binders ->
+    slurpSourceRefs source_binders source_fvs  `thenRn` \ (decls1, needed1, inst_gates) ->
 
        -- Now we can get the instance decls
-    getImportedInstDecls inst_gates2           `thenRn` \ inst_decls ->
-    rnIfaceDecls decls2 needed2 inst_decls     `thenRn` \ (decls3, needed3) ->
-    closeDecls  decls3 needed3
+    slurpInstDecls decls1 needed1 inst_gates   `thenRn` \ (decls2, needed2) ->
+
+       -- And finally get everything else
+    closeDecls  decls2 needed2
+
+-------------------------------------------------------
+slurpSourceRefs :: NameSet                     -- Variables defined in source
+               -> FreeVars                     -- Variables referenced in source
+               -> RnMG ([RenamedHsDecl],
+                        FreeVars,              -- Un-satisfied needs
+                        FreeVars)              -- "Gates"
+-- The declaration (and hence home module) of each gate has
+-- already been loaded
+
+slurpSourceRefs source_binders source_fvs
+  = go []                              -- Accumulating decls
+       emptyFVs                        -- Unsatisfied needs
+       source_fvs                      -- Accumulating gates
+       (nameSetToList source_fvs)      -- Gates whose defn hasn't been loaded yet
   where
-    load_home local_binders name 
-       | name `elemNameSet` local_binders = returnRn ()
+    go decls fvs gates []
+       = returnRn (decls, fvs, gates)
+
+    go decls fvs gates (wanted_name:refs) 
+       | isWiredInName wanted_name
+       = load_home wanted_name         `thenRn_`
+         go decls fvs (gates `plusFV` getWiredInGates wanted_name) refs
+
+       | otherwise
+       = importDecl wanted_name                `thenRn` \ maybe_decl ->
+         case maybe_decl of
+               -- No declaration... (already slurped, or local)
+           Nothing   -> go decls fvs gates refs
+           Just decl -> rnIfaceDecl decl               `thenRn` \ (new_decl, fvs1) ->
+                        go (new_decl : decls)
+                           (fvs1 `plusFV` fvs)
+                           (gates `plusFV` getGates source_fvs new_decl)
+                           refs
+
+       -- When we find a wired-in name we must load its
+       -- home module so that we find any instance decls therein
+    load_home name 
+       | name `elemNameSet` source_binders = returnRn ()
                -- When compiling the prelude, a wired-in thing may
                -- be defined in this module, in which case we don't
                -- want to load its home module!
@@ -244,44 +297,38 @@ slurpImpDecls source_fvs
                                                returnRn ()
         where
          doc = ptext SLIT("need home module for wired in thing") <+> ppr name
+\end{code}
+%
+@slurpInstDecls@ imports appropriate instance decls.
+It has to incorporate a loop, because consider
+\begin{verbatim}
+       instance Foo a => Baz (Maybe a) where ...
+\end{verbatim}
+It may be that @Baz@ and @Maybe@ are used in the source module,
+but not @Foo@; so we need to chase @Foo@ too.
 
--------------------------------------------------------
-slurpSourceRefs :: FreeVars                    -- Variables referenced in source
-               -> RnMG ([RenamedHsDecl],
-                        FreeVars,              -- Un-satisfied needs
-                        [Name])                -- Those variables referenced in the source
-                                               -- that turned out to be wired in things
-
-slurpSourceRefs source_fvs
-  = go [] emptyFVs [] (nameSetToList source_fvs)
+\begin{code}
+slurpInstDecls decls needed gates
+  = go decls needed gates gates
   where
-    go decls fvs wired []
-       = returnRn (decls, fvs, wired)
-    go decls fvs wired (wanted_name:refs) 
-       | isWiredInName wanted_name
-       = go decls fvs (wanted_name:wired) refs
+    go decls needed all_gates new_gates
+       | isEmptyFVs new_gates
+       = returnRn (decls, needed)
+
        | otherwise
-       = importDecl wanted_name                `thenRn` \ maybe_decl ->
-         case maybe_decl of
-               -- No declaration... (already slurped, or local)
-           Nothing   -> go decls fvs wired refs
-           Just decl -> rnIfaceDecl decl               `thenRn` \ (new_decl, fvs1) ->
-                        go (new_decl : decls) (fvs1 `plusFV` fvs) wired
-                           (extraGates new_decl ++ refs)
-
--- Hack alert.  If we suck in a class 
---     class Ord a => Baz a where ...
--- then Eq is also a 'gate'.  Why?  Because Eq is a superclass of Ord,
--- and hence may be needed during context reduction even though
--- Eq is never mentioned explicitly.  So we snaffle out the super-classes
--- right now, so that slurpSourceRefs will heave them in
---
--- Similarly the RHS of type synonyms
-extraGates (TyClD (ClassDecl ctxt _ tvs _ _ _ _ _ _ _))
-  = nameSetToList (delListFromNameSet (extractHsCtxtTyNames ctxt) (map getTyVarName tvs))
-extraGates (TyClD (TySynonym _ tvs ty _))
-  = nameSetToList (delListFromNameSet (extractHsTyNames ty) (map getTyVarName tvs))
-extraGates other = []
+       = getImportedInstDecls all_gates                `thenRn` \ inst_decls ->
+         rnInstDecls decls needed emptyFVs inst_decls  `thenRn` \ (decls1, needed1, new_gates) ->
+         go decls1 needed1 (all_gates `plusFV` new_gates) new_gates
+
+    rnInstDecls decls fvs gates []
+       = returnRn (decls, fvs, gates)
+    rnInstDecls decls fvs gates (d:ds) 
+       = rnIfaceDecl d         `thenRn` \ (new_decl, fvs1) ->
+         rnInstDecls (new_decl:decls) 
+                     (fvs1 `plusFV` fvs)
+                     (gates `plusFV` getInstDeclGates new_decl)
+                     ds
+    
 
 -------------------------------------------------------
 -- closeDecls keeps going until the free-var set is empty
@@ -334,18 +381,20 @@ slurpDecl decls fvs wanted_name
 
 %*********************************************************
 %*                                                      *
-\subsection{Extracting the 'gates'}
+\subsection{Extracting the `gates'}
 %*                                                      *
 %*********************************************************
 
 When we import a declaration like
-
+\begin{verbatim}
        data T = T1 Wibble | T2 Wobble
-
-we don't want to treat Wibble and Wobble as gates *unless* T1, T2
-respectively are mentioned by the user program.  If only T is mentioned
-we want only T to be a gate; that way we don't suck in useless instance
-decls for (say) Eq Wibble, when they can't possibly be useful.
+\end{verbatim}
+we don't want to treat @Wibble@ and @Wobble@ as gates
+{\em unless} @T1@, @T2@ respectively are mentioned by the user program.
+If only @T@ is mentioned
+we want only @T@ to be a gate;
+that way we don't suck in useless instance
+decls for (say) @Eq Wibble@, when they can't possibly be useful.
 
 @getGates@ takes a newly imported (and renamed) decl, and the free
 vars of the source program, and extracts from the decl the gate names.
@@ -366,7 +415,7 @@ getGates source_fvs (TyClD (ClassDecl ctxt cls tvs sigs _ _ _ _ _ _))
 getGates source_fvs (TyClD (TySynonym tycon tvs ty _))
   = delListFromNameSet (extractHsTyNames ty)
                       (map getTyVarName tvs)
-    `addOneToNameSet` tycon
+       -- A type synonym type constructor isn't a "gate" for instance decls
 
 getGates source_fvs (TyClD (TyData _ ctxt tycon tvs cons _ _ _))
   = delListFromNameSet (foldr (plusFV . get) (extractHsCtxtTyNames ctxt) cons)
@@ -403,30 +452,30 @@ getGates source_fvs (TyClD (TyData _ ctxt tycon tvs cons _ _ _))
 getGates source_fvs other_decl = emptyFVs
 \end{code}
 
-getWiredInGates is just like getGates, but it sees a wired-in Name
+@getWiredInGates@ is just like @getGates@, but it sees a wired-in @Name@
 rather than a declaration.
 
 \begin{code}
-getWiredInGates name | is_tycon  = get_wired_tycon the_tycon
-                    | otherwise = get_wired_id the_id
+getWiredInGates :: Name -> FreeVars
+getWiredInGates name   -- No classes are wired in
+  | is_id               = getWiredInGates_s (namesOfType (idType the_id))
+  | isSynTyCon the_tycon = getWiredInGates_s
+        (delListFromNameSet (namesOfType ty) (map getName tyvars))
+  | otherwise           = unitFV name
   where
-    maybe_wired_in_tycon = maybeWiredInTyConName name
-    is_tycon            = maybeToBool maybe_wired_in_tycon
     maybe_wired_in_id    = maybeWiredInIdName name
-    Just the_tycon      = maybe_wired_in_tycon
+    is_id               = maybeToBool maybe_wired_in_id
+    maybe_wired_in_tycon = maybeWiredInTyConName name
     Just the_id         = maybe_wired_in_id
+    Just the_tycon      = maybe_wired_in_tycon
+    (tyvars,ty)         = getSynTyConDefn the_tycon
 
-get_wired_id id = namesOfType (idType id)
-
-get_wired_tycon tycon 
-  | isSynTyCon tycon
-  = namesOfType ty `minusNameSet` mkNameSet (map getName tyvars)
+getWiredInGates_s names = foldr (plusFV . getWiredInGates) emptyFVs (nameSetToList names)
+\end{code}
 
-  | otherwise          -- data or newtype
-  = foldr (unionNameSets . namesOfType . dataConType) emptyNameSet data_cons
-  where
-    (tyvars,ty) = getSynTyConDefn tycon
-    data_cons   = tyConDataCons tycon
+\begin{code}
+getInstDeclGates (InstD (InstDecl inst_ty _ _ _ _)) = extractHsTyNames inst_ty
+getInstDeclGates other                             = emptyFVs
 \end{code}
 
 
@@ -438,46 +487,39 @@ get_wired_tycon tycon
 
 \begin{code}
 reportUnusedNames gbl_env avail_env (ExportEnv export_avails _) mentioned_names
-  | not (opt_WarnUnusedBinds || opt_WarnUnusedImports)
-  = returnRn ()
-
-  | otherwise
   = let
        used_names = mentioned_names `unionNameSets` availsToNameSet export_avails
 
        -- Now, a use of C implies a use of T,
        -- if C was brought into scope by T(..) or T(C)
        really_used_names = used_names `unionNameSets`
-                           mkNameSet [ availName avail 
-                                     | sub_name <- nameSetToList used_names,
-                                       let avail = case lookupNameEnv avail_env sub_name of
-                                                       Just avail -> avail
-                                                       Nothing -> pprTrace "r.u.n" (ppr sub_name) $
-                                                                  Avail sub_name
-                                     ]
+         mkNameSet [ availName avail   
+                   | sub_name <- nameSetToList used_names,
+                     let avail = case lookupNameEnv avail_env sub_name of
+                           Just avail -> avail
+                           Nothing -> WARN( True, text "reportUnusedName: not in avail_env" <+> ppr sub_name )
+                                      Avail sub_name
+                   ]
 
        defined_names = mkNameSet (concat (rdrEnvElts gbl_env))
-       defined_but_not_used = nameSetToList (defined_names `minusNameSet` really_used_names)
+       defined_but_not_used =
+          nameSetToList (defined_names `minusNameSet` really_used_names)
 
        -- Filter out the ones only defined implicitly
        bad_guys = filter reportableUnusedName defined_but_not_used
     in
-    warnUnusedTopNames bad_guys        `thenRn_`
-    returnRn ()
+    warnUnusedTopNames bad_guys
 
 reportableUnusedName :: Name -> Bool
 reportableUnusedName name
-  = explicitlyImported (getNameProvenance name) &&
-    not (startsWithUnderscore (occNameUserString (nameOccName name)))
+  = explicitlyImported (getNameProvenance name)
   where
-    explicitlyImported (LocalDef _ _)                       = True     -- Report unused defns of local vars
-    explicitlyImported (NonLocalDef (UserImport _ _ expl) _) = expl    -- Report unused explicit imports
-    explicitlyImported other                                = False    -- Don't report others
-   
-       -- Haskell 98 encourages compilers to suppress warnings about
-       -- unused names in a pattern if they start with "_".
-    startsWithUnderscore ('_' : _) = True      -- Suppress warnings for names starting
-    startsWithUnderscore other     = False     -- with an underscore
+    explicitlyImported (LocalDef _ _)                       = True
+       -- Report unused defns of local vars
+    explicitlyImported (NonLocalDef (UserImport _ _ expl) _) = expl
+       -- Report unused explicit imports
+    explicitlyImported other                                = False
+       -- Don't report others
 
 rnStats :: [RenamedHsDecl] -> RnMG ()
 rnStats imp_decls
@@ -507,10 +549,10 @@ getRnStats imported_decls
        n_mods = length [() | (_, _, Just _) <- eltsFM (iImpModInfo ifaces)]
 
        decls_read     = [decl | (_, avail, True, (_,decl)) <- nameEnvElts (iDecls ifaces),
-                                       -- Data, newtype, and class decls are in the decls_fm
-                                       -- under multiple names; the tycon/class, and each
-                                       -- constructor/class op too.
-                                       -- The 'True' selects just the 'main' decl
+                               -- Data, newtype, and class decls are in the decls_fm
+                               -- under multiple names; the tycon/class, and each
+                               -- constructor/class op too.
+                               -- The 'True' selects just the 'main' decl
                                 not (isLocallyDefined (availName avail))
                             ]