[project @ 2004-01-23 13:55:28 by simonmar]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcRnMonad.lhs
index f450dcf..350aca0 100644 (file)
@@ -1,92 +1,53 @@
 \begin{code}
 module TcRnMonad(
        module TcRnMonad,
-       module TcRnTypes
+       module TcRnTypes,
+       module IOEnv
   ) where
 
 #include "HsVersions.h"
 
-import HsSyn           ( MonoBinds(..) )
-import HscTypes                ( HscEnv(..), PersistentCompilerState(..),
-                         emptyFixityEnv, emptyGlobalRdrEnv, TyThing,
+import TcRnTypes       -- Re-export all
+import IOEnv           -- Re-export all
+
+import HscTypes                ( HscEnv(..), ModGuts(..), ModIface(..),
+                         TyThing, Dependencies(..), TypeEnv, emptyTypeEnv,
                          ExternalPackageState(..), HomePackageTable,
-                         ModDetails(..), HomeModInfo(..), Deprecations(..),
-                         GlobalRdrEnv, LocalRdrEnv, NameCache, FixityEnv,
+                         ModDetails(..), HomeModInfo(..), 
+                         Deprecs(..), FixityEnv, FixItem,
                          GhciMode, lookupType, unQualInScope )
-import TcRnTypes
-import Module          ( Module, foldModuleEnv )
+import Module          ( Module, ModuleName, unitModuleEnv, foldModuleEnv, emptyModuleEnv )
+import RdrName         ( GlobalRdrEnv, emptyGlobalRdrEnv,      
+                         LocalRdrEnv, emptyLocalRdrEnv )
 import Name            ( Name, isInternalName )
 import Type            ( Type )
 import NameEnv         ( extendNameEnvList )
-import InstEnv         ( InstEnv, extendInstEnv )
-import TysWiredIn      ( integerTy, doubleTy )
+import InstEnv         ( InstEnv, emptyInstEnv, extendInstEnv )
 
 import VarSet          ( emptyVarSet )
 import VarEnv          ( TidyEnv, emptyTidyEnv )
-import RdrName         ( emptyRdrEnv )
 import ErrUtils                ( Message, Messages, emptyMessages, errorsFound, 
-                         addShortErrLocLine, addShortWarnLocLine, printErrorsAndWarnings )
-import SrcLoc          ( SrcLoc, noSrcLoc )
+                         mkErrMsg, mkWarnMsg, printErrorsAndWarnings,
+                         mkLocMessage, mkLongErrMsg )
+import SrcLoc          ( mkGeneralSrcSpan, SrcSpan, Located(..) )
 import NameEnv         ( emptyNameEnv )
+import NameSet         ( emptyDUs, emptyNameSet )
+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 )
-import BasicTypes      ( FixitySig )
+import CmdLineOpts     ( DynFlags, DynFlag(..), dopt, opt_PprStyle_Debug, dopt_set )
 import Bag             ( snocBag, unionBags )
-
+import Panic           ( showException )
 import Maybe           ( isJust )
 import IO              ( stderr )
 import DATA_IOREF      ( newIORef, readIORef )
+import EXCEPTION       ( Exception )
 \end{code}
 
-%************************************************************************
-%*                                                                     *
-       Standard combinators, but specialised for this monad
-                       (for efficiency)
-%*                                                                     *
-6%************************************************************************
-
-\begin{code}
-mappM                :: (a -> TcRn m b) -> [a] -> TcRn m [b]
-mappM_               :: (a -> TcRn m b) -> [a] -> TcRn m ()
-       -- Funny names to avoid clash with Prelude
-sequenceM     :: [TcRn m a] -> TcRn m [a]
-foldlM        :: (a -> b -> TcRn m a)  -> a -> [b] -> TcRn m a
-mapAndUnzipM  :: (a -> TcRn m (b,c))   -> [a] -> TcRn m ([b],[c])
-mapAndUnzip3M :: (a -> TcRn m (b,c,d)) -> [a] -> TcRn m ([b],[c],[d])
-checkM       :: Bool -> TcRn m () -> TcRn m () -- Perform arg if bool is False
-ifM          :: Bool -> TcRn m () -> TcRn m () -- Perform arg if bool is True
-
-mappM f []     = return []
-mappM f (x:xs) = do { r <- f x; rs <- mappM f xs; return (r:rs) }
-
-mappM_ f []     = return ()
-mappM_ f (x:xs) = f x >> mappM_ f xs
-
-sequenceM [] = return []
-sequenceM (x:xs) = do { r <- x; rs <- sequenceM xs; return (r:rs) }
-
-foldlM k z [] = return z
-foldlM k z (x:xs) = do { r <- k z x; foldlM k r xs }
-
-mapAndUnzipM f []     = return ([],[])
-mapAndUnzipM f (x:xs) = do { (r,s) <- f x; 
-                            (rs,ss) <- mapAndUnzipM f xs; 
-                            return (r:rs, s:ss) }
-
-mapAndUnzip3M f []     = return ([],[], [])
-mapAndUnzip3M f (x:xs) = do { (r,s,t) <- f x; 
-                             (rs,ss,ts) <- mapAndUnzip3M f xs; 
-                             return (r:rs, s:ss, t:ts) }
-
-checkM True  err = return ()
-checkM False err = err
-
-ifM True  do_it = do_it
-ifM False do_it = return ()
-\end{code}
 
 
 %************************************************************************
