[project @ 2002-09-13 15:02:25 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcEnv.lhs
index b1a9084..ec0e3b8 100644 (file)
 \begin{code}
 module TcEnv(
-       TcId, TcIdSet, 
-       TyThing(..), TyThingDetails(..), TcTyThing(..),
+       TyThing(..), TyThingDetails(..), TcTyThing(..), TcId,
 
-       -- Getting stuff from the environment
-       TcEnv, initTcEnv, 
-       tcEnvTyCons, tcEnvClasses, tcEnvIds, tcLEnvElts,
-       getTcGEnv,
-       
        -- Instance environment, and InstInfo type
        tcGetInstEnv, tcSetInstEnv, 
-       InstInfo(..), pprInstInfo,
+       InstInfo(..), pprInstInfo, pprInstInfoDetails,
        simpleInstInfoTy, simpleInstInfoTyCon, 
 
        -- Global environment
-       tcExtendGlobalEnv, tcExtendGlobalValEnv, tcExtendGlobalTypeEnv,
-       tcLookupTyCon, tcLookupClass, tcLookupGlobalId, tcLookupDataCon,
-       tcLookupGlobal_maybe, tcLookupGlobal, 
+       tcExtendGlobalEnv, 
+       tcExtendGlobalValEnv,
+       tcExtendGlobalTypeEnv,
+       tcLookupTyCon, tcLookupClass, tcLookupDataCon,
+       tcLookupGlobal_maybe, tcLookupGlobal, tcLookupGlobalId,
+       getInGlobalScope,
 
        -- Local environment
-       tcExtendKindEnv,  tcInLocalScope,
+       tcExtendKindEnv,     
        tcExtendTyVarEnv,    tcExtendTyVarEnv2, 
        tcExtendLocalValEnv, tcExtendLocalValEnv2, 
-       tcLookup, tcLookupLocalIds, tcLookup_maybe, tcLookupId,
+       tcLookup, tcLookupLocalIds, tcLookup_maybe, 
+       tcLookupId, tcLookupIdLvl, 
+       getLclEnvElts, getInLocalScope,
+
+       -- Instance environment
+       tcExtendLocalInstEnv, tcExtendInstEnv, 
+
+       -- Rules
+       tcExtendRules,
 
        -- Global type variables
        tcGetGlobalTyVars,
 
        -- Random useful things
-       RecTcEnv, tcLookupRecId, tcLookupRecId_maybe, 
+       RecTcGblEnv, tcLookupRecId_maybe, 
+
+       -- Template Haskell stuff
+       wellStaged, spliceOK, bracketOK, tcMetaTy, metaLevel,
 
        -- New Ids
        newLocalName, newDFunName,
 
        -- Misc
-       isLocalThing, tcSetEnv
+       isLocalThing
   ) where
 
 #include "HsVersions.h"
 
 import RnHsSyn         ( RenamedMonoBinds, RenamedSig )
-import TcMonad
+import HsSyn           ( RuleDecl(..), ifaceRuleDeclName )
+import TcRnMonad
 import TcMType         ( zonkTcTyVarsAndFV )
 import TcType          ( Type, ThetaType, TcKind, TcTyVar, TcTyVarSet, 
-                         tyVarsOfTypes, tcSplitDFunTy,
-                         getDFunTyKey, tcTyConAppTyCon
+                         tyVarsOfTypes, tcSplitDFunTy, mkGenTyConApp,
+                         getDFunTyKey, tcTyConAppTyCon, 
                        )
+import Rules           ( extendRuleBase )
 import Id              ( idName, isDataConWrapId_maybe )
 import Var             ( TyVar, Id, idType )
 import VarSet
+import CoreSyn         ( IdCoreRule )
 import DataCon         ( DataCon )
 import TyCon           ( TyCon, DataConDetails )
 import Class           ( Class, ClassOpItem )
 import Name            ( Name, NamedThing(..), 
-                         getSrcLoc, mkInternalName, isInternalName, nameIsLocalOrFrom
+                         getSrcLoc, mkInternalName, nameIsLocalOrFrom
                        )
-import NameEnv         ( NameEnv, lookupNameEnv, nameEnvElts, elemNameEnv,
-                         extendNameEnvList, emptyNameEnv, plusNameEnv )
+import NameEnv
 import OccName         ( mkDFunOcc, occNameString )
-import HscTypes                ( DFunId, 
-                         PackageTypeEnv, TypeEnv, 
-                         extendTypeEnvList, extendTypeEnvWithIds,
-                         typeEnvTyCons, typeEnvClasses, typeEnvIds,
-                         HomeSymbolTable
-                       )
+import HscTypes                ( DFunId, TypeEnv, extendTypeEnvList, 
+                         TyThing(..), ExternalPackageState(..) )
+import Rules           ( RuleBase )
+import BasicTypes      ( EP )
 import Module          ( Module )
-import InstEnv         ( InstEnv, emptyInstEnv )
-import HscTypes                ( lookupType, TyThing(..) )
+import InstEnv         ( InstEnv, extendInstEnv )
+import Maybes          ( seqMaybe )
 import SrcLoc          ( SrcLoc )
 import Outputable
-
-import DATA_IOREF      ( newIORef )
+import Maybe           ( isJust )
+import List            ( partition )
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
-\subsection{TcEnv}
+               Meta level
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
-type TcId    = Id                      -- Type may be a TcType
-type TcIdSet = IdSet
-
-data TcEnv
-  = TcEnv {
-       tcGST    :: Name -> Maybe TyThing,      -- The type environment at the moment we began this compilation
-
-       tcInsts  :: InstEnv,            -- All instances (both imported and in this module)
-
-       tcGEnv   :: TypeEnv,            -- The global type environment we've accumulated while
-                {- NameEnv TyThing-}   -- compiling this module:
-                                       --      types and classes (both imported and local)
-                                       --      imported Ids
-                                       -- (Ids defined in this module start in the local envt, 
-                                       --  though they move to the global envt during zonking)
-
-       tcLEnv   :: NameEnv TcTyThing,  -- The local type environment: Ids and TyVars
-                                       -- defined in this module
-
-       tcTyVars :: TcRef TcTyVarSet    -- The "global tyvars"
-                                       -- Namely, the in-scope TyVars bound in tcLEnv, plus the tyvars
-                                       -- mentioned in the types of Ids bound in tcLEnv
-                                       -- Why mutable? see notes with tcGetGlobalTyVars
-    }
-
+instance Outputable Stage where
+   ppr Comp         = text "Comp"
+   ppr (Brack l _ _) = text "Brack" <+> int l
+   ppr (Splice l)    = text "Splice" <+> int l
+
+
+metaLevel :: Stage -> Level
+metaLevel Comp         = topLevel
+metaLevel (Splice l)    = l
+metaLevel (Brack l _ _) = l
+
+wellStaged :: Level    -- Binding level
+          -> Level     -- Use level
+          -> Bool
+wellStaged bind_stage use_stage 
+  = bind_stage <= use_stage
+
+-- Indicates the legal transitions on bracket( [| |] ).
+bracketOK :: Stage -> Maybe Level
+bracketOK (Brack _ _ _) = Nothing      -- Bracket illegal inside a bracket
+bracketOK stage         = (Just (metaLevel stage + 1))
+
+-- Indicates the legal transitions on splice($).
+spliceOK :: Stage -> Maybe Level
+spliceOK (Splice _) = Nothing  -- Splice illegal inside splice
+spliceOK stage      = Just (metaLevel stage - 1)
+
+tcMetaTy :: Name -> TcM Type
+-- Given the name of a Template Haskell data type, 
+-- return the type
+-- E.g. given the name "Expr" return the type "Expr"
+tcMetaTy tc_name
+  = tcLookupTyCon tc_name      `thenM` \ t ->
+    returnM (mkGenTyConApp t [])
+       -- Use mkGenTyConApp because it might be a synonym
 \end{code}
 
-The Global-Env/Local-Env story
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-During type checking, we keep in the GlobalEnv
-       * All types and classes
-       * All Ids derived from types and classes (constructors, selectors)
-       * Imported Ids
-
-At the end of type checking, we zonk the local bindings,
-and as we do so we add to the GlobalEnv
-       * Locally defined top-level Ids
-
-Why?  Because they are now Ids not TcIds.  This final GlobalEnv is
-used thus:
-       a) fed back (via the knot) to typechecking the 
-          unfoldings of interface signatures
-
-       b) used to augment the GlobalSymbolTable
-
-
-\begin{code}
-initTcEnv :: HomeSymbolTable -> PackageTypeEnv -> IO TcEnv
-initTcEnv hst pte 
-  = do { gtv_var <- newIORef emptyVarSet ;
-        return (TcEnv { tcGST    = lookup,
-                        tcGEnv   = emptyNameEnv,
-                        tcInsts  = emptyInstEnv,
-                        tcLEnv   = emptyNameEnv,
-                        tcTyVars = gtv_var
-        })}
-  where
-    lookup name | isInternalName name = Nothing
-               | otherwise           = lookupType hst pte name
-
 
