-%
+
% (c) The University of Glasgow, 2000
%
\section[HscTypes]{Types for the per-module compiler}
\begin{code}
module HscTypes (
- HscEnv(..),
- GhciMode(..),
+ -- * Sessions and compilation state
+ Session(..), HscEnv(..), hscEPS,
+ FinderCache, FinderCacheEntry,
+ Target(..), TargetId(..), pprTarget, pprTargetId,
+ ModuleGraph, emptyMG,
- ModDetails(..), ModIface(..),
- ModGuts(..), ModImports(..), ForeignStubs(..),
- ParsedIface(..), IfaceDeprecs,
+ ModDetails(..), emptyModDetails,
+ ModGuts(..), CgGuts(..), ModImports(..), ForeignStubs(..),
+ ModSummary(..), showModMsg, isBootSummary,
+ msHsFilePath, msHiFilePath, msObjFilePath,
+
+ HscSource(..), isHsBoot, hscSourceString, -- Re-exported from DriverPhases
+
HomePackageTable, HomeModInfo(..), emptyHomePackageTable,
+ hptInstances, hptRules,
- ExternalPackageState(..), emptyExternalPackageState,
+ ExternalPackageState(..), EpsStats(..), addEpsInStats,
PackageTypeEnv, PackageIfaceTable, emptyPackageIfaceTable,
- lookupIface, lookupIfaceByModName, moduleNameToModule,
- emptyModIface,
+ lookupIface, lookupIfaceByModule, emptyModIface,
- InteractiveContext(..), emptyInteractiveContext, icPrintUnqual,
+ InteractiveContext(..), emptyInteractiveContext,
+ icPrintUnqual, unQualInScope,
- IfaceDecls, mkIfaceDecls, dcl_tycl, dcl_rules, dcl_insts,
+ ModIface(..), mkIfaceDepCache, mkIfaceVerCache, mkIfaceFixCache,
+ emptyIfaceDepCache,
- VersionInfo(..), initialVersionInfo, lookupVersion,
- FixityEnv, lookupFixity, collectFixities, emptyFixityEnv,
+ Deprecs(..), IfaceDeprecs,
- TyThing(..), implicitTyThings,
+ FixityEnv, FixItem(..), lookupFixity, emptyFixityEnv,
+ implicitTyThings,
+
+ TyThing(..), tyThingClass, tyThingTyCon, tyThingDataCon, tyThingId,
TypeEnv, lookupType, mkTypeEnv, emptyTypeEnv,
- extendTypeEnvList, extendTypeEnvWithIds,
+ extendTypeEnv, extendTypeEnvList, extendTypeEnvWithIds, lookupTypeEnv,
typeEnvElts, typeEnvClasses, typeEnvTyCons, typeEnvIds,
- WhetherHasOrphans, IsBootInterface, DeclsMap, Usage(..),
+ WhetherHasOrphans, IsBootInterface, Usage(..),
Dependencies(..), noDependencies,
- IfaceInsts, IfaceRules, GatedDecl, GatedDecls, GateFn,
NameCache(..), OrigNameCache, OrigIParamCache,
Avails, availsToNameSet, availName, availNames,
GenAvailInfo(..), AvailInfo, RdrAvailInfo,
- ExportItem, RdrExportItem,
-
- PersistentCompilerState(..),
+ IfaceExport,
- Deprecations(..), lookupDeprec, plusDeprecs,
+ Deprecations, DeprecTxt, lookupDeprec, plusDeprecs,
- InstEnv, ClsInstEnv, DFunId,
PackageInstEnv, PackageRuleBase,
- GlobalRdrEnv, GlobalRdrElt(..), emptyGlobalRdrEnv, pprGlobalRdrEnv,
- LocalRdrEnv, extendLocalRdrEnv, isLocalGRE, unQualInScope,
-
-- Linker stuff
Linkable(..), isObjectLinkable,
Unlinked(..), CompiledByteCode,
- isObject, nameOfObject, isInterpretable, byteCodeOfObject,
-
- -- Provenance
- Provenance(..), ImportReason(..),
- pprNameProvenance, hasBetterProv
-
+ isObject, nameOfObject, isInterpretable, byteCodeOfObject
) where
#include "HsVersions.h"
import ByteCodeAsm ( CompiledByteCode )
#endif
-import RdrName ( RdrName, mkRdrUnqual,
- RdrNameEnv, addListToRdrEnv, foldRdrEnv, isUnqual,
- rdrEnvToList, emptyRdrEnv )
-import Name ( Name, NamedThing, getName, nameOccName, nameModule, nameSrcLoc )
+import RdrName ( GlobalRdrEnv, emptyGlobalRdrEnv,
+ LocalRdrEnv, emptyLocalRdrEnv,
+ GlobalRdrElt(..), mkRdrUnqual, lookupGRE_RdrName )
+import Name ( Name, NamedThing, getName, nameOccName, nameModule )
import NameEnv
import NameSet
-import OccName ( OccName )
+import OccName ( OccName, OccEnv, lookupOccEnv, mkOccEnv, emptyOccEnv,
+ extendOccEnv )
import Module
-import InstEnv ( InstEnv, ClsInstEnv, DFunId )
+import InstEnv ( InstEnv, Instance )
import Rules ( RuleBase )
import CoreSyn ( CoreBind )
-import Id ( Id, idName )
+import Id ( Id )
+import Type ( TyThing(..) )
+
import Class ( Class, classSelIds, classTyCon )
-import TyCon ( TyCon, tyConName, isNewTyCon, tyConGenIds, tyConSelIds, tyConDataCons )
-import TcType ( TyThing(..) )
-import DataCon ( dataConWorkId, dataConWrapId, dataConWrapId_maybe )
-import Packages ( PackageName, basePackage )
-import CmdLineOpts ( DynFlags )
-
-import BasicTypes ( Version, initialVersion, IPName,
- Fixity, FixitySig(..), defaultFixity )
-
-import HsSyn ( DeprecTxt, TyClDecl, InstDecl, RuleDecl,
- tyClDeclName, ifaceRuleDeclName, tyClDeclNames,
- instDeclDFun )
-import RnHsSyn ( RenamedTyClDecl, RenamedRuleDecl, RenamedInstDecl )
-
-import CoreSyn ( IdCoreRule )
-import PrelNames ( isBuiltInSyntaxName )
-import InstEnv ( emptyInstEnv )
-import Rules ( emptyRuleBase )
-
-import FiniteMap
-import Bag ( Bag, emptyBag )
-import Maybes ( orElse )
+import TyCon ( TyCon, tyConSelIds, tyConDataCons )
+import DataCon ( dataConImplicitIds )
+import Packages ( PackageIdH, PackageId, PackageConfig )
+import DynFlags ( DynFlags(..), isOneShot )
+import DriverPhases ( HscSource(..), isHsBoot, hscSourceString )
+import BasicTypes ( Version, initialVersion, IPName,
+ Fixity, defaultFixity, DeprecTxt )
+
+import IfaceSyn ( IfaceInst, IfaceRule, IfaceDecl(ifName) )
+
+import FiniteMap ( FiniteMap )
+import CoreSyn ( CoreRule )
+import Maybes ( orElse, fromJust, expectJust )
import Outputable
-import SrcLoc ( SrcLoc, isGoodSrcLoc )
-import Util ( thenCmp, sortLt )
+import SrcLoc ( SrcSpan )
import UniqSupply ( UniqSupply )
-import Maybe ( fromJust )
import FastString ( FastString )
+import DATA_IOREF ( IORef, readIORef )
+import StringBuffer ( StringBuffer )
import Time ( ClockTime )
\end{code}
%* *
%************************************************************************
-The HscEnv gives the environment in which to compile a chunk of code.
\begin{code}
-data HscEnv = HscEnv { hsc_mode :: GhciMode,
- hsc_dflags :: DynFlags,
- hsc_HPT :: HomePackageTable }
+-- | The Session is a handle to the complete state of a compilation
+-- session. A compilation session consists of a set of modules
+-- constituting the current program or library, the context for
+-- interactive evaluation, and various caches.
+newtype Session = Session (IORef HscEnv)
\end{code}
-The GhciMode is self-explanatory:
+HscEnv is like Session, except that some of the fields are immutable.
+An HscEnv is used to compile a single module from plain Haskell source
+code (after preprocessing) to either C, assembly or C--. Things like
+the module graph don't change during a single compilation.
-\begin{code}
-data GhciMode = Batch | Interactive | OneShot
- deriving Eq
-\end{code}
+Historical note: "hsc" used to be the name of the compiler binary,
+when there was a separate driver and compiler. To compile a single
+module, the driver would invoke hsc on the source code... so nowadays
+we think of hsc as the layer of the compiler that deals with compiling
+a single module.
\begin{code}
-type HomePackageTable = ModuleEnv HomeModInfo -- Domain = modules in the home package
-type PackageIfaceTable = ModuleEnv ModIface -- Domain = modules in the imported packages
+data HscEnv
+ = HscEnv {
+ hsc_dflags :: DynFlags,
+ -- The dynamic flag settings
+
+ hsc_targets :: [Target],
+ -- The targets (or roots) of the current session
+
+ hsc_mod_graph :: ModuleGraph,
+ -- The module graph of the current session
+
+ hsc_IC :: InteractiveContext,
+ -- The context for evaluating interactive statements
+
+ hsc_HPT :: HomePackageTable,
+ -- The home package table describes already-compiled
+ -- home-packge modules, *excluding* the module we
+ -- are compiling right now.
+ -- (In one-shot mode the current module is the only
+ -- home-package module, so hsc_HPT is empty. All other
+ -- modules count as "external-package" modules.
+ -- However, even in GHCi mode, hi-boot interfaces are
+ -- demand-loadeded into the external-package table.)
+ --
+ -- hsc_HPT is not mutable because we only demand-load
+ -- external packages; the home package is eagerly
+ -- loaded, module by module, by the compilation manager.
+ --
+ -- The HPT may contain modules compiled earlier by --make
+ -- but not actually below the current module in the dependency
+ -- graph. (This changes a previous invariant: changed Jan 05.)
+
+ hsc_EPS :: {-# UNPACK #-} !(IORef ExternalPackageState),
+ hsc_NC :: {-# UNPACK #-} !(IORef NameCache),
+ -- These are side-effected by compiling to reflect
+ -- sucking in interface files. They cache the state of
+ -- external interface files, in effect.
+
+ hsc_FC :: {-# UNPACK #-} !(IORef FinderCache)
+ -- The finder's cache. This caches the location of modules,
+ -- so we don't have to search the filesystem multiple times.
+ }
+
+hscEPS :: HscEnv -> IO ExternalPackageState
+hscEPS hsc_env = readIORef (hsc_EPS hsc_env)
+
+-- | A compilation target.
+--
+-- A target may be supplied with the actual text of the
+-- module. If so, use this instead of the file contents (this
+-- is for use in an IDE where the file hasn't been saved by
+-- the user yet).
+data Target = Target TargetId (Maybe (StringBuffer,ClockTime))
+
+data TargetId
+ = TargetModule Module -- ^ A module name: search for the file
+ | TargetFile FilePath -- ^ A filename: parse it to find the module name.
+ deriving Eq
+
+pprTarget :: Target -> SDoc
+pprTarget (Target id _) = pprTargetId id
+
+pprTargetId (TargetModule m) = ppr m
+pprTargetId (TargetFile f) = text f
+
+type FinderCache = ModuleEnv FinderCacheEntry
+type FinderCacheEntry = (ModLocation, Maybe (PackageConfig,Bool))
+ -- The finder's cache (see module Finder)
+
+type HomePackageTable = ModuleEnv HomeModInfo
+ -- Domain = modules in the home package
+type PackageIfaceTable = ModuleEnv ModIface
+ -- Domain = modules in the imported packages
emptyHomePackageTable = emptyModuleEnv
emptyPackageIfaceTable = emptyModuleEnv
-data HomeModInfo = HomeModInfo { hm_iface :: ModIface,
- hm_details :: ModDetails,
- hm_linkable :: Linkable }
+data HomeModInfo
+ = HomeModInfo { hm_iface :: !ModIface,
+ hm_details :: !ModDetails,
+ hm_linkable :: !(Maybe Linkable) }
+ -- hm_linkable might be Nothing if:
+ -- a) this is an .hs-boot module
+ -- b) temporarily during compilation if we pruned away
+ -- the old linkable because it was out of date.
+ -- after a complete compilation (GHC.load), all hm_linkable
+ -- fields in the HPT will be Just.
\end{code}
Simple lookups in the symbol table.
Just mod_info -> Just (hm_iface mod_info)
Nothing -> lookupModuleEnv pit mod
-lookupIfaceByModName :: HomePackageTable -> PackageIfaceTable -> ModuleName -> Maybe ModIface
+lookupIfaceByModule :: HomePackageTable -> PackageIfaceTable -> Module -> Maybe ModIface
-- We often have two IfaceTables, and want to do a lookup
-lookupIfaceByModName hpt pit mod
- = case lookupModuleEnvByName hpt mod of
+lookupIfaceByModule hpt pit mod
+ = case lookupModuleEnv hpt mod of
Just mod_info -> Just (hm_iface mod_info)
- Nothing -> lookupModuleEnvByName pit mod
+ Nothing -> lookupModuleEnv pit mod
\end{code}
+
\begin{code}
--- Use instead of Finder.findModule if possible: this way doesn't
--- require filesystem operations, and it is guaranteed not to fail
--- when the IfaceTables are properly populated (i.e. after the renamer).
-moduleNameToModule :: HomePackageTable -> PackageIfaceTable -> ModuleName -> Module
-moduleNameToModule hpt pit mod
- = mi_module (fromJust (lookupIfaceByModName hpt pit mod))
+hptInstances :: HscEnv -> (Module -> Bool) -> [Instance]
+-- Find all the instance declarations that are in modules imported
+-- by this one, directly or indirectly, and are in the Home Package Table
+-- This ensures that we don't see instances from modules --make compiled
+-- before this one, but which are not below this one
+hptInstances hsc_env want_this_module
+ = [ ispec
+ | mod_info <- moduleEnvElts (hsc_HPT hsc_env)
+ , want_this_module (mi_module (hm_iface mod_info))
+ , ispec <- md_insts (hm_details mod_info) ]
+
+hptRules :: HscEnv -> [(Module, IsBootInterface)] -> [CoreRule]
+-- Get rules from modules "below" this one (in the dependency sense)
+-- C.f Inst.hptInstances
+hptRules hsc_env deps
+ | isOneShot (ghcMode (hsc_dflags hsc_env)) = []
+ | otherwise
+ = let
+ hpt = hsc_HPT hsc_env
+ in
+ [ rule
+ | -- Find each non-hi-boot module below me
+ (mod, False) <- deps
+
+ -- Look it up in the HPT
+ , let mod_info = ASSERT( mod `elemModuleEnv` hpt )
+ fromJust (lookupModuleEnv hpt mod)
+
+ -- And get its dfuns
+ , rule <- md_rules (hm_details mod_info) ]
\end{code}
\begin{code}
data ModIface
= ModIface {
+ mi_package :: !PackageIdH, -- Which package the module comes from
mi_module :: !Module,
- mi_package :: !PackageName, -- Which package the module comes from
- mi_version :: !VersionInfo, -- Version info for everything in this module
+ mi_mod_vers :: !Version, -- Module version: changes when anything changes
+
mi_orphan :: !WhetherHasOrphans, -- Whether this module has orphans
mi_boot :: !IsBootInterface, -- Read from an hi-boot file?
mi_deps :: Dependencies,
- -- This is consulted for directly-imported modules, but
- -- not for anything else
+ -- This is consulted for directly-imported modules,
+ -- but not for anything else (hence lazy)
- mi_usages :: [Usage Name],
-- Usages; kept sorted so that it's easy to decide
-- whether to write a new iface file (changing usages
-- doesn't affect the version of this module)
+ mi_usages :: [Usage],
-- NOT STRICT! we read this field lazily from the interface file
-- It is *only* consulted by the recompilation checker
- mi_exports :: ![ExportItem],
- -- What it exports Kept sorted by (mod,occ), to make
- -- version comparisons easier
+ -- Exports
+ -- Kept sorted by (mod,occ), to make version comparisons easier
+ mi_exports :: ![IfaceExport],
+ mi_exp_vers :: !Version, -- Version number of export list
+
+ -- Fixities
+ mi_fixities :: [(OccName,Fixity)],
+ -- NOT STRICT! we read this field lazily from the interface file
+
+ -- Deprecations
+ mi_deprecs :: IfaceDeprecs,
+ -- NOT STRICT! we read this field lazily from the interface file
+
+ -- Type, class and variable declarations
+ -- The version of an Id changes if its fixity or deprecations change
+ -- (as well as its type of course)
+ -- Ditto data constructors, class operations, except that
+ -- the version of the parent class/tycon changes
+ mi_decls :: [(Version,IfaceDecl)], -- Sorted
mi_globals :: !(Maybe GlobalRdrEnv),
-- Its top level environment or Nothing if we read this
-- interface from an interface file. (We need the source
-- file to figure out the top-level environment.)
- mi_fixities :: !FixityEnv, -- Fixities
- mi_deprecs :: Deprecations, -- Deprecations
- -- NOT STRICT! we read this field lazilly from the interface file
-
- mi_decls :: IfaceDecls -- The RnDecls form of ModDetails
- -- NOT STRICT! we fill this field with _|_ sometimes
+ -- Instance declarations and rules
+ mi_insts :: [IfaceInst], -- Sorted
+ mi_rules :: [IfaceRule], -- Sorted
+ mi_rule_vers :: !Version, -- Version number for rules and instances combined
+
+ -- Cached environments for easy lookup
+ -- These are computed (lazily) from other fields
+ -- and are not put into the interface file
+ mi_dep_fn :: Name -> Maybe DeprecTxt, -- Cached lookup for mi_deprecs
+ mi_fix_fn :: OccName -> Fixity, -- Cached lookup for mi_fixities
+ mi_ver_fn :: OccName -> Maybe Version -- Cached lookup for mi_decls
+ -- The Nothing in mi_ver_fn means that the thing
+ -- isn't in decls. It's useful to know that when
+ -- seeing if we are up to date wrt the old interface
}
-- Should be able to construct ModDetails from mi_decls in ModIface
data ModDetails
= ModDetails {
-- The next three fields are created by the typechecker
+ md_exports :: NameSet,
md_types :: !TypeEnv,
- md_insts :: ![DFunId], -- Dfun-ids for the instances in this module
- md_rules :: ![IdCoreRule] -- Domain may include Ids from other modules
+ md_insts :: ![Instance], -- Dfun-ids for the instances in this module
+ md_rules :: ![CoreRule] -- Domain may include Ids from other modules
}
+emptyModDetails = ModDetails { md_types = emptyTypeEnv,
+ md_exports = emptyNameSet,
+ md_insts = [],
+ md_rules = [] }
+
-- A ModGuts is carried through the compiler, accumulating stuff as it goes
-- There is only one ModGuts at any time, the one for the module
-- being compiled right now. Once it is compiled, a ModIface and
data ModGuts
= ModGuts {
mg_module :: !Module,
- mg_exports :: !Avails, -- What it exports
+ mg_boot :: IsBootInterface, -- Whether it's an hs-boot module
+ mg_exports :: !NameSet, -- What it exports
mg_deps :: !Dependencies, -- What is below it, directly or otherwise
mg_dir_imps :: ![Module], -- Directly-imported modules; used to
-- generate initialisation code
- mg_usages :: ![Usage Name], -- Version info for what it needed
+ mg_usages :: ![Usage], -- Version info for what it needed
mg_rdr_env :: !GlobalRdrEnv, -- Top-level lexical environment
mg_fix_env :: !FixityEnv, -- Fixity env, for things declared in this module
mg_deprecs :: !Deprecations, -- Deprecations declared in the module
mg_types :: !TypeEnv,
- mg_insts :: ![DFunId], -- Instances
- mg_rules :: ![IdCoreRule], -- Rules from this module
+ mg_insts :: ![Instance], -- Instances
+ mg_rules :: ![CoreRule], -- Rules from this module
mg_binds :: ![CoreBind], -- Bindings for this module
mg_foreign :: !ForeignStubs
}
-- After simplification, the following fields change slightly:
-- mg_rules Orphan rules only (local ones now attached to binds)
-- mg_binds With rules attached
---
--- After CoreTidy, the following fields change slightly:
--- mg_types Now contains Ids as well, replete with final IdInfo
--- The Ids are only the ones that are visible from
--- importing modules. Without -O that means only
--- exported Ids, but with -O importing modules may
--- see ids mentioned in unfoldings of exported Ids
---
--- mg_insts Same DFunIds as before, but with final IdInfo,
--- and the unique might have changed; remember that
--- CoreTidy links up the uniques of old and new versions
---
--- mg_rules All rules for exported things, substituted with final Ids
---
--- mg_binds Tidied
+---------------------------------------------------------
+-- The Tidy pass forks the information about this module:
+-- * one lot goes to interface file generation (ModIface)
+-- and later compilations (ModDetails)
+-- * the other lot goes to code generation (CgGuts)
+data CgGuts
+ = CgGuts {
+ cg_module :: !Module,
+
+ cg_tycons :: [TyCon], -- Algebraic data types (including ones that started life
+ -- as classes); generate constructors and info tables
+ -- Includes newtypes, just for the benefit of External Core
+ cg_binds :: [CoreBind], -- The tidied main bindings, including previously-implicit
+ -- bindings for record and class selectors, and
+ -- data construtor wrappers.
+ -- But *not* data constructor workers; reason: we
+ -- we regard them as part of the code-gen of tycons
+
+ cg_dir_imps :: ![Module], -- Directly-imported modules; used to generate
+ -- initialisation code
+
+ cg_foreign :: !ForeignStubs,
+ cg_dep_pkgs :: ![PackageId] -- Used to generate #includes for C code gen
+ }
+
+-----------------------------------
data ModImports
= ModImports {
imp_direct :: ![(Module,Bool)], -- Explicitly-imported modules
-- directly or indirectly
}
+-----------------------------------
data ForeignStubs = NoStubs
| ForeignStubs
SDoc -- Header file prototypes for
[Id] -- Foreign-exported binders
-- we have to generate code to register these
-
-data IfaceDecls = IfaceDecls { dcl_tycl :: [RenamedTyClDecl], -- Sorted
- dcl_rules :: [RenamedRuleDecl], -- Sorted
- dcl_insts :: [RenamedInstDecl] } -- Unsorted
-
-mkIfaceDecls :: [RenamedTyClDecl] -> [RenamedRuleDecl] -> [RenamedInstDecl] -> IfaceDecls
--- Sort to put them in canonical order for version comparison
-mkIfaceDecls tycls rules insts
- = IfaceDecls { dcl_tycl = sortLt lt_tycl tycls,
- dcl_rules = sortLt lt_rule rules,
- dcl_insts = sortLt lt_inst insts }
- where
- d1 `lt_tycl` d2 = tyClDeclName d1 < tyClDeclName d2
- r1 `lt_rule` r2 = ifaceRuleDeclName r1 < ifaceRuleDeclName r2
- i1 `lt_inst` i2 = instDeclDFun i1 < instDeclDFun i2
\end{code}
\begin{code}
-emptyModIface :: Module -> ModIface
-emptyModIface mod
- = ModIface { mi_module = mod,
- mi_package = basePackage, -- XXX fully bogus
- mi_version = initialVersionInfo,
- mi_usages = [],
- mi_deps = noDependencies,
+emptyModIface :: PackageIdH -> Module -> ModIface
+emptyModIface pkg mod
+ = ModIface { mi_package = pkg,
+ mi_module = mod,
+ mi_mod_vers = initialVersion,
mi_orphan = False,
mi_boot = False,
+ mi_deps = noDependencies,
+ mi_usages = [],
mi_exports = [],
- mi_fixities = emptyNameEnv,
- mi_globals = Nothing,
+ mi_exp_vers = initialVersion,
+ mi_fixities = [],
mi_deprecs = NoDeprecs,
- mi_decls = panic "emptyModIface: decls"
+ mi_insts = [],
+ mi_rules = [],
+ mi_decls = [],
+ mi_globals = Nothing,
+ mi_rule_vers = initialVersion,
+ mi_dep_fn = emptyIfaceDepCache,
+ mi_fix_fn = emptyIfaceFixCache,
+ mi_ver_fn = emptyIfaceVerCache
}
\end{code}
%************************************************************************
%* *
- Parsed interface files
-%* *
-%************************************************************************
-
-A ParsedIface is exactly as read from an interface file.
-
-\begin{code}
-type IfaceDeprecs = Maybe (Either DeprecTxt [(RdrName,DeprecTxt)])
- -- Nothing => NoDeprecs
- -- Just (Left t) => DeprecAll
- -- Just (Right p) => DeprecSome
-
-data ParsedIface
- = ParsedIface {
- pi_mod :: ModuleName,
- pi_pkg :: PackageName,
- pi_vers :: Version, -- Module version number
- pi_orphan :: WhetherHasOrphans, -- Whether this module has orphans
- pi_deps :: Dependencies, -- What it depends on
- pi_usages :: [Usage OccName], -- Usages
- pi_exports :: (Version, [RdrExportItem]), -- Exports
- pi_decls :: [(Version, TyClDecl RdrName)], -- Local definitions
- pi_fixity :: [FixitySig RdrName], -- Local fixity declarations,
- pi_insts :: [InstDecl RdrName], -- Local instance declarations
- pi_rules :: (Version, [RuleDecl RdrName]), -- Rules, with their version
- pi_deprecs :: IfaceDeprecs -- Deprecations
- }
-\end{code}
-
-
-%************************************************************************
-%* *
\subsection{The interactive context}
%* *
%************************************************************************
emptyInteractiveContext
= InteractiveContext { ic_toplev_scope = [],
ic_exports = [],
- ic_rn_gbl_env = emptyRdrEnv,
- ic_rn_local_env = emptyRdrEnv,
+ ic_rn_gbl_env = emptyGlobalRdrEnv,
+ ic_rn_local_env = emptyLocalRdrEnv,
ic_type_env = emptyTypeEnv }
icPrintUnqual :: InteractiveContext -> PrintUnqualified
icPrintUnqual ictxt = unQualInScope (ic_rn_gbl_env ictxt)
\end{code}
+@unQualInScope@ returns a function that takes a @Name@ and tells whether
+its unqualified name is in scope. This is put as a boolean flag in
+the @Name@'s provenance to guide whether or not to print the name qualified
+in error messages.
+
+\begin{code}
+unQualInScope :: GlobalRdrEnv -> PrintUnqualified
+-- True if 'f' is in scope, and has only one binding,
+-- and the thing it is bound to is the name we are looking for
+-- (i.e. false if A.f and B.f are both in scope as unqualified 'f')
+--
+-- [Out of date] Also checks for built-in syntax, which is always 'in scope'
+unQualInScope env mod occ
+ = case lookupGRE_RdrName (mkRdrUnqual occ) env of
+ [gre] -> nameModule (gre_name gre) == mod
+ other -> False
+\end{code}
+
%************************************************************************
%* *
-\subsection{Type environment stuff}
+ TyThing
%* *
%************************************************************************
\begin{code}
+implicitTyThings :: TyThing -> [TyThing]
+implicitTyThings (AnId id) = []
+
+ -- For type constructors, add the data cons (and their extras),
+ -- and the selectors and generic-programming Ids too
+ --
+ -- Newtypes don't have a worker Id, so don't generate that?
+implicitTyThings (ATyCon tc) = map AnId (tyConSelIds tc) ++
+ concatMap (extras_plus . ADataCon) (tyConDataCons tc)
+
+ -- For classes, add the class TyCon too (and its extras)
+ -- and the class selector Ids
+implicitTyThings (AClass cl) = map AnId (classSelIds cl) ++
+ extras_plus (ATyCon (classTyCon cl))
+
+
+ -- For data cons add the worker and wrapper (if any)
+implicitTyThings (ADataCon dc) = map AnId (dataConImplicitIds dc)
+
+extras_plus thing = thing : implicitTyThings thing
+
+extendTypeEnvWithIds :: TypeEnv -> [Id] -> TypeEnv
+extendTypeEnvWithIds env ids
+ = extendNameEnvList env [(getName id, AnId id) | id <- ids]
+\end{code}
+
+%************************************************************************
+%* *
+ TypeEnv
+%* *
+%************************************************************************
+
+\begin{code}
+type TypeEnv = NameEnv TyThing
+
+emptyTypeEnv :: TypeEnv
typeEnvElts :: TypeEnv -> [TyThing]
typeEnvClasses :: TypeEnv -> [Class]
typeEnvTyCons :: TypeEnv -> [TyCon]
typeEnvIds :: TypeEnv -> [Id]
+lookupTypeEnv :: TypeEnv -> Name -> Maybe TyThing
+emptyTypeEnv = emptyNameEnv
typeEnvElts env = nameEnvElts env
typeEnvClasses env = [cl | AClass cl <- typeEnvElts env]
typeEnvTyCons env = [tc | ATyCon tc <- typeEnvElts env]
typeEnvIds env = [id | AnId id <- typeEnvElts env]
-\end{code}
-
-
-\begin{code}
-type TypeEnv = NameEnv TyThing
-
-emptyTypeEnv = emptyNameEnv
mkTypeEnv :: [TyThing] -> TypeEnv
mkTypeEnv things = extendTypeEnvList emptyTypeEnv things
-extendTypeEnvList :: TypeEnv -> [TyThing] -> TypeEnv
--- Extend the type environment
-extendTypeEnvList env things
- = foldl extend env things
- where
- extend env thing = extendNameEnv env (getName thing) thing
-
-implicitTyThings :: [TyThing] -> [TyThing]
-implicitTyThings things
- = concatMap extras things
- where
- extras_plus thing = thing : extras thing
-
- extras (AnId id) = []
-
- -- For type constructors, add the data cons (and their extras),
- -- and the selectors and generic-programming Ids too
- --
- -- Newtypes don't have a worker Id, so don't generate that
- extras (ATyCon tc) = map AnId (tyConGenIds tc ++ tyConSelIds tc) ++ data_con_stuff
- where
- data_con_stuff | isNewTyCon tc = (if (null dcs) then [] else [ADataCon dc1, AnId (dataConWrapId dc1)])
- | otherwise = concatMap (extras_plus . ADataCon) dcs
- dcs = tyConDataCons tc
- dc1 = head dcs
-
- -- For classes, add the class TyCon too (and its extras)
- -- and the class selector Ids
- extras (AClass cl) = map AnId (classSelIds cl) ++
- extras_plus (ATyCon (classTyCon cl))
-
+lookupTypeEnv = lookupNameEnv
- -- For data cons add the worker and wrapper (if any)
- extras (ADataCon dc)
- = AnId (dataConWorkId dc) : wrap_id_stuff
- where
- -- May or may not have a wrapper
- wrap_id_stuff = case dataConWrapId_maybe dc of
- Just id -> [AnId id]
- Nothing -> []
+-- Extend the type environment
+extendTypeEnv :: TypeEnv -> TyThing -> TypeEnv
+extendTypeEnv env thing = extendNameEnv env (getName thing) thing
-extendTypeEnvWithIds :: TypeEnv -> [Id] -> TypeEnv
-extendTypeEnvWithIds env ids
- = extendNameEnvList env [(getName id, AnId id) | id <- ids]
+extendTypeEnvList :: TypeEnv -> [TyThing] -> TypeEnv
+extendTypeEnvList env things = foldl extendTypeEnv env things
\end{code}
\begin{code}
Nothing -> lookupNameEnv pte name
\end{code}
+
+\begin{code}
+tyThingTyCon (ATyCon tc) = tc
+tyThingTyCon other = pprPanic "tyThingTyCon" (ppr other)
+
+tyThingClass (AClass cls) = cls
+tyThingClass other = pprPanic "tyThingClass" (ppr other)
+
+tyThingDataCon (ADataCon dc) = dc
+tyThingDataCon other = pprPanic "tyThingDataCon" (ppr other)
+
+tyThingId (AnId id) = id
+tyThingId other = pprPanic "tyThingId" (ppr other)
+\end{code}
+
%************************************************************************
%* *
\subsection{Auxiliary types}
but they are mostly elaborated elsewhere
\begin{code}
-data VersionInfo
- = VersionInfo {
- vers_module :: Version, -- Changes when anything changes
- vers_exports :: Version, -- Changes when export list changes
- vers_rules :: Version, -- Changes when any rule changes
- vers_decls :: NameEnv Version
- -- Versions for "big" names only (not data constructors, class ops)
- -- The version of an Id changes if its fixity changes
- -- Ditto data constructors, class operations, except that the version of
- -- the parent class/tycon changes
- --
- -- If a name isn't in the map, it means 'initialVersion'
- }
+mkIfaceVerCache :: [(Version,IfaceDecl)] -> OccName -> Maybe Version
+mkIfaceVerCache pairs
+ = \occ -> lookupOccEnv env occ
+ where
+ env = foldl add emptyOccEnv pairs
+ add env (v,d) = extendOccEnv env (ifName d) v
+
+emptyIfaceVerCache :: OccName -> Maybe Version
+emptyIfaceVerCache occ = Nothing
+
+------------------ Deprecations -------------------------
+data Deprecs a
+ = NoDeprecs
+ | DeprecAll DeprecTxt -- Whole module deprecated
+ | DeprecSome a -- Some specific things deprecated
+ deriving( Eq )
-initialVersionInfo :: VersionInfo
-initialVersionInfo = VersionInfo { vers_module = initialVersion,
- vers_exports = initialVersion,
- vers_rules = initialVersion,
- vers_decls = emptyNameEnv
- }
+type IfaceDeprecs = Deprecs [(OccName,DeprecTxt)]
+type Deprecations = Deprecs (NameEnv (OccName,DeprecTxt))
-lookupVersion :: NameEnv Version -> Name -> Version
-lookupVersion env name = lookupNameEnv env name `orElse` initialVersion
+mkIfaceDepCache:: IfaceDeprecs -> Name -> Maybe DeprecTxt
+mkIfaceDepCache NoDeprecs = \n -> Nothing
+mkIfaceDepCache (DeprecAll t) = \n -> Just t
+mkIfaceDepCache (DeprecSome pairs) = lookupOccEnv (mkOccEnv pairs) . nameOccName
-data Deprecations = NoDeprecs
- | DeprecAll DeprecTxt -- Whole module deprecated
- | DeprecSome (NameEnv (Name,DeprecTxt)) -- Some things deprecated
- -- Just "big" names
- -- We keep the Name in the range, so we can print them out
+emptyIfaceDepCache :: Name -> Maybe DeprecTxt
+emptyIfaceDepCache n = Nothing
lookupDeprec :: Deprecations -> Name -> Maybe DeprecTxt
lookupDeprec NoDeprecs name = Nothing
plusDeprecs d (DeprecAll t) = DeprecAll t
plusDeprecs (DeprecAll t) d = DeprecAll t
plusDeprecs (DeprecSome v1) (DeprecSome v2) = DeprecSome (v1 `plusNameEnv` v2)
-
-instance Eq Deprecations where
- -- Used when checking whether we need write a new interface
- NoDeprecs == NoDeprecs = True
- (DeprecAll t1) == (DeprecAll t2) = t1 == t2
- (DeprecSome e1) == (DeprecSome e2) = nameEnvElts e1 == nameEnvElts e2
- d1 == d2 = False
\end{code}
deriving( Eq )
-- Equality used when deciding if the interface has changed
-type RdrExportItem = (ModuleName, [RdrAvailInfo])
-type ExportItem = (ModuleName, [AvailInfo])
+type IfaceExport = (Module, [GenAvailInfo OccName])
availsToNameSet :: [AvailInfo] -> NameSet
availsToNameSet avails = foldl add emptyNameSet avails
\end{code}
\begin{code}
-type FixityEnv = NameEnv (FixitySig Name)
- -- We keep the whole fixity sig so that we
- -- can report line-number info when there is a duplicate
- -- fixity declaration
+mkIfaceFixCache :: [(OccName, Fixity)] -> OccName -> Fixity
+mkIfaceFixCache pairs
+ = \n -> lookupOccEnv env n `orElse` defaultFixity
+ where
+ env = mkOccEnv pairs
+
+emptyIfaceFixCache :: OccName -> Fixity
+emptyIfaceFixCache n = defaultFixity
+
+-- This fixity environment is for source code only
+type FixityEnv = NameEnv FixItem
+
+-- We keep the OccName in the range so that we can generate an interface from it
+data FixItem = FixItem OccName Fixity SrcSpan
+
+instance Outputable FixItem where
+ ppr (FixItem occ fix loc) = ppr fix <+> ppr occ <+> parens (ppr loc)
emptyFixityEnv :: FixityEnv
emptyFixityEnv = emptyNameEnv
lookupFixity :: FixityEnv -> Name -> Fixity
lookupFixity env n = case lookupNameEnv env n of
- Just (FixitySig _ fix _) -> fix
- Nothing -> defaultFixity
-
-collectFixities :: FixityEnv -> [TyClDecl Name] -> [FixitySig Name]
--- Collect fixities for the specified declarations
-collectFixities env decls
- = [ fix
- | d <- decls, (n,_) <- tyClDeclNames d,
- Just fix <- [lookupNameEnv env n]
- ]
+ Just (FixItem _ fix _) -> fix
+ Nothing -> defaultFixity
\end{code}
-- in the import hierarchy. See TcRnTypes.ImportAvails for details.
--
-- Invariant: the dependencies of a module M never includes M
+-- Invariant: the lists are unordered, with no duplicates
data Dependencies
- = Deps { dep_mods :: [(ModuleName,IsBootInterface)], -- Home-package module dependencies
- dep_pkgs :: [PackageName], -- External package dependencies
- dep_orphs :: [ModuleName] } -- Orphan modules (whether home or external pkg)
+ = Deps { dep_mods :: [(Module,IsBootInterface)], -- Home-package module dependencies
+ dep_pkgs :: [PackageId], -- External package dependencies
+ dep_orphs :: [Module] } -- Orphan modules (whether home or external pkg)
+ deriving( Eq )
+ -- Equality used only for old/new comparison in MkIface.addVersionInfo
noDependencies :: Dependencies
noDependencies = Deps [] [] []
-data Usage name
- = Usage { usg_name :: ModuleName, -- Name of the module
- usg_mod :: Version, -- Module version
- usg_exports :: Maybe Version, -- Export-list version, if we depend on it
- usg_entities :: [(name,Version)], -- Sorted by occurrence name
- usg_rules :: Version -- Rules version
+data Usage
+ = Usage { usg_name :: Module, -- Name of the module
+ usg_mod :: Version, -- Module version
+ usg_entities :: [(OccName,Version)], -- Sorted by occurrence name
+ usg_exports :: Maybe Version, -- Export-list version, if we depend on it
+ usg_rules :: Version -- Orphan-rules version (for non-orphan
+ -- modules this will always be initialVersion)
} deriving( Eq )
-- This type doesn't let you say "I imported f but none of the rules in
-- the module". If you use anything in the module you get its rule version
%************************************************************************
%* *
-\subsection{The persistent compiler state}
+ The External Package State
%* *
%************************************************************************
-The @PersistentCompilerState@ persists across successive calls to the
-compiler.
-
-\begin{code}
-data PersistentCompilerState
- = PCS {
- pcs_nc :: !NameCache,
- pcs_EPS :: ExternalPackageState
- -- non-strict because we fill it with error in HscMain
- }
-\end{code}
-
-
\begin{code}
type PackageTypeEnv = TypeEnv
type PackageRuleBase = RuleBase
data ExternalPackageState
= EPS {
+ eps_is_boot :: !(ModuleEnv (Module, IsBootInterface)),
+ -- In OneShot mode (only), home-package modules accumulate in the
+ -- external package state, and are sucked in lazily.
+ -- For these home-pkg modules (only) we need to record which are
+ -- boot modules. We set this field after loading all the
+ -- explicitly-imported interfaces, but before doing anything else
+ --
+ -- The Module part is not necessary, but it's useful for
+ -- debug prints, and it's convenient because this field comes
+ -- direct from TcRnTypes.ImportAvails.imp_dep_mods
+
eps_PIT :: !PackageIfaceTable,
-- The ModuleIFaces for modules in external packages
-- whose interfaces we have opened
-- The declarations in these interface files are held in
- -- eps_decls, eps_insts, eps_rules (below), not in the
+ -- eps_decls, eps_inst_env, eps_rules (below), not in the
-- mi_decls fields of the iPIT.
-- What _is_ in the iPIT is:
-- * The Module
-- all the external-package modules
eps_rule_base :: !PackageRuleBase, -- Ditto RuleEnv
-
- -- Holding pens for stuff that has been read in from file,
- -- but not yet slurped into the renamer
- eps_decls :: !DeclsMap,
- -- A single, global map of Names to unslurped decls
- eps_insts :: !IfaceInsts,
- -- The as-yet un-slurped instance decls; this bag is depleted when we
- -- slurp an instance decl so that we don't slurp the same one twice.
- -- Each is 'gated' by the names that must be available before
- -- this instance decl is needed.
- eps_rules :: !IfaceRules,
- -- Similar to instance decls, only for rules
-
- eps_inst_gates :: !NameSet -- Gates for instance decls
- -- The instance gates must accumulate across
- -- all invocations of the renamer;
- -- see "the gating story" in RnIfaces.lhs
- -- These names should all be from other packages;
- -- for the home package we have all the instance
- -- declarations anyhow
+ eps_stats :: !EpsStats
}
-emptyExternalPackageState = EPS {
- eps_decls = (emptyNameEnv, 0),
- eps_insts = (emptyBag, 0),
- eps_inst_gates = emptyNameSet,
- eps_rules = (emptyBag, 0),
- eps_PIT = emptyPackageIfaceTable,
- eps_PTE = emptyTypeEnv,
- eps_inst_env = emptyInstEnv,
- eps_rule_base = emptyRuleBase
- }
+-- "In" means read from iface files
+-- "Out" means actually sucked in and type-checked
+data EpsStats = EpsStats { n_ifaces_in
+ , n_decls_in, n_decls_out
+ , n_rules_in, n_rules_out
+ , n_insts_in, n_insts_out :: !Int }
+
+addEpsInStats :: EpsStats -> Int -> Int -> Int -> EpsStats
+-- Add stats for one newly-read interface
+addEpsInStats stats n_decls n_insts n_rules
+ = stats { n_ifaces_in = n_ifaces_in stats + 1
+ , n_decls_in = n_decls_in stats + n_decls
+ , n_insts_in = n_insts_in stats + n_insts
+ , n_rules_in = n_rules_in stats + n_rules }
\end{code}
The NameCache makes sure that there is just one Unique assigned for
interface file); so we give it 'noSrcLoc' then. Later, when we find
its binding site, we fix it up.
-Exactly the same is true of the Module stored in the Name. When we first
-encounter the occurrence, we may not know the details of the module, so
-we just store junk. Then when we find the binding site, we fix it up.
-
\begin{code}
data NameCache
= NameCache { nsUniqs :: UniqSupply,
-- Ensures that one implicit parameter name gets one unique
}
-type OrigNameCache = ModuleEnv (Module, OccNameCache)
- -- Maps a module *name* to a Module,
- -- plus the OccNameEnv fot that module
-type OccNameCache = FiniteMap OccName Name
- -- Maps the OccName to a Name
- -- A FiniteMap because OccNames have a Namespace/Faststring pair
-
-type OrigIParamCache = FiniteMap (IPName RdrName) (IPName Name)
+type OrigNameCache = ModuleEnv (OccEnv Name)
+type OrigIParamCache = FiniteMap (IPName OccName) (IPName Name)
\end{code}
-A DeclsMap contains a binding for each Name in the declaration
-including the constructors of a type decl etc. The Bool is True just
-for the 'main' Name.
+
+
+%************************************************************************
+%* *
+ The module graph and ModSummary type
+ A ModSummary is a node in the compilation manager's
+ dependency graph, and it's also passed to hscMain
+%* *
+%************************************************************************
+
+A ModuleGraph contains all the nodes from the home package (only).
+There will be a node for each source module, plus a node for each hi-boot
+module.
\begin{code}
-type DeclsMap = (NameEnv (AvailInfo, Bool, (Module, TyClDecl RdrName)), Int)
- -- The Int says how many have been sucked in
-
-type IfaceInsts = GatedDecls (InstDecl RdrName)
-type IfaceRules = GatedDecls (RuleDecl RdrName)
-
-type GatedDecls d = (Bag (GatedDecl d), Int) -- The Int says how many have been sucked in
-type GatedDecl d = (GateFn, (Module, d))
-type GateFn = (Name -> Bool) -> Bool -- Returns True <=> gate is open
- -- The (Name -> Bool) fn returns True for visible Names
- -- For example, suppose this is in an interface file
- -- instance C T where ...
- -- We want to slurp this decl if both C and T are "visible" in
- -- the importing module. See "The gating story" in RnIfaces for details.
+type ModuleGraph = [ModSummary] -- The module graph,
+ -- NOT NECESSARILY IN TOPOLOGICAL ORDER
+
+emptyMG :: ModuleGraph
+emptyMG = []
+
+-- The nodes of the module graph are
+-- EITHER a regular Haskell source module
+-- OR a hi-boot source module
+
+data ModSummary
+ = ModSummary {
+ ms_mod :: Module, -- Name of the module
+ ms_hsc_src :: HscSource, -- Source is Haskell, hs-boot, external core
+ ms_location :: ModLocation, -- Location
+ ms_hs_date :: ClockTime, -- Timestamp of source file
+ ms_obj_date :: Maybe ClockTime, -- Timestamp of object, maybe
+ ms_srcimps :: [Module], -- Source imports
+ ms_imps :: [Module], -- Non-source imports
+ ms_hspp_file :: Maybe FilePath, -- Filename of preprocessed source,
+ -- once we have preprocessed it.
+ ms_hspp_buf :: Maybe StringBuffer -- The actual preprocessed source, maybe.
+ }
+
+-- The ModLocation contains both the original source filename and the
+-- filename of the cleaned-up source file after all preprocessing has been
+-- done. The point is that the summariser will have to cpp/unlit/whatever
+-- all files anyway, and there's no point in doing this twice -- just
+-- park the result in a temp file, put the name of it in the location,
+-- and let @compile@ read from that file on the way back up.
+
+-- The ModLocation is stable over successive up-sweeps in GHCi, wheres
+-- the ms_hs_date and imports can, of course, change
+
+msHsFilePath, msHiFilePath, msObjFilePath :: ModSummary -> FilePath
+msHsFilePath ms = expectJust "msHsFilePath" (ml_hs_file (ms_location ms))
+msHiFilePath ms = ml_hi_file (ms_location ms)
+msObjFilePath ms = ml_obj_file (ms_location ms)
+
+isBootSummary :: ModSummary -> Bool
+isBootSummary ms = isHsBoot (ms_hsc_src ms)
+
+instance Outputable ModSummary where
+ ppr ms
+ = sep [text "ModSummary {",
+ nest 3 (sep [text "ms_hs_date = " <> text (show (ms_hs_date ms)),
+ text "ms_mod =" <+> ppr (ms_mod ms)
+ <> text (hscSourceString (ms_hsc_src ms)) <> comma,
+ text "ms_imps =" <+> ppr (ms_imps ms),
+ text "ms_srcimps =" <+> ppr (ms_srcimps ms)]),
+ char '}'
+ ]
+
+showModMsg :: Bool -> ModSummary -> String
+showModMsg use_object mod_summary
+ = showSDoc (hsep [text (mod_str ++ replicate (max 0 (16 - length mod_str)) ' '),
+ char '(', text (msHsFilePath mod_summary) <> comma,
+ if use_object then text (msObjFilePath mod_summary)
+ else text "interpreted",
+ char ')'])
+ where
+ mod = ms_mod mod_summary
+ mod_str = moduleUserString mod ++ hscSourceString (ms_hsc_src mod_summary)
\end{code}
linkableTime :: ClockTime, -- Time at which this linkable was built
-- (i.e. when the bytecodes were produced,
-- or the mod date on the files)
- linkableModName :: ModuleName, -- Should be Module, but see below
+ linkableModule :: Module, -- Should be Module, but see below
linkableUnlinked :: [Unlinked]
}
\end{code}
-%************************************************************************
-%* *
-\subsection{Provenance and export info}
-%* *
-%************************************************************************
-
-A LocalRdrEnv is used for local bindings (let, where, lambda, case)
-Also used in
-
-\begin{code}
-type LocalRdrEnv = RdrNameEnv Name
-
-extendLocalRdrEnv :: LocalRdrEnv -> [Name] -> LocalRdrEnv
-extendLocalRdrEnv env names
- = addListToRdrEnv env [(mkRdrUnqual (nameOccName n), n) | n <- names]
-\end{code}
-
-The GlobalRdrEnv gives maps RdrNames to Names. There is a separate
-one for each module, corresponding to that module's top-level scope.
-
-\begin{code}
-type GlobalRdrEnv = RdrNameEnv [GlobalRdrElt]
- -- The list is because there may be name clashes
- -- These only get reported on lookup, not on construction
-
-emptyGlobalRdrEnv = emptyRdrEnv
-
-data GlobalRdrElt
- = GRE { gre_name :: Name,
- gre_parent :: Maybe Name, -- Name of the "parent" structure, for
- -- * the tycon of a data con
- -- * the class of a class op
- -- For others it's Nothing
- -- Invariant: gre_name g /= gre_parent g
- -- when the latter is a Just
-
- gre_prov :: Provenance, -- Why it's in scope
- gre_deprec :: Maybe DeprecTxt -- Whether this name is deprecated
- }
-
-instance Outputable GlobalRdrElt where
- ppr gre = ppr (gre_name gre) <+>
- parens (pp_parent (gre_parent gre) <+> pprNameProvenance gre)
- where
- pp_parent (Just p) = text "parent:" <+> ppr p <> comma
- pp_parent Nothing = empty
-
-pprGlobalRdrEnv env
- = vcat (map pp (rdrEnvToList env))
- where
- pp (rn, gres) = ppr rn <> colon <+>
- vcat [ ppr (gre_name gre) <+> pprNameProvenance gre
- | gre <- gres]
-
-isLocalGRE :: GlobalRdrElt -> Bool
-isLocalGRE (GRE {gre_prov = LocalDef}) = True
-isLocalGRE other = False
-\end{code}
-
-@unQualInScope@ returns a function that takes a @Name@ and tells whether
-its unqualified name is in scope. This is put as a boolean flag in
-the @Name@'s provenance to guide whether or not to print the name qualified
-in error messages.
-
-\begin{code}
-unQualInScope :: GlobalRdrEnv -> Name -> Bool
--- True if 'f' is in scope, and has only one binding,
--- and the thing it is bound to is the name we are looking for
--- (i.e. false if A.f and B.f are both in scope as unqualified 'f')
---
--- Also checks for built-in syntax, which is always 'in scope'
---
--- This fn is only efficient if the shared
--- partial application is used a lot.
-unQualInScope env
- = \n -> n `elemNameSet` unqual_names || isBuiltInSyntaxName n
- where
- unqual_names :: NameSet
- unqual_names = foldRdrEnv add emptyNameSet env
- add rdr_name [gre] unquals | isUnqual rdr_name = addOneToNameSet unquals (gre_name gre)
- add _ _ unquals = unquals
-\end{code}
-The "provenance" of something says how it came to be in scope.
-
-\begin{code}
-data Provenance
- = LocalDef -- Defined locally
-
- | NonLocalDef -- Defined non-locally
- ImportReason
-
--- Just used for grouping error messages (in RnEnv.warnUnusedBinds)
-instance Eq Provenance where
- p1 == p2 = case p1 `compare` p2 of EQ -> True; _ -> False
-
-instance Eq ImportReason where
- p1 == p2 = case p1 `compare` p2 of EQ -> True; _ -> False
-
-instance Ord Provenance where
- compare LocalDef LocalDef = EQ
- compare LocalDef (NonLocalDef _) = LT
- compare (NonLocalDef _) LocalDef = GT
-
- compare (NonLocalDef reason1) (NonLocalDef reason2)
- = compare reason1 reason2
-
-instance Ord ImportReason where
- compare ImplicitImport ImplicitImport = EQ
- compare ImplicitImport (UserImport _ _ _) = LT
- compare (UserImport _ _ _) ImplicitImport = GT
- compare (UserImport m1 loc1 _) (UserImport m2 loc2 _)
- = (m1 `compare` m2) `thenCmp` (loc1 `compare` loc2)
-
-
-data ImportReason
- = UserImport Module SrcLoc Bool -- Imported from module M on line L
- -- Note the M may well not be the defining module
- -- for this thing!
- -- The Bool is true iff the thing was named *explicitly* in the import spec,
- -- rather than being imported as part of a group; e.g.
- -- import B
- -- import C( T(..) )
- -- Here, everything imported by B, and the constructors of T
- -- are not named explicitly; only T is named explicitly.
- -- This info is used when warning of unused names.
-
- | ImplicitImport -- Imported implicitly for some other reason
-\end{code}
-
-\begin{code}
-hasBetterProv :: Provenance -> Provenance -> Bool
--- Choose
--- a local thing over an imported thing
--- a user-imported thing over a non-user-imported thing
--- an explicitly-imported thing over an implicitly imported thing
-hasBetterProv LocalDef _ = True
-hasBetterProv (NonLocalDef (UserImport _ _ _ )) (NonLocalDef ImplicitImport) = True
-hasBetterProv _ _ = False
-
-pprNameProvenance :: GlobalRdrElt -> SDoc
-pprNameProvenance (GRE {gre_name = name, gre_prov = prov})
- = case prov of
- LocalDef -> ptext SLIT("defined at") <+> ppr (nameSrcLoc name)
- NonLocalDef why -> sep [ppr_reason why,
- nest 2 (ppr_defn (nameSrcLoc name))]
-
-ppr_reason ImplicitImport = ptext SLIT("implicitly imported")
-ppr_reason (UserImport mod loc _) = ptext SLIT("imported from") <+> ppr mod <+> ptext SLIT("at") <+> ppr loc
-
-ppr_defn loc | isGoodSrcLoc loc = parens (ptext SLIT("defined at") <+> ppr loc)
- | otherwise = empty
-\end{code}