@@ -96,101 +57,89 @@ ifM False do_it = return ()
 %************************************************************************
 
 \begin{code}
-initTc :: HscEnv -> PersistentCompilerState
+ioToTcRn :: IO r -> TcRn r
+ioToTcRn = ioToIOEnv
+\end{code}
+
+\begin{code}
+initTc :: HscEnv
        -> Module 
        -> TcM r
-       -> IO (PersistentCompilerState, Maybe r)
+       -> IO (Messages, Maybe r)
                -- Nothing => error thrown by the thing inside
                -- (error messages should have been printed already)
 
-initTc  (HscEnv { hsc_mode   = ghci_mode,
-                 hsc_HPT    = hpt,
-                 hsc_dflags = dflags })
-       pcs mod do_this
- = do { us       <- mkSplitUniqSupply 'a' ;
-       us_var   <- newIORef us ;
-       errs_var <- newIORef (emptyBag, emptyBag) ;
-       tvs_var  <- newIORef emptyVarSet ;
-       usg_var  <- newIORef emptyUsages ;
-       nc_var   <- newIORef (pcs_nc pcs) ;
-       eps_var  <- newIORef eps ;
-   
-       let {
-            env = Env { env_top = top_env,
-                        env_gbl = gbl_env,
-                        env_lcl = lcl_env,
-                        env_loc = noSrcLoc } ;
-
-            top_env = TopEnv { 
-               top_mode   = ghci_mode,
-               top_dflags = dflags,
-               top_eps    = eps_var,
-               top_hpt    = hpt,
-               top_nc     = nc_var,
-               top_us     = us_var,
-               top_errs   = errs_var } ;
+initTc hsc_env mod do_this
+ = do { errs_var     <- newIORef (emptyBag, emptyBag) ;
+       tvs_var      <- newIORef emptyVarSet ;
+       type_env_var <- newIORef emptyNameEnv ;
+       dfuns_var    <- newIORef emptyNameSet ;
 
+       let {
             gbl_env = TcGblEnv {
                tcg_mod      = mod,
-               tcg_usages   = usg_var,
                tcg_rdr_env  = emptyGlobalRdrEnv,
-               tcg_fix_env  = emptyFixityEnv,
-               tcg_default  = defaultDefaultTys,
+               tcg_fix_env  = emptyNameEnv,
+               tcg_default  = Nothing,
                tcg_type_env = emptyNameEnv,
-               tcg_ist      = mkImpTypeEnv eps hpt,
-               tcg_inst_env = mkImpInstEnv dflags eps hpt,
-               tcg_exports  = [],
-               tcg_imports  = emptyImportAvails,
-               tcg_binds    = EmptyMonoBinds,
+               tcg_type_env_var = type_env_var,
+               tcg_inst_env  = mkImpInstEnv hsc_env,
+               tcg_inst_uses = dfuns_var,
+               tcg_exports  = emptyNameSet,
+               tcg_imports  = init_imports,
+               tcg_dus      = emptyDUs,
+               tcg_binds    = emptyBag,
                tcg_deprecs  = NoDeprecs,
                tcg_insts    = [],
                tcg_rules    = [],
-               tcg_fords    = [] } ;
-
+               tcg_fords    = [],
+               tcg_keep     = emptyNameSet
+            } ;
             lcl_env = TcLclEnv {
-               tcl_ctxt   = [],
-               tcl_level  = topStage,
-               tcl_env    = emptyNameEnv,
-               tcl_tyvars = tvs_var,
-               tcl_lie    = panic "initTc:LIE" } ;
-                       -- LIE only valid inside a getLIE
+               tcl_errs       = errs_var,
+               tcl_loc        = mkGeneralSrcSpan FSLIT("Top level of module"),
+               tcl_ctxt       = [],
+               tcl_rdr        = emptyLocalRdrEnv,
+               tcl_th_ctxt    = topStage,
+               tcl_arrow_ctxt = topArrowCtxt,
+               tcl_env        = emptyNameEnv,
+               tcl_tyvars     = tvs_var,
+               tcl_lie        = panic "initTc:LIE"     -- LIE only valid inside a getLIE
             } ;
+       } ;
    
        -- OK, here's the business end!
-       maybe_res <- catch (do { res  <- runTcRn env do_this ;
-                                return (Just res) })
-                          (\_ -> return Nothing) ;
+       maybe_res <- initTcRnIf 'a' hsc_env gbl_env lcl_env $
+                            do { r <- tryM do_this 
+                               ; case r of
+                                   Right res -> return (Just res)
+                                   Left _    -> return Nothing } ;
 
-       -- Print any error messages
+       -- Collect any error messages
        msgs <- readIORef errs_var ;
-       printErrorsAndWarnings msgs ;
 
-       -- Get final PCS and return
-       eps' <- readIORef eps_var ;
-       nc'  <- readIORef nc_var ;
-       let { pcs' = PCS { pcs_EPS = eps', pcs_nc = nc' } ;
-             final_res | errorsFound msgs = Nothing
-                       | otherwise        = maybe_res } ;
+       let { dflags = hsc_dflags hsc_env
+           ; final_res | errorsFound dflags msgs = Nothing
+                       | otherwise               = maybe_res } ;
 
-       return (pcs', final_res)
+       return (msgs, final_res)
     }
   where
-    eps = pcs_EPS pcs
-
-defaultDefaultTys :: [Type]
-defaultDefaultTys = [integerTy, doubleTy]
-
-mkImpInstEnv :: DynFlags -> ExternalPackageState -> HomePackageTable -> InstEnv
-mkImpInstEnv dflags eps hpt
-  = foldModuleEnv (add . md_insts . hm_details) 
-                 (eps_inst_env eps)
-                 hpt
+    init_imports = emptyImportAvails { imp_qual = unitModuleEnv mod emptyAvailEnv }
+       -- 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".
+
+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
-         -- We shouldn't get instance conflict errors from
-         -- the package and home type envs
-    add dfuns inst_env = WARN( not (null errs), vcat (map snd errs) ) inst_env'
-                      where
-                        (inst_env', errs) = extendInstEnv dflags inst_env dfuns
+    add dfuns inst_env = foldl extendInstEnv inst_env dfuns
 
 -- mkImpTypeEnv makes the imported symbol table
 mkImpTypeEnv :: ExternalPackageState -> HomePackageTable
@@ -205,103 +154,202 @@ mkImpTypeEnv pcs hpt = lookup
 
 %************************************************************************
 %*                                                                     *
+               Initialisation
+%*                                                                     *
+%************************************************************************
+
+
+\begin{code}
+initTcRnIf :: Char             -- Tag for unique supply
+          -> HscEnv
+          -> gbl -> lcl 
+          -> TcRnIf gbl lcl a 
+          -> IO a
+initTcRnIf uniq_tag hsc_env gbl_env lcl_env thing_inside
+   = do        { us     <- mkSplitUniqSupply uniq_tag ;
+       ; us_var <- newIORef us ;
+
+       ; let { env = Env { env_top = hsc_env,
+                           env_us  = us_var,
+                           env_gbl = gbl_env,
+                           env_lcl = lcl_env } }
+
+       ; runIOEnv env thing_inside
+       }
+\end{code}
+
+%************************************************************************
+%*                                                                     *
                Simple accessors
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
-getTopEnv :: TcRn m TopEnv
+getTopEnv :: TcRnIf gbl lcl HscEnv
 getTopEnv = do { env <- getEnv; return (env_top env) }
 
-getGblEnv :: TcRn m TcGblEnv
+getGblEnv :: TcRnIf gbl lcl gbl
 getGblEnv = do { env <- getEnv; return (env_gbl env) }
 
-updGblEnv :: (TcGblEnv -> TcGblEnv) -> TcRn m a -> TcRn m a
+updGblEnv :: (gbl -> gbl) -> TcRnIf gbl lcl a -> TcRnIf gbl lcl a
 updGblEnv upd = updEnv (\ env@(Env { env_gbl = gbl }) -> 
                          env { env_gbl = upd gbl })
 
-setGblEnv :: TcGblEnv -> TcRn m a -> TcRn m a
+setGblEnv :: gbl -> TcRnIf gbl lcl a -> TcRnIf gbl lcl a
 setGblEnv gbl_env = updEnv (\ env -> env { env_gbl = gbl_env })
 
-getLclEnv :: TcRn m m
+getLclEnv :: TcRnIf gbl lcl lcl
 getLclEnv = do { env <- getEnv; return (env_lcl env) }
 
-updLclEnv :: (m -> m) -> TcRn m a -> TcRn m a
+updLclEnv :: (lcl -> lcl) -> TcRnIf gbl lcl a -> TcRnIf gbl lcl a
 updLclEnv upd = updEnv (\ env@(Env { env_lcl = lcl }) -> 
                          env { env_lcl = upd lcl })
 
-setLclEnv :: m -> TcRn m a -> TcRn n a
+setLclEnv :: lcl' -> TcRnIf gbl lcl' a -> TcRnIf gbl lcl a
 setLclEnv lcl_env = updEnv (\ env -> env { env_lcl = lcl_env })
+
+getEnvs :: TcRnIf gbl lcl (gbl, lcl)
+getEnvs = do { env <- getEnv; return (env_gbl env, env_lcl env) }
+
+setEnvs :: (gbl', lcl') -> TcRnIf gbl' lcl' a -> TcRnIf gbl lcl a
+setEnvs (gbl_env, lcl_env) = updEnv (\ env -> env { env_gbl = gbl_env, env_lcl = lcl_env })
 \end{code}
 
+
 Command-line flags
 
 \begin{code}
-getDOpts :: TcRn m DynFlags
-getDOpts = do { env <- getTopEnv; return (top_dflags env) }
+getDOpts :: TcRnIf gbl lcl DynFlags
+getDOpts = do { env <- getTopEnv; return (hsc_dflags env) }
 
-doptM :: DynFlag -> TcRn m Bool
+doptM :: DynFlag -> TcRnIf gbl lcl Bool
 doptM flag = do { dflags <- getDOpts; return (dopt flag dflags) }
 
-ifOptM :: DynFlag -> TcRn m () -> TcRn m ()    -- Do it flag is true
+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 () }
 
-getGhciMode :: TcRn m GhciMode
-getGhciMode = do { env <- getTopEnv; return (top_mode env) }
+getGhciMode :: TcRnIf gbl lcl GhciMode
+getGhciMode = do { env <- getTopEnv; return (hsc_mode env) }
 \end{code}
 
 \begin{code}
-getSrcLocM :: TcRn m SrcLoc
-       -- Avoid clash with Name.getSrcLoc
-getSrcLocM = do { env <- getEnv; return (env_loc env) }
+getEpsVar :: TcRnIf gbl lcl (TcRef ExternalPackageState)
+getEpsVar = do { env <- getTopEnv; return (hsc_EPS env) }
+
+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 }
+
+updateEps :: (ExternalPackageState -> (ExternalPackageState, a))
+         -> TcRnIf gbl lcl a
+updateEps upd_fn = do  { eps_var <- getEpsVar
+                       ; eps <- readMutVar eps_var
+                       ; let { (eps', val) = upd_fn 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 }
+
+getHpt :: TcRnIf gbl lcl HomePackageTable
+getHpt = do { env <- getTopEnv; return (hsc_HPT env) }
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+               Unique supply
+%*                                                                     *
+%************************************************************************
 
-addSrcLoc :: SrcLoc -> TcRn m a -> TcRn m a
-addSrcLoc loc = updEnv (\env -> env { env_loc = loc })
+\begin{code}
+newUnique :: TcRnIf gbl lcl Unique
+newUnique = do { us <- newUniqueSupply ; 
+                return (uniqFromSupply us) }
+
+newUniqueSupply :: TcRnIf gbl lcl UniqSupply
+newUniqueSupply
+ = do { env <- getEnv ;
+       let { u_var = env_us env } ;
+       us <- readMutVar u_var ;
+       let { (us1, us2) = splitUniqSupply us } ;
+       writeMutVar u_var us1 ;
+       return us2 }
 \end{code}
 
+
+%************************************************************************
+%*                                                                     *
+               Debugging
+%*                                                                     *
+%************************************************************************
+
 \begin{code}
-getEps :: TcRn m ExternalPackageState
-getEps = do { env <- getTopEnv; readMutVar (top_eps env) }
+traceTc, traceRn :: SDoc -> TcRn ()
+traceRn      = dumpOptTcRn Opt_D_dump_rn_trace
+traceTc      = dumpOptTcRn Opt_D_dump_tc_trace
+traceSplice  = dumpOptTcRn Opt_D_dump_splices
+
+
+traceIf :: SDoc -> TcRnIf m n ()       
+traceIf      = dumpOptIf Opt_D_dump_if_trace
+traceHiDiffs = dumpOptIf Opt_D_dump_hi_diffs
+
+
+dumpOptIf :: DynFlag -> SDoc -> TcRnIf m n ()  -- No RdrEnv available, so qualify everything
+dumpOptIf flag doc = ifOptM flag $
+                    ioToIOEnv (printForUser stderr alwaysQualify doc)
+
+dumpOptTcRn :: DynFlag -> SDoc -> TcRn ()
+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 ;
+                   ioToTcRn (printForUser stderr (unQualInScope rdr_env) doc) }
+\end{code}
 
-setEps :: ExternalPackageState -> TcRn m ()
-setEps eps = do { env <- getTopEnv; writeMutVar (top_eps env) eps }
 
-getHpt :: TcRn m HomePackageTable
-getHpt = do { env <- getTopEnv; return (top_hpt env) }
+%************************************************************************
+%*                                                                     *
+               Typechecker global environment
+%*                                                                     *
+%************************************************************************
 
-getModule :: TcRn m Module
+\begin{code}
+getModule :: TcRn Module
 getModule = do { env <- getGblEnv; return (tcg_mod env) }
 
-getGlobalRdrEnv :: TcRn m GlobalRdrEnv
+getGlobalRdrEnv :: TcRn GlobalRdrEnv
 getGlobalRdrEnv = do { env <- getGblEnv; return (tcg_rdr_env env) }
 
-getFixityEnv :: TcRn m FixityEnv
+getImports :: TcRn ImportAvails
+getImports = do { env <- getGblEnv; return (tcg_imports env) }
+
+getFixityEnv :: TcRn FixityEnv
 getFixityEnv = do { env <- getGblEnv; return (tcg_fix_env env) }
 
-extendFixityEnv :: [(Name,FixitySig Name)] -> RnM a -> RnM a
+extendFixityEnv :: [(Name,FixItem)] -> RnM a -> RnM a
 extendFixityEnv new_bit
   = updGblEnv (\env@(TcGblEnv { tcg_fix_env = old_fix_env }) -> 
                env {tcg_fix_env = extendNameEnvList old_fix_env new_bit})           
 
-getDefaultTys :: TcRn m [Type]
+getDefaultTys :: TcRn (Maybe [Type])
 getDefaultTys = do { env <- getGblEnv; return (tcg_default env) }
 \end{code}
 
-\begin{code}
-getUsageVar :: TcRn m (TcRef Usages)
-getUsageVar = do { env <- getGblEnv; return (tcg_usages env) }
-
-getUsages :: TcRn m Usages
-getUsages = do { usg_var <- getUsageVar; readMutVar usg_var }
-
-updUsages :: (Usages -> Usages) -> TcRn m () 
-updUsages upd = do { usg_var <- getUsageVar ;
-                    usg <- readMutVar usg_var ;
-                    writeMutVar usg_var (upd usg) }
-\end{code}
-
-
 %************************************************************************
 %*                                                                     *
                Error management
@@ -309,74 +357,124 @@ updUsages upd = do { usg_var <- getUsageVar ;
 %************************************************************************
 
 \begin{code}
-getErrsVar :: TcRn m (TcRef Messages)
-getErrsVar = do { env <- getTopEnv; return (top_errs env) }
+getSrcSpanM :: TcRn SrcSpan
+       -- Avoid clash with Name.getSrcLoc
+getSrcSpanM = do { env <- getLclEnv; return (tcl_loc env) }
+
+addSrcSpan :: SrcSpan -> TcRn a -> TcRn a
+addSrcSpan loc = updLclEnv (\env -> env { tcl_loc = loc })
 
-setErrsVar :: TcRef Messages -> TcRn m a -> TcRn m a
-setErrsVar v = updEnv (\ env@(Env { env_top = top_env }) ->
-                        env { env_top = top_env { top_errs = v }})
+addLocM :: (a -> TcM b) -> Located a -> TcM b
+addLocM fn (L loc a) = addSrcSpan loc $ fn a
 
-addErr :: Message -> TcRn m ()
-addErr msg = do { loc <- getSrcLocM ; addErrAt loc msg }
+wrapLocM :: (a -> TcM b) -> Located a -> TcM (Located b)
+wrapLocM fn (L loc a) = addSrcSpan loc $ do b <- fn a; return (L loc b)
 
-addErrAt :: SrcLoc -> Message -> TcRn m ()
-addErrAt loc msg
+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}
+
+
+\begin{code}
+getErrsVar :: TcRn (TcRef Messages)
+getErrsVar = do { env <- getLclEnv; return (tcl_errs env) }
+
+setErrsVar :: TcRef Messages -> TcRn a -> TcRn a
+setErrsVar v = updLclEnv (\ env -> env { tcl_errs =  v })
+
+addErr :: Message -> TcRn ()
+addErr msg = do { loc <- getSrcSpanM ; 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 m ()
+addErrs :: [(SrcSpan,Message)] -> TcRn ()
 addErrs msgs = mappM_ add msgs
             where
               add (loc,msg) = addErrAt loc msg
 
-addWarn :: Message -> TcRn m ()
-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) }
 
-checkErr :: Bool -> Message -> TcRn m ()
+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)
 
