[project @ 2002-10-11 16:45:16 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcEnv.lhs
index 8e546fe..ec0e3b8 100644 (file)
 \begin{code}
 module TcEnv(
-       TcId, TcIdSet, tcInstId,
-       tcLookupDataCon,
+       TyThing(..), TyThingDetails(..), TcTyThing(..), TcId,
 
-       TcEnv, ValueEnv, TcTyThing(..),
+       -- Instance environment, and InstInfo type
+       tcGetInstEnv, tcSetInstEnv, 
+       InstInfo(..), pprInstInfo, pprInstInfoDetails,
+       simpleInstInfoTy, simpleInstInfoTyCon, 
 
-       initEnv, getEnvTyCons, getEnvClasses, getAllEnvTyCons,
-       
-        tcExtendUVarEnv, tcLookupUVar,
+       -- Global environment
+       tcExtendGlobalEnv, 
+       tcExtendGlobalValEnv,
+       tcExtendGlobalTypeEnv,
+       tcLookupTyCon, tcLookupClass, tcLookupDataCon,
+       tcLookupGlobal_maybe, tcLookupGlobal, tcLookupGlobalId,
+       getInGlobalScope,
+
+       -- Local environment
+       tcExtendKindEnv,     
+       tcExtendTyVarEnv,    tcExtendTyVarEnv2, 
+       tcExtendLocalValEnv, tcExtendLocalValEnv2, 
+       tcLookup, tcLookupLocalIds, tcLookup_maybe, 
+       tcLookupId, tcLookupIdLvl, 
+       getLclEnvElts, getInLocalScope,
 
-       tcExtendTyVarEnv, tcExtendTyVarEnvForMeths, tcExtendTypeEnv, tcGetInScopeTyVars,
+       -- Instance environment
+       tcExtendLocalInstEnv, tcExtendInstEnv, 
 
-       tcLookupTy,
-       tcLookupTyCon, tcLookupTyConByKey, 
-       tcLookupClass, tcLookupClassByKey, tcLookupClassByKey_maybe,
+       -- Rules
+       tcExtendRules,
 
-       tcExtendGlobalValEnv, tcExtendLocalValEnv,
-       tcGetValueEnv,        tcSetValueEnv, 
-       tcAddImportedIdInfo,
+       -- Global type variables
+       tcGetGlobalTyVars,
 
-       tcLookupValue,      tcLookupValueMaybe, 
-       tcLookupValueByKey, tcLookupValueByKeyMaybe,
-       explicitLookupValueByKey, explicitLookupValue,
-       valueEnvIds,
+       -- Random useful things
+       RecTcGblEnv, tcLookupRecId_maybe, 
 
-       newLocalId, newSpecPragmaId,
-       tcGetGlobalTyVars, tcExtendGlobalTyVars,
+       -- Template Haskell stuff
+       wellStaged, spliceOK, bracketOK, tcMetaTy, metaLevel,
 
-       badCon, badPrimOp
+       -- New Ids
+       newLocalName, newDFunName,
+
+       -- Misc
+       isLocalThing
   ) where
 
 #include "HsVersions.h"
 
-import HsTypes ( HsTyVar, getTyVarName )
-import Id      ( mkUserLocal, isDataConWrapId_maybe )
-import MkId    ( mkSpecPragmaId )
-import Var     ( TyVar, Id, setVarName,
-                 idType, lazySetIdInfo, idInfo, tyVarKind, UVar,
-               )
-import TcType  ( TcType, TcTyVar, TcTyVarSet, TcThetaType,
-                 tcInstTyVars, zonkTcTyVars,
-                 TcKind, kindToTcKind
-               )
-import VarEnv
+import RnHsSyn         ( RenamedMonoBinds, RenamedSig )
+import HsSyn           ( RuleDecl(..), ifaceRuleDeclName )
+import TcRnMonad
+import TcMType         ( zonkTcTyVarsAndFV )
+import TcType          ( Type, ThetaType, TcKind, TcTyVar, TcTyVarSet, 
+                         tyVarsOfTypes, tcSplitDFunTy, mkGenTyConApp,
+                         getDFunTyKey, tcTyConAppTyCon, 
+                       )
+import Rules           ( extendRuleBase )
+import Id              ( idName, isDataConWrapId_maybe )
+import Var             ( TyVar, Id, idType )
 import VarSet
-import Type    ( Kind, superKind,
-                 tyVarsOfType, tyVarsOfTypes, mkTyVarTy,
-                 splitForAllTys, splitRhoTy, splitFunTys,
-                 splitAlgTyConApp_maybe, getTyVar
-               )
-import Subst   ( substTy )
-import UsageSPUtils ( unannotTy )
-import DataCon ( DataCon )
-import TyCon   ( TyCon, tyConKind, tyConArity, isSynTyCon )
-import Class   ( Class, classTyCon )
-
-import TcMonad
-
-import BasicTypes      ( Arity )
-import IdInfo          ( vanillaIdInfo )
-import Name            ( Name, OccName, nameOccName, getSrcLoc,
-                         maybeWiredInTyConName, maybeWiredInIdName, isLocallyDefined,
-                         NamedThing(..)
+import CoreSyn         ( IdCoreRule )
+import DataCon         ( DataCon )
+import TyCon           ( TyCon, DataConDetails )
+import Class           ( Class, ClassOpItem )
+import Name            ( Name, NamedThing(..), 
+                         getSrcLoc, mkInternalName, nameIsLocalOrFrom
                        )
-import Unique          ( pprUnique10, Unique, Uniquable(..) )
-import FiniteMap       ( lookupFM, addToFM )
-import UniqFM
-import Unique          ( Uniquable(..) )
-import Util            ( zipEqual, zipWith3Equal, mapAccumL )
-import Bag             ( bagToList )
-import Maybes          ( maybeToBool, catMaybes )
+import NameEnv
+import OccName         ( mkDFunOcc, occNameString )
+import HscTypes                ( DFunId, TypeEnv, extendTypeEnvList, 
+                         TyThing(..), ExternalPackageState(..) )
+import Rules           ( RuleBase )
+import BasicTypes      ( EP )
+import Module          ( Module )
+import InstEnv         ( InstEnv, extendInstEnv )
+import Maybes          ( seqMaybe )
 import SrcLoc          ( SrcLoc )
-import FastString      ( FastString )
 import Outputable
+import Maybe           ( isJust )
+import List            ( partition )
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
-\subsection{TcId}
+               Meta level
 %*                                                                     *
 %************************************************************************
 
-
 \begin{code}
-type TcId    = Id                      -- Type may be a TcType
-type TcIdSet = IdSet
+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}
 
-tcLookupDataCon :: Name -> TcM s (DataCon, [TcType], TcType)
-tcLookupDataCon con_name
-  = tcLookupValue con_name             `thenNF_Tc` \ con_id ->
-    case isDataConWrapId_maybe con_id of {
-       Nothing -> failWithTc (badCon con_id);
-       Just data_con ->
-
-    tcInstId con_id                    `thenNF_Tc` \ (_, _, con_tau) ->
-            -- Ignore the con_theta; overloaded constructors only
-            -- behave differently when called, not when used for
-            -- matching.
-    let
-       (arg_tys, result_ty) = splitFunTys con_tau
-    in
-    ASSERT( maybeToBool (splitAlgTyConApp_maybe result_ty) )
-    returnTc (data_con, arg_tys, result_ty) }
-
--- A useful function that takes an occurrence of a global thing
--- and instantiates its type with fresh type variables
-tcInstId :: Id
-        -> NF_TcM s ([TcTyVar],        -- It's instantiated type
-                     TcThetaType,      --
-                     TcType)           --
-tcInstId id
-  = let
-      (tyvars, rho) = splitForAllTys (unannotTy (idType id))
-    in
-    tcInstTyVars tyvars                `thenNF_Tc` \ (tyvars', arg_tys, tenv) ->
-    let
-       rho'           = substTy tenv rho
-       (theta', tau') = splitRhoTy rho' 
-    in
-    returnNF_Tc (tyvars', theta', tau')
+
+%************************************************************************
+%*                                                                     *
+\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] (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}
 
-Between the renamer and the first invocation of the UsageSP inference,
-identifiers read from interface files will have usage information in
-their types, whereas other identifiers will not.  The unannotTy here
-in @tcInstId@ prevents this information from pointlessly propagating
-further prior to the first usage inference.
 
+%************************************************************************
+%*                                                                     *
+\subsection{Basic lookups}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+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 :: RecTcGblEnv -> Name -> Maybe Id
+tcLookupRecId_maybe env name = case lookup_global env name of
+                                  Just (AnId id) -> Just id
+                                  other          -> Nothing
+\end{code}
 
 %************************************************************************
 %*                                                                     *
-\subsection{TcEnv}
+\subsection{Making new Ids}
 %*                                                                     *
 %************************************************************************
 
-Data type declarations
-~~~~~~~~~~~~~~~~~~~~~
+Constructing new Ids
+
+\begin{code}
+newLocalName :: Name -> TcM Name
+newLocalName name      -- Make a clone
+  = newUnique          `thenM` \ uniq ->
+    returnM (mkInternalName uniq (getOccName name) (getSrcLoc name))
+\end{code}
+
+Make a name for the dict fun for an instance decl.
+It's a *local* name for the moment.  The CoreTidy pass
+will externalise it.
 
 \begin{code}
-data TcEnv = TcEnv
-                  UsageEnv
-                 TypeEnv
-                 ValueEnv 
-                 (TcTyVarSet,          -- The in-scope TyVars
-                  TcRef TcTyVarSet)    -- Free type variables of the value env
-                                       -- ...why mutable? see notes with tcGetGlobalTyVars
-                                       -- Includes the in-scope tyvars
-
-type NameEnv val = UniqFM val          -- Keyed by Names
-
-type UsageEnv   = NameEnv UVar
-type TypeEnv   = NameEnv (TcKind, Maybe Arity, TcTyThing)
-type ValueEnv  = NameEnv Id    
-
-valueEnvIds :: ValueEnv -> [Id]
-valueEnvIds ve = eltsUFM ve
-
-data TcTyThing = ATyVar TcTyVar                -- Mutable only so that the kind can be mutable
-                                       -- if the kind is mutable, the tyvar must be so that
-                                       -- zonking works
-              | ATyCon TyCon
-              | AClass Class
-
-
-initEnv :: TcRef TcTyVarSet -> TcEnv
-initEnv mut = TcEnv emptyUFM emptyUFM emptyUFM (emptyVarSet, mut)
-
-getEnvTyCons  (TcEnv _ te _ _) = [tc | (_, _, ATyCon tc) <- eltsUFM te]
-getEnvClasses (TcEnv _ te _ _) = [cl | (_, _, AClass cl) <- eltsUFM te]
-getAllEnvTyCons (TcEnv _ te _ _) = catMaybes (map gettc (eltsUFM te))
-    where                          
-      gettc (_,_, ATyCon tc) = Just tc
-      gettc (_,_, AClass cl) = Just (classTyCon cl)
-      gettc _                = Nothing
+newDFunName :: Class -> [Type] -> SrcLoc -> TcM Name
+newDFunName clas (ty:_) 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)
+
+newDFunName clas [] loc = pprPanic "newDFunName" (ppr clas <+> ppr loc)
 \end{code}
 
-The UsageEnv
-~~~~~~~~~~~~
+\begin{code}
+isLocalThing :: NamedThing a => Module -> a -> Bool
+isLocalThing mod thing = nameIsLocalOrFrom mod (getName thing)
+\end{code}
 
-Extending the usage environment.
+%************************************************************************
+%*                                                                     *
+\subsection{The global environment}
+%*                                                                     *
+%************************************************************************
 
 \begin{code}
-tcExtendUVarEnv :: Name -> UVar -> TcM s r -> TcM s r
-tcExtendUVarEnv uv_name uv scope
-  = tcGetEnv                                                 `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-    tcSetEnv (TcEnv (addToUFM ue uv_name uv) te ve gtvs) scope
+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
+   = 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
+ = do { env <- getGblEnv 
+      ; let ge' = tcg_type_env env `plusNameEnv` extra_env 
+      ; setGblEnv (env {tcg_type_env = ge'}) thing_inside }
 \end{code}
 
-Looking up in the environments.
 
 \begin{code}
-tcLookupUVar :: Name -> NF_TcM s UVar
-tcLookupUVar uv_name
-  = tcGetEnv   `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-    case lookupUFM ue uv_name of
-      Just uv -> returnNF_Tc uv
-      Nothing -> failWithTc (uvNameOutOfScope uv_name)
-\end{code}     
+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
+  = 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 -> TcM TyThing
+tcLookupGlobal name
+  = tcLookupGlobal_maybe name  `thenM` \ maybe_thing ->
+    case maybe_thing of
+       Just thing -> returnM thing
+       other      -> notFound "tcLookupGlobal" name
+
+tcLookupGlobalId :: Name -> TcM Id
+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  `thenM` \ con_id ->
+    case isDataConWrapId_maybe con_id of
+       Just data_con -> returnM data_con
+       Nothing       -> failWithTc (badCon con_id)
+
+tcLookupClass :: Name -> TcM Class
+tcLookupClass name
+  = tcLookupGlobal_maybe name  `thenM` \ maybe_clas ->
+    case maybe_clas of
+       Just (AClass clas) -> returnM clas
+       other              -> notFound "tcLookupClass" name
+       
+tcLookupTyCon :: Name -> TcM TyCon
+tcLookupTyCon name
+  = tcLookupGlobal_maybe name  `thenM` \ maybe_tc ->
+    case maybe_tc of
+       Just (ATyCon tc) -> returnM tc
+       other            -> notFound "tcLookupTyCon" name
 
 
-The TypeEnv
-~~~~~~~~~~~~
+getInGlobalScope :: TcRn m (Name -> Bool)
+getInGlobalScope = do { gbl_env <- getGblEnv ;
+                       return (\n -> isJust (lookup_global gbl_env n)) }
+\end{code}
+
 
-Extending the type environment. 
+%************************************************************************
+%*                                                                     *
+\subsection{The local environment}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+tcLookup_maybe :: Name -> TcM (Maybe TcTyThing)
+tcLookup_maybe name
+  = 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                `thenM` \ maybe_thing ->
+    case maybe_thing of
+       Just thing -> returnM thing
+       other      -> notFound "tcLookup" name
+       -- Extract the IdInfo from an IfaceSig imported from an interface file
+
+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}
-tcExtendTyVarEnv :: [TyVar] -> TcM s r -> TcM s r
-tcExtendTyVarEnv tyvars scope
-  = tcGetEnv                           `thenNF_Tc` \ (TcEnv ue te ve (in_scope_tvs, gtvs)) ->
+tcExtendKindEnv :: [(Name,TcKind)] -> TcM r -> TcM r
+tcExtendKindEnv pairs thing_inside
+  = 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
+    
+tcExtendTyVarEnv :: [TyVar] -> TcM r -> TcM r
+tcExtendTyVarEnv tvs thing_inside
+  = tc_extend_tv_env [(getName tv, ATyVar tv) | tv <- tvs] tvs thing_inside
+
+tcExtendTyVarEnv2 :: [(TyVar,TcTyVar)] -> TcM r -> TcM r
+tcExtendTyVarEnv2 tv_pairs thing_inside
+  = tc_extend_tv_env [(getName tv1, ATyVar tv2) | (tv1,tv2) <- tv_pairs]
+                    [tv | (_,tv) <- tv_pairs]
+                    thing_inside
+
+tc_extend_tv_env binds tyvars thing_inside
+  = getLclEnv     `thenM` \ env@(TcLclEnv {tcl_env = le, tcl_tyvars = gtvs}) ->
     let
