\begin{code}
module TcEnv(
- TcIdOcc(..), TcIdBndr, tcIdType, tcIdTyVars, tcInstId,
+ TyThing(..), TyThingDetails(..), TcTyThing(..), TcId,
- TcEnv,
+ -- Instance environment, and InstInfo type
+ tcGetInstEnv, tcSetInstEnv,
+ InstInfo(..), pprInstInfo, pprInstInfoDetails,
+ simpleInstInfoTy, simpleInstInfoTyCon,
- initEnv, getEnv_LocalIds, getEnv_TyCons, getEnv_Classes,
-
- tcExtendTyVarEnv, tcLookupTyVar,
+ -- Global environment
+ tcExtendGlobalEnv,
+ tcExtendGlobalValEnv,
+ tcExtendGlobalTypeEnv,
+ tcLookupTyCon, tcLookupClass, tcLookupDataCon,
+ tcLookupGlobal_maybe, tcLookupGlobal, tcLookupGlobalId,
+ getInGlobalScope,
+
+ -- Local environment
+ tcExtendKindEnv,
+ tcExtendTyVarEnv, tcExtendTyVarEnv2,
+ tcExtendLocalValEnv, tcExtendLocalValEnv2,
+ tcLookup, tcLookupLocalIds, tcLookup_maybe,
+ tcLookupId, tcLookupIdLvl,
+ getLclEnvElts, getInLocalScope,
+
+ -- Instance environment
+ tcExtendLocalInstEnv, tcExtendInstEnv,
+
+ -- Rules
+ tcExtendRules,
- tcExtendTyConEnv, tcLookupTyCon, tcLookupTyConByKey,
- tcExtendClassEnv, tcLookupClass, tcLookupClassByKey,
- tcGetTyConsAndClasses,
+ -- Global type variables
+ tcGetGlobalTyVars,
- tcExtendGlobalValEnv, tcExtendLocalValEnv,
- tcLookupLocalValue, tcLookupLocalValueOK, tcLookupLocalValueByKey,
- tcLookupGlobalValue, tcLookupGlobalValueByKey, tcLookupGlobalValueMaybe,
- tcAddImportedIdInfo, tcExplicitLookupGlobal,
- tcLookupGlobalValueByKeyMaybe,
+ -- Random useful things
+ RecTcGblEnv, tcLookupRecId_maybe,
- newMonoIds, newLocalIds, newLocalId,
- tcGetGlobalTyVars, tcExtendGlobalTyVars
+ -- Template Haskell stuff
+ wellStaged, spliceOK, bracketOK, tcMetaTy, metaLevel,
+
+ -- New Ids
+ newLocalName, newDFunName,
+
+ -- Misc
+ isLocalThing
) where
#include "HsVersions.h"
-import Id ( Id, GenId, idType, mkUserLocal, mkUserId, replaceIdInfo, getIdInfo )
-import PragmaInfo ( PragmaInfo(..) )
-import TcKind ( TcKind, kindToTcKind, Kind )
-import TcType ( TcType, TcMaybe, TcTyVar, TcTyVarSet, TcThetaType,
- newTyVarTys, tcInstTyVars, zonkTcTyVars, tcInstType
- )
-import TyVar ( mkTyVarSet, unionTyVarSets, emptyTyVarSet, TyVar )
-import PprType ( GenTyVar )
-import Type ( tyVarsOfType, tyVarsOfTypes, splitForAllTys, splitRhoTy )
-import TyCon ( TyCon, tyConKind, tyConArity, isSynTyCon, Arity )
-import Class ( Class )
-
-import TcMonad
-
-import IdInfo ( noIdInfo )
-import Name ( Name, OccName(..),
- maybeWiredInTyConName, maybeWiredInIdName, isLocallyDefined,
- NamedThing(..)
+import RnHsSyn ( RenamedMonoBinds, RenamedSig )
+import HsSyn ( RuleDecl(..), ifaceRuleDeclName )
+import TcRnMonad
+import TcMType ( zonkTcTyVarsAndFV )
+import TcType ( Type, ThetaType, TcKind, TcTyVar, TcTyVarSet,
+ tyVarsOfTypes, tcSplitDFunTy, mkGenTyConApp,
+ getDFunTyKey, tcTyConAppTyCon,
+ )
+import Rules ( extendRuleBase )
+import Id ( idName, isDataConWrapId_maybe )
+import Var ( TyVar, Id, idType )
+import VarSet
+import CoreSyn ( IdCoreRule )
+import DataCon ( DataCon )
+import TyCon ( TyCon, DataConDetails )
+import Class ( Class, ClassOpItem )
+import Name ( Name, NamedThing(..),
+ getSrcLoc, mkInternalName, nameIsLocalOrFrom
)
-import Unique ( pprUnique10{-, pprUnique ToDo:rm-}, Unique, Uniquable(..) )
-import UniqFM
-import Util ( zipEqual, zipWithEqual, zipWith3Equal )
-import Maybes ( maybeToBool )
+import NameEnv
+import OccName ( mkDFunOcc, occNameString )
+import HscTypes ( DFunId, TypeEnv, extendTypeEnvList,
+ TyThing(..), ExternalPackageState(..) )
+import Rules ( RuleBase )
+import BasicTypes ( EP )
+import Module ( Module )
+import InstEnv ( InstEnv, extendInstEnv )
+import Maybes ( seqMaybe )
+import SrcLoc ( SrcLoc )
import Outputable
+import Maybe ( isJust )
+import List ( partition )
\end{code}
+
%************************************************************************
%* *
-\subsection{TcId, TcIdOcc}
+ Meta level
%* *
%************************************************************************
-
\begin{code}
-type TcIdBndr s = GenId (TcType s) -- Binders are all TcTypes
-data TcIdOcc s = TcId (TcIdBndr s) -- Bindees may be either
- | RealId Id
-
-instance Eq (TcIdOcc s) where
- (TcId id1) == (TcId id2) = id1 == id2
- (RealId id1) == (RealId id2) = id1 == id2
- _ == _ = False
-
-instance Ord (TcIdOcc s) where
- (TcId id1) `compare` (TcId id2) = id1 `compare` id2
- (RealId id1) `compare` (RealId id2) = id1 `compare` id2
- (TcId _) `compare` (RealId _) = LT
- (RealId _) `compare` (TcId _) = GT
-
-instance Outputable (TcIdOcc s) where
- ppr (TcId id) = ppr id
- ppr (RealId id) = ppr id
+instance Outputable Stage where
+ ppr Comp = text "Comp"
+ ppr (Brack l _ _) = text "Brack" <+> int l
+ ppr (Splice l) = text "Splice" <+> int l
+
+
+metaLevel :: Stage -> Level
+metaLevel Comp = topLevel
+metaLevel (Splice l) = l
+metaLevel (Brack l _ _) = l
+
+wellStaged :: Level -- Binding level
+ -> Level -- Use level
+ -> Bool
+wellStaged bind_stage use_stage
+ = bind_stage <= use_stage
+
+-- Indicates the legal transitions on bracket( [| |] ).
+bracketOK :: Stage -> Maybe Level
+bracketOK (Brack _ _ _) = Nothing -- Bracket illegal inside a bracket
+bracketOK stage = (Just (metaLevel stage + 1))
+
+-- Indicates the legal transitions on splice($).
+spliceOK :: Stage -> Maybe Level
+spliceOK (Splice _) = Nothing -- Splice illegal inside splice
+spliceOK stage = Just (metaLevel stage - 1)
+
+tcMetaTy :: Name -> TcM Type
+-- Given the name of a Template Haskell data type,
+-- return the type
+-- E.g. given the name "Expr" return the type "Expr"
+tcMetaTy tc_name
+ = tcLookupTyCon tc_name `thenM` \ t ->
+ returnM (mkGenTyConApp t [])
+ -- Use mkGenTyConApp because it might be a synonym
+\end{code}
-instance NamedThing (TcIdOcc s) where
- getName (TcId id) = getName id
- getName (RealId id) = getName id
+%************************************************************************
+%* *
+\subsection{TyThingDetails}
+%* *
+%************************************************************************
-tcIdType :: TcIdOcc s -> TcType s
-tcIdType (TcId id) = idType id
-tcIdType (RealId id) = pprPanic "tcIdType:" (ppr id)
+This data type is used to help tie the knot
+ when type checking type and class declarations
-tcIdTyVars (TcId id) = tyVarsOfType (idType id)
-tcIdTyVars (RealId _) = emptyTyVarSet -- Top level Ids have no free type variables
+\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}
--- 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 s], -- It's instantiated type
- TcThetaType s, --
- TcType s) --
+%************************************************************************
+%* *
+\subsection{Basic lookups}
+%* *
+%************************************************************************
-tcInstId id
- = let
- (tyvars, rho) = splitForAllTys (idType id)
- in
- tcInstTyVars tyvars `thenNF_Tc` \ (tyvars', arg_tys, tenv) ->
- tcInstType tenv rho `thenNF_Tc` \ rho' ->
- let
- (theta', tau') = splitRhoTy rho'
- in
- returnNF_Tc (tyvars', theta', tau')
+\begin{code}
+type RecTcGblEnv = TcGblEnv
+-- This environment is used for getting the 'right' IdInfo
+-- on imported things and for looking up Ids in unfoldings
+-- The environment doesn't have any local Ids in it
+
+tcLookupRecId_maybe :: RecTcGblEnv -> Name -> Maybe Id
+tcLookupRecId_maybe env name = case lookup_global env name of
+ Just (AnId id) -> Just id
+ other -> Nothing
\end{code}
-
%************************************************************************
%* *
-\subsection{TcEnv}
+\subsection{Making new Ids}
%* *
%************************************************************************
-Data type declarations
-~~~~~~~~~~~~~~~~~~~~~
+Constructing new Ids
\begin{code}
-data TcEnv s = TcEnv
- (TyVarEnv s)
- (TyConEnv s)
- (ClassEnv s)
- (ValueEnv Id) -- Globals
- (ValueEnv (TcIdBndr s)) -- Locals
- (TcRef s (TcTyVarSet s)) -- Free type variables of locals
- -- ...why mutable? see notes with tcGetGlobalTyVars
-
-type TyVarEnv s = UniqFM (TcKind s, TyVar)
-type TyConEnv s = UniqFM (TcKind s, Maybe Arity, TyCon) -- Arity present for Synonyms only
-type ClassEnv s = UniqFM ([TcKind s], Class) -- The kinds are the kinds of the args
- -- to the class
-type ValueEnv id = UniqFM id
-
-initEnv :: TcRef s (TcTyVarSet s) -> TcEnv s
-initEnv mut = TcEnv emptyUFM emptyUFM emptyUFM emptyUFM emptyUFM mut
-
-getEnv_LocalIds (TcEnv _ _ _ _ ls _) = eltsUFM ls
-getEnv_TyCons (TcEnv _ ts _ _ _ _) = [tycon | (_, _, tycon) <- eltsUFM ts]
-getEnv_Classes (TcEnv _ _ cs _ _ _) = [clas | (_, clas) <- eltsUFM cs]
+newLocalName :: Name -> TcM Name
+newLocalName name -- Make a clone
+ = newUnique `thenM` \ uniq ->
+ returnM (mkInternalName uniq (getOccName name) (getSrcLoc name))
\end{code}
-Type variable env
-~~~~~~~~~~~~~~~~~
+Make a name for the dict fun for an instance decl.
+It's a *local* name for the moment. The CoreTidy pass
+will externalise it.
+
\begin{code}
-tcExtendTyVarEnv :: [Name] -> [(TcKind s, TyVar)] -> TcM s r -> TcM s r
-tcExtendTyVarEnv names kinds_w_types scope
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- let
- tve' = addListToUFM tve (zipEqual "tcTyVarScope" names kinds_w_types)
- in
- tcSetEnv (TcEnv tve' tce ce gve lve gtvs) scope
+newDFunName :: Class -> [Type] -> SrcLoc -> TcM Name
+newDFunName clas (ty:_) loc
+ = newUnique `thenM` \ uniq ->
+ returnM (mkInternalName uniq (mkDFunOcc dfun_string) loc)
+ where
+ -- Any string that is somewhat unique will do
+ dfun_string = occNameString (getOccName clas) ++ occNameString (getDFunTyKey ty)
+
+newDFunName clas [] loc = pprPanic "newDFunName" (ppr clas <+> ppr loc)
\end{code}
-The Kind, TyVar, Class and TyCon envs
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+\begin{code}
+isLocalThing :: NamedThing a => Module -> a -> Bool
+isLocalThing mod thing = nameIsLocalOrFrom mod (getName thing)
+\end{code}
-Extending the environments.
+%************************************************************************
+%* *
+\subsection{The global environment}
+%* *
+%************************************************************************
\begin{code}
-tcExtendTyConEnv :: [(Name, (TcKind s, Maybe Arity, TyCon))] -> TcM s r -> TcM s r
-
-tcExtendTyConEnv bindings scope
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- let
- tce' = addListToUFM tce bindings
- in
- tcSetEnv (TcEnv tve tce' ce gve lve gtvs) scope
+tcExtendGlobalEnv :: [TyThing] -> TcM r -> TcM r
+ -- Given a mixture of Ids, TyCons, Classes, perhaps from the
+ -- module being compiled, perhaps from a package module,
+ -- extend the global environment, and update the EPS
+tcExtendGlobalEnv things thing_inside
+ = do { eps <- getEps
+ ; hpt <- getHpt
+ ; env <- getGblEnv
+ ; let mod = tcg_mod env
+ (lcl_things, pkg_things) = partition (isLocalThing mod) things
+ ge' = extendTypeEnvList (tcg_type_env env) lcl_things
+ eps' = eps { eps_PTE = extendTypeEnvList (eps_PTE eps) pkg_things }
+ ist' = mkImpTypeEnv eps' hpt
+ ; setEps eps'
+ ; setGblEnv (env {tcg_type_env = ge', tcg_ist = ist'}) thing_inside }
+
+tcExtendGlobalValEnv :: [Id] -> TcM a -> TcM a
+ -- Same deal as tcExtendGlobalEnv, but for Ids
+tcExtendGlobalValEnv ids thing_inside
+ = tcExtendGlobalEnv [AnId id | id <- ids] thing_inside
+
+tcExtendGlobalTypeEnv :: TypeEnv -> TcM r -> TcM r
+ -- Top-level things of the interactive context
+ -- No need to extend the package env
+tcExtendGlobalTypeEnv extra_env thing_inside
+ = do { env <- getGblEnv
+ ; let ge' = tcg_type_env env `plusNameEnv` extra_env
+ ; setGblEnv (env {tcg_type_env = ge'}) thing_inside }
+\end{code}
-tcExtendClassEnv :: [(Name, ([TcKind s], Class))] -> TcM s r -> TcM s r
-tcExtendClassEnv bindings scope
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- let
- ce' = addListToUFM ce bindings
- in
- tcSetEnv (TcEnv tve tce ce' gve lve gtvs) scope
+\begin{code}
+lookup_global :: TcGblEnv -> Name -> Maybe TyThing
+ -- Try the global envt and then the global symbol table
+lookup_global env name
+ = lookupNameEnv (tcg_type_env env) name
+ `seqMaybe`
+ tcg_ist env name
+
+tcLookupGlobal_maybe :: Name -> TcRn m (Maybe TyThing)
+tcLookupGlobal_maybe name
+ = getGblEnv `thenM` \ env ->
+ returnM (lookup_global env name)
\end{code}
-
-Looking up in the environments.
+A variety of global lookups, when we know what we are looking for.
\begin{code}
-tcLookupTyVar name
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- returnNF_Tc (lookupWithDefaultUFM tve (pprPanic "tcLookupTyVar:" (ppr name)) name)
+tcLookupGlobal :: Name -> TcM TyThing
+tcLookupGlobal name
+ = tcLookupGlobal_maybe name `thenM` \ maybe_thing ->
+ case maybe_thing of
+ Just thing -> returnM thing
+ other -> notFound "tcLookupGlobal" name
+
+tcLookupGlobalId :: Name -> TcM Id
+tcLookupGlobalId name
+ = tcLookupGlobal_maybe name `thenM` \ maybe_thing ->
+ case maybe_thing of
+ Just (AnId id) -> returnM id
+ other -> notFound "tcLookupGlobal" name
+
+tcLookupDataCon :: Name -> TcM DataCon
+tcLookupDataCon con_name
+ = tcLookupGlobalId con_name `thenM` \ con_id ->
+ case isDataConWrapId_maybe con_id of
+ Just data_con -> returnM data_con
+ Nothing -> failWithTc (badCon con_id)
+
+tcLookupClass :: Name -> TcM Class
+tcLookupClass name
+ = tcLookupGlobal_maybe name `thenM` \ maybe_clas ->
+ case maybe_clas of
+ Just (AClass clas) -> returnM clas
+ other -> notFound "tcLookupClass" name
+
+tcLookupTyCon :: Name -> TcM TyCon
+tcLookupTyCon name
+ = tcLookupGlobal_maybe name `thenM` \ maybe_tc ->
+ case maybe_tc of
+ Just (ATyCon tc) -> returnM tc
+ other -> notFound "tcLookupTyCon" name
-tcLookupTyCon name
- = -- Try for a wired-in tycon
- case maybeWiredInTyConName name of {
- Just tc | isSynTyCon tc -> returnTc (kind, Just (tyConArity tc), tc)
- | otherwise -> returnTc (kind, Nothing, tc)
- where {
- kind = kindToTcKind (tyConKind tc)
- };
-
- Nothing ->
-
- -- Try in the environment
- tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- case lookupUFM tce name of {
- Just stuff -> returnTc stuff;
-
- Nothing ->
-
- -- Could be that he's using a class name as a type constructor
- case lookupUFM ce name of
- Just _ -> failWithTc (classAsTyConErr name)
- Nothing -> pprPanic "tcLookupTyCon:" (ppr name)
- } }
-
-tcLookupTyConByKey uniq
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- let
- (kind, arity, tycon) = lookupWithDefaultUFM_Directly tce
- (pprPanic "tcLookupTyConByKey:" (pprUnique10 uniq))
- uniq
- in
- returnNF_Tc tycon
+getInGlobalScope :: TcRn m (Name -> Bool)
+getInGlobalScope = do { gbl_env <- getGblEnv ;
+ return (\n -> isJust (lookup_global gbl_env n)) }
+\end{code}
-tcLookupClass name
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- case lookupUFM ce name of
- Just stuff -- Common case: it's ok
- -> returnTc stuff
- Nothing -- Could be that he's using a type constructor as a class
- | maybeToBool (maybeWiredInTyConName name)
- || maybeToBool (lookupUFM tce name)
- -> failWithTc (tyConAsClassErr name)
+%************************************************************************
+%* *
+\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
- | otherwise -- Wierd! Renamer shouldn't let this happen
- -> pprPanic "tcLookupClass" (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
+ AGlobal (AnId id) -> returnM id
+ other -> pprPanic "tcLookupId" (ppr name)
+
+tcLookupIdLvl :: Name -> TcM (Id, Level)
+tcLookupIdLvl name
+ = tcLookup name `thenM` \ thing ->
+ case thing of
+ ATcId tc_id lvl -> returnM (tc_id, lvl)
+ AGlobal (AnId id) -> returnM (id, impLevel)
+ other -> pprPanic "tcLookupIdLvl" (ppr name)
+
+tcLookupLocalIds :: [Name] -> TcM [TcId]
+-- We expect the variables to all be bound, and all at
+-- the same level as the lookup. Only used in one place...
+tcLookupLocalIds ns
+ = getLclEnv `thenM` \ env ->
+ returnM (map (lookup (tcl_env env) (metaLevel (tcl_level env))) ns)
+ where
+ lookup lenv lvl name
+ = case lookupNameEnv lenv name of
+ Just (ATcId id lvl1) -> ASSERT( lvl == lvl1 ) id
+ other -> pprPanic "tcLookupLocalIds" (ppr name)
+
+getLclEnvElts :: TcM [TcTyThing]
+getLclEnvElts = getLclEnv `thenM` \ env ->
+ return (nameEnvElts (tcl_env env))
+
+getInLocalScope :: TcM (Name -> Bool)
+ -- Ids only
+getInLocalScope = getLclEnv `thenM` \ env ->
+ let
+ lcl_env = tcl_env env
+ in
+ return (`elemNameEnv` lcl_env)
+\end{code}
-tcLookupClassByKey uniq
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+\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
- (kind, clas) = lookupWithDefaultUFM_Directly ce
- (pprPanic "tcLookupClassByKey:" (pprUnique10 uniq))
- uniq
+ le' = extendNameEnvList le binds
+ new_tv_set = mkVarSet tyvars
in
- returnNF_Tc clas
-
-tcGetTyConsAndClasses :: NF_TcM s ([TyCon], [Class])
-tcGetTyConsAndClasses
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- returnNF_Tc ([tc | (_, _, tc) <- eltsUFM tce],
- [c | (_, c) <- eltsUFM ce])
+ -- 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 ...
+ -- 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
\end{code}
-
-Extending and consulting the value environment
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\begin{code}
-tcExtendGlobalValEnv ids scope
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+tcExtendLocalValEnv :: [TcId] -> TcM a -> TcM a
+tcExtendLocalValEnv ids thing_inside
+ = getLclEnv `thenM` \ env ->
let
- gve' = addListToUFM_Directly gve [(uniqueOf id, id) | id <- ids]
+ extra_global_tyvars = tyVarsOfTypes [idType id | id <- ids]
+ lvl = metaLevel (tcl_level env)
+ extra_env = [(idName id, ATcId id lvl) | id <- ids]
+ le' = extendNameEnvList (tcl_env env) extra_env
in
- tcSetEnv (TcEnv tve tce ce gve' lve gtvs) scope
+ tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars `thenM` \ gtvs' ->
+ setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside
-tcExtendLocalValEnv names ids scope
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- tcReadMutVar gtvs `thenNF_Tc` \ global_tvs ->
+tcExtendLocalValEnv2 :: [(Name,TcId)] -> TcM a -> TcM a
+tcExtendLocalValEnv2 names_w_ids thing_inside
+ = getLclEnv `thenM` \ env ->
let
- lve' = addListToUFM lve (zipEqual "tcExtendLocalValEnv" names ids)
- extra_global_tyvars = tyVarsOfTypes (map idType ids)
- new_global_tyvars = global_tvs `unionTyVarSets` extra_global_tyvars
+ extra_global_tyvars = tyVarsOfTypes [idType id | (name,id) <- names_w_ids]
+ lvl = metaLevel (tcl_level env)
+ extra_env = [(name, ATcId id lvl) | (name,id) <- names_w_ids]
+ le' = extendNameEnvList (tcl_env env) extra_env
in
- tcNewMutVar new_global_tyvars `thenNF_Tc` \ gtvs' ->
+ tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars `thenM` \ gtvs' ->
+ setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs'}) thing_inside
+\end{code}
+
- tcSetEnv (TcEnv tve tce ce gve lve' gtvs') scope
+%************************************************************************
+%* *
+\subsection{The global tyvars}
+%* *
+%************************************************************************
+
+\begin{code}
+tc_extend_gtvs gtvs extra_global_tvs
+ = readMutVar gtvs `thenM` \ global_tvs ->
+ newMutVar (global_tvs `unionVarSet` extra_global_tvs)
\end{code}
@tcGetGlobalTyVars@ returns a fully-zonked set of tyvars free in the environment.
the environment.
\begin{code}
-tcGetGlobalTyVars :: NF_TcM s (TcTyVarSet s)
+tcGetGlobalTyVars :: TcM TcTyVarSet
tcGetGlobalTyVars
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- tcReadMutVar gtvs `thenNF_Tc` \ global_tvs ->
- zonkTcTyVars global_tvs `thenNF_Tc` \ global_tvs' ->
- tcWriteMutVar gtvs global_tvs' `thenNF_Tc_`
- returnNF_Tc global_tvs'
-
-tcExtendGlobalTyVars extra_global_tvs scope
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- tcReadMutVar gtvs `thenNF_Tc` \ global_tvs ->
- let
- new_global_tyvars = global_tvs `unionTyVarSets` mkTyVarSet extra_global_tvs
- in
- tcNewMutVar new_global_tyvars `thenNF_Tc` \ gtvs' ->
- tcSetEnv (TcEnv tve tce ce gve lve gtvs') scope
+ = 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}
+%* *
+%************************************************************************
+
\begin{code}
-tcLookupLocalValue :: Name -> NF_TcM s (Maybe (TcIdBndr s))
-tcLookupLocalValue name
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- returnNF_Tc (lookupUFM lve name)
-
-tcLookupLocalValueByKey :: Unique -> NF_TcM s (Maybe (TcIdBndr s))
-tcLookupLocalValueByKey uniq
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- returnNF_Tc (lookupUFM_Directly lve uniq)
-
-tcLookupLocalValueOK :: String -> Name -> NF_TcM s (TcIdBndr s)
-tcLookupLocalValueOK err name
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- returnNF_Tc (lookupWithDefaultUFM lve (panic err) name)
-
-
-tcLookupGlobalValue :: Name -> NF_TcM s Id
-tcLookupGlobalValue name
- = case maybeWiredInIdName name of
- Just id -> returnNF_Tc id
- Nothing -> tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- returnNF_Tc (lookupWithDefaultUFM gve def name)
+tcGetInstEnv :: TcM InstEnv
+tcGetInstEnv = getGblEnv `thenM` \ env ->
+ returnM (tcg_inst_env env)
+
+tcSetInstEnv :: InstEnv -> TcM a -> TcM a
+tcSetInstEnv ie thing_inside
+ = getGblEnv `thenM` \ env ->
+ setGblEnv (env {tcg_inst_env = ie}) thing_inside
+
+tcExtendInstEnv :: [DFunId] -> TcM a -> TcM a
+ -- Add instances from local or imported
+ -- instances, and refresh the instance-env cache
+tcExtendInstEnv dfuns thing_inside
+ = do { dflags <- getDOpts
+ ; eps <- getEps
+ ; env <- getGblEnv
+ ; let
+ -- Extend the total inst-env with the new dfuns
+ (inst_env', errs) = extendInstEnv dflags (tcg_inst_env env) dfuns
+
+ -- Sort the ones from this module from the others
+ (lcl_dfuns, pkg_dfuns) = partition (isLocalThing mod) dfuns
+ mod = tcg_mod env
+
+ -- And add the pieces to the right places
+ (eps_inst_env', _) = extendInstEnv dflags (eps_inst_env eps) pkg_dfuns
+ eps' = eps { eps_inst_env = eps_inst_env' }
+
+ env' = env { tcg_inst_env = inst_env',
+ tcg_insts = lcl_dfuns ++ tcg_insts env }
+
+ ; traceDFuns dfuns
+ ; addErrs errs
+ ; setEps eps'
+ ; setGblEnv env' thing_inside }
+
+tcExtendLocalInstEnv :: [InstInfo] -> TcM a -> TcM a
+ -- Special case for local instance decls
+tcExtendLocalInstEnv infos thing_inside
+ = do { dflags <- getDOpts
+ ; env <- getGblEnv
+ ; let
+ dfuns = map iDFunId infos
+ (inst_env', errs) = extendInstEnv dflags (tcg_inst_env env) dfuns
+ env' = env { tcg_inst_env = inst_env',
+ tcg_insts = dfuns ++ tcg_insts env }
+ ; traceDFuns dfuns
+ ; addErrs errs
+ ; setGblEnv env' thing_inside }
+
+traceDFuns dfuns
+ = traceTc (text "Adding instances:" <+> vcat (map pp dfuns))
where
- def = pprPanic "tcLookupGlobalValue:" (ppr name)
-
-tcLookupGlobalValueMaybe :: Name -> NF_TcM s (Maybe Id)
-tcLookupGlobalValueMaybe name
- = case maybeWiredInIdName name of
- Just id -> returnNF_Tc (Just id)
- Nothing -> tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- returnNF_Tc (lookupUFM gve name)
+ pp dfun = ppr dfun <+> dcolon <+> ppr (idType dfun)
+\end{code}
-tcLookupGlobalValueByKey :: Unique -> NF_TcM s Id
-tcLookupGlobalValueByKey uniq
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- returnNF_Tc (lookupWithDefaultUFM_Directly gve def uniq)
- where
-#ifdef DEBUG
- def = pprPanic "tcLookupGlobalValueByKey:" (pprUnique10 uniq)
-#else
- def = panic "tcLookupGlobalValueByKey"
-#endif
+%************************************************************************
+%* *
+\subsection{Rules}
+%* *
+%************************************************************************
-tcLookupGlobalValueByKeyMaybe :: Unique -> NF_TcM s (Maybe Id)
-tcLookupGlobalValueByKeyMaybe uniq
- = tcGetEnv `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
- returnNF_Tc (lookupUFM_Directly gve uniq)
+\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}
--- Non-monadic version, environment given explicitly
-tcExplicitLookupGlobal :: TcEnv s -> Name -> Maybe Id
-tcExplicitLookupGlobal (TcEnv tve tce ce gve lve gtvs) name
- = case maybeWiredInIdName name of
- Just id -> Just id
- Nothing -> lookupUFM gve name
+%************************************************************************
+%* *
+\subsection{The InstInfo type}
+%* *
+%************************************************************************
- -- Extract the IdInfo from an IfaceSig imported from an interface file
-tcAddImportedIdInfo :: TcEnv s -> 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 `replaceIdInfo` new_info
- -- The Id must be returned without a data dependency on maybe_id
- where
- new_info = -- pprTrace "tcAdd" (ppr id) $
- case tcExplicitLookupGlobal unf_env (getName id) of
- Nothing -> noIdInfo
- Just imported_id -> getIdInfo imported_id
- -- ToDo: could check that types are the same
-\end{code}
+The InstInfo type summarises the information in an instance declaration
+ instance c => k (t tvs) where b
-Constructing new Ids
-~~~~~~~~~~~~~~~~~~~~
+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}
--- Uses the Name as the Name of the Id
-newMonoIds :: [Name] -> Kind -> ([TcIdBndr s] -> TcM s a) -> TcM s a
-
-newMonoIds names kind m
- = newTyVarTys no_of_names kind `thenNF_Tc` \ tys ->
- let
- new_ids = zipWithEqual "newMonoIds" mk_id names tys
- mk_id name ty = mkUserId name ty NoPragmaInfo
- in
- tcExtendLocalValEnv names new_ids (m new_ids)
- where
- no_of_names = length names
-
-newLocalId :: OccName -> TcType s -> NF_TcM s (TcIdBndr s)
-newLocalId name ty
- = tcGetSrcLoc `thenNF_Tc` \ loc ->
- tcGetUnique `thenNF_Tc` \ uniq ->
- returnNF_Tc (mkUserLocal name uniq ty loc)
-
-newLocalIds :: [OccName] -> [TcType s] -> NF_TcM s [TcIdBndr s]
-newLocalIds names tys
- = tcGetSrcLoc `thenNF_Tc` \ loc ->
- tcGetUniques (length names) `thenNF_Tc` \ uniqs ->
- let
- new_ids = zipWith3Equal "newLocalIds" mk_id names uniqs tys
- mk_id name uniq ty = mkUserLocal name uniq ty loc
- in
- returnNF_Tc new_ids
+data InstInfo
+ = InstInfo {
+ iDFunId :: DFunId, -- The dfun id
+ iBinds :: RenamedMonoBinds, -- Bindings, b
+ iPrags :: [RenamedSig] -- User pragmas recorded for generating specialised instances
+ }
+
+ | NewTypeDerived { -- Used for deriving instances of newtypes, where the
+ -- witness dictionary is identical to the argument dictionary
+ -- Hence no bindings.
+ iDFunId :: DFunId -- The dfun id
+ }
+
+pprInstInfo info = vcat [ptext SLIT("InstInfo:") <+> ppr (idType (iDFunId info))]
+pprInstInfoDetails (InstInfo { iBinds = b }) = ppr b
+pprInstInfoDetails (NewTypeDerived _) = text "Derived from the represenation type"
+
+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}
+%************************************************************************
+%* *
+\subsection{Errors}
+%* *
+%************************************************************************
+
\begin{code}
-classAsTyConErr name
- = ptext SLIT("Class used as a type constructor:") <+> ppr name
+badCon con_id = quotes (ppr con_id) <+> ptext SLIT("is not a data constructor")
-tyConAsClassErr name
- = ptext SLIT("Type constructor used as a class:") <+> ppr name
+notFound wheRe name = failWithTc (text wheRe <> colon <+> quotes (ppr name) <+>
+ ptext SLIT("is not in scope"))
\end{code}