[project @ 2000-03-23 17:45:17 by simonpj]
[ghc-hetmet.git] / ghc / compiler / rename / Rename.lhs
index 9893a3e..359f284 100644 (file)
@@ -15,8 +15,7 @@ import RnHsSyn                ( RenamedHsModule, RenamedHsDecl,
                        )
 
 import CmdLineOpts     ( opt_HiMap, opt_D_dump_rn_trace,
-                         opt_D_dump_rn, opt_D_dump_rn_stats,
-                         opt_WarnUnusedBinds, opt_WarnUnusedImports
+                         opt_D_dump_rn, opt_D_dump_rn_stats, opt_WarnDeprecations
                        )
 import RnMonad
 import RnNames         ( getGlobalNames )
@@ -24,33 +23,30 @@ import RnSource             ( rnSourceDecls, rnDecl )
 import RnIfaces                ( getImportedInstDecls, importDecl, getImportVersions,
                          getImportedRules, loadHomeInterface, getSlurped, removeContext
                        )
-import RnEnv           ( availName, availNames, availsToNameSet, 
-                         warnUnusedTopNames, mapFvRn, lookupImplicitOccRn,
+import RnEnv           ( availName, availsToNameSet, 
+                         warnUnusedImports, warnUnusedLocalBinds, lookupImplicitOccRn,
                          FreeVars, plusFVs, plusFV, unitFV, emptyFVs, isEmptyFVs
                        )
-import Module           ( Module, ModuleName, pprModule, mkSearchPath, mkThisModule )
-import Name            ( Name, isLocallyDefined,
-                         NamedThing(..), ImportReason(..), Provenance(..),
-                         pprOccName, nameOccName,
-                         getNameProvenance, 
+import Module           ( Module, ModuleName, mkSearchPath, mkThisModule )
+import Name            ( Name, isLocallyDefined, NamedThing(..), getSrcLoc,
+                         nameOccName, nameUnique, 
+                         isUserImportedExplicitlyName, isUserImportedName,
                          maybeWiredInTyConName, maybeWiredInIdName, isWiredInName
                        )
+import OccName         ( occNameFlavour, isValOcc )
 import Id              ( idType )
-import DataCon         ( dataConTyCon, dataConType )
-import TyCon           ( TyCon, tyConDataCons, isSynTyCon, getSynTyConDefn )
-import RdrName         ( RdrName )
+import TyCon           ( isSynTyCon, getSynTyConDefn )
 import NameSet
 import PrelMods                ( mAIN_Name, pREL_MAIN_Name )
 import TysWiredIn      ( unitTyCon, intTyCon, doubleTyCon, boolTyCon )
-import PrelInfo                ( ioTyCon_NAME, numClass_RDR, thinAirIdNames, derivingOccurrences )
+import PrelInfo                ( ioTyCon_NAME, thinAirIdNames, fractionalClassKeys, derivingOccurrences )
 import Type            ( namesOfType, funTyCon )
 import ErrUtils                ( printErrorsAndWarnings, dumpIfSet, ghcExit )
 import BasicTypes      ( NewOrData(..) )
 import Bag             ( isEmptyBag, bagToList )
-import FiniteMap       ( fmToList, delListFromFM, addToFM, sizeFM, eltsFM )
+import FiniteMap       ( eltsFM )
 import UniqSupply      ( UniqSupply )
 import UniqFM          ( lookupUFM )
-import Util            ( equivClasses )
 import Maybes          ( maybeToBool )
 import Outputable
 \end{code}
@@ -68,22 +64,17 @@ renameModule :: UniqSupply
                      , [ModuleName]      -- Imported modules; for profiling
                      ))
 
-renameModule us this_mod@(HsModule mod_name vers exports imports local_decls loc)
+renameModule us this_mod@(HsModule mod_name vers exports imports local_decls _ loc)
   =    -- Initialise the renamer monad
     initRn mod_name us (mkSearchPath opt_HiMap) loc
           (rename this_mod)                            >>=