-       extend_list = [ (getName tv, (kindToTcKind (tyVarKind tv), Nothing, ATyVar tv))
-                     | tv <- tyvars
-                     ]
-       te'           = addListToUFM te extend_list
-       new_tv_set    = mkVarSet tyvars
-       in_scope_tvs' = in_scope_tvs `unionVarSet` new_tv_set
+       le'        = extendNameEnvList le binds
+       new_tv_set = mkVarSet tyvars
     in
        -- It's important to add the in-scope tyvars to the global tyvar set
        -- as well.  Consider
@@ -222,38 +394,48 @@ tcExtendTyVarEnv tyvars scope
        -- 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 (TcEnv ue te' ve (in_scope_tvs', gtvs')) scope
-
--- This variant, tcExtendTyVarEnvForMeths, takes *two* bunches of tyvars:
---     the signature tyvars contain the original names
---     the instance  tyvars are what those names should be mapped to
--- It's needed when typechecking the method bindings of class and instance decls
--- It does *not* extend the global tyvars; tcMethodBind does that for itself
-
-tcExtendTyVarEnvForMeths :: [TyVar] -> [TcTyVar] -> TcM s r -> TcM s r
-tcExtendTyVarEnvForMeths sig_tyvars inst_tyvars thing_inside
-  = tcGetEnv                                   `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
+    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
+  = getLclEnv          `thenM` \ env ->
     let
-       te' = addListToUFM te stuff
+       extra_global_tyvars = tyVarsOfTypes [idType id | id <- ids]
+       lvl                 = metaLevel (tcl_level env)
+       extra_env           = [(idName id, ATcId id lvl) | id <- ids]
+       le'                 = extendNameEnvList (tcl_env env) extra_env
     in
-    tcSetEnv (TcEnv ue te' ve gtvs) thing_inside
-  where
-    stuff = [ (getName sig_tv, (kindToTcKind (tyVarKind inst_tv), Nothing, ATyVar inst_tv))
-           | (sig_tv, inst_tv) <- zipEqual "tcMeth" sig_tyvars inst_tyvars
-           ]
-
-tcExtendGlobalTyVars extra_global_tvs scope
-  = tcGetEnv                                   `thenNF_Tc` \ (TcEnv ue te ve (in_scope,gtvs)) ->
-    tc_extend_gtvs gtvs        extra_global_tvs        `thenNF_Tc` \ gtvs' ->
-    tcSetEnv (TcEnv ue te ve (in_scope,gtvs')) scope
+    tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars        `thenM` \ gtvs' ->
+    setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside
 
-tc_extend_gtvs gtvs extra_global_tvs
-  = tcReadMutVar gtvs                  `thenNF_Tc` \ global_tvs ->
+tcExtendLocalValEnv2 :: [(Name,TcId)] -> TcM a -> TcM a
+tcExtendLocalValEnv2 names_w_ids thing_inside
+  = getLclEnv          `thenM` \ env ->
     let
-       new_global_tyvars = global_tvs `unionVarSet` extra_global_tvs
+       extra_global_tyvars = tyVarsOfTypes [idType id | (name,id) <- names_w_ids]
+       lvl                 = metaLevel (tcl_level env)
+       extra_env           = [(name, ATcId id lvl) | (name,id) <- names_w_ids]
+       le'                 = extendNameEnvList (tcl_env env) extra_env
     in
-    tcNewMutVar new_global_tyvars
+    tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars        `thenM` \ gtvs' ->
+    setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+\subsection{The global tyvars}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+tc_extend_gtvs gtvs 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.
@@ -261,207 +443,157 @@ To improve subsequent calls to the same function it writes the zonked set back i
 the environment.
 
 \begin{code}
-tcGetGlobalTyVars :: NF_TcM s TcTyVarSet
+tcGetGlobalTyVars :: TcM TcTyVarSet
 tcGetGlobalTyVars
-  = tcGetEnv                                           `thenNF_Tc` \ (TcEnv ue te ve (_,gtvs)) ->
-    tcReadMutVar gtvs                                  `thenNF_Tc` \ global_tvs ->
-    zonkTcTyVars (varSetElems global_tvs)              `thenNF_Tc` \ global_tys' ->
-    let
-       global_tvs' = (tyVarsOfTypes global_tys')
-    in
-    tcWriteMutVar gtvs global_tvs'                     `thenNF_Tc_` 
-    returnNF_Tc global_tvs'
-
-tcGetInScopeTyVars :: NF_TcM s [TcTyVar]
-tcGetInScopeTyVars
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv ue te ve (in_scope_tvs, gtvs)) ->
-    returnNF_Tc (varSetElems in_scope_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}
 
 
-Type constructors and classes
+%************************************************************************
+%*                                                                     *
+\subsection{The instance environment}
+%*                                                                     *
+%************************************************************************
 
 \begin{code}
-tcExtendTypeEnv :: [(Name, (TcKind, Maybe Arity, TcTyThing))] -> TcM s r -> TcM s r
-tcExtendTypeEnv bindings scope
-  = ASSERT( null [tv | (_, (_,_,ATyVar tv)) <- bindings] )
-       -- Not for tyvars; use tcExtendTyVarEnv
-    tcGetEnv                                   `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-    let
-       te' = addListToUFM te bindings
-    in
-    tcSetEnv (TcEnv ue te' ve gtvs) scope
+tcGetInstEnv :: TcM InstEnv
+tcGetInstEnv = getGblEnv       `thenM` \ env -> 
+              returnM (tcg_inst_env env)
+
+tcSetInstEnv :: InstEnv -> TcM a -> TcM a
+tcSetInstEnv ie thing_inside
+  = 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}
 
 
-Looking up in the environments.
+%************************************************************************
+%*                                                                     *
+\subsection{Rules}
+%*                                                                     *
+%************************************************************************
 
 \begin{code}
-tcLookupTy :: Name ->  NF_TcM s (TcKind, Maybe Arity, TcTyThing)
-tcLookupTy name
-  = tcGetEnv   `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-    case lookupUFM te name of {
-       Just thing -> returnNF_Tc thing ;
-       Nothing    -> 
-
-    case maybeWiredInTyConName name of
-       Just tc -> returnNF_Tc (kindToTcKind (tyConKind tc), maybe_arity, ATyCon tc)
-               where
-                  maybe_arity | isSynTyCon tc = Just (tyConArity tc)
-                              | otherwise     = Nothing 
-
-       Nothing ->      -- This can happen if an interface-file
-                       -- unfolding is screwed up
-                  failWithTc (tyNameOutOfScope name)
-    }
-       
-tcLookupClass :: Name -> NF_TcM s Class
-tcLookupClass name
-  = tcLookupTy name    `thenNF_Tc` \ (_, _, AClass clas) ->
-    returnNF_Tc clas
-
-tcLookupTyCon :: Name -> NF_TcM s TyCon
-tcLookupTyCon name
-  = tcLookupTy name    `thenNF_Tc` \ (_, _, ATyCon tycon) ->
-    returnNF_Tc tycon
-
-tcLookupClassByKey :: Unique -> NF_TcM s Class
-tcLookupClassByKey key
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-    case lookupUFM_Directly te key of
-       Just (_, _, AClass cl) -> returnNF_Tc cl
-       other                  -> pprPanic "tcLookupClassByKey:" (pprUnique10 key)
-
-tcLookupClassByKey_maybe :: Unique -> NF_TcM s (Maybe Class)
-tcLookupClassByKey_maybe key
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-    case lookupUFM_Directly te key of
-       Just (_, _, AClass cl) -> returnNF_Tc (Just cl)
-       other                  -> returnNF_Tc Nothing
-
-tcLookupTyConByKey :: Unique -> NF_TcM s TyCon
-tcLookupTyConByKey key
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-    case lookupUFM_Directly te key of
-       Just (_, _, ATyCon tc) -> returnNF_Tc tc
-       other                  -> pprPanic "tcLookupTyConByKey:" (pprUnique10 key)
+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}
 
 
-
-
 %************************************************************************
 %*                                                                     *
-\subsection{The value environment}
+\subsection{The InstInfo type}
 %*                                                                     *
 %************************************************************************
 
-\begin{code}
-tcExtendGlobalValEnv :: [Id] -> TcM s a -> TcM s a
-tcExtendGlobalValEnv ids scope
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-    let
-       ve' = addListToUFM_Directly ve [(getUnique id, id) | id <- ids]
-    in
-    tcSetEnv (TcEnv ue te ve' gtvs) scope
+The InstInfo type summarises the information in an instance declaration
 
-tcExtendLocalValEnv :: [(Name,TcId)] -> TcM s a -> TcM s a
-tcExtendLocalValEnv names_w_ids scope
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv ue te ve (in_scope_tvs,gtvs)) ->
-    tcReadMutVar gtvs  `thenNF_Tc` \ global_tvs ->
-    let
-       ve'                 = addListToUFM ve names_w_ids
-       extra_global_tyvars = tyVarsOfTypes (map (idType . snd) names_w_ids)
-    in
-    tc_extend_gtvs gtvs extra_global_tyvars    `thenNF_Tc` \ gtvs' ->
-    tcSetEnv (TcEnv ue te ve' (in_scope_tvs,gtvs')) scope
-\end{code}
+    instance c => k (t tvs) where b
 
+It is used just for *local* instance decls (not ones from interface files).
+But local instance decls includes
+       - derived ones
+       - generic ones
+as well as explicit user written ones.
 
 \begin{code}
-tcLookupValue :: Name -> NF_TcM s Id   -- Panics if not found
-tcLookupValue name
-  = case maybeWiredInIdName name of
-       Just id -> returnNF_Tc id
-       Nothing -> tcGetEnv             `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-                  returnNF_Tc (lookupWithDefaultUFM ve def name)
-  where
-    def = pprPanic "tcLookupValue:" (ppr name)
-
-tcLookupValueMaybe :: Name -> NF_TcM s (Maybe Id)
-tcLookupValueMaybe name
-  = case maybeWiredInIdName name of
-       Just id -> returnNF_Tc (Just id)
-       Nothing -> tcGetEnv             `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-                  returnNF_Tc (lookupUFM ve name)
-
-tcLookupValueByKey :: Unique -> NF_TcM s Id    -- Panics if not found
-tcLookupValueByKey key
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-    returnNF_Tc (explicitLookupValueByKey ve key)
-
-tcLookupValueByKeyMaybe :: Unique -> NF_TcM s (Maybe Id)
-tcLookupValueByKeyMaybe key
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-    returnNF_Tc (lookupUFM_Directly ve key)
-
-tcGetValueEnv :: NF_TcM s ValueEnv
-tcGetValueEnv
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv ue te ve gtvs) ->
-    returnNF_Tc ve
-
-tcSetValueEnv :: ValueEnv -> TcM s a -> TcM s a
-tcSetValueEnv ve scope
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv ue te _ gtvs) ->
-    tcSetEnv (TcEnv ue te ve gtvs) scope
-
--- Non-monadic version, environment given explicitly
-explicitLookupValueByKey :: ValueEnv -> Unique -> Id
-explicitLookupValueByKey ve key
-  = lookupWithDefaultUFM_Directly ve def key
-  where
-    def = pprPanic "lookupValueByKey:" (pprUnique10 key)
-
-explicitLookupValue :: ValueEnv -> Name -> Maybe Id
-explicitLookupValue ve name
-  = case maybeWiredInIdName name of
-       Just id -> Just id
-       Nothing -> lookupUFM ve name
+data InstInfo
+  = InstInfo {
+      iDFunId :: DFunId,               -- The dfun id
+      iBinds  :: RenamedMonoBinds,     -- Bindings, b
+      iPrags  :: [RenamedSig]          -- User pragmas recorded for generating specialised instances
+    }
 
-       -- Extract the IdInfo from an IfaceSig imported from an interface file
-tcAddImportedIdInfo :: ValueEnv -> Id -> Id
-tcAddImportedIdInfo unf_env id
-  | isLocallyDefined id                -- Don't look up locally defined Ids, because they
-                               -- have explicit local definitions, so we get a black hole!
-  = id
-  | otherwise
-  = id `lazySetIdInfo` new_info
-       -- The Id must be returned without a data dependency on maybe_id
-  where
-    new_info = -- pprTrace "tcAdd" (ppr id) $
-              case explicitLookupValue unf_env (getName id) of
-                    Nothing          -> vanillaIdInfo
-                    Just imported_id -> idInfo imported_id
-               -- ToDo: could check that types are the same
-\end{code}
+  | NewTypeDerived {           -- Used for deriving instances of newtypes, where the
+                               -- witness dictionary is identical to the argument dictionary
+                               -- Hence no bindings.
+      iDFunId :: DFunId                        -- The dfun id
+    }
 
+pprInstInfo info = vcat [ptext SLIT("InstInfo:") <+> ppr (idType (iDFunId info))]
+pprInstInfoDetails (InstInfo { iBinds = b }) = ppr b
+pprInstInfoDetails (NewTypeDerived _)       = text "Derived from the represenation type"
 
-%************************************************************************
-%*                                                                     *
-\subsection{Constructing new Ids}
-%*                                                                     *
-%************************************************************************
+simpleInstInfoTy :: InstInfo -> Type
+simpleInstInfoTy info = case tcSplitDFunTy (idType (iDFunId info)) of
+                         (_, _, _, [ty]) -> ty
 
-\begin{code}
-newLocalId :: OccName -> TcType -> SrcLoc -> NF_TcM s TcId
-newLocalId name ty loc
-  = tcGetUnique                `thenNF_Tc` \ uniq ->
-    returnNF_Tc (mkUserLocal name uniq ty loc)
-
-newSpecPragmaId :: Name -> TcType -> NF_TcM s TcId
-newSpecPragmaId name ty 
-  = tcGetUnique                `thenNF_Tc` \ uniq ->
-    returnNF_Tc (mkSpecPragmaId (nameOccName name) uniq ty (getSrcLoc name))
+simpleInstInfoTyCon :: InstInfo -> TyCon
+  -- Gets the type constructor for a simple instance declaration,
+  -- i.e. one of the form      instance (...) => C (T a b c) where ...
+simpleInstInfoTyCon inst = tcTyConAppTyCon (simpleInstInfoTy inst)
 \end{code}
 
 
@@ -472,14 +604,8 @@ newSpecPragmaId name ty
 %************************************************************************
 
 \begin{code}
-badCon con_id
-  = quotes (ppr con_id) <+> ptext SLIT("is not a data constructor")
-badPrimOp op
-  = quotes (ppr op) <+> ptext SLIT("is not a primop")
-
-uvNameOutOfScope name
-  = ptext SLIT("UVar") <+> quotes (ppr name) <+> ptext SLIT("is not in scope")
+badCon con_id = quotes (ppr con_id) <+> ptext SLIT("is not a data constructor")
 
-tyNameOutOfScope name
-  = quotes (ppr name) <+> ptext SLIT("is not in scope")
+notFound wheRe name = failWithTc (text wheRe <> colon <+> quotes (ppr name) <+> 
+                                 ptext SLIT("is not in scope"))
 \end{code}