-warnIf :: Bool -> Message -> TcRn m ()
+warnIf :: Bool -> Message -> TcRn ()
 warnIf True  msg = addWarn msg
 warnIf False msg = return ()
 
-addMessages :: Messages -> TcRn m ()
+addMessages :: Messages -> TcRn ()
 addMessages (m_warns, m_errs)
   = do { errs_var <- getErrsVar ;
         (warns, errs) <- readMutVar errs_var ;
         writeMutVar errs_var (warns `unionBags` m_warns,
                               errs  `unionBags` m_errs) }
 
-checkGHCI :: Message -> TcRn m ()      -- Check that GHCI is on
-                                       -- otherwise add the error message
-#ifdef GHCI 
-checkGHCI m = returnM ()
-#else
-checkGHCI m = addErr m
-#endif
+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}
 
 
 \begin{code}
-recoverM :: TcRn m r   -- Recovery action; do this if the main one fails
-        -> TcRn m r    -- Main action: do this first
-        -> TcRn m r
+recoverM :: TcRn r     -- Recovery action; do this if the main one fails
+        -> TcRn r      -- Main action: do this first
+        -> TcRn r
 recoverM recover thing 
-  = do { mb_res <- tryM thing ;
+  = do { mb_res <- try_m thing ;
         case mb_res of
           Left exn  -> recover
           Right res -> returnM res }
 
-tryTc :: TcRn m a -> TcRn m (Messages, Maybe a)
+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
@@ -387,17 +485,29 @@ tryTc :: TcRn m a -> TcRn m (Messages, Maybe a)
 tryTc m 
  = do {        errs_var <- newMutVar emptyMessages ;
        
-       mb_r <- tryM (setErrsVar errs_var m) ; 
+       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 new_errs -> Nothing
-                         | otherwise            -> Just r) 
+                 Left exn -> Nothing
+                 Right r | errorsFound dflags new_errs -> Nothing
+                         | otherwise                   -> Just r) 
    }
 