-       \ (maybe_rn_stuff, rn_errs_bag, rn_warns_bag) ->
+       \ ((maybe_rn_stuff, dump_action), rn_errs_bag, rn_warns_bag) ->
 
        -- Check for warnings
     printErrorsAndWarnings rn_errs_bag rn_warns_bag    >>
 
-       -- Dump output, if any
-    (case maybe_rn_stuff of
-       Nothing  -> return ()
-       Just results@(_, rn_mod, _, _, _)
-                -> dumpIfSet opt_D_dump_rn "Renamer:"
-                             (ppr rn_mod)
-    )                                                  >>
+       -- Dump any debugging output
+    dump_action                                        >>
 
        -- Return results
     if not (isEmptyBag rn_errs_bag) then
@@ -94,18 +85,21 @@ renameModule us this_mod@(HsModule mod_name vers exports imports local_decls loc
 
 
 \begin{code}
-rename this_mod@(HsModule mod_name vers exports imports local_decls loc)
+rename :: RdrNameHsModule
+       -> RnMG (Maybe (Module, RenamedHsModule, InterfaceDetails, RnNameSupply, [ModuleName]), IO ())
+rename this_mod@(HsModule mod_name vers _ imports local_decls mod_deprec loc)
   =    -- FIND THE GLOBAL NAME ENVIRONMENT
     getGlobalNames this_mod                    `thenRn` \ maybe_stuff ->
 
        -- CHECK FOR EARLY EXIT
     if not (maybeToBool maybe_stuff) then
        -- Everything is up to date; no need to recompile further
-       rnStats []              `thenRn_`
-       returnRn Nothing
+       rnDump [] []            `thenRn` \ dump_action ->
+       returnRn (Nothing, dump_action)
     else
     let
        Just (export_env, gbl_env, fixity_env, global_avail_env) = maybe_stuff
+        ExportEnv export_avails _ _ = export_env
     in
 
        -- RENAME THE SOURCE
@@ -116,24 +110,38 @@ rename this_mod@(HsModule mod_name vers exports imports local_decls loc)
        -- SLURP IN ALL THE NEEDED DECLARATIONS
     implicitFVs mod_name rn_local_decls        `thenRn` \ implicit_fvs -> 
     let
-       real_source_fvs = implicit_fvs `plusFV` source_fvs
+       real_source_fvs = implicit_fvs `plusFV` source_fvs `plusFV` export_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. 
+
+               -- The export_fvs make the exported names look just as if they
+               -- occurred in the source program.  For the reasoning, see the
+               -- comments with RnIfaces.getImportVersions
+       export_fvs = mkNameSet (map availName export_avails)
     in
     slurpImpDecls real_source_fvs      `thenRn` \ rn_imp_decls ->
+    let
+       rn_all_decls       = rn_local_decls ++ rn_imp_decls
+
+       -- COLLECT ALL DEPRECATIONS
+       deprec_sigs = [ ds | ValD bnds <- rn_local_decls, ds <- collectDeprecs bnds ]
+       deprecs = case mod_deprec of
+          Nothing -> deprec_sigs
+          Just txt -> Deprecation (IEModuleContents undefined) txt : deprec_sigs
+    in
 
        -- EXIT IF ERRORS FOUND
-    checkErrsRn                                `thenRn` \ no_errs_so_far ->
+    checkErrsRn                                        `thenRn` \ no_errs_so_far ->
     if not no_errs_so_far then
        -- Found errors already, so exit now
-       rnStats []              `thenRn_`
-       returnRn Nothing
+       rnDump rn_imp_decls rn_all_decls        `thenRn` \ dump_action ->
+       returnRn (Nothing, dump_action)
     else
 
        -- GENERATE THE VERSION/USAGE INFO
-    getImportVersions mod_name exports                 `thenRn` \ my_usages ->
-    getNameSupplyRn                                    `thenRn` \ name_supply ->
+    getImportVersions mod_name export_env      `thenRn` \ my_usages ->
+    getNameSupplyRn                            `thenRn` \ name_supply ->
 
        -- REPORT UNUSED NAMES
     reportUnusedNames gbl_env global_avail_env
@@ -144,21 +152,25 @@ rename this_mod@(HsModule mod_name vers exports imports local_decls loc)
     let
        has_orphans        = any isOrphanDecl rn_local_decls
        direct_import_mods = [mod | ImportDecl mod _ _ _ _ _ <- imports]
-       rn_all_decls       = rn_imp_decls ++ rn_local_decls 
        renamed_module = HsModule mod_name vers 
                                  trashed_exports trashed_imports
                                  rn_all_decls
+                                 mod_deprec
                                  loc
     in
-    rnStats rn_imp_decls       `thenRn_`
+    rnDump rn_imp_decls        rn_all_decls            `thenRn` \ dump_action ->
     returnRn (Just (mkThisModule mod_name,
                    renamed_module, 
-                   (has_orphans, my_usages, export_env),
+                   (InterfaceDetails has_orphans my_usages export_env deprecs),
                    name_supply,
-                   direct_import_mods))
+                   direct_import_mods), dump_action)
   where
     trashed_exports  = {-trace "rnSource:trashed_exports"-} Nothing
     trashed_imports  = {-trace "rnSource:trashed_imports"-} []
