import TcRnTypes -- Re-export all
import IOEnv -- Re-export all
-import HsSyn ( MonoBinds(..) )
import HscTypes ( HscEnv(..), ModGuts(..), ModIface(..),
- TyThing, Dependencies(..),
+ TyThing, Dependencies(..), TypeEnv, emptyTypeEnv,
ExternalPackageState(..), HomePackageTable,
ModDetails(..), HomeModInfo(..),
Deprecs(..), FixityEnv, FixItem,
import VarSet ( emptyVarSet )
import VarEnv ( TidyEnv, emptyTidyEnv )
import ErrUtils ( Message, Messages, emptyMessages, errorsFound,
- addShortErrLocLine, addShortWarnLocLine, printErrorsAndWarnings )
-import SrcLoc ( SrcLoc, mkGeneralSrcLoc )
+ mkErrMsg, mkWarnMsg, printErrorsAndWarnings,
+ mkLocMessage, mkLongErrMsg )
+import SrcLoc ( mkGeneralSrcSpan, isGoodSrcSpan, SrcSpan, Located(..) )
import NameEnv ( emptyNameEnv )
import NameSet ( emptyDUs, emptyNameSet )
import OccName ( emptyOccEnv )
import Outputable
import UniqSupply ( UniqSupply, mkSplitUniqSupply, uniqFromSupply, splitUniqSupply )
import Unique ( Unique )
-import CmdLineOpts ( DynFlags, DynFlag(..), dopt, opt_PprStyle_Debug )
+import CmdLineOpts ( DynFlags, DynFlag(..), dopt, opt_PprStyle_Debug, dopt_set )
import Bag ( snocBag, unionBags )
import Panic ( showException )
initTc :: HscEnv
-> Module
-> TcM r
- -> IO (Maybe r)
+ -> IO (Messages, Maybe r)
-- Nothing => error thrown by the thing inside
-- (error messages should have been printed already)
tvs_var <- newIORef emptyVarSet ;
type_env_var <- newIORef emptyNameEnv ;
dfuns_var <- newIORef emptyNameSet ;
+ th_var <- newIORef False ;
let {
gbl_env = TcGblEnv {
tcg_type_env_var = type_env_var,
tcg_inst_env = mkImpInstEnv hsc_env,
tcg_inst_uses = dfuns_var,
- tcg_exports = [],
+ tcg_th_used = th_var,
+ tcg_exports = emptyNameSet,
tcg_imports = init_imports,
tcg_dus = emptyDUs,
- tcg_binds = EmptyMonoBinds,
+ tcg_binds = emptyBag,
tcg_deprecs = NoDeprecs,
tcg_insts = [],
tcg_rules = [],
- tcg_fords = []
+ tcg_fords = [],
+ tcg_keep = emptyNameSet
} ;
lcl_env = TcLclEnv {
tcl_errs = errs_var,
- tcl_loc = mkGeneralSrcLoc FSLIT("Top level of module"),
+ tcl_loc = mkGeneralSrcSpan FSLIT("Top level"),
tcl_ctxt = [],
tcl_rdr = emptyLocalRdrEnv,
tcl_th_ctxt = topStage,
Right res -> return (Just res)
Left _ -> return Nothing } ;
- -- Print any error messages
+ -- Collect any error messages
msgs <- readIORef errs_var ;
- printErrorsAndWarnings msgs ;
let { dflags = hsc_dflags hsc_env
; final_res | errorsFound dflags msgs = Nothing
| otherwise = maybe_res } ;
- return final_res
+ return (msgs, final_res)
}
where
init_imports = emptyImportAvails { imp_qual = unitModuleEnv mod emptyAvailEnv }
-- list, and there are no bindings in M, we don't bleat
-- "unknown module M".
+initTcPrintErrors
+ :: HscEnv
+ -> Module
+ -> TcM r
+ -> IO (Maybe r)
+initTcPrintErrors env mod todo = do
+ (msgs, res) <- initTc env 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.
doptM :: DynFlag -> TcRnIf gbl lcl Bool
doptM flag = do { dflags <- getDOpts; return (dopt flag dflags) }
+setOptM :: DynFlag -> TcRnIf gbl lcl a -> TcRnIf gbl lcl a
+setOptM flag = updEnv (\ env@(Env { env_top = top }) ->
+ env { env_top = top { hsc_dflags = dopt_set (hsc_dflags top) flag}} )
+
ifOptM :: DynFlag -> TcRnIf gbl lcl () -> TcRnIf gbl lcl () -- Do it flag is true
ifOptM flag thing_inside = do { b <- doptM flag;
if b then thing_inside else return () }
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) }
+
+getEpsAndHpt :: TcRnIf gbl lcl (ExternalPackageState, HomePackageTable)
+getEpsAndHpt = do { env <- getTopEnv; eps <- readMutVar (hsc_EPS env)
+ ; return (eps, hsc_HPT env) }
\end{code}
%************************************************************************
ioToIOEnv (printForUser stderr alwaysQualify doc)
dumpOptTcRn :: DynFlag -> SDoc -> TcRn ()
-dumpOptTcRn flag doc = ifOptM flag (dumpTcRn doc)
+dumpOptTcRn flag doc = ifOptM flag $ do
+ { ctxt <- getErrCtxt
+ ; loc <- getSrcSpanM
+ ; ctxt_msgs <- do_ctxt emptyTidyEnv ctxt
+ ; let real_doc = mkLocMessage loc (vcat (doc : ctxt_to_use ctxt_msgs))
+ ; dumpTcRn real_doc }
dumpTcRn :: SDoc -> TcRn ()
dumpTcRn doc = do { rdr_env <- getGlobalRdrEnv ;
%************************************************************************
\begin{code}
-getSrcLocM :: TcRn SrcLoc
+getSrcSpanM :: TcRn SrcSpan
-- Avoid clash with Name.getSrcLoc
-getSrcLocM = do { env <- getLclEnv; return (tcl_loc env) }
-
-addSrcLoc :: SrcLoc -> TcRn a -> TcRn a
-addSrcLoc loc = updLclEnv (\env -> env { tcl_loc = loc })
+getSrcSpanM = do { env <- getLclEnv; return (tcl_loc env) }
+
+addSrcSpan :: SrcSpan -> TcRn a -> TcRn a
+addSrcSpan 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
+
+wrapLocM :: (a -> TcM b) -> Located a -> TcM (Located b)
+wrapLocM fn (L loc a) = addSrcSpan 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
+ (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
+ (b,c) <- fn a
+ return (b, L loc c)
\end{code}
setErrsVar v = updLclEnv (\ env -> env { tcl_errs = v })
addErr :: Message -> TcRn ()
-addErr msg = do { loc <- getSrcLocM ; addErrAt loc msg }
+addErr msg = do { loc <- getSrcSpanM ; addErrAt loc msg }
-addErrAt :: SrcLoc -> Message -> TcRn ()
-addErrAt loc msg
+addLocErr :: Located e -> (e -> Message) -> TcRn ()
+addLocErr (L loc e) fn = addErrAt loc (fn e)
+
+addErrAt :: SrcSpan -> Message -> TcRn ()
+addErrAt loc msg = addLongErrAt loc msg empty
+
+addLongErrAt :: SrcSpan -> Message -> Message -> TcRn ()
+addLongErrAt loc msg extra
= do { errs_var <- getErrsVar ;
rdr_env <- getGlobalRdrEnv ;
- let { err = addShortErrLocLine loc (unQualInScope rdr_env) msg } ;
+ let { err = mkLongErrMsg loc (unQualInScope rdr_env) msg extra } ;
(warns, errs) <- readMutVar errs_var ;
writeMutVar errs_var (warns, errs `snocBag` err) }
-addErrs :: [(SrcLoc,Message)] -> TcRn ()
+addErrs :: [(SrcSpan,Message)] -> TcRn ()
addErrs msgs = mappM_ add msgs
where
add (loc,msg) = addErrAt loc msg
-addWarn :: Message -> TcRn ()
-addWarn msg
+addReport :: Message -> TcRn ()
+addReport msg = do loc <- getSrcSpanM; addReportAt loc msg
+
+addReportAt :: SrcSpan -> Message -> TcRn ()
+addReportAt loc msg
= do { errs_var <- getErrsVar ;
- loc <- getSrcLocM ;
rdr_env <- getGlobalRdrEnv ;
- let { warn = addShortWarnLocLine loc (unQualInScope rdr_env) msg } ;
+ let { warn = mkWarnMsg loc (unQualInScope rdr_env) msg } ;
(warns, errs) <- readMutVar errs_var ;
writeMutVar errs_var (warns `snocBag` warn, errs) }
+addWarn :: Message -> TcRn ()
+addWarn msg = addReport (ptext SLIT("Warning:") <+> msg)
+
+addWarnAt :: SrcSpan -> Message -> TcRn ()
+addWarnAt loc msg = addReportAt loc (ptext SLIT("Warning:") <+> msg)
+
+addLocWarn :: Located e -> (e -> Message) -> TcRn ()
+addLocWarn (L loc e) fn = addReportAt loc (fn e)
+
checkErr :: Bool -> Message -> TcRn ()
-- Add the error if the bool is False
checkErr ok msg = checkM ok (addErr msg)
(warns, errs) <- readMutVar errs_var ;
writeMutVar errs_var (warns `unionBags` m_warns,
errs `unionBags` m_errs) }
+
+discardWarnings :: TcRn a -> TcRn a
+-- Ignore warnings inside the thing inside;
+-- used to ignore-unused-variable warnings inside derived code
+-- With -dppr-debug, the effects is switched off, so you can still see
+-- what warnings derived code would give
+discardWarnings thing_inside
+ | opt_PprStyle_Debug = thing_inside
+ | otherwise
+ = do { errs_var <- newMutVar emptyMessages
+ ; result <- setErrsVar errs_var thing_inside
+ ; (_warns, errs) <- readMutVar errs_var
+ ; addMessages (emptyBag, errs)
+ ; return result }
\end{code}
getInstLoc :: InstOrigin -> TcM InstLoc
getInstLoc origin
- = do { loc <- getSrcLocM ; env <- getLclEnv ;
+ = do { loc <- getSrcSpanM ; env <- getLclEnv ;
return (InstLoc origin loc (tcl_ctxt env)) }
addInstCtxt :: InstLoc -> TcM a -> TcM a
--- Add the SrcLoc and context from the first Inst in the list
+-- Add the SrcSpan and context from the first Inst in the list
-- (they all have similar locations)
addInstCtxt (InstLoc _ src_loc ctxt) thing_inside
- = addSrcLoc src_loc (updCtxt (\ old_ctxt -> ctxt) thing_inside)
+ = addSrcSpan src_loc (updCtxt (\ old_ctxt -> ctxt) thing_inside)
\end{code}
The addErrTc functions add an error message, but do not cause failure.
addErrTcM :: (TidyEnv, Message) -> TcM ()
addErrTcM (tidy_env, err_msg)
= do { ctxt <- getErrCtxt ;
- loc <- getSrcLocM ;
+ loc <- getSrcSpanM ;
add_err_tcm tidy_env err_msg loc ctxt }
\end{code}
\begin{code}
add_err_tcm tidy_env err_msg loc ctxt
= do { ctxt_msgs <- do_ctxt tidy_env ctxt ;
- addErrAt loc (vcat (err_msg : ctxt_to_use ctxt_msgs)) }
+ addLongErrAt loc err_msg (vcat (ctxt_to_use ctxt_msgs)) }
do_ctxt tidy_env []
= return []
%************************************************************************
\begin{code}
+recordThUse :: TcM ()
+recordThUse = do { env <- getGblEnv; writeMutVar (tcg_th_used env) True }
+
getStage :: TcM ThStage
getStage = do { env <- getLclEnv; return (tcl_th_ctxt env) }
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) }
+ 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 }
= do { tcg_env <- getGblEnv
; let { mod = tcg_mod tcg_env
; 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_rec_types = Just (mod, return (tcg_type_env tcg_env)) }
; if_lenv = IfLclEnv { if_mod = moduleName mod,
if_tv_env = emptyOccEnv,
if_id_env = emptyOccEnv }
-- 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 -> IfG a -> IO a
+initIfaceTc :: HscEnv -> ModIface
+ -> (TcRef TypeEnv -> IfL a) -> IO 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 { let { gbl_env = IfGblEnv { if_is_boot = mkModDeps (dep_mods (mi_deps iface)),
- if_rec_types = Nothing } ;
+ = do { tc_env_var <- newIORef emptyTypeEnv
+ ; let { gbl_env = IfGblEnv { if_rec_types = Just (mod, readMutVar tc_env_var) } ;
+ ; if_lenv = IfLclEnv { if_mod = moduleName mod,
+ if_tv_env = emptyOccEnv,
+ if_id_env = emptyOccEnv }
}
- ; initTcRnIf 'i' hsc_env gbl_env () do_this
+ ; initTcRnIf 'i' hsc_env gbl_env if_lenv (do_this tc_env_var)
}
+ where
+ mod = mi_module iface
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