+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)
+
 tryTcLIE :: TcM a -> TcM (Messages, Maybe a)
 -- Just like tryTc, except that it ensures that the LIE
 -- for the thing is propagated only if there are no errors
@@ -408,7 +518,7 @@ tryTcLIE thing_inside
         return (errs, mb_r) }
 
 tryTcLIE_ :: TcM r -> TcM r -> TcM r
--- (tryM_ r m) tries m; if it succeeds it returns it,
+-- (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_ recover main
@@ -432,112 +542,24 @@ checkNoErrs main
           Nothing -> failM
    }
 
-ifErrsM :: TcRn m r -> TcRn m r -> TcRn m r
+ifErrsM :: TcRn r -> TcRn r -> TcRn r
 --     ifErrsM bale_out main
 -- does 'bale_out' if there are errors in errors collection
 -- otherwise does 'main'
 ifErrsM bale_out normal
  = do { errs_var <- getErrsVar ;
        msgs <- readMutVar errs_var ;
-       if errorsFound msgs then
+       dflags <- getDOpts ;
+       if errorsFound dflags msgs then
           bale_out
        else    
           normal }
 
-failIfErrsM :: TcRn m ()
+failIfErrsM :: TcRn ()
 -- Useful to avoid error cascades
 failIfErrsM = ifErrsM failM (return ())
 \end{code}
 