+
+    collectDeprecs EmptyBinds = []
+    collectDeprecs (ThenBinds x y) = collectDeprecs x ++ collectDeprecs y
+    collectDeprecs (MonoBind _ sigs _) = [ d | DeprecSig d _ <- sigs ]
 \end{code}
 
 @implicitFVs@ forces the renamer to slurp in some things which aren't
@@ -167,21 +179,20 @@ mentioned explicitly, but which might be needed by the type checker.
 \begin{code}
 implicitFVs mod_name decls
   = mapRn lookupImplicitOccRn implicit_occs    `thenRn` \ implicit_names ->
-    returnRn (implicit_main            `plusFV` 
-             mkNameSet default_tys     `plusFV`
-             mkNameSet thinAirIdNames  `plusFV`
+    returnRn (implicit_main                            `plusFV` 
+             mkNameSet (map getName default_tycons)    `plusFV`
+             mkNameSet thinAirIdNames                  `plusFV`
              mkNameSet implicit_names)
-    
   where
-       -- Add occurrences for Int, Double, and (), because they
+       -- Add occurrences for Int, and (), because they
        -- are the types to which ambigious type variables may be defaulted by
        -- the type checker; so they won't always appear explicitly.
        -- [The () one is a GHC extension for defaulting CCall results.]
        -- ALSO: funTyCon, since it occurs implicitly everywhere!
        --       (we don't want to be bothered with making funTyCon a
        --        free var at every function application!)
-    default_tys = [getName intTyCon, getName doubleTyCon,
-                  getName unitTyCon, getName funTyCon, getName boolTyCon]
+       -- Double is dealt with separately in getGates
+    default_tycons = [unitTyCon, funTyCon, boolTyCon, intTyCon]
 
        -- Add occurrences for IO or PrimIO
     implicit_main |  mod_name == mAIN_Name
@@ -193,7 +204,6 @@ implicitFVs mod_name decls
        -- 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 = []
@@ -214,13 +224,35 @@ isOrphanDecl (InstD (InstDecl inst_ty _ _ _ _))
 isOrphanDecl (RuleD (RuleDecl _ _ _ lhs _ _))
   = check lhs
   where
-    check (HsVar v)   = not (isLocallyDefined v)
-    check (HsApp f a) = check f && check a
-    check other              = True
+       -- At the moment we just check for common LHS forms
+       -- Expand as necessary.  Getting it wrong just means
+       -- more orphans than necessary
+    check (HsVar v)      = not (isLocallyDefined v)
+    check (HsApp f a)    = check f && check a
+    check (HsLit _)      = False
+    check (OpApp l o _ r) = check l && check o && check r
+    check (NegApp e _)    = check e
+    check (HsPar e)      = check e
+    check (SectionL e o)  = check e && check o
+    check (SectionR o e)  = check e && check o
+
+    check other                  = True        -- Safe fall through
+
 isOrphanDecl other = False
 \end{code}
 
 
+\begin{code}
+dupDefaultDeclErrRn (DefaultDecl _ locn1 : dup_things)
+  = pushSrcLocRn locn1 $
+    addErrRn msg
+  where
+    msg = hang (ptext SLIT("Multiple default declarations"))
+              4  (vcat (map pp dup_things))
+    pp (DefaultDecl _ locn) = ptext SLIT("here was another default declaration") <+> ppr locn
+\end{code}
+
+
 %*********************************************************
 %*                                                      *
 \subsection{Slurping declarations}
@@ -277,7 +309,7 @@ slurpSourceRefs source_binders source_fvs
          rnInstDecls decls1 fvs1 gates1 inst_decls             `thenRn` \ (decls2, fvs2, gates2) ->
          go_outer decls2 fvs2 (all_gates `plusFV` gates2)
                               (nameSetToList (gates2 `minusNameSet` all_gates))
-               -- Knock out the all_gates because even ifwe don't slurp any new
+               -- Knock out the all_gates because even if we don't slurp any new
                -- decls we can get some apparently-new gates from wired-in names
 
     go_inner decls fvs gates []
@@ -399,15 +431,26 @@ vars of the source program, and extracts from the decl the gate names.
 getGates source_fvs (SigD (IfaceSig _ ty _ _))
   = extractHsTyNames ty
 
-getGates source_fvs (TyClD (ClassDecl ctxt cls tvs _ sigs _ _ _ _ _ _))
-  = delListFromNameSet (foldr (plusFV . get) (extractHsCtxtTyNames ctxt) sigs)
+getGates source_fvs (TyClD (ClassDecl ctxt cls tvs _ sigs _ _ _ _ _ _ _))
+  = (delListFromNameSet (foldr (plusFV . get) (extractHsCtxtTyNames ctxt) sigs)
                       (map getTyVarName tvs)
-    `addOneToNameSet` cls
+     `addOneToNameSet` cls)
+    `plusFV` maybe_double
   where
     get (ClassOpSig n _ _ ty _) 
        | n `elemNameSet` source_fvs = extractHsTyNames ty
        | otherwise                  = emptyFVs
 
+       -- If we load any numeric class that doesn't have
+       -- Int as an instance, add Double to the gates. 
+       -- This takes account of the fact that Double might be needed for
+       -- defaulting, but we don't want to load Double (and all its baggage)
+       -- if the more exotic classes aren't used at all.
+    maybe_double | nameUnique cls `elem` fractionalClassKeys 
+                = unitFV (getName doubleTyCon)
+                | otherwise
+                = emptyFVs
+
 getGates source_fvs (TyClD (TySynonym tycon tvs ty _))
   = delListFromNameSet (extractHsTyNames ty)
                       (map getTyVarName tvs)
@@ -418,13 +461,13 @@ getGates source_fvs (TyClD (TyData _ ctxt tycon tvs cons _ _ _))
                       (map getTyVarName tvs)
     `addOneToNameSet` tycon
   where
-    get (ConDecl n tvs ctxt details _)
+    get (ConDecl n _ tvs ctxt details _)
        | n `elemNameSet` source_fvs
                -- If the constructor is method, get fvs from all its fields
        = delListFromNameSet (get_details details `plusFV` 
                              extractHsCtxtTyNames ctxt)
                             (map getTyVarName tvs)
-    get (ConDecl n tvs ctxt (RecCon fields) _)
+    get (ConDecl n _ tvs ctxt (RecCon fields) _)
                -- Even if the constructor isn't mentioned, the fields
                -- might be, as selectors.  They can't mention existentially
                -- bound tyvars (typechecker checks for that) so no need for 
@@ -482,19 +525,36 @@ getInstDeclGates other                                = emptyFVs
 %*********************************************************
 
 \begin{code}
-reportUnusedNames gbl_env avail_env (ExportEnv export_avails _) mentioned_names
+reportUnusedNames :: GlobalRdrEnv -> NameEnv AvailInfo -> ExportEnv -> NameSet -> RnM d ()
+reportUnusedNames gbl_env avail_env (ExportEnv export_avails _ _) mentioned_names
   = 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 -> WARN( True, text "reportUnusedName: not in avail_env" <+> ppr sub_name )
-                                      Avail sub_name
+         mkNameSet [ availName parent_avail
+                   | sub_name <- nameSetToList used_names
+                   , isValOcc (getOccName sub_name)
+
+                       -- Usually, every used name will appear in avail_env, but there 
+                       -- is one time when it doesn't: tuples and other built in syntax.  When you
+                       -- write (a,b) that gives rise to a *use* of "(,)", so that the
+                       -- instances will get pulled in, but the tycon "(,)" isn't actually
+                       -- in scope.  Hence the isValOcc filter.
+                       --
+                       -- Also, (-x) gives rise to an implicit use of 'negate'; similarly, 
+                       --   3.5 gives rise to an implcit use of :%
+                       -- hence the isUserImportedName filter on the warning
+                     
+                   , let parent_avail 
+                           = case lookupNameEnv avail_env sub_name of
+                               Just avail -> avail
+                               Nothing -> WARN( isUserImportedName sub_name,
+                                                text "reportUnusedName: not in avail_env" <+> ppr sub_name )
+                                          Avail sub_name
+                     
+                   , case parent_avail of { AvailTC _ _ -> True; other -> False }
                    ]
 
        defined_names = mkNameSet (concat (rdrEnvElts gbl_env))
@@ -502,33 +562,43 @@ reportUnusedNames gbl_env avail_env (ExportEnv export_avails _) mentioned_names
           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
+       bad_locals = [n | n <- defined_but_not_used, isLocallyDefined             n]
+       bad_imps   = [n | n <- defined_but_not_used, isUserImportedExplicitlyName n]
 
-reportableUnusedName :: Name -> Bool
-reportableUnusedName 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
-
-rnStats :: [RenamedHsDecl] -> RnMG ()
-rnStats imp_decls
+       deprec_used deprec_env = [ (n,txt)
+                                 | n <- nameSetToList mentioned_names,
+                                   not (isLocallyDefined n),
+                                   Just txt <- [lookupNameEnv deprec_env n] ]
+    in
+    warnUnusedLocalBinds bad_locals                            `thenRn_`
+    warnUnusedImports bad_imps                                 `thenRn_`
+    getIfacesRn                                                        `thenRn` \ ifaces ->
+    (if opt_WarnDeprecations
+       then mapRn_ warnDeprec (deprec_used (iDeprecs ifaces))
+       else returnRn ())
+
+warnDeprec :: (Name, DeprecTxt) -> RnM d ()
+warnDeprec (name, txt)
+  = pushSrcLocRn (getSrcLoc name)      $
+    addWarnRn                          $
+    sep [ text (occNameFlavour (nameOccName name)) <+> ppr name <+>
+          text "is deprecated:", nest 4 (ppr txt) ]
+
+
+rnDump  :: [RenamedHsDecl]     -- Renamed imported decls
+       -> [RenamedHsDecl]      -- Renamed local decls
+       -> RnMG (IO ())
+rnDump imp_decls decls
         | opt_D_dump_rn_trace || 
          opt_D_dump_rn_stats ||
          opt_D_dump_rn 
-       = getRnStats imp_decls          `thenRn` \ msg ->
-         ioToRnM (printErrs msg)       `thenRn_`
-         returnRn ()
+       = getRnStats imp_decls          `thenRn` \ stats_msg ->
 
-       | otherwise = returnRn ()
-\end{code}
+         returnRn (printErrs stats_msg >> 
+                   dumpIfSet opt_D_dump_rn "Renamer:" (vcat (map ppr decls)))
 
+       | otherwise = returnRn (return ())
+\end{code}
 
 
 %*********************************************************
@@ -542,7 +612,7 @@ getRnStats :: [RenamedHsDecl] -> RnMG SDoc
 getRnStats imported_decls
   = getIfacesRn                `thenRn` \ ifaces ->
     let
-       n_mods = length [() | (_, _, Just _) <- eltsFM (iImpModInfo ifaces)]
+       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