-tcEnvClasses env = typeEnvClasses (tcGEnv env)
-tcEnvTyCons  env = typeEnvTyCons  (tcGEnv env) 
-tcEnvIds     env = typeEnvIds     (tcGEnv env) 
-tcLEnvElts   env = nameEnvElts (tcLEnv env)
-
-getTcGEnv (TcEnv { tcGEnv = genv }) = genv
-
-tcInLocalScope :: TcEnv -> Name -> Bool
-tcInLocalScope env v = v `elemNameEnv` (tcLEnv env)
-\end{code}
-
-\begin{code}
-data TcTyThing
-  = AGlobal TyThing            -- Used only in the return type of a lookup
-  | ATcId   TcId               -- Ids defined in this module
-  | ATyVar  TyVar              -- Type variables
-  | AThing  TcKind             -- Used temporarily, during kind checking
--- Here's an example of how the AThing guy is used
--- Suppose we are checking (forall a. T a Int):
---     1. We first bind (a -> AThink kv), where kv is a kind variable. 
---     2. Then we kind-check the (T a Int) part.
---     3. Then we zonk the kind variable.
---     4. Now we know the kind for 'a', and we add (a -> ATyVar a::K) to the environment
-
-\end{code}
+%************************************************************************
+%*                                                                     *
+\subsection{TyThingDetails}
+%*                                                                     *
+%************************************************************************
 
 This data type is used to help tie the knot
  when type checking type and class declarations
 
 \begin{code}