-\begin{code}
-forkM :: SDoc -> TcM a -> TcM (Maybe a)
--- Run thing_inside in an interleaved thread.  It gets a separate
---     * errs_var, and
---     * unique supply, 
--- but everything else is shared, so this is DANGEROUS.  
---
--- It returns Nothing if the computation fails
--- 
--- It's used for lazily type-checking interface
--- signatures, which is pretty benign
-
-forkM doc thing_inside
- = do {        us <- newUniqueSupply ;
-       unsafeInterleaveM $
-       do { us_var <- newMutVar us ;
-            (msgs, mb_res) <- tryTcLIE (setUsVar us_var thing_inside) ;
-            case mb_res of
-               Just r  -> return (Just r) 
-               Nothing -> do {
-                   -- Bleat about errors in the forked thread
-                   ioToTcRn (do { printErrs (hdr_doc defaultErrStyle) ;
-                                  printErrorsAndWarnings msgs }) ;
-                   return Nothing }
-       }}
-  where
-    hdr_doc = text "forkM failed:" <+> doc
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-               Unique supply
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-getUsVar :: TcRn m (TcRef UniqSupply)
-getUsVar = do { env <- getTopEnv; return (top_us env) }
-
-setUsVar :: TcRef UniqSupply -> TcRn m a -> TcRn m a
-setUsVar v = updEnv (\ env@(Env { env_top = top_env }) ->
-                      env { env_top = top_env { top_us = v }})
-
-newUnique :: TcRn m Unique
-newUnique = do { us <- newUniqueSupply ; 
-                return (uniqFromSupply us) }
-
-newUniqueSupply :: TcRn m UniqSupply
-newUniqueSupply
- = do { u_var <- getUsVar ;
-       us <- readMutVar u_var ;
-       let { (us1, us2) = splitUniqSupply us } ;
-       writeMutVar u_var us1 ;
-       return us2 }
-\end{code}
-
-
-\begin{code}
-getNameCache :: TcRn m NameCache
-getNameCache = do { TopEnv { top_nc = nc_var } <- getTopEnv; 
-                   readMutVar nc_var }
-
-setNameCache :: NameCache -> TcRn m ()
-setNameCache nc = do { TopEnv { top_nc = nc_var } <- getTopEnv; 
-                      writeMutVar nc_var nc }
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-               Debugging
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-traceTc, traceRn :: SDoc -> TcRn a ()
-traceRn      = dumpOptTcRn Opt_D_dump_rn_trace
-traceTc      = dumpOptTcRn Opt_D_dump_tc_trace
-traceHiDiffs = dumpOptTcRn Opt_D_dump_hi_diffs
-
-dumpOptTcRn :: DynFlag -> SDoc -> TcRn a ()
-dumpOptTcRn flag doc = ifOptM flag (dumpTcRn doc)
-
-dumpTcRn :: SDoc -> TcRn a ()
-dumpTcRn doc = do { rdr_env <- getGlobalRdrEnv ;
-                   ioToTcRn (printForUser stderr (unQualInScope rdr_env) doc) }
-\end{code}
-
 
 %************************************************************************
 %*                                                                     *
