\begin{code}
module TcEnv(
- TyThing(..), TyThingDetails(..), TcTyThing(..), TcId,
+ TyThing(..), TcTyThing(..), TcId,
-- Instance environment, and InstInfo type
- tcGetInstEnv, tcSetInstEnv,
- InstInfo(..), pprInstInfo, pprInstInfoDetails,
- simpleInstInfoTy, simpleInstInfoTyCon,
+ InstInfo(..), iDFunId, pprInstInfo, pprInstInfoDetails,
+ simpleInstInfoClsTy, simpleInstInfoTy, simpleInstInfoTyCon,
InstBindings(..),
-- Global environment
tcExtendGlobalEnv,
tcExtendGlobalValEnv,
- tcExtendGlobalTypeEnv,
- tcLookupTyCon, tcLookupClass, tcLookupDataCon,
- tcLookupGlobal_maybe, tcLookupGlobal, tcLookupGlobalId,
- getInGlobalScope,
-
+ tcLookupLocatedGlobal, tcLookupGlobal,
+ tcLookupGlobalId, tcLookupTyCon, tcLookupClass, tcLookupDataCon,
+ tcLookupLocatedGlobalId, tcLookupLocatedTyCon,
+ tcLookupLocatedClass,
+
-- Local environment
- tcExtendKindEnv,
- tcExtendTyVarEnv, tcExtendTyVarEnv2,
- tcExtendLocalValEnv, tcExtendLocalValEnv2,
- tcLookup, tcLookupLocalIds, tcLookup_maybe,
- tcLookupId, tcLookupIdLvl,
+ tcExtendKindEnv, tcExtendKindEnvTvs,
+ tcExtendTyVarEnv, tcExtendTyVarEnv2,
+ tcExtendIdEnv, tcExtendIdEnv1, tcExtendIdEnv2,
+ tcLookup, tcLookupLocated, tcLookupLocalIds, tcLookupLocalId_maybe,
+ tcLookupId, tcLookupTyVar, getScopedTyVarBinds,
lclEnvElts, getInLocalScope, findGlobals,
+ wrongThingErr, pprBinders,
+ refineEnvironment,
- -- Instance environment
- tcExtendLocalInstEnv, tcExtendInstEnv,
+ tcExtendRecEnv, -- For knot-tying
-- Rules
tcExtendRules,
tcGetGlobalTyVars,
-- Template Haskell stuff
- checkWellStaged, spliceOK, bracketOK, tcMetaTy, metaLevel,
+ checkWellStaged, spliceOK, bracketOK, tcMetaTy, thLevel,
topIdLvl,
-- New Ids
- newLocalName, newDFunName,
-
- -- Misc
- isLocalThing
+ newLocalName, newDFunName
) where
#include "HsVersions.h"
-import RnHsSyn ( RenamedMonoBinds, RenamedSig )
-import HsSyn ( RuleDecl(..), ifaceRuleDeclName )
+import HsSyn ( LRuleDecl, LHsBinds, LSig,
+ LHsTyVarBndr, HsTyVarBndr(..), pprLHsBinds )
+import TcIface ( tcImportDecl )
+import IfaceEnv ( newGlobalBinder )
import TcRnMonad
-import TcMType ( zonkTcType, zonkTcTyVar, zonkTcTyVarsAndFV )
-import TcType ( Type, ThetaType, TcKind, TcTyVar, TcTyVarSet,
- tyVarsOfType, tyVarsOfTypes, tcSplitDFunTy, mkGenTyConApp,
- getDFunTyKey, tcTyConAppTyCon, tyVarBindingInfo,
- tidyOpenType, tidyOpenTyVar
+import TcMType ( zonkTcType, zonkTcTyVarsAndFV )
+import TcType ( Type, TcKind, TcTyVar, TcTyVarSet, TcType, TvSubst,
+ substTy, substTyVar, tyVarsOfType, tcTyVarsOfTypes, mkTyConApp,
+ getDFunTyKey, tcTyConAppTyCon, tcGetTyVar, mkTyVarTy,
+ tidyOpenType, isRefineableTy
)
import qualified Type ( getTyVar_maybe )
-import Rules ( extendRuleBase )
-import Id ( idName, isLocalId, isDataConWrapId_maybe )
-import Var ( TyVar, Id, idType )
+import Id ( idName, isLocalId, setIdType )
+import Var ( TyVar, Id, idType, tyVarName )
import VarSet
import VarEnv
-import CoreSyn ( IdCoreRule )
-import DataCon ( DataCon, dataConWrapId )
-import TyCon ( TyCon, DataConDetails )
-import Class ( Class, ClassOpItem )
-import Name ( Name, NamedThing(..),
- getSrcLoc, mkInternalName, nameIsLocalOrFrom
- )
+import RdrName ( extendLocalRdrEnv )
+import InstEnv ( Instance, DFunId, instanceDFunId, instanceHead )
+import DataCon ( DataCon )
+import TyCon ( TyCon )
+import Class ( Class )
+import Name ( Name, NamedThing(..), getSrcLoc, nameModule, isExternalName )
+import PrelNames ( thFAKE )
import NameEnv
import OccName ( mkDFunOcc, occNameString )
-import HscTypes ( DFunId, TypeEnv, extendTypeEnvList, lookupType,
- TyThing(..), ExternalPackageState(..) )
-import Rules ( RuleBase )
-import BasicTypes ( EP )
-import Module ( Module )
-import InstEnv ( InstEnv, extendInstEnv )
-import Maybes ( seqMaybe )
-import SrcLoc ( SrcLoc )
-import Outputable
-import Maybe ( isJust )
-import List ( partition )
-\end{code}
-
-
-%************************************************************************
-%* *
- Meta level
-%* *
-%************************************************************************
-
-\begin{code}
-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
-
-
-checkWellStaged :: SDoc -- What the stage check is for
- -> Level -- Binding level
- -> Stage -- 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 = metaLevel use_stage
-
-
-topIdLvl :: Id -> Level
--- 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 :: 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)
+import HscTypes ( extendTypeEnvList, lookupType,
+ TyThing(..), tyThingId, tyThingDataCon,
+ ExternalPackageState(..) )
-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
+import SrcLoc ( SrcLoc, Located(..) )
+import Outputable
\end{code}
%************************************************************************
%* *
-\subsection{TyThingDetails}
+%* tcLookupGlobal *
%* *
%************************************************************************
-This data type is used to help tie the knot
- when type checking type and class declarations
+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}
-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}
-
+tcLookupLocatedGlobal :: Located Name -> TcM TyThing
+-- c.f. IfaceEnvEnv.tcIfaceGlobal
+tcLookupLocatedGlobal name
+ = addLocM tcLookupGlobal name
-%************************************************************************
-%* *
-\subsection{Making new Ids}
-%* *
-%************************************************************************
+tcLookupGlobal :: Name -> TcM TyThing
+-- The Name is almost always an ExternalName, but not always
+-- In GHCi, we may make command-line bindings (ghci> let x = True)
+-- that bind a GlobalId, but with an InternalName
+tcLookupGlobal name
+ = do { env <- getGblEnv
+
+ -- Try local envt
+ ; case lookupNameEnv (tcg_type_env env) name of {
+ Just thing -> return thing ;
+ Nothing -> do
+
+ -- Try global envt
+ { (eps,hpt) <- getEpsAndHpt
+ ; case lookupType hpt (eps_PTE eps) name of {
+ Just thing -> return thing ;
+ Nothing -> do
+
+ -- Should it have been in the local envt?
+ { let mod = nameModule name
+ ; if mod == tcg_mod env || mod == thFAKE then
+ notFound name -- It should be local, so panic
+ -- The thFAKE possibility is because it
+ -- might be in a declaration bracket
+ else
+ tcImportDecl name -- Go find it in an interface
+ }}}}}
-Constructing new Ids
+tcLookupGlobalId :: Name -> TcM Id
+-- Never used for Haskell-source DataCons, hence no ADataCon case
+tcLookupGlobalId name
+ = tcLookupGlobal name `thenM` \ thing ->
+ return (tyThingId thing)
-\begin{code}
-newLocalName :: Name -> TcM Name
-newLocalName name -- Make a clone
- = newUnique `thenM` \ uniq ->
- returnM (mkInternalName uniq (getOccName name) (getSrcLoc name))
-\end{code}
+tcLookupDataCon :: Name -> TcM DataCon
+tcLookupDataCon con_name
+ = tcLookupGlobal con_name `thenM` \ thing ->
+ return (tyThingDataCon thing)
-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
+tcLookupClass :: Name -> TcM Class
+tcLookupClass name
+ = tcLookupGlobal name `thenM` \ thing ->
+ case thing of
+ AClass cls -> return cls
+ other -> wrongThingErr "class" (AGlobal thing) name
+
+tcLookupTyCon :: Name -> TcM TyCon
+tcLookupTyCon name
+ = tcLookupGlobal name `thenM` \ thing ->
+ case thing of
+ ATyCon tc -> return tc
+ other -> wrongThingErr "type constructor" (AGlobal thing) name
-\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)
+tcLookupLocatedGlobalId :: Located Name -> TcM Id
+tcLookupLocatedGlobalId = addLocM tcLookupId
-newDFunName clas [] loc = pprPanic "newDFunName" (ppr clas <+> ppr loc)
-\end{code}
+tcLookupLocatedClass :: Located Name -> TcM Class
+tcLookupLocatedClass = addLocM tcLookupClass
-\begin{code}
-isLocalThing :: NamedThing a => Module -> a -> Bool
-isLocalThing mod thing = nameIsLocalOrFrom mod (getName thing)
+tcLookupLocatedTyCon :: Located Name -> TcM TyCon
+tcLookupLocatedTyCon = addLocM tcLookupTyCon
\end{code}
%************************************************************************
%* *
-\subsection{The global environment}
+ Extending the global environment
%* *
%************************************************************************
+
\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
+ -- Given a mixture of Ids, TyCons, Classes, all from the
+ -- module being compiled, extend the global environment
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 }
- ; setEps eps'
+ = 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
-- 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}
-
-
-\begin{code}
-tcLookupGlobal_maybe :: Name -> TcRn m (Maybe TyThing)
--- This is a rather heavily-used function, so I've inlined a few things (e.g. getEps)
--- Notice that for imported things we read the current version from the EPS
--- mutable variable. This is important in situations like
--- ...$(e1)...$(e2)...
--- where the code that e1 expands to might import some defns that
--- also turn out to be needed by the code that e2 expands to.
-tcLookupGlobal_maybe name
- = do { env <- getGblEnv
- ; if nameIsLocalOrFrom (tcg_mod env) name then
- -- Defined in this module
- return (lookupNameEnv (tcg_type_env env) name)
- else
- do { env <- getTopEnv
- ; eps <- readMutVar (top_eps env)
- ; return (lookupType (top_hpt env) (eps_PTE eps) 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
--- Never used for Haskell-source DataCons, hence no ADataCon case
-tcLookupGlobalId name
- = tcLookupGlobal_maybe name `thenM` \ maybe_thing ->
- case maybe_thing of
- Just (AnId id) -> returnM id
- other -> notFound "tcLookupGlobal (id)" name
-
-tcLookupDataCon :: Name -> TcM DataCon
-tcLookupDataCon con_name
- = tcLookupGlobal_maybe con_name `thenM` \ maybe_thing ->
- case maybe_thing of
- Just (ADataCon data_con) -> returnM data_con
- other -> notFound "tcLookupDataCon" con_name
-
-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
-
-
-getInGlobalScope :: TcRn m (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)) }
+tcExtendRecEnv :: [(Name,TyThing)] -> TcM r -> TcM r
+-- Extend the global environments for the type/class knot tying game
+tcExtendRecEnv gbl_stuff thing_inside
+ = updGblEnv upd thing_inside
+ where
+ upd env = env { tcg_type_env = extend (tcg_type_env env) }
+ extend env = extendNameEnvList env gbl_stuff
\end{code}
%************************************************************************
\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)
+tcLookupLocated :: Located Name -> TcM TcTyThing
+tcLookupLocated = addLocM tcLookup
tcLookup :: Name -> TcM TcTyThing
tcLookup name
- = tcLookup_maybe name `thenM` \ maybe_thing ->
- case maybe_thing of
+ = getLclEnv `thenM` \ local_env ->
+ case lookupNameEnv (tcl_env local_env) name of
Just thing -> returnM thing
- other -> notFound "tcLookup" name
- -- Extract the IdInfo from an IfaceSig imported from an interface file
+ Nothing -> tcLookupGlobal name `thenM` \ thing ->
+ returnM (AGlobal thing)
+
+tcLookupTyVar :: Name -> TcM TcTyVar
+tcLookupTyVar name
+ = tcLookup name `thenM` \ thing ->
+ case thing of
+ ATyVar _ ty -> return (tcGetTyVar "tcLookupTyVar" ty)
+ other -> pprPanic "tcLookupTyVar" (ppr name)
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
+ ATcId tc_id _ _ -> returnM tc_id
AGlobal (AnId id) -> returnM id
other -> pprPanic "tcLookupId" (ppr name)
-tcLookupIdLvl :: Name -> TcM (Id, Level)
--- DataCons dealt with separately
-tcLookupIdLvl name
- = tcLookup name `thenM` \ thing ->
- case thing of
- ATcId tc_id lvl -> returnM (tc_id, lvl)
- AGlobal (AnId id) -> returnM (id, topIdLvl id)
- other -> pprPanic "tcLookupIdLvl" (ppr name)
+tcLookupLocalId_maybe :: Name -> TcM (Maybe Id)
+tcLookupLocalId_maybe name
+ = getLclEnv `thenM` \ local_env ->
+ case lookupNameEnv (tcl_env local_env) name of
+ Just (ATcId tc_id _ _) -> return (Just tc_id)
+ other -> return Nothing
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)
+ 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)
+ Just (ATcId id lvl1 _) -> ASSERT( lvl == lvl1 ) id
+ other -> pprPanic "tcLookupLocalIds" (ppr name)
lclEnvElts :: TcLclEnv -> [TcTyThing]
lclEnvElts env = nameEnvElts (tcl_env env)
\end{code}
\begin{code}
-tcExtendKindEnv :: [(Name,TcKind)] -> TcM r -> TcM r
-tcExtendKindEnv pairs thing_inside
+tcExtendKindEnv :: [(Name, TcKind)] -> TcM r -> TcM r
+tcExtendKindEnv things 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
-
+ extend env = extendNameEnvList env [(n, AThing k) | (n,k) <- things]
+
+tcExtendKindEnvTvs :: [LHsTyVarBndr Name] -> TcM r -> TcM r
+tcExtendKindEnvTvs bndrs thing_inside
+ = updLclEnv upd thing_inside
+ where
+ upd lcl_env = lcl_env { tcl_env = extend (tcl_env lcl_env) }
+ extend env = extendNameEnvList env pairs
+ pairs = [(n, AThing k) | L _ (KindedTyVar n k) <- bndrs]
+
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
+ = tcExtendTyVarEnv2 [(tyVarName tv, mkTyVarTy tv) | tv <- tvs] thing_inside
-tc_extend_tv_env binds tyvars thing_inside
- = getLclEnv `thenM` \ env@(TcLclEnv {tcl_env = le, tcl_tyvars = gtvs}) ->
+tcExtendTyVarEnv2 :: [(Name,TcType)] -> TcM r -> TcM r
+tcExtendTyVarEnv2 binds thing_inside
+ = getLclEnv `thenM` \ env@(TcLclEnv {tcl_env = le,
+ tcl_tyvars = gtvs,
+ tcl_rdr = rdr_env}) ->
let
- le' = extendNameEnvList le binds
- new_tv_set = mkVarSet tyvars
+ rdr_env' = extendLocalRdrEnv rdr_env (map fst binds)
+ new_tv_set = tcTyVarsOfTypes (map snd binds)
+ le' = extendNameEnvList le [(name, ATyVar name ty) | (name, ty) <- binds]
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 `thenM` \ gtvs' ->
- setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside
+ setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs', tcl_rdr = rdr_env'}) thing_inside
+
+getScopedTyVarBinds :: TcM [(Name, TcType)]
+getScopedTyVarBinds
+ = do { lcl_env <- getLclEnv
+ ; return [(name, ty) | ATyVar name ty <- nameEnvElts (tcl_env lcl_env)] }
\end{code}
\begin{code}
-tcExtendLocalValEnv :: [TcId] -> TcM a -> TcM a
-tcExtendLocalValEnv ids thing_inside
+tcExtendIdEnv :: [TcId] -> TcM a -> TcM a
+-- Invariant: the TcIds are fully zonked. Reasons:
+-- (a) The kinds of the forall'd type variables are defaulted
+-- (see Kind.defaultKind, done in zonkQuantifiedTyVar)
+-- (b) There are no via-Indirect occurrences of the bound variables
+-- in the types, because instantiation does not look through such things
+-- (c) The call to tyVarsOfTypes is ok without looking through refs
+tcExtendIdEnv ids thing_inside = tcExtendIdEnv2 [(idName id, id) | id <- ids] thing_inside
+
+tcExtendIdEnv1 :: Name -> TcId -> TcM a -> TcM a
+tcExtendIdEnv1 name id thing_inside = tcExtendIdEnv2 [(name,id)] thing_inside
+
+tcExtendIdEnv2 :: [(Name,TcId)] -> TcM a -> TcM a
+-- Invariant: the TcIds are fully zonked (see tcExtendIdEnv above)
+tcExtendIdEnv2 names_w_ids thing_inside
= getLclEnv `thenM` \ env ->
let
- extra_global_tyvars = tyVarsOfTypes [idType id | id <- ids]
- lvl = metaLevel (tcl_level env)
- extra_env = [(idName id, ATcId id lvl) | id <- ids]
+ extra_global_tyvars = tcTyVarsOfTypes [idType id | (_,id) <- names_w_ids]
+ th_lvl = thLevel (tcl_th_ctxt env)
+ extra_env = [ (name, ATcId id th_lvl (isRefineableTy (idType id)))
+ | (name,id) <- names_w_ids]
le' = extendNameEnvList (tcl_env env) extra_env
+ rdr_env' = extendLocalRdrEnv (tcl_rdr env) [name | (name,_) <- names_w_ids]
in
+ traceTc (text "env2") `thenM_`
+ traceTc (text "env3" <+> ppr extra_env) `thenM_`
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
- = getLclEnv `thenM` \ env ->
- let
- 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
- tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars `thenM` \ gtvs' ->
- setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside
+ (traceTc (text "env4") `thenM_`
+ setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs', tcl_rdr = rdr_env'}) thing_inside)
\end{code}
-- We must be careful to pass it a zonked type variable, too.
findGlobals :: TcTyVarSet
- -> TidyEnv
- -> TcM (TidyEnv, [SDoc])
+ -> TidyEnv
+ -> TcM (TidyEnv, [SDoc])
findGlobals tvs tidy_env
= getLclEnv `thenM` \ lcl_env ->
ignore_it ty = not (tvs `intersectsVarSet` tyVarsOfType ty)
-----------------------
-find_thing ignore_it tidy_env (ATcId id _)
+find_thing ignore_it tidy_env (ATcId id _ _)
= zonkTcType (idType id) `thenM` \ id_ty ->
if ignore_it id_ty then
returnM (tidy_env, Nothing)
in
returnM (tidy_env', Just msg)
-find_thing ignore_it tidy_env (ATyVar tv)
- = zonkTcTyVar tv `thenM` \ tv_ty ->
+find_thing ignore_it tidy_env (ATyVar tv ty)
+ = zonkTcType ty `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]
+ -- The name tv is scoped, so we don't need to tidy it
+ (tidy_env1, tidy_ty) = tidyOpenType tidy_env tv_ty
+ msg = sep [ptext SLIT("Scoped type variable") <+> quotes (ppr tv) <+> eq_stuff, nest 2 bound_at]
- eq_stuff | Just tv' <- Type.getTyVar_maybe tv_ty, tv == tv' = empty
- | otherwise = equals <+> ppr tv_ty
+ eq_stuff | Just tv' <- Type.getTyVar_maybe tv_ty,
+ getOccName tv == getOccName 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
+ bound_at = parens $ ptext SLIT("bound at:") <+> ppr (getSrcLoc tv)
in
- returnM (tidy_env2, Just msg)
+ returnM (tidy_env1, Just msg)
\end{code}
+\begin{code}
+refineEnvironment :: TvSubst -> TcM a -> TcM a
+refineEnvironment reft thing_inside
+ = do { env <- getLclEnv
+ ; let le' = mapNameEnv refine (tcl_env env)
+ ; gtvs' <- refineGlobalTyVars reft (tcl_tyvars env)
+ ; setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside }
+ where
+ refine (ATcId id lvl True) = ATcId (setIdType id (substTy reft (idType id))) lvl True
+ refine (ATyVar tv ty) = ATyVar tv (substTy reft ty)
+ refine elt = elt
+\end{code}
%************************************************************************
%* *
tc_extend_gtvs gtvs extra_global_tvs
= readMutVar gtvs `thenM` \ global_tvs ->
newMutVar (global_tvs `unionVarSet` extra_global_tvs)
+
+refineGlobalTyVars :: GadtRefinement -> TcRef TcTyVarSet -> TcM (TcRef TcTyVarSet)
+refineGlobalTyVars reft gtv_var
+ = readMutVar gtv_var `thenM` \ gbl_tvs ->
+ newMutVar (tcTyVarsOfTypes (map (substTyVar reft) (varSetElems gbl_tvs)))
\end{code}
@tcGetGlobalTyVars@ returns a fully-zonked set of tyvars free in the environment.
%************************************************************************
%* *
-\subsection{The instance environment}
+\subsection{Rules}
%* *
%************************************************************************
-The TcGblEnv holds a mutable variable containing the current full, instance environment.
-The ExtendInstEnv functions extend this environment by side effect, in case we are
-sucking in new instance declarations deep in the body of a TH splice, which are needed
-in another TH splice. The tcg_insts field of the TcGblEnv contains just the dfuns
-from this module
-
\begin{code}
-tcGetInstEnv :: TcM InstEnv
-tcGetInstEnv = getGblEnv `thenM` \ env ->
- readMutVar (tcg_inst_env env)
-
-tcSetInstEnv :: InstEnv -> TcM a -> TcM a
--- Horribly imperative;
--- but used only when temporarily enhancing the instance
--- envt during 'deriving' context inference
-tcSetInstEnv ie thing_inside
- = getGblEnv `thenM` \ env ->
- let
- ie_var = tcg_inst_env env
- in
- readMutVar ie_var `thenM` \ old_ie ->
- writeMutVar ie_var ie `thenM_`
- thing_inside `thenM` \ result ->
- writeMutVar ie_var old_ie `thenM_`
- returnM result
-
-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 ie_var = tcg_inst_env env
- ; inst_env <- readMutVar ie_var
- ; let
- -- Extend the total inst-env with the new dfuns
- (inst_env', errs) = extendInstEnv dflags inst_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_insts = lcl_dfuns ++ tcg_insts env }
-
- ; traceDFuns dfuns
- ; addErrs errs
- ; writeMutVar ie_var inst_env'
- ; 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 ie_var = tcg_inst_env env
- ; inst_env <- readMutVar ie_var
+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
- dfuns = map iDFunId infos
- (inst_env', errs) = extendInstEnv dflags inst_env dfuns
- env' = env { tcg_insts = dfuns ++ tcg_insts env }
- ; traceDFuns dfuns
- ; addErrs errs
- ; writeMutVar ie_var inst_env'
+ env' = env { tcg_rules = lcl_rules ++ tcg_rules env }
; 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}
+ Meta level
%* *
%************************************************************************
\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
+instance Outputable ThStage where
+ ppr Comp = text "Comp"
+ ppr (Brack l _ _) = text "Brack" <+> int l
+ ppr (Splice l) = text "Splice" <+> int l
- 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 }
+thLevel :: ThStage -> ThLevel
+thLevel Comp = topLevel
+thLevel (Splice l) = l
+thLevel (Brack l _ _) = l
- ; setEps eps'
- ; setGblEnv env' thing_inside }
-addIfaceRules :: RuleBase -> [IdCoreRule] -> RuleBase
-addIfaceRules rule_base rules
- = foldl extendRuleBase rule_base rules
+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 (mkTyConApp t [])
\end{code}
\begin{code}
data InstInfo
= InstInfo {
- iDFunId :: DFunId, -- The dfun id
- iBinds :: InstBindings
+ iSpec :: Instance, -- Includes the dfun id. Its forall'd type
+ iBinds :: InstBindings -- variables scope over the stuff in InstBindings!
}
+iDFunId :: InstInfo -> DFunId
+iDFunId info = instanceDFunId (iSpec info)
+
data InstBindings
= VanillaInst -- The normal case
- RenamedMonoBinds -- Bindings
- [RenamedSig] -- User pragmas recorded for generating
+ (LHsBinds Name) -- Bindings
+ [LSig Name] -- User pragmas recorded for generating
-- specialised instances
| NewTypeDerived -- Used for deriving instances of newtypes, where the
pprInstInfo info = vcat [ptext SLIT("InstInfo:") <+> ppr (idType (iDFunId info))]
-pprInstInfoDetails (InstInfo { iBinds = VanillaInst b _ }) = ppr b
-pprInstInfoDetails (InstInfo { iBinds = NewTypeDerived _}) = text "Derived from the representation type"
+pprInstInfoDetails info = pprInstInfo info $$ nest 2 (details (iBinds info))
+ where
+ details (VanillaInst b _) = pprLHsBinds b
+ details (NewTypeDerived _) = text "Derived from the representation type"
+
+simpleInstInfoClsTy :: InstInfo -> (Class, Type)
+simpleInstInfoClsTy info = case instanceHead (iSpec info) of
+ (_, _, cls, [ty]) -> (cls, ty)
simpleInstInfoTy :: InstInfo -> Type
-simpleInstInfoTy info = case tcSplitDFunTy (idType (iDFunId info)) of
- (_, _, _, [ty]) -> ty
+simpleInstInfoTy info = snd (simpleInstInfoClsTy info)
simpleInstInfoTyCon :: InstInfo -> TyCon
-- Gets the type constructor for a simple instance declaration,
simpleInstInfoTyCon inst = tcTyConAppTyCon (simpleInstInfoTy inst)
\end{code}
+Make a name for the dict fun for an instance decl. It's an *external*
+name, like otber top-level names, and hence must be made with newGlobalBinder.
+
+\begin{code}
+newDFunName :: Class -> [Type] -> SrcLoc -> TcM Name
+newDFunName clas (ty:_) loc
+ = do { index <- nextDFunIndex
+ ; is_boot <- tcIsHsBoot
+ ; mod <- getModule
+ ; let info_string = occNameString (getOccName clas) ++
+ occNameString (getDFunTyKey ty)
+ dfun_occ = mkDFunOcc info_string is_boot index
+
+ ; newGlobalBinder mod dfun_occ Nothing loc }
+
+newDFunName clas [] loc = pprPanic "newDFunName" (ppr clas <+> ppr loc)
+\end{code}
+
%************************************************************************
%* *
%************************************************************************
\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"))
+pprBinders :: [Name] -> SDoc
+-- Used in error messages
+-- Use quotes for a single one; they look a bit "busy" for several
+pprBinders [bndr] = quotes (ppr bndr)
+pprBinders bndrs = pprWithCommas ppr bndrs
+
+notFound name
+ = failWithTc (ptext SLIT("GHC internal error:") <+> quotes (ppr name) <+>
+ ptext SLIT("is not in scope"))
+
+wrongThingErr expected thing name
+ = failWithTc (pprTcTyThingCategory thing <+> quotes (ppr name) <+>
+ ptext SLIT("used as a") <+> text expected)
\end{code}