\begin{code}
module TcEnv(
- TcId, TcIdSet,
- TyThing(..), TyThingDetails(..), TcTyThing(..),
+ TyThing(..), 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,
+ InstBindings(..),
-- Global environment
- tcExtendGlobalEnv, tcExtendGlobalValEnv, tcExtendGlobalTypeEnv,
- tcLookupTyCon, tcLookupClass, tcLookupGlobalId, tcLookupDataCon,
- tcLookupGlobal_maybe, tcLookupGlobal,
+ tcExtendGlobalEnv,
+ tcExtendGlobalValEnv,
+ tcLookupLocatedGlobal, tcLookupGlobal,
+ tcLookupGlobalId, tcLookupTyCon, tcLookupClass, tcLookupDataCon,
+ tcLookupLocatedGlobalId, tcLookupLocatedTyCon,
+ tcLookupLocatedClass, tcLookupLocatedDataCon,
+
+ getInGlobalScope,
-- Local environment
- tcExtendKindEnv, tcLookupLocalIds, tcInLocalScope,
- tcExtendTyVarEnv, tcExtendTyVarEnvForMeths,
- tcExtendLocalValEnv, tcLookup, tcLookup_maybe, tcLookupId,
+ tcExtendTyVarKindEnv,
+ tcExtendTyVarEnv, tcExtendTyVarEnv2,
+ tcExtendLocalValEnv, tcExtendLocalValEnv2,
+ tcLookup, tcLookupLocated, tcLookupLocalIds,
+ tcLookupId, tcLookupTyVar,
+ lclEnvElts, getInLocalScope, findGlobals,
+
+ tcExtendRecEnv, -- For knot-tying
+
+ -- Rules
+ tcExtendRules,
-- Global type variables
- tcGetGlobalTyVars, tcExtendGlobalTyVars,
+ tcGetGlobalTyVars,
- -- Random useful things
- RecTcEnv, tcAddImportedIdInfo, tcLookupRecId, tcLookupRecId_maybe,
+ -- Template Haskell stuff
+ checkWellStaged, spliceOK, bracketOK, tcMetaTy, thLevel,
+ topIdLvl,
- -- New Ids
- newLocalId, newSpecPragmaId,
- newDFunName,
+ -- Arrow stuff
+ checkProcLevel,
- -- Misc
- isLocalThing, tcSetEnv
+ -- New Ids
+ newLocalName, newDFunName
) where
#include "HsVersions.h"
-import RnHsSyn ( RenamedMonoBinds, RenamedSig )
-import TcMonad
-import TcMType ( zonkTcTyVarsAndFV )
-import TcType ( Type, ThetaType, TcType, TcKind, TcTyVar, TcTyVarSet,
- tyVarsOfTypes, tcSplitDFunTy,
- getDFunTyKey, tcTyConAppTyCon
+import HsSyn ( LRuleDecl, , HsTyVarBndr(..), LHsTyVarBndr, LHsBinds,
+ LSig )
+import TcIface ( tcImportDecl )
+import TcRnMonad
+import TcMType ( zonkTcType, zonkTcTyVar, zonkTcTyVarsAndFV )
+import TcType ( Type, TcTyVar, TcTyVarSet,
+ tyVarsOfType, tyVarsOfTypes, tcSplitDFunTy, mkGenTyConApp,
+ getDFunTyKey, tcTyConAppTyCon, tyVarBindingInfo,
+ tidyOpenType, tidyOpenTyVar
)
-import Id ( idName, mkSpecPragmaId, mkUserLocal, isDataConWrapId_maybe )
-import IdInfo ( vanillaIdInfo )
-import Var ( TyVar, Id, idType, lazySetIdInfo, idInfo )
+import qualified Type ( getTyVar_maybe )
+import Id ( idName, isLocalId )
+import Var ( TyVar, Id, mkTyVar, idType )
import VarSet
+import VarEnv
+import RdrName ( extendLocalRdrEnv )
import DataCon ( DataCon )
import TyCon ( TyCon )
-import Class ( Class, ClassOpItem )
-import Name ( Name, OccName, NamedThing(..),
- nameOccName, getSrcLoc, mkLocalName, isLocalName,
- nameIsLocalOrFrom
- )
-import NameEnv ( NameEnv, lookupNameEnv, nameEnvElts, elemNameEnv,
- extendNameEnvList, emptyNameEnv, plusNameEnv )
+import Class ( Class )
+import Name ( Name, NamedThing(..), getSrcLoc, mkInternalName, nameIsLocalOrFrom )
+import NameEnv
import OccName ( mkDFunOcc, occNameString )
-import HscTypes ( DFunId,
- PackageTypeEnv, TypeEnv,
- extendTypeEnvList, extendTypeEnvWithIds,
- typeEnvTyCons, typeEnvClasses, typeEnvIds,
- HomeSymbolTable
- )
-import Module ( Module )
-import InstEnv ( InstEnv, emptyInstEnv )
-import HscTypes ( lookupType, TyThing(..) )
-import Util ( zipEqual )
-import SrcLoc ( SrcLoc )
-import Outputable
+import HscTypes ( DFunId, extendTypeEnvList, lookupType,
+ TyThing(..), tyThingId, tyThingTyCon, tyThingClass, tyThingDataCon,
+ ExternalPackageState(..) )
-import IOExts ( newIORef )
+import SrcLoc ( SrcLoc, Located(..) )
+import Outputable
+import Maybe ( isJust )
\end{code}
+
%************************************************************************
%* *
-\subsection{TcEnv}
+%* tcLookupGlobal *
%* *
%************************************************************************
-\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
- }
-
-\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
-
+Using the Located versions (eg. tcLookupLocatedGlobal) is preferred,
+unless you know that the SrcSpan in the monad is already set to the
+span of the Name.
\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 | isLocalName 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)
+tcLookupLocatedGlobal :: Located Name -> TcM TyThing
+-- c.f. IfaceEnvEnv.tcIfaceGlobal
+tcLookupLocatedGlobal name
+ = addLocM tcLookupGlobal name
-getTcGEnv (TcEnv { tcGEnv = genv }) = genv
-
-tcInLocalScope :: TcEnv -> Name -> Bool
-tcInLocalScope env v = v `elemNameEnv` (tcLEnv env)
+tcLookupGlobal :: Name -> TcM TyThing
+tcLookupGlobal name
+ = do { env <- getGblEnv
+ ; if nameIsLocalOrFrom (tcg_mod env) name
+
+ then -- It's defined in this module
+ case lookupNameEnv (tcg_type_env env) name of
+ Just thing -> return thing
+ Nothing -> notFound "tcLookupGlobal" name
+
+ else do -- It's imported
+ { eps <- getEps
+ ; hpt <- getHpt
+ ; case lookupType hpt (eps_PTE eps) name of
+ Just thing -> return thing
+ Nothing -> do { traceIf (text "tcLookupGlobal" <+> ppr name)
+ ; initIfaceTcRn (tcImportDecl name) }
+ }}
\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
+tcLookupGlobalId :: Name -> TcM Id
+-- Never used for Haskell-source DataCons, hence no ADataCon case
+tcLookupGlobalId name
+ = tcLookupGlobal name `thenM` \ thing ->
+ return (tyThingId thing)
-\end{code}
+tcLookupDataCon :: Name -> TcM DataCon
+tcLookupDataCon con_name
+ = tcLookupGlobal con_name `thenM` \ thing ->
+ return (tyThingDataCon thing)
-This data type is used to help tie the knot
- when type checking type and class declarations
+tcLookupClass :: Name -> TcM Class
+tcLookupClass name
+ = tcLookupGlobal name `thenM` \ thing ->
+ return (tyThingClass thing)
+
+tcLookupTyCon :: Name -> TcM TyCon
+tcLookupTyCon name
+ = tcLookupGlobal name `thenM` \ thing ->
+ return (tyThingTyCon thing)
-\begin{code}
-data TyThingDetails = SynTyDetails Type
- | DataTyDetails ThetaType [DataCon] [Id]
- | ClassDetails ThetaType [Id] [ClassOpItem] DataCon
- | ForeignTyDetails -- Nothing yet
-\end{code}
+tcLookupLocatedGlobalId :: Located Name -> TcM Id
+tcLookupLocatedGlobalId = addLocM tcLookupId
-%************************************************************************
-%* *
-\subsection{Basic lookups}
-%* *
-%************************************************************************
+tcLookupLocatedDataCon :: Located Name -> TcM DataCon
+tcLookupLocatedDataCon = addLocM tcLookupDataCon
-\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}
+tcLookupLocatedClass :: Located Name -> TcM Class
+tcLookupLocatedClass = addLocM tcLookupClass
-\begin{code}
-type RecTcEnv = TcEnv
--- 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
-
-tcAddImportedIdInfo :: RecTcEnv -> Id -> Id
-tcAddImportedIdInfo env id
- = id `lazySetIdInfo` new_info
- -- The Id must be returned without a data dependency on maybe_id
- where
- new_info = case tcLookupRecId_maybe env (idName id) of
- Nothing -> pprTrace "tcAddIdInfo" (ppr id) vanillaIdInfo
- Just imported_id -> idInfo imported_id
- -- ToDo: could check that types are the same
-
-tcLookupRecId_maybe :: RecTcEnv -> 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)
+tcLookupLocatedTyCon :: Located Name -> TcM TyCon
+tcLookupLocatedTyCon = addLocM tcLookupTyCon
\end{code}
%************************************************************************
%* *
-\subsection{Making new Ids}
+ Extending the global environment
%* *
%************************************************************************
-Constructing new Ids
-
-\begin{code}
-newLocalId :: OccName -> TcType -> SrcLoc -> NF_TcM TcId
-newLocalId name ty loc
- = tcGetUnique `thenNF_Tc` \ uniq ->
- returnNF_Tc (mkUserLocal name uniq ty loc)
-
-newSpecPragmaId :: Name -> TcType -> NF_TcM TcId
-newSpecPragmaId name ty
- = tcGetUnique `thenNF_Tc` \ uniq ->
- returnNF_Tc (mkSpecPragmaId (nameOccName name) uniq ty (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 globalise it.
-
-\begin{code}
-newDFunName :: Class -> [Type] -> SrcLoc -> NF_TcM Name
-newDFunName clas (ty:_) loc
- = tcGetUnique `thenNF_Tc` \ uniq ->
- returnNF_Tc (mkLocalName 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}
-
-\begin{code}
-isLocalThing :: NamedThing a => Module -> a -> Bool
-isLocalThing mod thing = nameIsLocalOrFrom mod (getName thing)
-\end{code}
-
-%************************************************************************
-%* *
-\subsection{The global environment}
-%* *
-%************************************************************************
\begin{code}
tcExtendGlobalEnv :: [TyThing] -> TcM r -> TcM r
+ -- Given a mixture of Ids, TyCons, Classes, all from the
+ -- module being compiled, extend the global environment
tcExtendGlobalEnv things thing_inside
- = tcGetEnv `thenNF_Tc` \ env ->
- let
- ge' = extendTypeEnvList (tcGEnv env) things
- in
- tcSetEnv (env {tcGEnv = ge'}) thing_inside
-
-
-tcExtendGlobalTypeEnv :: TypeEnv -> TcM r -> TcM r
-tcExtendGlobalTypeEnv extra_env thing_inside
- = tcGetEnv `thenNF_Tc` \ env ->
- let
- ge' = tcGEnv env `plusNameEnv` extra_env
- in
- tcSetEnv (env {tcGEnv = ge'}) thing_inside
+ = do { env <- getGblEnv
+ ; let ge' = extendTypeEnvList (tcg_type_env env) things
+ ; setGblEnv (env {tcg_type_env = 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
+ -- Same deal as tcExtendGlobalEnv, but for Ids
+tcExtendGlobalValEnv ids thing_inside
+ = tcExtendGlobalEnv [AnId id | id <- ids] thing_inside
\end{code}
+A variety of global lookups, when we know what we are looking for.
\begin{code}
-tcLookupGlobal_maybe :: Name -> NF_TcM (Maybe TyThing)
-tcLookupGlobal_maybe name
- = tcGetEnv `thenNF_Tc` \ env ->
- returnNF_Tc (lookup_global env name)
+getInGlobalScope :: TcM (Name -> Bool)
+-- Get all things in the global environment; used for deciding what
+-- rules to suck in. Anything defined in this module (nameIsLocalOrFrom)
+-- is certainly in the envt, so we don't bother to look.
+getInGlobalScope
+ = do { mod <- getModule
+ ; eps <- getEps
+ ; hpt <- getHpt
+ ; return (\n -> nameIsLocalOrFrom mod n ||
+ isJust (lookupType hpt (eps_PTE eps) n)) }
\end{code}
-A variety of global lookups, when we know what we are looking for.
\begin{code}
-tcLookupGlobal :: Name -> NF_TcM TyThing
-tcLookupGlobal name
- = tcLookupGlobal_maybe name `thenNF_Tc` \ maybe_thing ->
- case maybe_thing of
- Just thing -> returnNF_Tc thing
- other -> notFound "tcLookupGlobal" name
-
-tcLookupGlobalId :: Name -> NF_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
-
-tcLookupDataCon :: Name -> TcM DataCon
-tcLookupDataCon con_name
- = tcLookupGlobalId con_name `thenNF_Tc` \ con_id ->
- case isDataConWrapId_maybe con_id of
- Just data_con -> returnTc data_con
- Nothing -> failWithTc (badCon con_id)
-
-
-tcLookupClass :: Name -> NF_TcM Class
-tcLookupClass name
- = tcLookupGlobal_maybe name `thenNF_Tc` \ maybe_clas ->
- case maybe_clas of
- Just (AClass clas) -> returnNF_Tc clas
- other -> notFound "tcLookupClass" name
-
-tcLookupTyCon :: Name -> NF_TcM TyCon
-tcLookupTyCon name
- = tcLookupGlobal_maybe name `thenNF_Tc` \ maybe_tc ->
- case maybe_tc of
- Just (ATyCon tc) -> returnNF_Tc 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)
+tcExtendRecEnv :: [(Name,TyThing)] -- Global bindings
+ -> [(Name,TcTyThing)] -- Local bindings
+ -> TcM r -> TcM r
+-- Extend both local and global environments for the type/class knot tying game
+tcExtendRecEnv gbl_stuff lcl_stuff thing_inside
+ = do { (gbl_env, lcl_env) <- getEnvs
+ ; let { ge' = extendNameEnvList (tcg_type_env gbl_env) gbl_stuff
+ ; le' = extendNameEnvList (tcl_env lcl_env) lcl_stuff }
+ ; setEnvs (gbl_env {tcg_type_env = ge'}, lcl_env {tcl_env = le'})
+ thing_inside }
\end{code}
%************************************************************************
\begin{code}
-tcLookup_maybe :: Name -> NF_TcM (Maybe TcTyThing)
-tcLookup_maybe name
- = tcGetEnv `thenNF_Tc` \ env ->
- returnNF_Tc (lookup_local env name)
+tcLookupLocated :: Located Name -> TcM TcTyThing
+tcLookupLocated = addLocM tcLookup
-tcLookup :: Name -> NF_TcM TcTyThing
+tcLookup :: Name -> TcM TcTyThing
tcLookup name
- = tcLookup_maybe name `thenNF_Tc` \ maybe_thing ->
- case maybe_thing of
- Just thing -> returnNF_Tc thing
- other -> notFound "tcLookup" name
- -- Extract the IdInfo from an IfaceSig imported from an interface file
-\end{code}
+ = getLclEnv `thenM` \ local_env ->
+ case lookupNameEnv (tcl_env local_env) name of
+ Just thing -> returnM thing
+ Nothing -> tcLookupGlobal name `thenM` \ thing ->
+ returnM (AGlobal thing)
+
+tcLookupTyVar :: Name -> TcM Id
+tcLookupTyVar name
+ = tcLookup name `thenM` \ thing ->
+ case thing of
+ ATyVar tv -> returnM tv
+ other -> pprPanic "tcLookupTyVar" (ppr name)
+tcLookupId :: Name -> TcM Id
+-- Used when we aren't interested in the binding level
+-- Never a DataCon. (Why does that matter? see TcExpr.tcId)
+tcLookupId name
+ = tcLookup name `thenM` \ thing ->
+ case thing of
+ ATcId tc_id _ _ -> returnM tc_id
+ AGlobal (AnId id) -> returnM id
+ other -> pprPanic "tcLookupId" (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) (thLevel (tcl_th_ctxt 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)
+
+lclEnvElts :: TcLclEnv -> [TcTyThing]
+lclEnvElts env = 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]
+tcExtendTyVarKindEnv :: [LHsTyVarBndr Name] -> TcM r -> TcM r
+-- The tyvars are all kinded
+tcExtendTyVarKindEnv tvs thing_inside
+ = updLclEnv upd thing_inside
+ where
+ upd lcl_env = lcl_env { tcl_env = extend (tcl_env lcl_env) }
+ extend env = extendNameEnvList env [(n, ATyVar (mkTyVar n k))
+ | L _ (KindedTyVar n k) <- tvs]
-- No need to extend global tyvars for kind checking
- in
- tcSetEnv (env {tcLEnv = le'}) thing_inside
-
+
tcExtendTyVarEnv :: [TyVar] -> TcM r -> TcM r
-tcExtendTyVarEnv tyvars thing_inside
- = tcGetEnv `thenNF_Tc` \ env@(TcEnv {tcLEnv = le, tcTyVars = gtvs}) ->
+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,
+ tcl_rdr = rdr_env}) ->
let
- le' = extendNameEnvList le [ (getName tv, ATyVar tv) | tv <- tyvars]
+ le' = extendNameEnvList le binds
+ rdr_env' = extendLocalRdrEnv rdr_env (map fst binds)
new_tv_set = mkVarSet tyvars
in
-- It's important to add the in-scope tyvars to the global tyvar set
-- as well. Consider
- -- f (x::r) = let g y = y::r in ...
+ -- f (_::r) = let g y = y::r in ...
-- 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
-
--- 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 r -> TcM r
-tcExtendTyVarEnvForMeths sig_tyvars inst_tyvars thing_inside
- = tcGetEnv `thenNF_Tc` \ env ->
- let
- le' = extendNameEnvList (tcLEnv env) stuff
- stuff = [ (getName sig_tv, ATyVar inst_tv)
- | (sig_tv, inst_tv) <- zipEqual "tcMeth" sig_tyvars inst_tyvars
- ]
- in
- tcSetEnv (env {tcLEnv = le'}) thing_inside
+ tc_extend_gtvs gtvs new_tv_set `thenM` \ gtvs' ->
+ setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs', tcl_rdr = rdr_env'}) thing_inside
\end{code}
\begin{code}
-tcExtendLocalValEnv :: [(Name,TcId)] -> TcM a -> TcM a
-tcExtendLocalValEnv names_w_ids thing_inside
- = tcGetEnv `thenNF_Tc` \ env ->
+tcExtendLocalValEnv :: [TcId] -> TcM a -> TcM a
+tcExtendLocalValEnv ids thing_inside
+ = getLclEnv `thenM` \ env ->
+ let
+ extra_global_tyvars = tyVarsOfTypes [idType id | id <- ids]
+ th_lvl = thLevel (tcl_th_ctxt env)
+ proc_lvl = proc_level (tcl_arrow_ctxt env)
+ extra_env = [(idName id, ATcId id th_lvl proc_lvl) | id <- ids]
+ le' = extendNameEnvList (tcl_env env) extra_env
+ rdr_env' = extendLocalRdrEnv (tcl_rdr env) (map idName ids)
+ in
+ tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars `thenM` \ gtvs' ->
+ setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs', tcl_rdr = rdr_env'}) thing_inside
+
+tcExtendLocalValEnv2 :: [(Name,TcId)] -> TcM a -> TcM a
+tcExtendLocalValEnv2 names_w_ids thing_inside
+ = 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
+ th_lvl = thLevel (tcl_th_ctxt env)
+ proc_lvl = proc_level (tcl_arrow_ctxt env)
+ extra_env = [(name, ATcId id th_lvl proc_lvl) | (name,id) <- names_w_ids]
+ le' = extendNameEnvList (tcl_env env) extra_env
+ rdr_env' = extendLocalRdrEnv (tcl_rdr env) (map fst names_w_ids)
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', tcl_rdr = rdr_env'}) thing_inside
+\end{code}
+
+
+\begin{code}
+-----------------------
+-- findGlobals looks at the value environment and finds values
+-- whose types mention the offending type variable. It has to be
+-- careful to zonk the Id's type first, so it has to be in the monad.
+-- We must be careful to pass it a zonked type variable, too.
+
+findGlobals :: TcTyVarSet
+ -> TidyEnv
+ -> TcM (TidyEnv, [SDoc])
+
+findGlobals tvs tidy_env
+ = getLclEnv `thenM` \ lcl_env ->
+ go tidy_env [] (lclEnvElts lcl_env)
+ where
+ go tidy_env acc [] = returnM (tidy_env, acc)
+ go tidy_env acc (thing : things)
+ = find_thing ignore_it tidy_env thing `thenM` \ (tidy_env1, maybe_doc) ->
+ case maybe_doc of
+ Just d -> go tidy_env1 (d:acc) things
+ Nothing -> go tidy_env1 acc things
+
+ ignore_it ty = not (tvs `intersectsVarSet` tyVarsOfType ty)
+
+-----------------------
+find_thing ignore_it tidy_env (ATcId id _ _)
+ = zonkTcType (idType id) `thenM` \ id_ty ->
+ if ignore_it id_ty then
+ returnM (tidy_env, Nothing)
+ else let
+ (tidy_env', tidy_ty) = tidyOpenType tidy_env id_ty
+ msg = sep [ppr id <+> dcolon <+> ppr tidy_ty,
+ nest 2 (parens (ptext SLIT("bound at") <+>
+ ppr (getSrcLoc id)))]
+ in
+ returnM (tidy_env', Just msg)
+
+find_thing ignore_it tidy_env (ATyVar tv)
+ = zonkTcTyVar tv `thenM` \ tv_ty ->
+ if ignore_it tv_ty then
+ returnM (tidy_env, Nothing)
+ else let
+ (tidy_env1, tv1) = tidyOpenTyVar tidy_env tv
+ (tidy_env2, tidy_ty) = tidyOpenType tidy_env1 tv_ty
+ msg = sep [ppr tv1 <+> eq_stuff, nest 2 bound_at]
+
+ eq_stuff | Just tv' <- Type.getTyVar_maybe tv_ty,
+ tv == tv' = empty
+ | otherwise = equals <+> ppr tidy_ty
+ -- It's ok to use Type.getTyVar_maybe because ty is zonked by now
+
+ bound_at = tyVarBindingInfo tv
+ in
+ returnM (tidy_env2, Just msg)
\end{code}
%************************************************************************
\begin{code}
-tcExtendGlobalTyVars extra_global_tvs thing_inside
- = tcGetEnv `thenNF_Tc` \ env ->
- tc_extend_gtvs (tcTyVars env) extra_global_tvs `thenNF_Tc` \ gtvs' ->
- tcSetEnv (env {tcTyVars = gtvs'}) thing_inside
-
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.
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}
%************************************************************************
%* *
-\subsection{The instance environment}
+\subsection{Rules}
%* *
%************************************************************************
\begin{code}
-tcGetInstEnv :: NF_TcM InstEnv
-tcGetInstEnv = tcGetEnv `thenNF_Tc` \ env ->
- returnNF_Tc (tcInsts env)
+tcExtendRules :: [LRuleDecl 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 lcl_rules thing_inside
+ = do { env <- getGblEnv
+ ; let
+ env' = env { tcg_rules = lcl_rules ++ tcg_rules env }
+ ; setGblEnv env' thing_inside }
+\end{code}
-tcSetInstEnv :: InstEnv -> TcM a -> TcM a
-tcSetInstEnv ie thing_inside
- = tcGetEnv `thenNF_Tc` \ env ->
- tcSetEnv (env {tcInsts = ie}) thing_inside
-\end{code}
+
+%************************************************************************
+%* *
+ Arrow notation proc levels
+%* *
+%************************************************************************
+
+\begin{code}
+checkProcLevel :: TcId -> ProcLevel -> TcM ()
+checkProcLevel id id_lvl
+ = do { banned <- getBannedProcLevels
+ ; checkTc (not (id_lvl `elem` banned))
+ (procLevelErr id id_lvl) }
+
+procLevelErr id id_lvl
+ = hang (ptext SLIT("Command-bound variable") <+> quotes (ppr id) <+> ptext SLIT("is not in scope here"))
+ 4 (ptext SLIT("Reason: it is used in the left argument of (-<)"))
+\end{code}
+
+
+%************************************************************************
+%* *
+ Meta level
+%* *
+%************************************************************************
+
+\begin{code}
+instance Outputable ThStage where
+ ppr Comp = text "Comp"
+ ppr (Brack l _ _) = text "Brack" <+> int l
+ ppr (Splice l) = text "Splice" <+> int l
+
+
+thLevel :: ThStage -> ThLevel
+thLevel Comp = topLevel
+thLevel (Splice l) = l
+thLevel (Brack l _ _) = l
+
+
+checkWellStaged :: SDoc -- What the stage check is for
+ -> ThLevel -- Binding level
+ -> ThStage -- Use stage
+ -> TcM () -- Fail if badly staged, adding an error
+checkWellStaged pp_thing bind_lvl use_stage
+ | bind_lvl <= use_lvl -- OK!
+ = returnM ()
+
+ | bind_lvl == topLevel -- GHC restriction on top level splices
+ = failWithTc $
+ sep [ptext SLIT("GHC stage restriction:") <+> pp_thing,
+ nest 2 (ptext SLIT("is used in a top-level splice, and must be imported, not defined locally"))]
+
+ | otherwise -- Badly staged
+ = failWithTc $
+ ptext SLIT("Stage error:") <+> pp_thing <+>
+ hsep [ptext SLIT("is bound at stage") <+> ppr bind_lvl,
+ ptext SLIT("but used at stage") <+> ppr use_lvl]
+ where
+ use_lvl = thLevel use_stage
+
+
+topIdLvl :: Id -> ThLevel
+-- Globals may either be imported, or may be from an earlier "chunk"
+-- (separated by declaration splices) of this module. The former
+-- *can* be used inside a top-level splice, but the latter cannot.
+-- Hence we give the former impLevel, but the latter topLevel
+-- E.g. this is bad:
+-- x = [| foo |]
+-- $( f x )
+-- By the time we are prcessing the $(f x), the binding for "x"
+-- will be in the global env, not the local one.
+topIdLvl id | isLocalId id = topLevel
+ | otherwise = impLevel
+
+-- Indicates the legal transitions on bracket( [| |] ).
+bracketOK :: ThStage -> Maybe ThLevel
+bracketOK (Brack _ _ _) = Nothing -- Bracket illegal inside a bracket
+bracketOK stage = (Just (thLevel stage + 1))
+
+-- Indicates the legal transitions on splice($).
+spliceOK :: ThStage -> Maybe ThLevel
+spliceOK (Splice _) = Nothing -- Splice illegal inside splice
+spliceOK stage = Just (thLevel 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}
+
+
+%************************************************************************
+%* *
+\subsection{Making new Ids}
+%* *
+%************************************************************************
+
+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. Even in
+--make and ghci stuff, we rebuild the instance environment each time,
+so the dfun id is internal to begin with, and external when compiling
+other modules
+
+\begin{code}
+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}
%************************************************************************
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}
data InstInfo
= InstInfo {
iDFunId :: DFunId, -- The dfun id
- iBinds :: RenamedMonoBinds, -- Bindings, b
- iPrags :: [RenamedSig] -- User pragmas recorded for generating specialised instances
+ iBinds :: InstBindings
}
-pprInstInfo info = vcat [ptext SLIT("InstInfo:") <+> ppr (idType (iDFunId info)),
- nest 4 (ppr (iBinds info))]
+data InstBindings
+ = VanillaInst -- The normal case
+ (LHsBinds Name) -- Bindings
+ [LSig Name] -- User pragmas recorded for generating
+ -- specialised instances
+
+ | NewTypeDerived -- Used for deriving instances of newtypes, where the
+ [Type] -- witness dictionary is identical to the argument
+ -- dictionary. Hence no bindings, no pragmas
+ -- The [Type] are the representation types
+ -- See notes in TcDeriv
+
+pprInstInfo info = vcat [ptext SLIT("InstInfo:") <+> ppr (idType (iDFunId info))]
+
+pprInstInfoDetails info = pprInstInfo info $$ nest 2 (details (iBinds info))
+ where
+ details (VanillaInst b _) = ppr b
+ details (NewTypeDerived _) = text "Derived from the representation type"
simpleInstInfoTy :: InstInfo -> Type
simpleInstInfoTy info = case tcSplitDFunTy (idType (iDFunId info)) of
%************************************************************************
\begin{code}
-badCon con_id = quotes (ppr con_id) <+> ptext SLIT("is not a data constructor")
-
notFound wheRe name = failWithTc (text wheRe <> colon <+> quotes (ppr name) <+>
ptext SLIT("is not in scope"))
\end{code}