@@ -568,8 +590,14 @@ updCtxt upd = updLclEnv (\ env@(TcLclEnv { tcl_ctxt = ctxt }) ->
 
 getInstLoc :: InstOrigin -> TcM InstLoc
 getInstLoc origin
-  = do { loc <- getSrcLocM ; env <- getLclEnv ;
-        return (origin, loc, (tcl_ctxt env)) }
+  = do { loc <- getSrcSpanM ; env <- getLclEnv ;
+        return (InstLoc origin loc (tcl_ctxt env)) }
+
+addInstCtxt :: InstLoc -> TcM a -> TcM a
+-- 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)
 \end{code}
 
     The addErrTc functions add an error message, but do not cause failure.
@@ -586,14 +614,8 @@ addErrsTc err_msgs = mappM_ addErrTc err_msgs
 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 }
-
-addInstErrTcM :: InstLoc -> (TidyEnv, Message) -> TcM ()
-addInstErrTcM inst_loc@(_, loc, ctxt) (tidy_env, err_msg)
-  = add_err_tcm tidy_env err_msg loc full_ctxt
-  where
-    full_ctxt = (\env -> returnM (env, pprInstLoc inst_loc)) : ctxt
 \end{code}
 
 The failWith functions add an error message and cause failure
@@ -632,7 +654,7 @@ warnTc warn_if_true warn_msg
 \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 []
