import TcRnTypes -- Re-export all
import IOEnv -- Re-export all
+import HsSyn ( emptyLHsBinds )
import HscTypes ( HscEnv(..), ModGuts(..), ModIface(..),
- TyThing, Dependencies(..), TypeEnv, emptyTypeEnv,
+ TyThing, TypeEnv, emptyTypeEnv, HscSource(..),
+ isHsBoot, ModSummary(..),
ExternalPackageState(..), HomePackageTable,
- ModDetails(..), HomeModInfo(..),
- Deprecs(..), FixityEnv, FixItem,
- GhciMode, lookupType, unQualInScope )
-import Module ( Module, ModuleName, unitModuleEnv, foldModuleEnv, emptyModuleEnv )
+ Deprecs(..), FixityEnv, FixItem,
+ lookupType, unQualInScope )
+import Module ( Module, unitModuleEnv )
import RdrName ( GlobalRdrEnv, emptyGlobalRdrEnv,
LocalRdrEnv, emptyLocalRdrEnv )
-import Name ( Name, isInternalName )
+import Name ( Name, isInternalName, mkInternalName, getOccName, getSrcLoc )
import Type ( Type )
import NameEnv ( extendNameEnvList )
-import InstEnv ( InstEnv, emptyInstEnv, extendInstEnv )
+import InstEnv ( emptyInstEnv )
import VarSet ( emptyVarSet )
-import VarEnv ( TidyEnv, emptyTidyEnv )
+import VarEnv ( TidyEnv, emptyTidyEnv, emptyVarEnv )
import ErrUtils ( Message, Messages, emptyMessages, errorsFound,
- mkErrMsg, mkWarnMsg, printErrorsAndWarnings,
+ mkWarnMsg, printErrorsAndWarnings, pprBagOfErrors,
mkLocMessage, mkLongErrMsg )
+import Packages ( mkHomeModules )
import SrcLoc ( mkGeneralSrcSpan, isGoodSrcSpan, SrcSpan, Located(..) )
import NameEnv ( emptyNameEnv )
-import NameSet ( emptyDUs, emptyNameSet )
+import NameSet ( NameSet, emptyDUs, emptyNameSet, unionNameSets, addOneToNameSet )
import OccName ( emptyOccEnv )
-import Module ( moduleName )
import Bag ( emptyBag )
import Outputable
import UniqSupply ( UniqSupply, mkSplitUniqSupply, uniqFromSupply, splitUniqSupply )
import Unique ( Unique )
-import CmdLineOpts ( DynFlags, DynFlag(..), dopt, opt_PprStyle_Debug, dopt_set )
-import Bag ( snocBag, unionBags )
+import DynFlags ( DynFlags(..), DynFlag(..), dopt, dopt_set, GhcMode )
+import StaticFlags ( opt_PprStyle_Debug )
+import Bag ( snocBag, unionBags, unitBag )
import Panic ( showException )
-import Maybe ( isJust )
import IO ( stderr )
import DATA_IOREF ( newIORef, readIORef )
import EXCEPTION ( Exception )
\begin{code}
initTc :: HscEnv
+ -> HscSource
-> Module
-> TcM r
-> IO (Messages, Maybe r)
-- Nothing => error thrown by the thing inside
-- (error messages should have been printed already)
-initTc hsc_env mod do_this
+initTc hsc_env hsc_src mod do_this
= do { errs_var <- newIORef (emptyBag, emptyBag) ;
tvs_var <- newIORef emptyVarSet ;
type_env_var <- newIORef emptyNameEnv ;
dfuns_var <- newIORef emptyNameSet ;
+ keep_var <- newIORef emptyNameSet ;
th_var <- newIORef False ;
+ dfun_n_var <- newIORef 1 ;
let {
gbl_env = TcGblEnv {
tcg_mod = mod,
+ tcg_src = hsc_src,
tcg_rdr_env = emptyGlobalRdrEnv,
tcg_fix_env = emptyNameEnv,
tcg_default = Nothing,
tcg_type_env = emptyNameEnv,
tcg_type_env_var = type_env_var,
- tcg_inst_env = mkImpInstEnv hsc_env,
+ tcg_inst_env = emptyInstEnv,
tcg_inst_uses = dfuns_var,
tcg_th_used = th_var,
tcg_exports = emptyNameSet,
tcg_imports = init_imports,
+ tcg_home_mods = home_mods,
tcg_dus = emptyDUs,
- tcg_binds = emptyBag,
+ tcg_rn_decls = Nothing,
+ tcg_binds = emptyLHsBinds,
tcg_deprecs = NoDeprecs,
tcg_insts = [],
tcg_rules = [],
tcg_fords = [],
- tcg_keep = emptyNameSet
+ tcg_dfun_n = dfun_n_var,
+ tcg_keep = keep_var
} ;
lcl_env = TcLclEnv {
tcl_errs = errs_var,
tcl_ctxt = [],
tcl_rdr = emptyLocalRdrEnv,
tcl_th_ctxt = topStage,
- tcl_arrow_ctxt = topArrowCtxt,
+ tcl_arrow_ctxt = NoArrowCtxt,
tcl_env = emptyNameEnv,
tcl_tyvars = tvs_var,
- tcl_lie = panic "initTc:LIE" -- LIE only valid inside a getLIE
+ tcl_lie = panic "initTc:LIE", -- LIE only valid inside a getLIE
+ tcl_gadt = emptyVarEnv
} ;
} ;
return (msgs, final_res)
}
where
- init_imports = emptyImportAvails { imp_qual = unitModuleEnv mod emptyAvailEnv }
+ home_mods = mkHomeModules (map ms_mod (hsc_mod_graph hsc_env))
+ -- A guess at the home modules. This will be correct in
+ -- --make and GHCi modes, but in one-shot mode we need to
+ -- fix it up after we know the real dependencies of the current
+ -- module (see tcRnModule).
+ -- Setting it here is necessary for the typechecker entry points
+ -- other than tcRnModule: tcRnGetInfo, for example. These are
+ -- all called via the GHC module, so hsc_mod_graph will contain
+ -- something sensible.
+
+ init_imports = emptyImportAvails {imp_env = unitModuleEnv mod emptyNameSet}
-- Initialise tcg_imports with an empty set of bindings for
-- this module, so that if we see 'module M' in the export
-- list, and there are no bindings in M, we don't bleat
-- "unknown module M".
-initTcPrintErrors
+initTcPrintErrors -- Used from the interactive loop only
:: HscEnv
-> Module
-> TcM r
-> IO (Maybe r)
initTcPrintErrors env mod todo = do
- (msgs, res) <- initTc env mod todo
+ (msgs, res) <- initTc env HsSrcFile mod todo
printErrorsAndWarnings msgs
return res
-mkImpInstEnv :: HscEnv -> InstEnv
--- At the moment we (wrongly) build an instance environment from all the
--- home-package modules we have already compiled.
--- We should really only get instances from modules below us in the
--- module import tree.
-mkImpInstEnv (HscEnv {hsc_dflags = dflags, hsc_HPT = hpt})
- = foldModuleEnv (add . md_insts . hm_details) emptyInstEnv hpt
- where
- add dfuns inst_env = foldl extendInstEnv inst_env dfuns
-
-- mkImpTypeEnv makes the imported symbol table
mkImpTypeEnv :: ExternalPackageState -> HomePackageTable
-> Name -> Maybe TyThing
ifOptM flag thing_inside = do { b <- doptM flag;
if b then thing_inside else return () }
-getGhciMode :: TcRnIf gbl lcl GhciMode
-getGhciMode = do { env <- getTopEnv; return (hsc_mode env) }
+getGhciMode :: TcRnIf gbl lcl GhcMode
+getGhciMode = do { env <- getTopEnv; return (ghcMode (hsc_dflags env)) }
\end{code}
\begin{code}
getEps :: TcRnIf gbl lcl ExternalPackageState
getEps = do { env <- getTopEnv; readMutVar (hsc_EPS env) }
-setEps :: ExternalPackageState -> TcRnIf gbl lcl ()
-setEps eps = do { env <- getTopEnv; writeMutVar (hsc_EPS env) eps }
+-- Updating the EPS. This should be an atomic operation.
+-- Note the delicate 'seq' which forces the EPS before putting it in the
+-- variable. Otherwise what happens is that we get
+-- write eps_var (....(unsafeRead eps_var)....)
+-- and if the .... is strict, that's obviously bottom. By forcing it beforehand
+-- we make the unsafeRead happen before we update the variable.
updateEps :: (ExternalPackageState -> (ExternalPackageState, a))
-> TcRnIf gbl lcl a
-updateEps upd_fn = do { eps_var <- getEpsVar
+updateEps upd_fn = do { traceIf (text "updating EPS")
+ ; eps_var <- getEpsVar
; eps <- readMutVar eps_var
; let { (eps', val) = upd_fn eps }
- ; writeMutVar eps_var eps'
+ ; seq eps' (writeMutVar eps_var eps')
; return val }
updateEps_ :: (ExternalPackageState -> ExternalPackageState)
-> TcRnIf gbl lcl ()
-updateEps_ upd_fn = do { eps_var <- getEpsVar
- ; updMutVar eps_var upd_fn }
+updateEps_ upd_fn = do { traceIf (text "updating EPS_")
+ ; eps_var <- getEpsVar
+ ; eps <- readMutVar eps_var
+ ; let { eps' = upd_fn eps }
+ ; seq eps' (writeMutVar eps_var eps') }
getHpt :: TcRnIf gbl lcl HomePackageTable
getHpt = do { env <- getTopEnv; return (hsc_HPT env) }
let { (us1, us2) = splitUniqSupply us } ;
writeMutVar u_var us1 ;
return us2 }
+
+newLocalName :: Name -> TcRnIf gbl lcl Name
+newLocalName name -- Make a clone
+ = newUnique `thenM` \ uniq ->
+ returnM (mkInternalName uniq (getOccName name) (getSrcLoc name))
\end{code}
\begin{code}
traceTc, traceRn :: SDoc -> TcRn ()
-traceRn = dumpOptTcRn Opt_D_dump_rn_trace
-traceTc = dumpOptTcRn Opt_D_dump_tc_trace
-traceSplice = dumpOptTcRn Opt_D_dump_splices
+traceRn = traceOptTcRn Opt_D_dump_rn_trace
+traceTc = traceOptTcRn Opt_D_dump_tc_trace
+traceSplice = traceOptTcRn Opt_D_dump_splices
traceIf :: SDoc -> TcRnIf m n ()
-traceIf = dumpOptIf Opt_D_dump_if_trace
-traceHiDiffs = dumpOptIf Opt_D_dump_hi_diffs
+traceIf = traceOptIf Opt_D_dump_if_trace
+traceHiDiffs = traceOptIf Opt_D_dump_hi_diffs
-dumpOptIf :: DynFlag -> SDoc -> TcRnIf m n () -- No RdrEnv available, so qualify everything
-dumpOptIf flag doc = ifOptM flag $
+traceOptIf :: DynFlag -> SDoc -> TcRnIf m n () -- No RdrEnv available, so qualify everything
+traceOptIf flag doc = ifOptM flag $
ioToIOEnv (printForUser stderr alwaysQualify doc)
-dumpOptTcRn :: DynFlag -> SDoc -> TcRn ()
-dumpOptTcRn flag doc = ifOptM flag $ do
+traceOptTcRn :: DynFlag -> SDoc -> TcRn ()
+traceOptTcRn flag doc = ifOptM flag $ do
{ ctxt <- getErrCtxt
; loc <- getSrcSpanM
; ctxt_msgs <- do_ctxt emptyTidyEnv ctxt
dumpTcRn :: SDoc -> TcRn ()
dumpTcRn doc = do { rdr_env <- getGlobalRdrEnv ;
ioToTcRn (printForUser stderr (unQualInScope rdr_env) doc) }
+
+dumpOptTcRn :: DynFlag -> SDoc -> TcRn ()
+dumpOptTcRn flag doc = ifOptM flag (dumpTcRn doc)
\end{code}
getModule :: TcRn Module
getModule = do { env <- getGblEnv; return (tcg_mod env) }
+tcIsHsBoot :: TcRn Bool
+tcIsHsBoot = do { env <- getGblEnv; return (isHsBoot (tcg_src env)) }
+
getGlobalRdrEnv :: TcRn GlobalRdrEnv
getGlobalRdrEnv = do { env <- getGblEnv; return (tcg_rdr_env env) }
-- Avoid clash with Name.getSrcLoc
getSrcSpanM = do { env <- getLclEnv; return (tcl_loc env) }
-addSrcSpan :: SrcSpan -> TcRn a -> TcRn a
-addSrcSpan loc thing_inside
+setSrcSpan :: SrcSpan -> TcRn a -> TcRn a
+setSrcSpan loc thing_inside
| isGoodSrcSpan loc = updLclEnv (\env -> env { tcl_loc = loc }) thing_inside
| otherwise = thing_inside -- Don't overwrite useful info with useless
addLocM :: (a -> TcM b) -> Located a -> TcM b
-addLocM fn (L loc a) = addSrcSpan loc $ fn a
+addLocM fn (L loc a) = setSrcSpan loc $ fn a
wrapLocM :: (a -> TcM b) -> Located a -> TcM (Located b)
-wrapLocM fn (L loc a) = addSrcSpan loc $ do b <- fn a; return (L loc b)
+wrapLocM fn (L loc a) = setSrcSpan loc $ do b <- fn a; return (L loc b)
wrapLocFstM :: (a -> TcM (b,c)) -> Located a -> TcM (Located b, c)
wrapLocFstM fn (L loc a) =
- addSrcSpan loc $ do
+ setSrcSpan loc $ do
(b,c) <- fn a
return (L loc b, c)
wrapLocSndM :: (a -> TcM (b,c)) -> Located a -> TcM (b, Located c)
wrapLocSndM fn (L loc a) =
- addSrcSpan loc $ do
+ setSrcSpan loc $ do
(b,c) <- fn a
return (b, L loc c)
\end{code}
rdr_env <- getGlobalRdrEnv ;
let { err = mkLongErrMsg loc (unQualInScope rdr_env) msg extra } ;
(warns, errs) <- readMutVar errs_var ;
+ traceTc (ptext SLIT("Adding error:") <+> \ _ -> pprBagOfErrors (unitBag err)) ;
+ -- Ugh! traceTc is too specific; unitBag is horrible
writeMutVar errs_var (warns, errs `snocBag` err) }
addErrs :: [(SrcSpan,Message)] -> TcRn ()
\begin{code}
+try_m :: TcRn r -> TcRn (Either Exception r)
+-- Does try_m, with a debug-trace on failure
+try_m thing
+ = do { mb_r <- tryM thing ;
+ case mb_r of
+ Left exn -> do { traceTc (exn_msg exn); return mb_r }
+ Right r -> return mb_r }
+ where
+ exn_msg exn = text "tryTc/recoverM recovering from" <+> text (showException exn)
+
+-----------------------
recoverM :: TcRn r -- Recovery action; do this if the main one fails
-> TcRn r -- Main action: do this first
-> TcRn r
+-- Errors in 'thing' are retained
recoverM recover thing
= do { mb_res <- try_m thing ;
case mb_res of
Left exn -> recover
Right res -> returnM res }
+-----------------------
tryTc :: TcRn a -> TcRn (Messages, Maybe a)
- -- (tryTc m) executes m, and returns
- -- Just r, if m succeeds (returning r) and caused no errors
- -- Nothing, if m fails, or caused errors
- -- It also returns all the errors accumulated by m
- -- (even in the Just case, there might be warnings)
- --
- -- It always succeeds (never raises an exception)
+-- (tryTc m) executes m, and returns
+-- Just r, if m succeeds (returning r)
+-- Nothing, if m fails
+-- It also returns all the errors and warnings accumulated by m
+-- It always succeeds (never raises an exception)
tryTc m
= do { errs_var <- newMutVar emptyMessages ;
-
- mb_r <- try_m (setErrsVar errs_var m) ;
-
- new_errs <- readMutVar errs_var ;
-
- dflags <- getDOpts ;
-
- return (new_errs,
- case mb_r of
- Left exn -> Nothing
- Right r | errorsFound dflags new_errs -> Nothing
- | otherwise -> Just r)
+ res <- try_m (setErrsVar errs_var m) ;
+ msgs <- readMutVar errs_var ;
+ return (msgs, case res of
+ Left exn -> Nothing
+ Right val -> Just val)
+ -- The exception is always the IOEnv built-in
+ -- in exception; see IOEnv.failM
}
-try_m :: TcRn r -> TcRn (Either Exception r)
--- Does try_m, with a debug-trace on failure
-try_m thing
- = do { mb_r <- tryM thing ;
- case mb_r of
- Left exn -> do { traceTc (exn_msg exn); return mb_r }
- Right r -> return mb_r }
- where
- exn_msg exn = text "tryTc/recoverM recovering from" <+> text (showException exn)
+-----------------------
+tryTcErrs :: TcRn a -> TcRn (Messages, Maybe a)
+-- Run the thing, returning
+-- Just r, if m succceeds with no error messages
+-- Nothing, if m fails, or if it succeeds but has error messages
+-- Either way, the messages are returned; even in the Just case
+-- there might be warnings
+tryTcErrs thing
+ = do { (msgs, res) <- tryTc thing
+ ; dflags <- getDOpts
+ ; let errs_found = errorsFound dflags msgs
+ ; return (msgs, case res of
+ Nothing -> Nothing
+ Just val | errs_found -> Nothing
+ | otherwise -> Just val)
+ }
+-----------------------
tryTcLIE :: TcM a -> TcM (Messages, Maybe a)
--- Just like tryTc, except that it ensures that the LIE
+-- Just like tryTcErrs, except that it ensures that the LIE
-- for the thing is propagated only if there are no errors
-- Hence it's restricted to the type-check monad
tryTcLIE thing_inside
- = do { ((errs, mb_r), lie) <- getLIE (tryTc thing_inside) ;
- ifM (isJust mb_r) (extendLIEs lie) ;
- return (errs, mb_r) }
+ = do { ((msgs, mb_res), lie) <- getLIE (tryTcErrs thing_inside) ;
+ ; case mb_res of
+ Nothing -> return (msgs, Nothing)
+ Just val -> do { extendLIEs lie; return (msgs, Just val) }
+ }
+-----------------------
tryTcLIE_ :: TcM r -> TcM r -> TcM r
--- (tryTcLIE_ r m) tries m; if it succeeds it returns it,
--- otherwise it returns r. Any error messages added by m are discarded,
--- whether or not m succeeds.
+-- (tryTcLIE_ r m) tries m;
+-- if m succeeds with no error messages, it's the answer
+-- otherwise tryTcLIE_ drops everything from m and tries r instead.
tryTcLIE_ recover main
- = do { (_msgs, mb_res) <- tryTcLIE main ;
- case mb_res of
- Just res -> return res
- Nothing -> recover }
+ = do { (msgs, mb_res) <- tryTcLIE main
+ ; case mb_res of
+ Just val -> do { addMessages msgs -- There might be warnings
+ ; return val }
+ Nothing -> recover -- Discard all msgs
+ }
+-----------------------
checkNoErrs :: TcM r -> TcM r
-- (checkNoErrs m) succeeds iff m succeeds and generates no errors
-- If m fails then (checkNoErrsTc m) fails.
-- If so, it fails too.
-- Regardless, any errors generated by m are propagated to the enclosing context.
checkNoErrs main
- = do { (msgs, mb_res) <- tryTcLIE main ;
- addMessages msgs ;
- case mb_res of
- Just r -> return r
- Nothing -> failM
- }
+ = do { (msgs, mb_res) <- tryTcLIE main
+ ; addMessages msgs
+ ; case mb_res of
+ Nothing -> failM
+ Just val -> return val
+ }
ifErrsM :: TcRn r -> TcRn r -> TcRn r
-- ifErrsM bale_out main
%************************************************************************
\begin{code}
-setErrCtxtM, addErrCtxtM :: (TidyEnv -> TcM (TidyEnv, Message)) -> TcM a -> TcM a
-setErrCtxtM msg = updCtxt (\ msgs -> [msg])
-addErrCtxtM msg = updCtxt (\ msgs -> msg : msgs)
+getErrCtxt :: TcM ErrCtxt
+getErrCtxt = do { env <- getLclEnv; return (tcl_ctxt env) }
-setErrCtxt, addErrCtxt :: Message -> TcM a -> TcM a
-setErrCtxt msg = setErrCtxtM (\env -> returnM (env, msg))
-addErrCtxt msg = addErrCtxtM (\env -> returnM (env, msg))
+setErrCtxt :: ErrCtxt -> TcM a -> TcM a
+setErrCtxt ctxt = updLclEnv (\ env -> env { tcl_ctxt = ctxt })
-popErrCtxt :: TcM a -> TcM a
-popErrCtxt = updCtxt (\ msgs -> case msgs of { [] -> []; (m:ms) -> ms })
+addErrCtxtM :: (TidyEnv -> TcM (TidyEnv, Message)) -> TcM a -> TcM a
+addErrCtxtM msg = updCtxt (\ msgs -> msg : msgs)
-getErrCtxt :: TcM ErrCtxt
-getErrCtxt = do { env <- getLclEnv ; return (tcl_ctxt env) }
+addErrCtxt :: Message -> TcM a -> TcM a
+addErrCtxt msg = addErrCtxtM (\env -> returnM (env, msg))
-- Helper function for the above
updCtxt :: (ErrCtxt -> ErrCtxt) -> TcM a -> TcM a
updCtxt upd = updLclEnv (\ env@(TcLclEnv { tcl_ctxt = ctxt }) ->
env { tcl_ctxt = upd ctxt })
+-- Conditionally add an error context
+maybeAddErrCtxt :: Maybe Message -> TcM a -> TcM a
+maybeAddErrCtxt (Just msg) thing_inside = addErrCtxt msg thing_inside
+maybeAddErrCtxt Nothing thing_inside = thing_inside
+
+popErrCtxt :: TcM a -> TcM a
+popErrCtxt = updCtxt (\ msgs -> case msgs of { [] -> []; (m:ms) -> ms })
+
getInstLoc :: InstOrigin -> TcM InstLoc
getInstLoc origin
= do { loc <- getSrcSpanM ; env <- getLclEnv ;
-- Add the SrcSpan and context from the first Inst in the list
-- (they all have similar locations)
addInstCtxt (InstLoc _ src_loc ctxt) thing_inside
- = addSrcSpan src_loc (updCtxt (\ old_ctxt -> ctxt) thing_inside)
+ = setSrcSpan src_loc (updCtxt (\ old_ctxt -> ctxt) thing_inside)
\end{code}
The addErrTc functions add an error message, but do not cause failure.
| otherwise = take 3 ctxt
\end{code}
-%************************************************************************
+debugTc is useful for monadi debugging code
+
+\begin{code}
+debugTc :: TcM () -> TcM ()
+#ifdef DEBUG
+debugTc thing = thing
+#else
+debugTc thing = return ()
+#endif
+\end{code}
+
+ %************************************************************************
%* *
Type constraints (the so-called LIE)
%* *
%************************************************************************
\begin{code}
+nextDFunIndex :: TcM Int -- Get the next dfun index
+nextDFunIndex = do { env <- getGblEnv
+ ; let dfun_n_var = tcg_dfun_n env
+ ; n <- readMutVar dfun_n_var
+ ; writeMutVar dfun_n_var (n+1)
+ ; return n }
+
getLIEVar :: TcM (TcRef LIE)
getLIEVar = do { env <- getLclEnv; return (tcl_lie env) }
recordThUse :: TcM ()
recordThUse = do { env <- getGblEnv; writeMutVar (tcg_th_used env) True }
+keepAliveTc :: Name -> TcM () -- Record the name in the keep-alive set
+keepAliveTc n = do { env <- getGblEnv;
+ ; updMutVar (tcg_keep env) (`addOneToNameSet` n) }
+
+keepAliveSetTc :: NameSet -> TcM () -- Record the name in the keep-alive set
+keepAliveSetTc ns = do { env <- getGblEnv;
+ ; updMutVar (tcg_keep env) (`unionNameSets` ns) }
+
getStage :: TcM ThStage
getStage = do { env <- getLclEnv; return (tcl_th_ctxt env) }
%************************************************************************
%* *
- Arrow context
-%* *
-%************************************************************************
-
-\begin{code}
-popArrowBinders :: TcM a -> TcM a -- Move to the left of a (-<); see comments in TcRnTypes
-popArrowBinders
- = updLclEnv (\ env -> env { tcl_arrow_ctxt = pop (tcl_arrow_ctxt env) })
- where
- pop (ArrCtxt {proc_level = curr_lvl, proc_banned = banned})
- = ASSERT( not (curr_lvl `elem` banned) )
- ArrCtxt {proc_level = curr_lvl, proc_banned = curr_lvl : banned}
-
-getBannedProcLevels :: TcM [ProcLevel]
- = do { env <- getLclEnv; return (proc_banned (tcl_arrow_ctxt env)) }
-
-incProcLevel :: TcM a -> TcM a
-incProcLevel
- = updLclEnv (\ env -> env { tcl_arrow_ctxt = inc (tcl_arrow_ctxt env) })
- where
- inc ctxt = ctxt { proc_level = proc_level ctxt + 1 }
-\end{code}
-
-
-%************************************************************************
-%* *
Stuff for the renamer's local env
%* *
%************************************************************************
%************************************************************************
\begin{code}
+mkIfLclEnv :: Module -> SDoc -> IfLclEnv
+mkIfLclEnv mod loc = IfLclEnv { if_mod = mod,
+ if_loc = loc,
+ if_tv_env = emptyOccEnv,
+ if_id_env = emptyOccEnv }
+
initIfaceTcRn :: IfG a -> TcRn a
initIfaceTcRn thing_inside
= do { tcg_env <- getGblEnv
- ; let { if_env = IfGblEnv {
- if_rec_types = Just (tcg_mod tcg_env, get_type_env),
- if_is_boot = imp_dep_mods (tcg_imports tcg_env) }
+ ; let { if_env = IfGblEnv { if_rec_types = Just (tcg_mod tcg_env, get_type_env) }
; get_type_env = readMutVar (tcg_type_env_var tcg_env) }
; setEnvs (if_env, ()) thing_inside }
initIfaceExtCore thing_inside
= do { tcg_env <- getGblEnv
; let { mod = tcg_mod tcg_env
+ ; doc = ptext SLIT("External Core file for") <+> quotes (ppr mod)
; if_env = IfGblEnv {
- if_rec_types = Just (mod, return (tcg_type_env tcg_env)),
- if_is_boot = imp_dep_mods (tcg_imports tcg_env) }
- ; if_lenv = IfLclEnv { if_mod = moduleName mod,
- if_tv_env = emptyOccEnv,
- if_id_env = emptyOccEnv }
+ if_rec_types = Just (mod, return (tcg_type_env tcg_env)) }
+ ; if_lenv = mkIfLclEnv mod doc
}
; setEnvs (if_env, if_lenv) thing_inside }
-- Used when checking the up-to-date-ness of the old Iface
-- Initialise the environment with no useful info at all
initIfaceCheck hsc_env do_this
- = do { let { gbl_env = IfGblEnv { if_is_boot = emptyModuleEnv,
- if_rec_types = Nothing } ;
- }
+ = do { let gbl_env = IfGblEnv { if_rec_types = Nothing }
; initTcRnIf 'i' hsc_env gbl_env () do_this
}
-initIfaceTc :: HscEnv -> ModIface
- -> (TcRef TypeEnv -> IfL a) -> IO a
+initIfaceTc :: ModIface
+ -> (TcRef TypeEnv -> IfL a) -> TcRnIf gbl lcl a
-- Used when type-checking checking an up-to-date interface file
-- No type envt from the current module, but we do know the module dependencies
-initIfaceTc hsc_env iface do_this
- = do { tc_env_var <- newIORef emptyTypeEnv
- ; let { gbl_env = IfGblEnv { if_is_boot = mkModDeps (dep_mods (mi_deps iface)),
- if_rec_types = Just (mod, readMutVar tc_env_var) } ;
- ; if_lenv = IfLclEnv { if_mod = moduleName mod,
- if_tv_env = emptyOccEnv,
- if_id_env = emptyOccEnv }
+initIfaceTc iface do_this
+ = do { tc_env_var <- newMutVar emptyTypeEnv
+ ; let { gbl_env = IfGblEnv { if_rec_types = Just (mod, readMutVar tc_env_var) } ;
+ ; if_lenv = mkIfLclEnv mod doc
}
- ; initTcRnIf 'i' hsc_env gbl_env if_lenv (do_this tc_env_var)
+ ; setEnvs (gbl_env, if_lenv) (do_this tc_env_var)
}
where
mod = mi_module iface
+ doc = ptext SLIT("The interface for") <+> quotes (ppr mod)
initIfaceRules :: HscEnv -> ModGuts -> IfG a -> IO a
-- Used when sucking in new Rules in SimplCore
-- We have available the type envt of the module being compiled, and we must use it
initIfaceRules hsc_env guts do_this
= do { let {
- is_boot = mkModDeps (dep_mods (mg_deps guts))
- -- Urgh! But we do somehow need to get the info
- -- on whether (for this particular compilation) we should
- -- import a hi-boot file or not.
- ; type_info = (mg_module guts, return (mg_types guts))
- ; gbl_env = IfGblEnv { if_is_boot = is_boot,
- if_rec_types = Just type_info } ;
+ type_info = (mg_module guts, return (mg_types guts))
+ ; gbl_env = IfGblEnv { if_rec_types = Just type_info } ;
}
-- Run the thing; any exceptions just bubble out from here
; initTcRnIf 'i' hsc_env gbl_env () do_this
}
-initIfaceLcl :: ModuleName -> IfL a -> IfM lcl a
-initIfaceLcl mod thing_inside
- = setLclEnv (IfLclEnv { if_mod = mod,
- if_tv_env = emptyOccEnv,
- if_id_env = emptyOccEnv })
- thing_inside
+initIfaceLcl :: Module -> SDoc -> IfL a -> IfM lcl a
+initIfaceLcl mod loc_doc thing_inside
+ = setLclEnv (mkIfLclEnv mod loc_doc) thing_inside
+getIfModule :: IfL Module
+getIfModule = do { env <- getLclEnv; return (if_mod env) }
+
+--------------------
+failIfM :: Message -> IfL a
+-- The Iface monad doesn't have a place to accumulate errors, so we
+-- just fall over fast if one happens; it "shouldnt happen".
+-- We use IfL here so that we can get context info out of the local env
+failIfM msg
+ = do { env <- getLclEnv
+ ; let full_msg = if_loc env $$ nest 2 msg
+ ; ioToIOEnv (printErrs (full_msg defaultErrStyle))
+ ; failM }
--------------------
forkM_maybe :: SDoc -> IfL a -> IfL (Maybe a)
Nothing -> pprPanic "forkM" doc
Just r -> r) }
\end{code}
+
+%************************************************************************
+%* *
+ Stuff for GADTs
+%* *
+%************************************************************************
+
+\begin{code}
+getTypeRefinement :: TcM GadtRefinement
+getTypeRefinement = do { lcl_env <- getLclEnv; return (tcl_gadt lcl_env) }
+
+setTypeRefinement :: GadtRefinement -> TcM a -> TcM a
+setTypeRefinement gadt = updLclEnv (\env -> env { tcl_gadt = gadt })
+\end{code}