-data TyThingDetails = SynTyDetails Type
-                   | DataTyDetails ThetaType (DataConDetails DataCon) [Id]
-                   | ClassDetails ThetaType [Id] [ClassOpItem] DataCon
+data TyThingDetails = SynTyDetails  Type
+                   | DataTyDetails ThetaType (DataConDetails DataCon) [Id] (Maybe (EP Id))
+                   | ClassDetails  ThetaType [Id] [ClassOpItem] DataCon Name
+                               -- The Name is the Name of the implicit TyCon for the class
                    | ForeignTyDetails  -- Nothing yet
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
 \subsection{Basic lookups}
@@ -184,38 +152,15 @@ data TyThingDetails = SynTyDetails Type
 %************************************************************************
 
 \begin{code}
-lookup_global :: TcEnv -> Name -> Maybe TyThing
-       -- Try the global envt and then the global symbol table
-lookup_global env name 
-  = case lookupNameEnv (tcGEnv env) name of
-       Just thing -> Just thing
-       Nothing    -> tcGST env name
-
-lookup_local :: TcEnv -> Name -> Maybe TcTyThing
-       -- Try the local envt and then try the global
-lookup_local env name
-  = case lookupNameEnv (tcLEnv env) name of
-       Just thing -> Just thing
-       Nothing    -> case lookup_global env name of
-                       Just thing -> Just (AGlobal thing)
-                       Nothing    -> Nothing
-\end{code}
-
-\begin{code}
-type RecTcEnv = TcEnv
+type RecTcGblEnv = TcGblEnv
 -- This environment is used for getting the 'right' IdInfo 
 -- on imported things and for looking up Ids in unfoldings
 -- The environment doesn't have any local Ids in it
 
-tcLookupRecId_maybe :: RecTcEnv -> Name -> Maybe Id
+tcLookupRecId_maybe :: RecTcGblEnv -> Name -> Maybe Id
 tcLookupRecId_maybe env name = case lookup_global env name of
                                   Just (AnId id) -> Just id
                                   other          -> Nothing
-
-tcLookupRecId ::  RecTcEnv -> Name -> Id
-tcLookupRecId env name = case lookup_global env name of
-                               Just (AnId id) -> id
-                               Nothing        -> pprPanic "tcLookupRecId" (ppr name)
 \end{code}
 
 %************************************************************************
@@ -227,10 +172,10 @@ tcLookupRecId env name = case lookup_global env name of
 Constructing new Ids
 
 \begin{code}
-newLocalName :: Name -> NF_TcM Name
+newLocalName :: Name -> TcM Name
 newLocalName name      -- Make a clone