@@ -647,7 +669,7 @@ ctxt_to_use ctxt | opt_PprStyle_Debug = ctxt
 
 %************************************************************************
 %*                                                                     *
-            Other stuff specific to type checker
+            Type constraints (the so-called LIE)
 %*                                                                     *
 %************************************************************************
 
@@ -682,14 +704,7 @@ extendLIEs insts
         writeMutVar lie_var (mkLIE insts `plusLIE` lie) }
 \end{code}
 
-
 \begin{code}
-getStage :: TcM Stage
-getStage = do { env <- getLclEnv; return (tcl_level env) }
-
-setStage :: Stage -> TcM a -> TcM a 
-setStage s = updLclEnv (\ env -> env { tcl_level = s })
-
 setLclTypeEnv :: TcLclEnv -> TcM a -> TcM a
 -- Set the local type envt, but do *not* disturb other fields,
 -- notably the lie_var
@@ -703,29 +718,179 @@ setLclTypeEnv lcl_env thing_inside
 
 %************************************************************************
 %*                                                                     *
-            Stuff for the renamer's local env
+            Template Haskell context
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
-initRn :: RnMode -> RnM a -> TcRn m a
-initRn mode thing_inside
- = do { env <- getGblEnv ;
-       let { lcl_env = RnLclEnv {
-                            rn_mode = mode,
-                            rn_lenv = emptyRdrEnv }} ;
-       setLclEnv lcl_env thing_inside }
+getStage :: TcM ThStage
+getStage = do { env <- getLclEnv; return (tcl_th_ctxt env) }
+
+setStage :: ThStage -> TcM a -> TcM a 
+setStage s = updLclEnv (\ env -> env { tcl_th_ctxt = s })
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+            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}
 getLocalRdrEnv :: RnM LocalRdrEnv
