\begin{code}
module TcEnv(
- TcId, TcIdSet, tcInstId,
- tcLookupDataCon,
-
- TcEnv, ValueEnv, TcTyThing(..),
-
- initEnv, getEnvTyCons, getEnvClasses, getAllEnvTyCons,
-
- tcExtendUVarEnv, tcLookupUVar,
-
- tcExtendTyVarEnv, tcExtendTyVarEnvForMeths, tcExtendTypeEnv, tcGetInScopeTyVars,
-
- tcLookupTy,
- tcLookupTyCon, tcLookupTyConByKey,
- tcLookupClass, tcLookupClassByKey, tcLookupClassByKey_maybe,
-
- tcExtendGlobalValEnv, tcExtendLocalValEnv,
- tcGetValueEnv, tcSetValueEnv,
- tcAddImportedIdInfo,
-
- tcLookupValue, tcLookupValueMaybe,
- tcLookupValueByKey, tcLookupValueByKeyMaybe,
- explicitLookupValueByKey, explicitLookupValue,
- valueEnvIds,
-
- newLocalId, newSpecPragmaId,
- tcGetGlobalTyVars, tcExtendGlobalTyVars,
-
- badCon, badPrimOp
+ TyThing(..), TyThingDetails(..), TcTyThing(..), TcId,
+
+ -- Instance environment, and InstInfo type
+ tcGetInstEnv,
+ InstInfo(..), pprInstInfo, pprInstInfoDetails,
+ simpleInstInfoTy, simpleInstInfoTyCon,
+ InstBindings(..),
+
+ -- 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,
+ lclEnvElts, getInLocalScope, findGlobals,
+
+ -- Instance environment
+ tcExtendLocalInstEnv, tcExtendInstEnv, tcExtendTempInstEnv, tcWithTempInstEnv,
+
+ -- Rules
+ tcExtendRules,
+
+ -- Global type variables
+ tcGetGlobalTyVars,
+
+ -- Template Haskell stuff
+ checkWellStaged, spliceOK, bracketOK, tcMetaTy, thLevel,
+ topIdLvl,
+
+ -- Arrow stuff
+ checkProcLevel,
+
+ -- New Ids
+ newLocalName, newDFunName,
+
+ -- Misc
+ isLocalThing
) where
#include "HsVersions.h"
-import HsTypes ( HsTyVar, getTyVarName )
-import Id ( mkUserLocal, isDataConId_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 ( zonkTcType, zonkTcTyVar, zonkTcTyVarsAndFV )
+import TcType ( Type, ThetaType, TcKind, TcTyVar, TcTyVarSet,
+ tyVarsOfType, tyVarsOfTypes, tcSplitDFunTy, mkGenTyConApp,
+ getDFunTyKey, tcTyConAppTyCon, tyVarBindingInfo,
+ tidyOpenType, tidyOpenTyVar
+ )
+import qualified Type ( getTyVar_maybe )
+import Rules ( extendRuleBase )
+import Id ( idName, isLocalId )
+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 VarEnv
+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, lookupType,
+ TyThing(..), ExternalPackageState(..) )
+import Rules ( RuleBase )
+import BasicTypes ( EP )
+import Module ( Module )
+import InstEnv ( InstEnv, extendInstEnv )
import SrcLoc ( SrcLoc )
-import FastString ( FastString )
import Outputable
+import Maybe ( isJust )
+import List ( partition )
\end{code}
+
%************************************************************************
%* *
-\subsection{TcId}
+ Arrow notation proc levels
%* *
%************************************************************************
-
\begin{code}
-type TcId = Id -- Type may be a TcType
-type TcIdSet = IdSet
+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}
+
-tcLookupDataCon :: Name -> TcM s (DataCon, [TcType], TcType)
-tcLookupDataCon con_name
- = tcLookupValue con_name `thenNF_Tc` \ con_id ->
- case isDataConId_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')
+%************************************************************************
+%* *
+ 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}
-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{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}
%************************************************************************
%* *
-\subsection{TcEnv}
+\subsection{Making new Ids}
%* *
%************************************************************************
-Data type declarations
-~~~~~~~~~~~~~~~~~~~~~
+Constructing new Ids
\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
+newLocalName :: Name -> TcM Name
+newLocalName name -- Make a clone
+ = newUnique `thenM` \ uniq ->
+ returnM (mkInternalName uniq (getOccName name) (getSrcLoc name))
\end{code}
-The UsageEnv
-~~~~~~~~~~~~
+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
-Extending the usage environment.
+\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}
\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
+isLocalThing :: NamedThing a => Module -> a -> Bool
+isLocalThing mod thing = nameIsLocalOrFrom mod (getName thing)
\end{code}
-Looking up in the environments.
+%************************************************************************
+%* *
+\subsection{The global environment}
+%* *
+%************************************************************************
\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}
+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 }
+ ; setEps eps'
+ ; 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}
-The TypeEnv
-~~~~~~~~~~~~
+\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}
-Extending the type environment.
+A variety of global lookups, when we know what we are looking for.
\begin{code}
-tcExtendTyVarEnv :: [TyVar] -> TcM s r -> TcM s r
-tcExtendTyVarEnv tyvars scope
- = tcGetEnv `thenNF_Tc` \ (TcEnv ue te ve (in_scope_tvs, gtvs)) ->
+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)) }
+\end{code}
+
+
+%************************************************************************
+%* *
+\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
+-- 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
+ = 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
-- 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) ->
- let
- te' = addListToUFM te stuff
- 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 gtvs extra_global_tvs
- = tcReadMutVar gtvs `thenNF_Tc` \ global_tvs ->
- let
- new_global_tyvars = global_tvs `unionVarSet` extra_global_tvs
- in
- tcNewMutVar new_global_tyvars
+ tc_extend_gtvs gtvs new_tv_set `thenM` \ gtvs' ->
+ setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside
\end{code}
-@tcGetGlobalTyVars@ returns a fully-zonked set of tyvars free in the environment.
-To improve subsequent calls to the same function it writes the zonked set back into
-the environment.
\begin{code}
-tcGetGlobalTyVars :: NF_TcM s TcTyVarSet
-tcGetGlobalTyVars
- = tcGetEnv `thenNF_Tc` \ (TcEnv ue te ve (_,gtvs)) ->
- tcReadMutVar gtvs `thenNF_Tc` \ global_tvs ->
- zonkTcTyVars (varSetElems global_tvs) `thenNF_Tc` \ global_tys' ->
+tcExtendLocalValEnv :: [TcId] -> TcM a -> TcM a
+tcExtendLocalValEnv ids thing_inside
+ = getLclEnv `thenM` \ env ->
let
- global_tvs' = (tyVarsOfTypes global_tys')
+ 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
in
- tcWriteMutVar gtvs global_tvs' `thenNF_Tc_`
- returnNF_Tc global_tvs'
+ tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars `thenM` \ gtvs' ->
+ setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside
-tcGetInScopeTyVars :: NF_TcM s [TcTyVar]
-tcGetInScopeTyVars
- = tcGetEnv `thenNF_Tc` \ (TcEnv ue te ve (in_scope_tvs, gtvs)) ->
- returnNF_Tc (varSetElems in_scope_tvs)
+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]
+ 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
+ in
+ tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars `thenM` \ gtvs' ->
+ setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside
\end{code}
-Type constructors and classes
-
\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
+-----------------------
+-- 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 tv_ty
+ -- It's ok to use Type.getTyVar_maybe because ty is zonked by now
+
+ bound_at = tyVarBindingInfo tv
in
- tcSetEnv (TcEnv ue te' ve gtvs) scope
+ returnM (tidy_env2, Just msg)
\end{code}
-Looking up in the environments.
+%************************************************************************
+%* *
+\subsection{The global tyvars}
+%* *
+%************************************************************************
\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)
+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.
+To improve subsequent calls to the same function it writes the zonked set back into
+the environment.
+\begin{code}
+tcGetGlobalTyVars :: TcM TcTyVarSet
+tcGetGlobalTyVars
+ = 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 value environment}
+\subsection{The instance environment}
%* *
%************************************************************************
-\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
-
-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}
-
+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}
-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
+tcGetInstEnv :: TcM InstEnv
+tcGetInstEnv = do { env <- getGblEnv; readMutVar (tcg_inst_env env) }
+
+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
+ ; 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'
+ ; setGblEnv env' thing_inside }
+
+tcExtendTempInstEnv :: [DFunId] -> TcM a -> TcM a
+ -- Extend the instance envt, but with *no* permanent
+ -- effect on mutable variables; also ignore errors
+ -- Used during 'deriving' stuff
+tcExtendTempInstEnv dfuns thing_inside
+ = do { dflags <- getDOpts
+ ; env <- getGblEnv
+ ; let ie_var = tcg_inst_env env
+ ; inst_env <- readMutVar ie_var
+ ; let (inst_env', errs) = extendInstEnv dflags inst_env dfuns
+ -- Ignore the errors about duplicate instances.
+ -- We don't want repeated error messages
+ -- They'll appear later, when we do the top-level extendInstEnvs
+ ; writeMutVar ie_var inst_env'
+ ; result <- thing_inside
+ ; writeMutVar ie_var inst_env -- Restore!
+ ; return result }
+
+tcWithTempInstEnv :: TcM a -> TcM a
+-- Run thing_inside, discarding any effects on the instance environment
+tcWithTempInstEnv thing_inside
+ = do { env <- getGblEnv
+ ; let ie_var = tcg_inst_env env
+ ; old_ie <- readMutVar ie_var
+ ; result <- thing_inside
+ ; writeMutVar ie_var old_ie -- Restore
+ ; return result }
+
+traceDFuns dfuns
+ = traceTc (text "Adding instances:" <+> vcat (map pp dfuns))
where
- def = pprPanic "lookupValueByKey:" (pprUnique10 key)
+ pp dfun = ppr dfun <+> dcolon <+> ppr (idType dfun)
+\end{code}
-explicitLookupValue :: ValueEnv -> Name -> Maybe Id
-explicitLookupValue ve name
- = case maybeWiredInIdName name of
- Just id -> Just id
- Nothing -> lookupUFM ve name
- -- 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
+%************************************************************************
+%* *
+\subsection{Rules}
+%* *
+%************************************************************************
+
+\begin{code}
+tcExtendRules :: [RuleDecl Id] -> TcM a -> TcM a
+ -- Just pop the new rules into the EPS and envt resp
+ -- All the rules come from an interface file, not soruce
+ -- Nevertheless, some may be for this module, if we read
+ -- its interface instead of its source code
+tcExtendRules rules thing_inside
+ = do { eps <- getEps
+ ; env <- getGblEnv
+ ; let
+ (lcl_rules, pkg_rules) = partition is_local_rule rules
+ is_local_rule = isLocalThing mod . ifaceRuleDeclName
+ mod = tcg_mod env
+
+ core_rules = [(id,rule) | IfaceRuleOut id rule <- pkg_rules]
+ eps' = eps { eps_rule_base = addIfaceRules (eps_rule_base eps) core_rules }
+ -- All the rules from an interface are of the IfaceRuleOut form
+
+ env' = env { tcg_rules = lcl_rules ++ tcg_rules env }
+
+ ; setEps eps'
+ ; setGblEnv env' thing_inside }
+
+addIfaceRules :: RuleBase -> [IdCoreRule] -> RuleBase
+addIfaceRules rule_base rules
+ = foldl extendRuleBase rule_base rules
\end{code}
%************************************************************************
%* *
-\subsection{Constructing new Ids}
+\subsection{The InstInfo type}
%* *
%************************************************************************
+The InstInfo type summarises the information in an instance declaration
+
+ 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}
-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))
+data InstInfo
+ = InstInfo {
+ iDFunId :: DFunId, -- The dfun id
+ iBinds :: InstBindings
+ }
+
+data InstBindings
+ = VanillaInst -- The normal case
+ RenamedMonoBinds -- Bindings
+ [RenamedSig] -- 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 (InstInfo { iBinds = VanillaInst b _ }) = ppr b
+pprInstInfoDetails (InstInfo { iBinds = NewTypeDerived _}) = text "Derived from the representation type"
+
+simpleInstInfoTy :: InstInfo -> Type
+simpleInstInfoTy info = case tcSplitDFunTy (idType (iDFunId info)) of
+ (_, _, _, [ty]) -> ty
+
+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}
%************************************************************************
\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}