-  = tcGetUnique                `thenNF_Tc` \ uniq ->
-    returnNF_Tc (mkInternalName uniq (getOccName name) (getSrcLoc name))
+  = newUnique          `thenM` \ uniq ->
+    returnM (mkInternalName uniq (getOccName name) (getSrcLoc name))
 \end{code}
 
 Make a name for the dict fun for an instance decl.
@@ -238,10 +183,10 @@ It's a *local* name for the moment.  The CoreTidy pass
 will externalise it.
 
 \begin{code}
-newDFunName :: Class -> [Type] -> SrcLoc -> NF_TcM Name
+newDFunName :: Class -> [Type] -> SrcLoc -> TcM Name
 newDFunName clas (ty:_) loc
-  = tcGetUnique                        `thenNF_Tc` \ uniq ->
-    returnNF_Tc (mkInternalName uniq (mkDFunOcc dfun_string) loc)
+  = newUnique                  `thenM` \ uniq ->
+    returnM (mkInternalName uniq (mkDFunOcc dfun_string) loc)
   where
        -- Any string that is somewhat unique will do
     dfun_string = occNameString (getOccName clas) ++ occNameString (getDFunTyKey ty)
@@ -262,94 +207,92 @@ isLocalThing mod thing = nameIsLocalOrFrom mod (getName thing)
 
 \begin{code}
 tcExtendGlobalEnv :: [TyThing] -> TcM r -> TcM r
+  -- Given a mixture of Ids, TyCons, Classes, perhaps from the
+  -- module being compiled, perhaps from a package module,
+  -- extend the global environment, and update the EPS
 tcExtendGlobalEnv things thing_inside