-getLocalRdrEnv = do { env <- getLclEnv; return (rn_lenv env) }
+getLocalRdrEnv = do { env <- getLclEnv; return (tcl_rdr env) }
 
 setLocalRdrEnv :: LocalRdrEnv -> RnM a -> RnM a
 setLocalRdrEnv rdr_env thing_inside 
-  = updLclEnv (\env -> env {rn_lenv = rdr_env}) thing_inside
-
-getModeRn :: RnM RnMode
-getModeRn = do { env <- getLclEnv; return (rn_mode env) }
+  = updLclEnv (\env -> env {tcl_rdr = rdr_env}) thing_inside
 \end{code}
 
+
+%************************************************************************
+%*                                                                     *
+            Stuff for interface decls
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+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) }
+             ; get_type_env = readMutVar (tcg_type_env_var tcg_env) }
+       ; setEnvs (if_env, ()) thing_inside }
+
+initIfaceExtCore :: IfL a -> TcRn a
+initIfaceExtCore 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_lenv = IfLclEnv { if_mod     = moduleName mod,
+                                    if_tv_env  = emptyOccEnv,
+                                    if_id_env  = emptyOccEnv }
+         }
+       ; setEnvs (if_env, if_lenv) thing_inside }
+
+initIfaceCheck :: HscEnv -> IfG a -> IO a
+-- 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 } ;
+          }
+       ; initTcRnIf 'i' hsc_env gbl_env () do_this
+    }
+
+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  { 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 }
+          }
+       ; 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 } ;
+          }
+
+       -- 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
+
+
+--------------------
+forkM_maybe :: SDoc -> IfL a -> IfL (Maybe a)
+-- Run thing_inside in an interleaved thread.  
+-- It shares everything with the parent thread, so this is DANGEROUS.  
+--
+-- It returns Nothing if the computation fails
+-- 
+-- It's used for lazily type-checking interface
+-- signatures, which is pretty benign
+
+forkM_maybe doc thing_inside
+ = do {        unsafeInterleaveM $
+       do { traceIf (text "Starting fork {" <+> doc)
+          ; mb_res <- tryM thing_inside ;
+            case mb_res of
+               Right r  -> do  { traceIf (text "} ending fork" <+> doc)
+                               ; return (Just r) }
+               Left exn -> do {
+
+                   -- Bleat about errors in the forked thread, if -ddump-if-trace is on
+                   -- Otherwise we silently discard errors. Errors can legitimately
+                   -- happen when compiling interface signatures (see tcInterfaceSigs)
+                     ifOptM Opt_D_dump_if_trace 
+                            (print_errs (hang (text "forkM failed:" <+> doc)
+                                            4 (text (show exn))))
+
+                   ; traceIf (text "} ending fork (badly)" <+> doc)
+                   ; return Nothing }
+       }}
+  where
+    print_errs sdoc = ioToIOEnv (printErrs (sdoc defaultErrStyle))
+
+forkM :: SDoc -> IfL a -> IfL a
+forkM doc thing_inside
+ = do  { mb_res <- forkM_maybe doc thing_inside
+       ; return (case mb_res of 
+                       Nothing -> pprPanic "forkM" doc
+                       Just r  -> r) }
+\end{code}