/compiler/main/HscTypes.hs
Haskell | 2903 lines | 1394 code | 371 blank | 1138 comment | 22 complexity | 44b3ff6530491897c9c42f3695c3acc6 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, GPL-3.0
Large files files are truncated, but you can click here to view the full file
- {-
- (c) The University of Glasgow, 2006
- \section[HscTypes]{Types for the per-module compiler}
- -}
- {-# LANGUAGE CPP, ScopedTypeVariables #-}
- -- | Types for the per-module compiler
- module HscTypes (
- -- * compilation state
- HscEnv(..), hscEPS,
- FinderCache, FindResult(..),
- Target(..), TargetId(..), pprTarget, pprTargetId,
- ModuleGraph, emptyMG,
- HscStatus(..),
- #ifdef GHCI
- IServ(..),
- #endif
- -- * Hsc monad
- Hsc(..), runHsc, runInteractiveHsc,
- -- * Information about modules
- ModDetails(..), emptyModDetails,
- ModGuts(..), CgGuts(..), ForeignStubs(..), appendStubC,
- ImportedMods, ImportedModsVal(..),
- ModSummary(..), ms_imps, ms_mod_name, showModMsg, isBootSummary,
- msHsFilePath, msHiFilePath, msObjFilePath,
- SourceModified(..),
- -- * Information about the module being compiled
- -- (re-exported from DriverPhases)
- HscSource(..), isHsBootOrSig, hscSourceString,
- -- * State relating to modules in this package
- HomePackageTable, HomeModInfo(..), emptyHomePackageTable,
- lookupHpt, eltsHpt, filterHpt, allHpt, mapHpt, delFromHpt,
- addToHpt, addListToHpt, lookupHptDirectly, listToHpt,
- hptInstances, hptRules, hptVectInfo, pprHPT,
- hptObjs,
- -- * State relating to known packages
- ExternalPackageState(..), EpsStats(..), addEpsInStats,
- PackageTypeEnv, PackageIfaceTable, emptyPackageIfaceTable,
- lookupIfaceByModule, emptyModIface, lookupHptByModule,
- PackageInstEnv, PackageFamInstEnv, PackageRuleBase,
- mkSOName, mkHsSOName, soExt,
- -- * Metaprogramming
- MetaRequest(..),
- MetaResult, -- data constructors not exported to ensure correct response type
- metaRequestE, metaRequestP, metaRequestT, metaRequestD, metaRequestAW,
- MetaHook,
- -- * Annotations
- prepareAnnotations,
- -- * Interactive context
- InteractiveContext(..), emptyInteractiveContext,
- icPrintUnqual, icInScopeTTs, icExtendGblRdrEnv,
- extendInteractiveContext, extendInteractiveContextWithIds,
- substInteractiveContext,
- setInteractivePrintName, icInteractiveModule,
- InteractiveImport(..), setInteractivePackage,
- mkPrintUnqualified, pprModulePrefix,
- mkQualPackage, mkQualModule, pkgQual,
- -- * Interfaces
- ModIface(..), mkIfaceWarnCache, mkIfaceHashCache, mkIfaceFixCache,
- emptyIfaceWarnCache, mi_boot, mi_fix,
- -- * Fixity
- FixityEnv, FixItem(..), lookupFixity, emptyFixityEnv,
- -- * TyThings and type environments
- TyThing(..), tyThingAvailInfo,
- tyThingTyCon, tyThingDataCon,
- tyThingId, tyThingCoAxiom, tyThingParent_maybe, tyThingsTyCoVars,
- implicitTyThings, implicitTyConThings, implicitClassThings,
- isImplicitTyThing,
- TypeEnv, lookupType, lookupTypeHscEnv, mkTypeEnv, emptyTypeEnv,
- typeEnvFromEntities, mkTypeEnvWithImplicits,
- extendTypeEnv, extendTypeEnvList,
- extendTypeEnvWithIds, plusTypeEnv,
- lookupTypeEnv,
- typeEnvElts, typeEnvTyCons, typeEnvIds, typeEnvPatSyns,
- typeEnvDataCons, typeEnvCoAxioms, typeEnvClasses,
- -- * MonadThings
- MonadThings(..),
- -- * Information on imports and exports
- WhetherHasOrphans, IsBootInterface, Usage(..),
- Dependencies(..), noDependencies,
- NameCache(..), OrigNameCache, updNameCacheIO,
- IfaceExport,
- -- * Warnings
- Warnings(..), WarningTxt(..), plusWarns,
- -- * Linker stuff
- Linkable(..), isObjectLinkable, linkableObjs,
- Unlinked(..), CompiledByteCode,
- isObject, nameOfObject, isInterpretable, byteCodeOfObject,
- -- * Program coverage
- HpcInfo(..), emptyHpcInfo, isHpcUsed, AnyHpcUsage,
- -- * Breakpoints
- ModBreaks (..), emptyModBreaks,
- -- * Vectorisation information
- VectInfo(..), IfaceVectInfo(..), noVectInfo, plusVectInfo,
- noIfaceVectInfo, isNoIfaceVectInfo,
- -- * Safe Haskell information
- IfaceTrustInfo, getSafeMode, setSafeMode, noIfaceTrustInfo,
- trustInfoToNum, numToTrustInfo, IsSafeImport,
- -- * result of the parser
- HsParsedModule(..),
- -- * Compilation errors and warnings
- SourceError, GhcApiError, mkSrcErr, srcErrorMessages, mkApiErr,
- throwOneError, handleSourceError,
- handleFlagWarnings, printOrThrowWarnings,
- ) where
- #include "HsVersions.h"
- #ifdef GHCI
- import ByteCodeTypes
- import InteractiveEvalTypes ( Resume )
- import GHCi.Message ( Pipe )
- import GHCi.RemoteTypes
- #endif
- import UniqFM
- import HsSyn
- import RdrName
- import Avail
- import Module
- import InstEnv ( InstEnv, ClsInst, identicalClsInstHead )
- import FamInstEnv
- import CoreSyn ( CoreProgram, RuleBase )
- import Name
- import NameEnv
- import NameSet
- import VarEnv
- import VarSet
- import Var
- import Id
- import IdInfo ( IdDetails(..), RecSelParent(..))
- import Type
- import ApiAnnotation ( ApiAnns )
- import Annotations ( Annotation, AnnEnv, mkAnnEnv, plusAnnEnv )
- import Class
- import TyCon
- import CoAxiom
- import ConLike
- import DataCon
- import PatSyn
- import PrelNames ( gHC_PRIM, ioTyConName, printName, mkInteractiveModule
- , eqTyConName )
- import TysWiredIn
- import Packages hiding ( Version(..) )
- import DynFlags
- import DriverPhases ( Phase, HscSource(..), isHsBootOrSig, hscSourceString )
- import BasicTypes
- import IfaceSyn
- import CoreSyn ( CoreRule, CoreVect )
- import Maybes
- import Outputable
- import SrcLoc
- import Unique
- import UniqDFM
- import UniqSupply
- import FastString
- import StringBuffer ( StringBuffer )
- import Fingerprint
- import MonadUtils
- import Bag
- import Binary
- import ErrUtils
- import Platform
- import Util
- import GHC.Serialized ( Serialized )
- import Foreign
- import Control.Monad ( guard, liftM, when, ap )
- import Data.IORef
- import Data.Time
- import Exception
- import System.FilePath
- #ifdef GHCI
- import Control.Concurrent
- import System.Process ( ProcessHandle )
- #endif
- -- -----------------------------------------------------------------------------
- -- Compilation state
- -- -----------------------------------------------------------------------------
- -- | Status of a compilation to hard-code
- data HscStatus
- = HscNotGeneratingCode
- | HscUpToDate
- | HscUpdateBoot
- | HscUpdateSig
- | HscRecomp CgGuts ModSummary
- -- -----------------------------------------------------------------------------
- -- The Hsc monad: Passing an environment and warning state
- newtype Hsc a = Hsc (HscEnv -> WarningMessages -> IO (a, WarningMessages))
- instance Functor Hsc where
- fmap = liftM
- instance Applicative Hsc where
- pure a = Hsc $ \_ w -> return (a, w)
- (<*>) = ap
- instance Monad Hsc where
- Hsc m >>= k = Hsc $ \e w -> do (a, w1) <- m e w
- case k a of
- Hsc k' -> k' e w1
- instance MonadIO Hsc where
- liftIO io = Hsc $ \_ w -> do a <- io; return (a, w)
- instance HasDynFlags Hsc where
- getDynFlags = Hsc $ \e w -> return (hsc_dflags e, w)
- runHsc :: HscEnv -> Hsc a -> IO a
- runHsc hsc_env (Hsc hsc) = do
- (a, w) <- hsc hsc_env emptyBag
- printOrThrowWarnings (hsc_dflags hsc_env) w
- return a
- runInteractiveHsc :: HscEnv -> Hsc a -> IO a
- -- A variant of runHsc that switches in the DynFlags from the
- -- InteractiveContext before running the Hsc computation.
- runInteractiveHsc hsc_env
- = runHsc (hsc_env { hsc_dflags = interactive_dflags })
- where
- interactive_dflags = ic_dflags (hsc_IC hsc_env)
- -- -----------------------------------------------------------------------------
- -- Source Errors
- -- When the compiler (HscMain) discovers errors, it throws an
- -- exception in the IO monad.
- mkSrcErr :: ErrorMessages -> SourceError
- mkSrcErr = SourceError
- srcErrorMessages :: SourceError -> ErrorMessages
- srcErrorMessages (SourceError msgs) = msgs
- mkApiErr :: DynFlags -> SDoc -> GhcApiError
- mkApiErr dflags msg = GhcApiError (showSDoc dflags msg)
- throwOneError :: MonadIO m => ErrMsg -> m ab
- throwOneError err = liftIO $ throwIO $ mkSrcErr $ unitBag err
- -- | A source error is an error that is caused by one or more errors in the
- -- source code. A 'SourceError' is thrown by many functions in the
- -- compilation pipeline. Inside GHC these errors are merely printed via
- -- 'log_action', but API clients may treat them differently, for example,
- -- insert them into a list box. If you want the default behaviour, use the
- -- idiom:
- --
- -- > handleSourceError printExceptionAndWarnings $ do
- -- > ... api calls that may fail ...
- --
- -- The 'SourceError's error messages can be accessed via 'srcErrorMessages'.
- -- This list may be empty if the compiler failed due to @-Werror@
- -- ('Opt_WarnIsError').
- --
- -- See 'printExceptionAndWarnings' for more information on what to take care
- -- of when writing a custom error handler.
- newtype SourceError = SourceError ErrorMessages
- instance Show SourceError where
- show (SourceError msgs) = unlines . map show . bagToList $ msgs
- instance Exception SourceError
- -- | Perform the given action and call the exception handler if the action
- -- throws a 'SourceError'. See 'SourceError' for more information.
- handleSourceError :: (ExceptionMonad m) =>
- (SourceError -> m a) -- ^ exception handler
- -> m a -- ^ action to perform
- -> m a
- handleSourceError handler act =
- gcatch act (\(e :: SourceError) -> handler e)
- -- | An error thrown if the GHC API is used in an incorrect fashion.
- newtype GhcApiError = GhcApiError String
- instance Show GhcApiError where
- show (GhcApiError msg) = msg
- instance Exception GhcApiError
- -- | Given a bag of warnings, turn them into an exception if
- -- -Werror is enabled, or print them out otherwise.
- printOrThrowWarnings :: DynFlags -> Bag WarnMsg -> IO ()
- printOrThrowWarnings dflags warns
- | gopt Opt_WarnIsError dflags
- = when (not (isEmptyBag warns)) $ do
- throwIO $ mkSrcErr $ warns `snocBag` warnIsErrorMsg dflags
- | otherwise
- = printBagOfErrors dflags warns
- handleFlagWarnings :: DynFlags -> [Located String] -> IO ()
- handleFlagWarnings dflags warns
- = when (wopt Opt_WarnDeprecatedFlags dflags) $ do
- -- It would be nicer if warns :: [Located MsgDoc], but that
- -- has circular import problems.
- let bag = listToBag [ mkPlainWarnMsg dflags loc (text warn)
- | L loc warn <- warns ]
- printOrThrowWarnings dflags bag
- {-
- ************************************************************************
- * *
- \subsection{HscEnv}
- * *
- ************************************************************************
- -}
- -- | 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.
- --
- -- 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.
- 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-package 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-loaded 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),
- -- ^ Information about the currently loaded external packages.
- -- This is mutable because packages will be demand-loaded during
- -- a compilation run as required.
- hsc_NC :: {-# UNPACK #-} !(IORef NameCache),
- -- ^ As with 'hsc_EPS', this is 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 cached result of performing finding in the file system
- hsc_type_env_var :: Maybe (Module, IORef TypeEnv)
- -- ^ Used for one-shot compilation only, to initialise
- -- the 'IfGblEnv'. See 'TcRnTypes.tcg_type_env_var' for
- -- 'TcRnTypes.TcGblEnv'
- #ifdef GHCI
- , hsc_iserv :: MVar (Maybe IServ)
- -- ^ interactive server process. Created the first
- -- time it is needed.
- #endif
- }
- #ifdef GHCI
- data IServ = IServ
- { iservPipe :: Pipe
- , iservProcess :: ProcessHandle
- , iservLookupSymbolCache :: IORef (UniqFM (Ptr ()))
- , iservPendingFrees :: [HValueRef]
- }
- #endif
- -- | Retrieve the ExternalPackageState cache.
- 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 :: TargetId, -- ^ module or filename
- targetAllowObjCode :: Bool, -- ^ object code allowed?
- targetContents :: Maybe (StringBuffer,UTCTime)
- -- ^ in-memory text buffer?
- }
- data TargetId
- = TargetModule ModuleName
- -- ^ A module name: search for the file
- | TargetFile FilePath (Maybe Phase)
- -- ^ A filename: preprocess & parse it to find the module name.
- -- If specified, the Phase indicates how to compile this file
- -- (which phase to start from). Nothing indicates the starting phase
- -- should be determined from the suffix of the filename.
- deriving Eq
- pprTarget :: Target -> SDoc
- pprTarget (Target id obj _) =
- (if obj then char '*' else empty) <> pprTargetId id
- instance Outputable Target where
- ppr = pprTarget
- pprTargetId :: TargetId -> SDoc
- pprTargetId (TargetModule m) = ppr m
- pprTargetId (TargetFile f _) = text f
- instance Outputable TargetId where
- ppr = pprTargetId
- {-
- ************************************************************************
- * *
- \subsection{Package and Module Tables}
- * *
- ************************************************************************
- -}
- -- | Helps us find information about modules in the home package
- type HomePackageTable = DModuleNameEnv HomeModInfo
- -- Domain = modules in the home package that have been fully compiled
- -- "home" unit id cached here for convenience
- -- | Helps us find information about modules in the imported packages
- type PackageIfaceTable = ModuleEnv ModIface
- -- Domain = modules in the imported packages
- -- | Constructs an empty HomePackageTable
- emptyHomePackageTable :: HomePackageTable
- emptyHomePackageTable = emptyUDFM
- -- | Constructs an empty PackageIfaceTable
- emptyPackageIfaceTable :: PackageIfaceTable
- emptyPackageIfaceTable = emptyModuleEnv
- pprHPT :: HomePackageTable -> SDoc
- -- A bit aribitrary for now
- pprHPT hpt = pprUDFM hpt $ \hms ->
- vcat [ hang (ppr (mi_module (hm_iface hm)))
- 2 (ppr (md_types (hm_details hm)))
- | hm <- hms ]
- lookupHpt :: HomePackageTable -> ModuleName -> Maybe HomeModInfo
- lookupHpt = lookupUDFM
- lookupHptDirectly :: HomePackageTable -> Unique -> Maybe HomeModInfo
- lookupHptDirectly = lookupUDFM_Directly
- eltsHpt :: HomePackageTable -> [HomeModInfo]
- eltsHpt = eltsUDFM
- filterHpt :: (HomeModInfo -> Bool) -> HomePackageTable -> HomePackageTable
- filterHpt = filterUDFM
- allHpt :: (HomeModInfo -> Bool) -> HomePackageTable -> Bool
- allHpt = allUDFM
- mapHpt :: (HomeModInfo -> HomeModInfo) -> HomePackageTable -> HomePackageTable
- mapHpt = mapUDFM
- delFromHpt :: HomePackageTable -> ModuleName -> HomePackageTable
- delFromHpt = delFromUDFM
- addToHpt :: HomePackageTable -> ModuleName -> HomeModInfo -> HomePackageTable
- addToHpt = addToUDFM
- addListToHpt
- :: HomePackageTable -> [(ModuleName, HomeModInfo)] -> HomePackageTable
- addListToHpt = addListToUDFM
- listToHpt :: [(ModuleName, HomeModInfo)] -> HomePackageTable
- listToHpt = listToUDFM
- lookupHptByModule :: HomePackageTable -> Module -> Maybe HomeModInfo
- -- The HPT is indexed by ModuleName, not Module,
- -- we must check for a hit on the right Module
- lookupHptByModule hpt mod
- = case lookupHpt hpt (moduleName mod) of
- Just hm | mi_module (hm_iface hm) == mod -> Just hm
- _otherwise -> Nothing
- -- | Information about modules in the package being compiled
- data HomeModInfo
- = HomeModInfo {
- hm_iface :: !ModIface,
- -- ^ The basic loaded interface file: every loaded module has one of
- -- these, even if it is imported from another package
- hm_details :: !ModDetails,
- -- ^ Extra information that has been created from the 'ModIface' for
- -- the module, typically during typechecking
- hm_linkable :: !(Maybe Linkable)
- -- ^ The actual artifact we would like to link to access things in
- -- this module.
- --
- -- 'hm_linkable' might be Nothing:
- --
- -- 1. If this is an .hs-boot module
- --
- -- 2. 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 'HomePackageTable' will be @Just@.
- --
- -- When re-linking a module ('HscMain.HscNoRecomp'), we construct the
- -- 'HomeModInfo' by building a new 'ModDetails' from the old
- -- 'ModIface' (only).
- }
- -- | Find the 'ModIface' for a 'Module', searching in both the loaded home
- -- and external package module information
- lookupIfaceByModule
- :: DynFlags
- -> HomePackageTable
- -> PackageIfaceTable
- -> Module
- -> Maybe ModIface
- lookupIfaceByModule _dflags hpt pit mod
- = case lookupHptByModule hpt mod of
- Just hm -> Just (hm_iface hm)
- Nothing -> lookupModuleEnv pit mod
- -- If the module does come from the home package, why do we look in the PIT as well?
- -- (a) In OneShot mode, even home-package modules accumulate in the PIT
- -- (b) Even in Batch (--make) mode, there is *one* case where a home-package
- -- module is in the PIT, namely GHC.Prim when compiling the base package.
- -- We could eliminate (b) if we wanted, by making GHC.Prim belong to a package
- -- of its own, but it doesn't seem worth the bother.
- -- | Find all the instance declarations (of classes and families) from
- -- the Home Package Table filtered by the provided predicate function.
- -- Used in @tcRnImports@, to select the instances that are in the
- -- transitive closure of imports from the currently compiled module.
- hptInstances :: HscEnv -> (ModuleName -> Bool) -> ([ClsInst], [FamInst])
- hptInstances hsc_env want_this_module
- = let (insts, famInsts) = unzip $ flip hptAllThings hsc_env $ \mod_info -> do
- guard (want_this_module (moduleName (mi_module (hm_iface mod_info))))
- let details = hm_details mod_info
- return (md_insts details, md_fam_insts details)
- in (concat insts, concat famInsts)
- -- | Get the combined VectInfo of all modules in the home package table. In
- -- contrast to instances and rules, we don't care whether the modules are
- -- "below" us in the dependency sense. The VectInfo of those modules not "below"
- -- us does not affect the compilation of the current module.
- hptVectInfo :: HscEnv -> VectInfo
- hptVectInfo = concatVectInfo . hptAllThings ((: []) . md_vect_info . hm_details)
- -- | Get rules from modules "below" this one (in the dependency sense)
- hptRules :: HscEnv -> [(ModuleName, IsBootInterface)] -> [CoreRule]
- hptRules = hptSomeThingsBelowUs (md_rules . hm_details) False
- -- | Get annotations from modules "below" this one (in the dependency sense)
- hptAnns :: HscEnv -> Maybe [(ModuleName, IsBootInterface)] -> [Annotation]
- hptAnns hsc_env (Just deps) = hptSomeThingsBelowUs (md_anns . hm_details) False hsc_env deps
- hptAnns hsc_env Nothing = hptAllThings (md_anns . hm_details) hsc_env
- hptAllThings :: (HomeModInfo -> [a]) -> HscEnv -> [a]
- hptAllThings extract hsc_env = concatMap extract (eltsHpt (hsc_HPT hsc_env))
- -- | Get things from modules "below" this one (in the dependency sense)
- -- C.f Inst.hptInstances
- hptSomeThingsBelowUs :: (HomeModInfo -> [a]) -> Bool -> HscEnv -> [(ModuleName, IsBootInterface)] -> [a]
- hptSomeThingsBelowUs extract include_hi_boot hsc_env deps
- | isOneShot (ghcMode (hsc_dflags hsc_env)) = []
- | otherwise
- = let hpt = hsc_HPT hsc_env
- in
- [ thing
- | -- Find each non-hi-boot module below me
- (mod, is_boot_mod) <- deps
- , include_hi_boot || not is_boot_mod
- -- unsavoury: when compiling the base package with --make, we
- -- sometimes try to look up RULES etc for GHC.Prim. GHC.Prim won't
- -- be in the HPT, because we never compile it; it's in the EPT
- -- instead. ToDo: clean up, and remove this slightly bogus filter:
- , mod /= moduleName gHC_PRIM
- -- Look it up in the HPT
- , let things = case lookupHpt hpt mod of
- Just info -> extract info
- Nothing -> pprTrace "WARNING in hptSomeThingsBelowUs" msg []
- msg = vcat [text "missing module" <+> ppr mod,
- text "Probable cause: out-of-date interface files"]
- -- This really shouldn't happen, but see Trac #962
- -- And get its dfuns
- , thing <- things ]
- hptObjs :: HomePackageTable -> [FilePath]
- hptObjs hpt = concat (map (maybe [] linkableObjs . hm_linkable) (eltsHpt hpt))
- {-
- ************************************************************************
- * *
- \subsection{Metaprogramming}
- * *
- ************************************************************************
- -}
- -- | The supported metaprogramming result types
- data MetaRequest
- = MetaE (LHsExpr RdrName -> MetaResult)
- | MetaP (LPat RdrName -> MetaResult)
- | MetaT (LHsType RdrName -> MetaResult)
- | MetaD ([LHsDecl RdrName] -> MetaResult)
- | MetaAW (Serialized -> MetaResult)
- -- | data constructors not exported to ensure correct result type
- data MetaResult
- = MetaResE { unMetaResE :: LHsExpr RdrName }
- | MetaResP { unMetaResP :: LPat RdrName }
- | MetaResT { unMetaResT :: LHsType RdrName }
- | MetaResD { unMetaResD :: [LHsDecl RdrName] }
- | MetaResAW { unMetaResAW :: Serialized }
- type MetaHook f = MetaRequest -> LHsExpr Id -> f MetaResult
- metaRequestE :: Functor f => MetaHook f -> LHsExpr Id -> f (LHsExpr RdrName)
- metaRequestE h = fmap unMetaResE . h (MetaE MetaResE)
- metaRequestP :: Functor f => MetaHook f -> LHsExpr Id -> f (LPat RdrName)
- metaRequestP h = fmap unMetaResP . h (MetaP MetaResP)
- metaRequestT :: Functor f => MetaHook f -> LHsExpr Id -> f (LHsType RdrName)
- metaRequestT h = fmap unMetaResT . h (MetaT MetaResT)
- metaRequestD :: Functor f => MetaHook f -> LHsExpr Id -> f [LHsDecl RdrName]
- metaRequestD h = fmap unMetaResD . h (MetaD MetaResD)
- metaRequestAW :: Functor f => MetaHook f -> LHsExpr Id -> f Serialized
- metaRequestAW h = fmap unMetaResAW . h (MetaAW MetaResAW)
- {-
- ************************************************************************
- * *
- \subsection{Dealing with Annotations}
- * *
- ************************************************************************
- -}
- -- | Deal with gathering annotations in from all possible places
- -- and combining them into a single 'AnnEnv'
- prepareAnnotations :: HscEnv -> Maybe ModGuts -> IO AnnEnv
- prepareAnnotations hsc_env mb_guts = do
- eps <- hscEPS hsc_env
- let -- Extract annotations from the module being compiled if supplied one
- mb_this_module_anns = fmap (mkAnnEnv . mg_anns) mb_guts
- -- Extract dependencies of the module if we are supplied one,
- -- otherwise load annotations from all home package table
- -- entries regardless of dependency ordering.
- home_pkg_anns = (mkAnnEnv . hptAnns hsc_env) $ fmap (dep_mods . mg_deps) mb_guts
- other_pkg_anns = eps_ann_env eps
- ann_env = foldl1' plusAnnEnv $ catMaybes [mb_this_module_anns,
- Just home_pkg_anns,
- Just other_pkg_anns]
- return ann_env
- {-
- ************************************************************************
- * *
- \subsection{The Finder cache}
- * *
- ************************************************************************
- -}
- -- | The 'FinderCache' maps modules to the result of
- -- searching for that module. It records the results of searching for
- -- modules along the search path. On @:load@, we flush the entire
- -- contents of this cache.
- --
- -- Although the @FinderCache@ range is 'FindResult' for convenience,
- -- in fact it will only ever contain 'Found' or 'NotFound' entries.
- --
- type FinderCache = ModuleEnv FindResult
- -- | The result of searching for an imported module.
- data FindResult
- = Found ModLocation Module
- -- ^ The module was found
- | NoPackage UnitId
- -- ^ The requested package was not found
- | FoundMultiple [(Module, ModuleOrigin)]
- -- ^ _Error_: both in multiple packages
- -- | Not found
- | NotFound
- { fr_paths :: [FilePath] -- Places where I looked
- , fr_pkg :: Maybe UnitId -- Just p => module is in this package's
- -- manifest, but couldn't find
- -- the .hi file
- , fr_mods_hidden :: [UnitId] -- Module is in these packages,
- -- but the *module* is hidden
- , fr_pkgs_hidden :: [UnitId] -- Module is in these packages,
- -- but the *package* is hidden
- , fr_suggestions :: [ModuleSuggestion] -- Possible mis-spelled modules
- }
- {-
- ************************************************************************
- * *
- \subsection{Symbol tables and Module details}
- * *
- ************************************************************************
- -}
- -- | A 'ModIface' plus a 'ModDetails' summarises everything we know
- -- about a compiled module. The 'ModIface' is the stuff *before* linking,
- -- and can be written out to an interface file. The 'ModDetails is after
- -- linking and can be completely recovered from just the 'ModIface'.
- --
- -- When we read an interface file, we also construct a 'ModIface' from it,
- -- except that we explicitly make the 'mi_decls' and a few other fields empty;
- -- as when reading we consolidate the declarations etc. into a number of indexed
- -- maps and environments in the 'ExternalPackageState'.
- data ModIface
- = ModIface {
- mi_module :: !Module, -- ^ Name of the module we are for
- mi_sig_of :: !(Maybe Module), -- ^ Are we a sig of another mod?
- mi_iface_hash :: !Fingerprint, -- ^ Hash of the whole interface
- mi_mod_hash :: !Fingerprint, -- ^ Hash of the ABI only
- mi_flag_hash :: !Fingerprint, -- ^ Hash of the important flags
- -- used when compiling this module
- mi_orphan :: !WhetherHasOrphans, -- ^ Whether this module has orphans
- mi_finsts :: !WhetherHasFamInst, -- ^ Whether this module has family instances
- mi_hsc_src :: !HscSource, -- ^ Boot? Signature?
- mi_deps :: Dependencies,
- -- ^ The dependencies of the module. This is
- -- consulted for directly-imported modules, but not
- -- for anything else (hence lazy)
- mi_usages :: [Usage],
- -- ^ Usages; kept sorted so that it's easy to decide
- -- whether to write a new iface file (changing usages
- -- doesn't affect the hash of this module)
- -- NOT STRICT! we read this field lazily from the interface file
- -- It is *only* consulted by the recompilation checker
- mi_exports :: ![IfaceExport],
- -- ^ Exports
- -- Kept sorted by (mod,occ), to make version comparisons easier
- -- Records the modules that are the declaration points for things
- -- exported by this module, and the 'OccName's of those things
- mi_exp_hash :: !Fingerprint,
- -- ^ Hash of export list
- mi_used_th :: !Bool,
- -- ^ Module required TH splices when it was compiled.
- -- This disables recompilation avoidance (see #481).
- mi_fixities :: [(OccName,Fixity)],
- -- ^ Fixities
- -- NOT STRICT! we read this field lazily from the interface file
- mi_warns :: Warnings,
- -- ^ Warnings
- -- NOT STRICT! we read this field lazily from the interface file
- mi_anns :: [IfaceAnnotation],
- -- ^ Annotations
- -- NOT STRICT! we read this field lazily from the interface file
- mi_decls :: [(Fingerprint,IfaceDecl)],
- -- ^ Type, class and variable declarations
- -- The hash 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 hash of the parent class/tycon changes
- mi_globals :: !(Maybe GlobalRdrEnv),
- -- ^ Binds all the things defined at the top level in
- -- the /original source/ code for this module. which
- -- is NOT the same as mi_exports, nor mi_decls (which
- -- may contains declarations for things not actually
- -- defined by the user). Used for GHCi and for inspecting
- -- the contents of modules via the GHC API only.
- --
- -- (We need the source file to figure out the
- -- top-level environment, if we didn't compile this module
- -- from source then this field contains @Nothing@).
- --
- -- Strictly speaking this field should live in the
- -- 'HomeModInfo', but that leads to more plumbing.
- -- Instance declarations and rules
- mi_insts :: [IfaceClsInst], -- ^ Sorted class instance
- mi_fam_insts :: [IfaceFamInst], -- ^ Sorted family instances
- mi_rules :: [IfaceRule], -- ^ Sorted rules
- mi_orphan_hash :: !Fingerprint, -- ^ Hash for orphan rules, class and family
- -- instances, and vectorise pragmas combined
- mi_vect_info :: !IfaceVectInfo, -- ^ Vectorisation information
- -- Cached environments for easy lookup
- -- These are computed (lazily) from other fields
- -- and are not put into the interface file
- mi_warn_fn :: OccName -> Maybe WarningTxt,
- -- ^ Cached lookup for 'mi_warns'
- mi_fix_fn :: OccName -> Maybe Fixity,
- -- ^ Cached lookup for 'mi_fixities'
- mi_hash_fn :: OccName -> Maybe (OccName, Fingerprint),
- -- ^ Cached lookup for 'mi_decls'.
- -- The @Nothing@ in 'mi_hash_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.
- -- The 'OccName' is the parent of the name, if it has one.
- mi_hpc :: !AnyHpcUsage,
- -- ^ True if this program uses Hpc at any point in the program.
- mi_trust :: !IfaceTrustInfo,
- -- ^ Safe Haskell Trust information for this module.
- mi_trust_pkg :: !Bool
- -- ^ Do we require the package this module resides in be trusted
- -- to trust this module? This is used for the situation where a
- -- module is Safe (so doesn't require the package be trusted
- -- itself) but imports some trustworthy modules from its own
- -- package (which does require its own package be trusted).
- -- See Note [RnNames . Trust Own Package]
- }
- -- | Old-style accessor for whether or not the ModIface came from an hs-boot
- -- file.
- mi_boot :: ModIface -> Bool
- mi_boot iface = mi_hsc_src iface == HsBootFile
- -- | Lookups up a (possibly cached) fixity from a 'ModIface'. If one cannot be
- -- found, 'defaultFixity' is returned instead.
- mi_fix :: ModIface -> OccName -> Fixity
- mi_fix iface name = mi_fix_fn iface name `orElse` defaultFixity
- instance Binary ModIface where
- put_ bh (ModIface {
- mi_module = mod,
- mi_sig_of = sig_of,
- mi_hsc_src = hsc_src,
- mi_iface_hash= iface_hash,
- mi_mod_hash = mod_hash,
- mi_flag_hash = flag_hash,
- mi_orphan = orphan,
- mi_finsts = hasFamInsts,
- mi_deps = deps,
- mi_usages = usages,
- mi_exports = exports,
- mi_exp_hash = exp_hash,
- mi_used_th = used_th,
- mi_fixities = fixities,
- mi_warns = warns,
- mi_anns = anns,
- mi_decls = decls,
- mi_insts = insts,
- mi_fam_insts = fam_insts,
- mi_rules = rules,
- mi_orphan_hash = orphan_hash,
- mi_vect_info = vect_info,
- mi_hpc = hpc_info,
- mi_trust = trust,
- mi_trust_pkg = trust_pkg }) = do
- put_ bh mod
- put_ bh hsc_src
- put_ bh iface_hash
- put_ bh mod_hash
- put_ bh flag_hash
- put_ bh orphan
- put_ bh hasFamInsts
- lazyPut bh deps
- lazyPut bh usages
- put_ bh exports
- put_ bh exp_hash
- put_ bh used_th
- put_ bh fixities
- lazyPut bh warns
- lazyPut bh anns
- put_ bh decls
- put_ bh insts
- put_ bh fam_insts
- lazyPut bh rules
- put_ bh orphan_hash
- put_ bh vect_info
- put_ bh hpc_info
- put_ bh trust
- put_ bh trust_pkg
- put_ bh sig_of
- get bh = do
- mod_name <- get bh
- hsc_src <- get bh
- iface_hash <- get bh
- mod_hash <- get bh
- flag_hash <- get bh
- orphan <- get bh
- hasFamInsts <- get bh
- deps <- lazyGet bh
- usages <- {-# SCC "bin_usages" #-} lazyGet bh
- exports <- {-# SCC "bin_exports" #-} get bh
- exp_hash <- get bh
- used_th <- get bh
- fixities <- {-# SCC "bin_fixities" #-} get bh
- warns <- {-# SCC "bin_warns" #-} lazyGet bh
- anns <- {-# SCC "bin_anns" #-} lazyGet bh
- decls <- {-# SCC "bin_tycldecls" #-} get bh
- insts <- {-# SCC "bin_insts" #-} get bh
- fam_insts <- {-# SCC "bin_fam_insts" #-} get bh
- rules <- {-# SCC "bin_rules" #-} lazyGet bh
- orphan_hash <- get bh
- vect_info <- get bh
- hpc_info <- get bh
- trust <- get bh
- trust_pkg <- get bh
- sig_of <- get bh
- return (ModIface {
- mi_module = mod_name,
- mi_sig_of = sig_of,
- mi_hsc_src = hsc_src,
- mi_iface_hash = iface_hash,
- mi_mod_hash = mod_hash,
- mi_flag_hash = flag_hash,
- mi_orphan = orphan,
- mi_finsts = hasFamInsts,
- mi_deps = deps,
- mi_usages = usages,
- mi_exports = exports,
- mi_exp_hash = exp_hash,
- mi_used_th = used_th,
- mi_anns = anns,
- mi_fixities = fixities,
- mi_warns = warns,
- mi_decls = decls,
- mi_globals = Nothing,
- mi_insts = insts,
- mi_fam_insts = fam_insts,
- mi_rules = rules,
- mi_orphan_hash = orphan_hash,
- mi_vect_info = vect_info,
- mi_hpc = hpc_info,
- mi_trust = trust,
- mi_trust_pkg = trust_pkg,
- -- And build the cached values
- mi_warn_fn = mkIfaceWarnCache warns,
- mi_fix_fn = mkIfaceFixCache fixities,
- mi_hash_fn = mkIfaceHashCache decls })
- -- | The original names declared of a certain module that are exported
- type IfaceExport = AvailInfo
- -- | Constructs an empty ModIface
- emptyModIface :: Module -> ModIface
- emptyModIface mod
- = ModIface { mi_module = mod,
- mi_sig_of = Nothing,
- mi_iface_hash = fingerprint0,
- mi_mod_hash = fingerprint0,
- mi_flag_hash = fingerprint0,
- mi_orphan = False,
- mi_finsts = False,
- mi_hsc_src = HsSrcFile,
- mi_deps = noDependencies,
- mi_usages = [],
- mi_exports = [],
- mi_exp_hash = fingerprint0,
- mi_used_th = False,
- mi_fixities = [],
- mi_warns = NoWarnings,
- mi_anns = [],
- mi_insts = [],
- mi_fam_insts = [],
- mi_rules = [],
- mi_decls = [],
- mi_globals = Nothing,
- mi_orphan_hash = fingerprint0,
- mi_vect_info = noIfaceVectInfo,
- mi_warn_fn = emptyIfaceWarnCache,
- mi_fix_fn = emptyIfaceFixCache,
- mi_hash_fn = emptyIfaceHashCache,
- mi_hpc = False,
- mi_trust = noIfaceTrustInfo,
- mi_trust_pkg = False }
- -- | Constructs cache for the 'mi_hash_fn' field of a 'ModIface'
- mkIfaceHashCache :: [(Fingerprint,IfaceDecl)]
- -> (OccName -> Maybe (OccName, Fingerprint))
- mkIfaceHashCache pairs
- = \occ -> lookupOccEnv env occ
- where
- env = foldr add_decl emptyOccEnv pairs
- add_decl (v,d) env0 = foldr add env0 (ifaceDeclFingerprints v d)
- where
- add (occ,hash) env0 = extendOccEnv env0 occ (occ,hash)
- emptyIfaceHashCache :: OccName -> Maybe (OccName, Fingerprint)
- emptyIfaceHashCache _occ = Nothing
- -- | The 'ModDetails' is essentially a cache for information in the 'ModIface'
- -- for home modules only. Information relating to packages will be loaded into
- -- global environments in 'ExternalPackageState'.
- data ModDetails
- = ModDetails {
- -- The next two fields are created by the typechecker
- md_exports :: [AvailInfo],
- md_types :: !TypeEnv, -- ^ Local type environment for this particular module
- -- Includes Ids, TyCons, PatSyns
- md_insts :: ![ClsInst], -- ^ 'DFunId's for the instances in this module
- md_fam_insts :: ![FamInst],
- md_rules :: ![CoreRule], -- ^ Domain may include 'Id's from other modules
- md_anns :: ![Annotation], -- ^ Annotations present in this module: currently
- -- they only annotate things also declared in this module
- md_vect_info :: !VectInfo -- ^ Module vectorisation information
- }
- -- | Constructs an empty ModDetails
- emptyModDetails :: ModDetails
- emptyModDetails
- = ModDetails { md_types = emptyTypeEnv,
- md_exports = [],
- md_insts = [],
- md_rules = [],
- md_fam_insts = [],
- md_anns = [],
- md_vect_info = noVectInfo }
- -- | Records the modules directly imported by a module for extracting e.g.
- -- usage information, and also to give better error message
- type ImportedMods = ModuleEnv [ImportedModsVal]
- data ImportedModsVal
- = ImportedModsVal {
- imv_name :: ModuleName, -- ^ The name the module is imported with
- imv_span :: SrcSpan, -- ^ the source span of the whole import
- imv_is_safe :: IsSafeImport, -- ^ whether this is a safe import
- imv_is_hiding :: Bool, -- ^ whether this is an "hiding" import
- imv_all_exports :: GlobalRdrEnv, -- ^ all the things the module could provide
- imv_qualified :: Bool -- ^ whether this is a qualified import
- }
- -- | 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
- -- 'ModDetails' are extracted and the ModGuts is discarded.
- data ModGuts
- = ModGuts {
- mg_module :: !Module, -- ^ Module being compiled
- mg_hsc_src :: HscSource, -- ^ Whether it's an hs-boot module
- mg_loc :: SrcSpan, -- ^ For error messages from inner passes
- mg_exports :: ![AvailInfo], -- ^ What it exports
- mg_deps :: !Dependencies, -- ^ What it depends on, directly or
- -- otherwise
- mg_usages :: ![Usage], -- ^ What was used? Used for interfaces.
- mg_used_th :: !Bool, -- ^ Did we run a TH splice?
- mg_rdr_env :: !GlobalRdrEnv, -- ^ Top-level lexical environment
- -- These fields all describe the things **declared in this module**
- mg_fix_env :: !FixityEnv, -- ^ Fixities declared in this module.
- -- Used for creating interface files.
- mg_tcs :: ![TyCon], -- ^ TyCons declared in this module
- -- (includes TyCons for classes)
- mg_insts :: ![ClsInst], -- ^ Class instances declared in this module
- mg_fam_insts :: ![FamInst],
- -- ^ Family instances declared in this module
- mg_patsyns :: ![PatSyn], -- ^ Pattern synonyms declared in this module
- mg_rules :: ![CoreRule], -- ^ Before the core pipeline starts, contains
- -- See Note [Overall plumbing for rules] in Rules.hs
- mg_binds :: !CoreProgram, -- ^ Bindings for this module
- mg_foreign :: !ForeignStubs, -- ^ Foreign exports declared in this module
- mg_warns :: !Warnings, -- ^ Warnings declared in the module
- mg_anns :: [Annotation], -- ^ Annotations declared in this module
- mg_hpc_info :: !HpcInfo, -- ^ Coverage tick boxes in the module
- mg_modBreaks :: !(Maybe ModBreaks), -- ^ Breakpoints for the module
- mg_vect_decls:: ![CoreVect], -- ^ Vectorisation declarations in this module
- -- (produced by desugarer & consumed by vectoriser)
- mg_vect_info :: !VectInfo, -- ^ Pool of vectorised declarations in the module
- -- The next two fields are unusual, because they give instance
- -- environments for *all* modules in the home package, including
- -- this module, rather than for *just* this module.
- -- Reason: when looking up an instance we don't want to have to
- -- look at each module in the home package in turn
- mg_inst_env :: InstEnv, -- ^ Class instance environment for
- -- /home-package/ modules (including this
- -- one); c.f. 'tcg_inst_env'
- mg_fam_inst_env :: FamInstEnv, -- ^ Type-family instance environment for
- -- /home-package/ modules (including this
- -- one); c.f. 'tcg_fam_inst_env'
- mg_safe_haskell :: SafeHaskellMode, -- ^ Safe Haskell mode
- mg_trust_pkg :: Bool -- ^ Do we need to trust our
- -- own package for Safe Haskell?
- -- See Note [RnNames . Trust Own Package]
- }
- -- The ModGuts takes on several slightly different forms:
- --
- -- After simplification, the following fields change slightly:
- -- mg_rules Orphan rules only (local ones now attached to binds)
- -- mg_binds With rules attached
- ---------------------------------------------------------
- -- 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)
- -- | A restricted form of 'ModGuts' for code generation purposes
- data CgGuts
- = CgGuts {
- cg_module :: !Module,
- -- ^ Module being compiled
- 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 :: CoreProgram,
- -- ^ The tidied main bindings, including
- -- previously-implicit bindings for record and class
- -- selectors, and data constructor wrappers. But *not*
- -- data constructor workers; reason: we we regard them
- -- as part of the code-gen of tycons
- cg_foreign :: !ForeignStubs, -- ^ Foreign export stubs
- cg_dep_pkgs :: ![UnitId], -- ^ Dependent packages, used to
- -- generate #includes for C code gen
- cg_hpc_info :: !HpcInfo, -- ^ Program coverage tick box information
- cg_modBreaks :: !(Maybe ModBreaks) -- ^ Module breakpoints
- }
- -----------------------------------
- -- | Foreign export stubs
- data ForeignStubs
- = NoStubs
- -- ^ We don't have any stubs
- | ForeignStubs SDoc SDoc
- -- ^ There are some stubs. Parameters:
- --
- -- 1) Header file prototypes for
- -- "foreign exported" functions
- --
- -- 2) C stubs to use when calling
- -- "foreign exported" functions
- appendStubC :: ForeignStubs -> SDoc -> ForeignStubs
- appendStubC NoStubs c_code = ForeignStubs empty c_code
- appendStubC (ForeignStubs h c) c_code = ForeignStubs h (c $$ c_code)
- {-
- ************************************************************************
- * *
- The interactive context
- * *
- ************************************************************************
- Note [The interactive package]
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Type, class, and value declarations at the command prompt are treated
- as if they were defined in modules
- interactive:Ghci1
- interactive:Ghci2
- ...etc...
- with each bunch of declarations using a new module, all sharing a
- common package 'interactive' (see Module.interactiveUnitId, and
- PrelNames.mkInteractiv…
Large files files are truncated, but you can click here to view the full file