-  = tcGetEnv                           `thenNF_Tc` \ env ->
-    let
-       ge' = extendTypeEnvList (tcGEnv env) things
-    in
-    tcSetEnv (env {tcGEnv = ge'}) thing_inside
+   = do        { eps <- getEps
+       ; hpt <- getHpt
+       ; env <- getGblEnv
+       ; let mod = tcg_mod env
+             (lcl_things, pkg_things) = partition (isLocalThing mod) things
+             ge'  = extendTypeEnvList (tcg_type_env env) lcl_things
+             eps' = eps { eps_PTE = extendTypeEnvList (eps_PTE eps) pkg_things }
+             ist' = mkImpTypeEnv eps' hpt
+       ; setEps eps'
+       ; setGblEnv (env {tcg_type_env = ge', tcg_ist = ist'}) thing_inside }
 
+tcExtendGlobalValEnv :: [Id] -> TcM a -> TcM a
+  -- Same deal as tcExtendGlobalEnv, but for Ids
+tcExtendGlobalValEnv ids thing_inside 
+  = tcExtendGlobalEnv [AnId id | id <- ids] thing_inside
 
 tcExtendGlobalTypeEnv :: TypeEnv -> TcM r -> TcM r
+  -- Top-level things of the interactive context
+  -- No need to extend the package env
 tcExtendGlobalTypeEnv extra_env thing_inside
-  = tcGetEnv                           `thenNF_Tc` \ env ->
-    let
-       ge' = tcGEnv env `plusNameEnv` extra_env
-    in
-    tcSetEnv (env {tcGEnv = ge'}) thing_inside
-
-tcExtendGlobalValEnv :: [Id] -> TcM a -> TcM a
-tcExtendGlobalValEnv ids thing_inside
-  = tcGetEnv                           `thenNF_Tc` \ env ->
-    let
-       ge' = extendTypeEnvWithIds (tcGEnv env) ids
-    in
-    tcSetEnv (env {tcGEnv = ge'}) thing_inside
+ = do { env <- getGblEnv 
+      ; let ge' = tcg_type_env env `plusNameEnv` extra_env 
+      ; setGblEnv (env {tcg_type_env = ge'}) thing_inside }
 \end{code}
 
 
 \begin{code}
-tcLookupGlobal_maybe :: Name -> NF_TcM (Maybe TyThing)
+lookup_global :: TcGblEnv -> Name -> Maybe TyThing
+       -- Try the global envt and then the global symbol table
+lookup_global env name 
+  = lookupNameEnv (tcg_type_env env) name 
+       `seqMaybe`
+    tcg_ist env name
+
+tcLookupGlobal_maybe :: Name -> TcRn m (Maybe TyThing)
 tcLookupGlobal_maybe name
-  = tcGetEnv           `thenNF_Tc` \ env ->
-    returnNF_Tc (lookup_global env name)
+  = getGblEnv          `thenM` \ env ->
+    returnM (lookup_global env name)
 \end{code}
 
 A variety of global lookups, when we know what we are looking for.
 
 \begin{code}
-tcLookupGlobal :: Name -> NF_TcM TyThing
+tcLookupGlobal :: Name -> TcM TyThing
 tcLookupGlobal name
-  = tcLookupGlobal_maybe name  `thenNF_Tc` \ maybe_thing ->
+  = tcLookupGlobal_maybe name  `thenM` \ maybe_thing ->
     case maybe_thing of
-       Just thing -> returnNF_Tc thing
+       Just thing -> returnM thing
        other      -> notFound "tcLookupGlobal" name
 
-tcLookupGlobalId :: Name -> NF_TcM Id
+tcLookupGlobalId :: Name -> TcM Id
 tcLookupGlobalId name
-  = tcLookupGlobal_maybe name  `thenNF_Tc` \ maybe_id ->
-    case maybe_id of
-       Just (AnId id) -> returnNF_Tc id
-       other          -> notFound "tcLookupGlobalId" name
-       
+  = tcLookupGlobal_maybe name  `thenM` \ maybe_thing ->
+    case maybe_thing of
+       Just (AnId id) -> returnM id
+       other          -> notFound "tcLookupGlobal" name
+
 tcLookupDataCon :: Name -> TcM DataCon
 tcLookupDataCon con_name
-  = tcLookupGlobalId con_name          `thenNF_Tc` \ con_id ->
+  = tcLookupGlobalId con_name  `thenM` \ con_id ->
     case isDataConWrapId_maybe con_id of
-       Just data_con -> returnTc data_con
+       Just data_con -> returnM data_con
        Nothing       -> failWithTc (badCon con_id)
 
-
-tcLookupClass :: Name -> NF_TcM Class
+tcLookupClass :: Name -> TcM Class
 tcLookupClass name
-  = tcLookupGlobal_maybe name  `thenNF_Tc` \ maybe_clas ->
+  = tcLookupGlobal_maybe name  `thenM` \ maybe_clas ->
     case maybe_clas of
-       Just (AClass clas) -> returnNF_Tc clas
+       Just (AClass clas) -> returnM clas
        other              -> notFound "tcLookupClass" name
        
-tcLookupTyCon :: Name -> NF_TcM TyCon
+tcLookupTyCon :: Name -> TcM TyCon
 tcLookupTyCon name
-  = tcLookupGlobal_maybe name  `thenNF_Tc` \ maybe_tc ->
+  = tcLookupGlobal_maybe name  `thenM` \ maybe_tc ->
     case maybe_tc of
-       Just (ATyCon tc) -> returnNF_Tc tc
+       Just (ATyCon tc) -> returnM tc
        other            -> notFound "tcLookupTyCon" name
 
-tcLookupId :: Name -> NF_TcM Id
-tcLookupId name
-  = tcLookup name      `thenNF_Tc` \ thing -> 
-    case thing of
-       ATcId tc_id       -> returnNF_Tc tc_id
-       AGlobal (AnId id) -> returnNF_Tc id
-       other             -> pprPanic "tcLookupId" (ppr name)
 
-tcLookupLocalIds :: [Name] -> NF_TcM [TcId]
-tcLookupLocalIds ns
-  = tcGetEnv           `thenNF_Tc` \ env ->
-    returnNF_Tc (map (lookup (tcLEnv env)) ns)
-  where
-    lookup lenv name = case lookupNameEnv lenv name of
-                       Just (ATcId id) -> id
-                       other           -> pprPanic "tcLookupLocalIds" (ppr name)
+getInGlobalScope :: TcRn m (Name -> Bool)
+getInGlobalScope = do { gbl_env <- getGblEnv ;
+                       return (\n -> isJust (lookup_global gbl_env n)) }
 \end{code}
 
 
@@ -360,30 +303,74 @@ tcLookupLocalIds ns
 %************************************************************************
 
 \begin{code}
-tcLookup_maybe :: Name -> NF_TcM (Maybe TcTyThing)
+tcLookup_maybe :: Name -> TcM (Maybe TcTyThing)
 tcLookup_maybe name
-  = tcGetEnv           `thenNF_Tc` \ env ->
-    returnNF_Tc (lookup_local env name)
-
-tcLookup :: Name -> NF_TcM TcTyThing
+  = getLclEnv          `thenM` \ local_env ->
+    case lookupNameEnv (tcl_env local_env) name of
+       Just thing -> returnM (Just thing)
+       Nothing    -> tcLookupGlobal_maybe name `thenM` \ mb_res ->
+                     returnM (case mb_res of
+                                Just thing -> Just (AGlobal thing)
+                                Nothing    -> Nothing)
+
+tcLookup :: Name -> TcM TcTyThing
 tcLookup name
-  = tcLookup_maybe name                `thenNF_Tc` \ maybe_thing ->
+  = tcLookup_maybe name                `thenM` \ maybe_thing ->
     case maybe_thing of
-       Just thing -> returnNF_Tc thing
+       Just thing -> returnM thing
        other      -> notFound "tcLookup" name
        -- Extract the IdInfo from an IfaceSig imported from an interface file
-\end{code}
 
+tcLookupId :: Name -> TcM Id
+-- Used when we aren't interested in the binding level
+tcLookupId name
+  = tcLookup name      `thenM` \ thing -> 
+    case thing of
+       ATcId tc_id lvl   -> returnM tc_id
+       AGlobal (AnId id) -> returnM id
+       other             -> pprPanic "tcLookupId" (ppr name)
+
+tcLookupIdLvl :: Name -> TcM (Id, Level)
+tcLookupIdLvl name
+  = tcLookup name      `thenM` \ thing -> 
+    case thing of
+       ATcId tc_id lvl   -> returnM (tc_id, lvl)
+       AGlobal (AnId id) -> returnM (id, impLevel)
+       other             -> pprPanic "tcLookupIdLvl" (ppr name)
+
+tcLookupLocalIds :: [Name] -> TcM [TcId]
+-- We expect the variables to all be bound, and all at
+-- the same level as the lookup.  Only used in one place...
+tcLookupLocalIds ns
+  = getLclEnv          `thenM` \ env ->
+    returnM (map (lookup (tcl_env env) (metaLevel (tcl_level env))) ns)
+  where
+    lookup lenv lvl name 
+       = case lookupNameEnv lenv name of
+               Just (ATcId id lvl1) -> ASSERT( lvl == lvl1 ) id
+               other                -> pprPanic "tcLookupLocalIds" (ppr name)
+
+getLclEnvElts :: TcM [TcTyThing]
+getLclEnvElts = getLclEnv      `thenM` \ env ->
+               return (nameEnvElts (tcl_env env))
+
+getInLocalScope :: TcM (Name -> Bool)
+  -- Ids only
+getInLocalScope = getLclEnv    `thenM` \ env ->
+                 let 
+                       lcl_env = tcl_env env
+                 in
+                 return (`elemNameEnv` lcl_env)
+\end{code}
 
 \begin{code}
 tcExtendKindEnv :: [(Name,TcKind)] -> TcM r -> TcM r
 tcExtendKindEnv pairs thing_inside
-  = tcGetEnv                           `thenNF_Tc` \ env ->
-    let
-       le' = extendNameEnvList (tcLEnv env) [(n, AThing k) | (n,k) <- pairs]
+  = updLclEnv upd thing_inside
+  where
+    upd lcl_env = lcl_env { tcl_env = extend (tcl_env lcl_env) }
+    extend env = extendNameEnvList env [(n, AThing k) | (n,k) <- pairs]
        -- No need to extend global tyvars for kind checking
-    in
-    tcSetEnv (env {tcLEnv = le'}) thing_inside
     
 tcExtendTyVarEnv :: [TyVar] -> TcM r -> TcM r
 tcExtendTyVarEnv tvs thing_inside
@@ -396,7 +383,7 @@ tcExtendTyVarEnv2 tv_pairs thing_inside
                     thing_inside
 
 tc_extend_tv_env binds tyvars thing_inside
-  = tcGetEnv                   `thenNF_Tc` \ env@(TcEnv {tcLEnv = le, tcTyVars = gtvs}) ->
+  = getLclEnv     `thenM` \ env@(TcLclEnv {tcl_env = le, tcl_tyvars = gtvs}) ->
     let
        le'        = extendNameEnvList le binds
        new_tv_set = mkVarSet tyvars
@@ -407,33 +394,35 @@ tc_extend_tv_env binds tyvars thing_inside
        -- Here, g mustn't be generalised.  This is also important during
        -- class and instance decls, when we mustn't generalise the class tyvars
        -- when typechecking the methods.
-    tc_extend_gtvs gtvs new_tv_set             `thenNF_Tc` \ gtvs' ->
-    tcSetEnv (env {tcLEnv = le', tcTyVars = gtvs'}) thing_inside
+    tc_extend_gtvs gtvs new_tv_set             `thenM` \ gtvs' ->
+    setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside
 \end{code}
 
 
 \begin{code}
 tcExtendLocalValEnv :: [TcId] -> TcM a -> TcM a
 tcExtendLocalValEnv ids thing_inside
-  = tcGetEnv           `thenNF_Tc` \ env ->
+  = getLclEnv          `thenM` \ env ->
     let
        extra_global_tyvars = tyVarsOfTypes [idType id | id <- ids]
-       extra_env           = [(idName id, ATcId id) | id <- ids]
-       le'                 = extendNameEnvList (tcLEnv env) extra_env
+       lvl                 = metaLevel (tcl_level env)
+       extra_env           = [(idName id, ATcId id lvl) | id <- ids]
+       le'                 = extendNameEnvList (tcl_env env) extra_env
     in
-    tc_extend_gtvs (tcTyVars env) extra_global_tyvars  `thenNF_Tc` \ gtvs' ->
-    tcSetEnv (env {tcLEnv = le', tcTyVars = gtvs'}) thing_inside
+    tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars        `thenM` \ gtvs' ->
+    setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside
 
 tcExtendLocalValEnv2 :: [(Name,TcId)] -> TcM a -> TcM a
 tcExtendLocalValEnv2 names_w_ids thing_inside
-  = tcGetEnv           `thenNF_Tc` \ env ->
+  = getLclEnv          `thenM` \ env ->
     let
        extra_global_tyvars = tyVarsOfTypes [idType id | (name,id) <- names_w_ids]
-       extra_env           = [(name, ATcId id) | (name,id) <- names_w_ids]
-       le'                 = extendNameEnvList (tcLEnv env) extra_env
+       lvl                 = metaLevel (tcl_level env)
+       extra_env           = [(name, ATcId id lvl) | (name,id) <- names_w_ids]
+       le'                 = extendNameEnvList (tcl_env env) extra_env
     in
-    tc_extend_gtvs (tcTyVars env) extra_global_tyvars  `thenNF_Tc` \ gtvs' ->
-    tcSetEnv (env {tcLEnv = le', tcTyVars = gtvs'}) thing_inside
+    tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars        `thenM` \ gtvs' ->
+    setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside
 \end{code}
 
 
@@ -445,8 +434,8 @@ tcExtendLocalValEnv2 names_w_ids thing_inside
 
 \begin{code}
 tc_extend_gtvs gtvs extra_global_tvs
-  = tcReadMutVar gtvs                  `thenNF_Tc` \ global_tvs ->
-    tcNewMutVar (global_tvs `unionVarSet` extra_global_tvs)
+  = readMutVar gtvs            `thenM` \ global_tvs ->
+    newMutVar (global_tvs `unionVarSet` extra_global_tvs)
 \end{code}
 
 @tcGetGlobalTyVars@ returns a fully-zonked set of tyvars free in the environment.
@@ -454,13 +443,13 @@ To improve subsequent calls to the same function it writes the zonked set back i
 the environment.
 
 \begin{code}
-tcGetGlobalTyVars :: NF_TcM TcTyVarSet
+tcGetGlobalTyVars :: TcM TcTyVarSet
 tcGetGlobalTyVars
-  = tcGetEnv                                   `thenNF_Tc` \ (TcEnv {tcTyVars = gtv_var}) ->
-    tcReadMutVar gtv_var                       `thenNF_Tc` \ gbl_tvs ->
-    zonkTcTyVarsAndFV (varSetElems gbl_tvs)    `thenNF_Tc` \ gbl_tvs' ->
-    tcWriteMutVar gtv_var gbl_tvs'             `thenNF_Tc_` 
-    returnNF_Tc gbl_tvs'
+  = getLclEnv                                  `thenM` \ (TcLclEnv {tcl_tyvars = gtv_var}) ->
+    readMutVar gtv_var                         `thenM` \ gbl_tvs ->
+    zonkTcTyVarsAndFV (varSetElems gbl_tvs)    `thenM` \ gbl_tvs' ->
+    writeMutVar gtv_var gbl_tvs'               `thenM_` 
+    returnM gbl_tvs'
 \end{code}
 
 
@@ -471,15 +460,96 @@ tcGetGlobalTyVars
 %************************************************************************
 
 \begin{code}
-tcGetInstEnv :: NF_TcM InstEnv
-tcGetInstEnv = tcGetEnv        `thenNF_Tc` \ env -> 
-              returnNF_Tc (tcInsts env)
+tcGetInstEnv :: TcM InstEnv
+tcGetInstEnv = getGblEnv       `thenM` \ env -> 
+              returnM (tcg_inst_env env)
 
 tcSetInstEnv :: InstEnv -> TcM a -> TcM a
 tcSetInstEnv ie thing_inside
-  = tcGetEnv   `thenNF_Tc` \ env ->
-    tcSetEnv (env {tcInsts = ie}) thing_inside
-\end{code}    
+  = getGblEnv  `thenM` \ env ->
+    setGblEnv (env {tcg_inst_env = ie}) thing_inside
+
+tcExtendInstEnv :: [DFunId] -> TcM a -> TcM a
+       -- Add instances from local or imported
+       -- instances, and refresh the instance-env cache
+tcExtendInstEnv dfuns thing_inside
+ = do { dflags <- getDOpts
+      ; eps <- getEps
+      ; env <- getGblEnv
+      ; let
+         -- Extend the total inst-env with the new dfuns
+         (inst_env', errs) = extendInstEnv dflags (tcg_inst_env env) dfuns
+  
+         -- Sort the ones from this module from the others
+         (lcl_dfuns, pkg_dfuns) = partition (isLocalThing mod) dfuns
+         mod = tcg_mod env
+  
+         -- And add the pieces to the right places
+                 (eps_inst_env', _) = extendInstEnv dflags (eps_inst_env eps) pkg_dfuns
+         eps'               = eps { eps_inst_env = eps_inst_env' }
+  
+         env'  = env { tcg_inst_env = inst_env', 
+                       tcg_insts = lcl_dfuns ++ tcg_insts env }
+
+      ; traceDFuns dfuns
+      ; addErrs errs
+      ; setEps eps'
+      ; setGblEnv env' thing_inside }
+
+tcExtendLocalInstEnv :: [InstInfo] -> TcM a -> TcM a
+  -- Special case for local instance decls
+tcExtendLocalInstEnv infos thing_inside
+ = do { dflags <- getDOpts
+      ; env <- getGblEnv
+      ; let
+         dfuns             = map iDFunId infos
+         (inst_env', errs) = extendInstEnv dflags (tcg_inst_env env) dfuns
+         env'              = env { tcg_inst_env = inst_env', 
+                                   tcg_insts = dfuns ++ tcg_insts env }
+      ; traceDFuns dfuns
+      ; addErrs errs
+      ; setGblEnv env' thing_inside }
+
+traceDFuns dfuns
+  = traceTc (text "Adding instances:" <+> vcat (map pp dfuns))
+  where
+    pp dfun   = ppr dfun <+> dcolon <+> ppr (idType dfun)
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+\subsection{Rules}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+tcExtendRules :: [RuleDecl Id] -> TcM a -> TcM a
+       -- Just pop the new rules into the EPS and envt resp
+       -- All the rules come from an interface file, not soruce
+       -- Nevertheless, some may be for this module, if we read
+       -- its interface instead of its source code
+tcExtendRules rules thing_inside
+ = do { eps <- getEps
+      ; env <- getGblEnv
+      ; let
+         (lcl_rules, pkg_rules) = partition is_local_rule rules
+         is_local_rule = isLocalThing mod . ifaceRuleDeclName
+         mod = tcg_mod env
+
+         core_rules = [(id,rule) | IfaceRuleOut id rule <- pkg_rules]
+         eps'   = eps { eps_rule_base = addIfaceRules (eps_rule_base eps) core_rules }
+                 -- All the rules from an interface are of the IfaceRuleOut form
+
+         env' = env { tcg_rules = lcl_rules ++ tcg_rules env }
+
+      ; setEps eps' 
+      ; setGblEnv env' thing_inside }
+
+addIfaceRules :: RuleBase -> [IdCoreRule] -> RuleBase
+addIfaceRules rule_base rules
+  = foldl extendRuleBase rule_base rules
+\end{code}
 
 
 %************************************************************************
@@ -513,6 +583,8 @@ data InstInfo
     }
 
 pprInstInfo info = vcat [ptext SLIT("InstInfo:") <+> ppr (idType (iDFunId info))]
+pprInstInfoDetails (InstInfo { iBinds = b }) = ppr b
+pprInstInfoDetails (NewTypeDerived _)       = text "Derived from the represenation type"
 
 simpleInstInfoTy :: InstInfo -> Type
 simpleInstInfoTy info = case tcSplitDFunTy (idType (iDFunId info)) of