\begin{code}
module TcEnv(
TcId, TcIdSet,
- TyThing(..), TyThingDetails(..),
+ TyThing(..), TyThingDetails(..), TcTyThing(..),
-- Getting stuff from the environment
TcEnv, initTcEnv,
- tcEnvTyCons, tcEnvClasses, tcEnvIds, tcEnvTcIds,
+ tcEnvTyCons, tcEnvClasses, tcEnvIds, tcLEnvElts,
+ getTcGEnv,
- -- Instance environment
+ -- Instance environment, and InstInfo type
tcGetInstEnv, tcSetInstEnv,
+ InstInfo(..), pprInstInfo,
+ simpleInstInfoTy, simpleInstInfoTyCon,
-- Global environment
- tcExtendGlobalEnv, tcExtendGlobalValEnv,
- tcLookupTy, tcLookupTyCon, tcLookupClass, tcLookupGlobalId, tcLookupDataCon,
+ tcExtendGlobalEnv, tcExtendGlobalValEnv, tcExtendGlobalTypeEnv,
+ tcLookupTyCon, tcLookupClass, tcLookupGlobalId, tcLookupDataCon,
+ tcLookupGlobal_maybe, tcLookupGlobal,
-- Local environment
- tcExtendKindEnv,
+ tcExtendKindEnv, tcLookupLocalIds, tcInLocalScope,
tcExtendTyVarEnv, tcExtendTyVarEnvForMeths,
- tcExtendLocalValEnv,
+ tcExtendLocalValEnv, tcLookup, tcLookup_maybe, tcLookupId,
-- Global type variables
tcGetGlobalTyVars, tcExtendGlobalTyVars,
-- Random useful things
- tcAddImportedIdInfo, tcInstId,
+ RecTcEnv, tcLookupRecId, tcLookupRecId_maybe,
-- New Ids
- newLocalId, newSpecPragmaId,
- newDefaultMethodName, newDFunName
+ newLocalName, newDFunName,
+
+ -- Misc
+ isLocalThing, isHomePackageThing, tcSetEnv
) where
#include "HsVersions.h"
+import RnHsSyn ( RenamedMonoBinds, RenamedSig )
import TcMonad
-import TcType ( TcKind, TcType, TcTyVar, TcTyVarSet, TcThetaType,
- tcInstTyVars, zonkTcTyVars,
- )
-import Id ( mkUserLocal, isDataConWrapId_maybe )
-import IdInfo ( vanillaIdInfo )
-import MkId ( mkSpecPragmaId )
-import Var ( TyVar, Id, setVarName,
- idType, lazySetIdInfo, idInfo, tyVarKind, UVar,
- )
+import TcMType ( zonkTcTyVarsAndFV )
+import TcType ( Type, ThetaType, TcKind, TcTyVar, TcTyVarSet,
+ tyVarsOfTypes, tcSplitDFunTy,
+ getDFunTyKey, tcTyConAppTyCon
+ )
+import Id ( idName, isDataConWrapId_maybe )
+import IdInfo ( vanillaIdInfo )
+import Var ( TyVar, Id, idType, lazySetIdInfo, idInfo )
import VarSet
-import VarEnv ( TyVarSubstEnv )
-import Type ( Kind, Type, superKind,
- tyVarsOfType, tyVarsOfTypes,
- splitForAllTys, splitRhoTy, splitFunTys,
- splitAlgTyConApp_maybe, getTyVar, getDFunTyKey
- )
-import DataCon ( DataCon )
-import TyCon ( TyCon, tyConKind, tyConArity, isSynTyCon )
-import Class ( Class, ClassOpItem, ClassContext, classTyCon )
-import Subst ( substTy )
-import Name ( Name, OccName, Provenance(..), ExportFlag(..), NamedThing(..),
- nameOccName, nameModule, getSrcLoc, mkGlobalName,
- maybeWiredInTyConName, maybeWiredInIdName, isLocallyDefined,
- NameEnv, emptyNameEnv, lookupNameEnv, nameEnvElts,
- extendNameEnv, extendNameEnvList
- )
-import OccName ( mkDFunOcc, mkDefaultMethodOcc, occNameString )
-import Module ( Module )
-import Unify ( unifyTyListsX, matchTys )
-import HscTypes ( ModDetails(..), InstEnv, lookupTypeEnv )
-import Unique ( pprUnique10, Unique, Uniquable(..) )
-import UniqFM
-import Unique ( Uniquable(..) )
-import Util ( zipEqual, zipWith3Equal, mapAccumL )
-import SrcLoc ( SrcLoc )
-import FastString ( FastString )
-import Maybes
+import DataCon ( DataCon )
+import TyCon ( TyCon )
+import Class ( Class, ClassOpItem )
+import Name ( Name, NamedThing(..),
+ getSrcLoc, mkLocalName, isLocalName, nameIsLocalOrFrom,
+ isHomePackageName
+ )
+import NameEnv ( NameEnv, lookupNameEnv, nameEnvElts, elemNameEnv,
+ extendNameEnvList, emptyNameEnv, plusNameEnv )
+import OccName ( mkDFunOcc, occNameString )
+import HscTypes ( DFunId,
+ PackageTypeEnv, TypeEnv,
+ extendTypeEnvList, extendTypeEnvWithIds,
+ typeEnvTyCons, typeEnvClasses, typeEnvIds,
+ HomeSymbolTable
+ )
+import Module ( Module )
+import InstEnv ( InstEnv, emptyInstEnv )
+import HscTypes ( lookupType, TyThing(..) )
+import Util ( zipEqual )
+import SrcLoc ( SrcLoc )
import Outputable
+
+import IOExts ( newIORef )
\end{code}
%************************************************************************
data TcEnv
= TcEnv {
- tcGST :: GlobalSymbolTable, -- The symbol table at the moment we began this compilation
+ tcGST :: Name -> Maybe TyThing, -- The type environment at the moment we began this compilation
tcInsts :: InstEnv, -- All instances (both imported and in this module)
- tcGEnv :: NameEnv TyThing, -- The global type environment we've accumulated while
- -- compiling this module:
+ tcGEnv :: TypeEnv, -- The global type environment we've accumulated while
+ {- NameEnv TyThing-} -- compiling this module:
-- types and classes (both imported and local)
-- imported Ids
- -- (Ids defined in this module are in the local envt)
+ -- (Ids defined in this module start in the local envt,
+ -- though they move to the global envt during zonking)
tcLEnv :: NameEnv TcTyThing, -- The local type environment: Ids and TyVars
-- defined in this module
\begin{code}
+initTcEnv :: HomeSymbolTable -> PackageTypeEnv -> IO TcEnv
+initTcEnv hst pte
+ = do { gtv_var <- newIORef emptyVarSet ;
+ return (TcEnv { tcGST = lookup,
+ tcGEnv = emptyNameEnv,
+ tcInsts = emptyInstEnv,
+ tcLEnv = emptyNameEnv,
+ tcTyVars = gtv_var
+ })}
+ where
+ lookup name | isLocalName name = Nothing
+ | otherwise = lookupType hst pte name
+
+
+tcEnvClasses env = typeEnvClasses (tcGEnv env)
+tcEnvTyCons env = typeEnvTyCons (tcGEnv env)
+tcEnvIds env = typeEnvIds (tcGEnv env)
+tcLEnvElts env = nameEnvElts (tcLEnv env)
+
+getTcGEnv (TcEnv { tcGEnv = genv }) = genv
+
+tcInLocalScope :: TcEnv -> Name -> Bool
+tcInLocalScope env v = v `elemNameEnv` (tcLEnv env)
+\end{code}
+
+\begin{code}
data TcTyThing
- = AGlobal TyThing -- Used only in the return type of a lookup
- | ATcId TcId -- Ids defined in this module
- | ATyVar TyVar -- Type variables
- | AThing TcKind -- Used temporarily, during kind checking
+ = AGlobal TyThing -- Used only in the return type of a lookup
+ | ATcId TcId -- Ids defined in this module
+ | ATyVar TyVar -- Type variables
+ | AThing TcKind -- Used temporarily, during kind checking
-- Here's an example of how the AThing guy is used
-- Suppose we are checking (forall a. T a Int):
-- 1. We first bind (a -> AThink kv), where kv is a kind variable.
-- 3. Then we zonk the kind variable.
-- 4. Now we know the kind for 'a', and we add (a -> ATyVar a::K) to the environment
-initTcEnv :: GlobalSymbolTable -> InstEnv -> IO TcEnv
-initTcEnv gst inst_env
- = do { gtv_var <- newIORef emptyVarSet
- return (TcEnv { tcGST = gst,
- tcGEnv = emptyNameEnv,
- tcInsts = inst_env,
- tcLEnv = emptyNameEnv,
- tcTyVars = gtv_var
- })}
+\end{code}
-tcEnvClasses env = [cl | AClass cl <- nameEnvElts (tcGEnv env)]
-tcEnvTyCons env = [tc | ATyCon tc <- nameEnvElts (tcGEnv env)]
-tcEnvIds env = [id | AnId id <- nameEnvElts (tcGEnv env)]
-tcEnvTyVars env = [tv | ATyVar tv <- nameEnvElts (tcLEnv env)]
-tcEnvTcIds env = [id | ATcId id <- nameEnvElts (tcLEnv env)]
+This data type is used to help tie the knot
+ when type checking type and class declarations
--- This data type is used to help tie the knot
--- when type checking type and class declarations
+\begin{code}
data TyThingDetails = SynTyDetails Type
- | DataTyDetails ClassContext [DataCon] [Class]
- | ClassDetails ClassContext [Id] [ClassOpItem] DataCon
+ | DataTyDetails ThetaType [DataCon] [Id]
+ | ClassDetails ThetaType [Id] [ClassOpItem] DataCon
+ | ForeignTyDetails -- Nothing yet
\end{code}
-
%************************************************************************
%* *
\subsection{Basic lookups}
lookup_global env name
= case lookupNameEnv (tcGEnv env) name of
Just thing -> Just thing
- Nothing -> lookupTypeEnv (tcGST env) name
+ Nothing -> tcGST env name
lookup_local :: TcEnv -> Name -> Maybe TcTyThing
-- Try the local envt and then try the global
= case lookupNameEnv (tcLEnv env) name of
Just thing -> Just thing
Nothing -> case lookup_global env name of
- Just thing -> AGlobal thing
+ Just thing -> Just (AGlobal thing)
Nothing -> Nothing
-
-explicitLookupId :: TcEnv -> Name -> Maybe Id
-explicitLookupId env name = case lookup_global env name of
- Just (AnId id) -> Just id
- other -> Nothing
\end{code}
-
-%************************************************************************
-%* *
-\subsection{Random useful functions}
-%* *
-%************************************************************************
-
-
\begin{code}
--- A useful function that takes an occurrence of a global thing
--- and instantiates its type with fresh type variables
-tcInstId :: Id
- -> NF_TcM ([TcTyVar], -- It's instantiated type
- TcThetaType, --
- TcType) --
-tcInstId id
- = let
- (tyvars, rho) = splitForAllTys (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')
-
-tcAddImportedIdInfo :: TcEnv -> 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 = case explicitLookupId unf_env (getName id) of
- Nothing -> vanillaIdInfo
- Just imported_id -> idInfo imported_id
- -- ToDo: could check that types are the same
+type RecTcEnv = TcEnv
+-- This environment is used for getting the 'right' IdInfo
+-- on imported things and for looking up Ids in unfoldings
+-- The environment doesn't have any local Ids in it
+
+tcLookupRecId_maybe :: RecTcEnv -> Name -> Maybe Id
+tcLookupRecId_maybe env name = case lookup_global env name of
+ Just (AnId id) -> Just id
+ other -> Nothing
+
+tcLookupRecId :: RecTcEnv -> Name -> Id
+tcLookupRecId env name = case lookup_global env name of
+ Just (AnId id) -> id
+ Nothing -> pprPanic "tcLookupRecId" (ppr name)
\end{code}
-
%************************************************************************
%* *
\subsection{Making new Ids}
Constructing new Ids
\begin{code}
-newLocalId :: OccName -> TcType -> SrcLoc -> NF_TcM TcId
-newLocalId name ty loc
- = tcGetUnique `thenNF_Tc` \ uniq ->
- returnNF_Tc (mkUserLocal name uniq ty loc)
-
-newSpecPragmaId :: Name -> TcType -> NF_TcM TcId
-newSpecPragmaId name ty
+newLocalName :: Name -> NF_TcM Name
+newLocalName name -- Make a clone
= tcGetUnique `thenNF_Tc` \ uniq ->
- returnNF_Tc (mkSpecPragmaId (nameOccName name) uniq ty (getSrcLoc name))
+ returnNF_Tc (mkLocalName uniq (getOccName name) (getSrcLoc name))
\end{code}
-Make a name for the dict fun for an instance decl
+Make a name for the dict fun for an instance decl.
+It's a *local* name for the moment. The CoreTidy pass
+will globalise it.
\begin{code}
-newDFunName :: Module -> Class -> [Type] -> SrcLoc -> NF_TcM Name
-newDFunName mod clas (ty:_) loc
- = tcGetDFunUniq dfun_string `thenNF_Tc` \ inst_uniq ->
- tcGetUnique `thenNF_Tc` \ uniq ->
- returnNF_Tc (mkGlobalName uniq mod
- (mkDFunOcc dfun_string inst_uniq)
- (LocalDef loc Exported))
+newDFunName :: Class -> [Type] -> SrcLoc -> NF_TcM Name
+newDFunName clas (ty:_) loc
+ = tcGetUnique `thenNF_Tc` \ uniq ->
+ returnNF_Tc (mkLocalName uniq (mkDFunOcc dfun_string) loc)
where
-- Any string that is somewhat unique will do
dfun_string = occNameString (getOccName clas) ++ occNameString (getDFunTyKey ty)
-newDefaultMethodName :: Name -> SrcLoc -> NF_TcM Name
-newDefaultMethodName op_name loc
- = tcGetUnique `thenNF_Tc` \ uniq ->
- returnNF_Tc (mkGlobalName uniq (nameModule op_name)
- (mkDefaultMethodOcc (getOccName op_name))
- (LocalDef loc Exported))
+newDFunName clas [] loc = pprPanic "newDFunName" (ppr clas <+> ppr loc)
\end{code}
+\begin{code}
+isLocalThing :: NamedThing a => Module -> a -> Bool
+isLocalThing mod thing = nameIsLocalOrFrom mod (getName thing)
+
+isHomePackageThing :: NamedThing a => a -> Bool
+isHomePackageThing thing = isHomePackageName (getName thing)
+\end{code}
%************************************************************************
%* *
%************************************************************************
\begin{code}
-tcExtendGlobalEnv :: [(Name, TyThing)] -> TcM r -> TcM r
-tcExtendGlobalEnv bindings thing_inside
+tcExtendGlobalEnv :: [TyThing] -> TcM r -> TcM r
+tcExtendGlobalEnv things thing_inside
+ = tcGetEnv `thenNF_Tc` \ env ->
+ let
+ ge' = extendTypeEnvList (tcGEnv env) things
+ in
+ tcSetEnv (env {tcGEnv = ge'}) thing_inside
+
+
+tcExtendGlobalTypeEnv :: TypeEnv -> TcM r -> TcM r
+tcExtendGlobalTypeEnv extra_env thing_inside
= tcGetEnv `thenNF_Tc` \ env ->
let
- ge' = extendNameEnvList (tcGEnv env) bindings
+ ge' = tcGEnv env `plusNameEnv` extra_env
in
tcSetEnv (env {tcGEnv = ge'}) thing_inside
tcExtendGlobalValEnv :: [Id] -> TcM a -> TcM a
tcExtendGlobalValEnv ids thing_inside
- = tcExtendGlobalEnv [(getName id, AnId id) | id <- ids] thing_inside
+ = tcGetEnv `thenNF_Tc` \ env ->
+ let
+ ge' = extendTypeEnvWithIds (tcGEnv env) ids
+ in
+ tcSetEnv (env {tcGEnv = ge'}) thing_inside
\end{code}
\begin{code}
tcLookupGlobal :: Name -> NF_TcM TyThing
+tcLookupGlobal name
= tcLookupGlobal_maybe name `thenNF_Tc` \ maybe_thing ->
case maybe_thing of
Just thing -> returnNF_Tc thing
- other -> notFound "tcLookupGlobal:" name
+ other -> notFound "tcLookupGlobal" name
tcLookupGlobalId :: Name -> NF_TcM Id
tcLookupGlobalId name
= tcLookupGlobal_maybe name `thenNF_Tc` \ maybe_id ->
case maybe_id of
- Just (AnId clas) -> returnNF_Tc id
- other -> notFound "tcLookupGlobalId:" name
+ Just (AnId id) -> returnNF_Tc id
+ other -> notFound "tcLookupGlobalId" name
tcLookupDataCon :: Name -> TcM DataCon
tcLookupDataCon con_name
= tcLookupGlobal_maybe name `thenNF_Tc` \ maybe_clas ->
case maybe_clas of
Just (AClass clas) -> returnNF_Tc clas
- other -> notFound "tcLookupClass:" name
+ other -> notFound "tcLookupClass" name
tcLookupTyCon :: Name -> NF_TcM TyCon
tcLookupTyCon name
= tcLookupGlobal_maybe name `thenNF_Tc` \ maybe_tc ->
case maybe_tc of
Just (ATyCon tc) -> returnNF_Tc tc
- other -> notFound "tcLookupTyCon:" name
+ other -> notFound "tcLookupTyCon" name
+
+tcLookupId :: Name -> NF_TcM Id
+tcLookupId name
+ = tcLookup name `thenNF_Tc` \ thing ->
+ case thing of
+ ATcId tc_id -> returnNF_Tc tc_id
+ AGlobal (AnId id) -> returnNF_Tc id
+ other -> pprPanic "tcLookupId" (ppr name)
+
+tcLookupLocalIds :: [Name] -> NF_TcM [TcId]
+tcLookupLocalIds ns
+ = tcGetEnv `thenNF_Tc` \ env ->
+ returnNF_Tc (map (lookup (tcLEnv env)) ns)
+ where
+ lookup lenv name = case lookupNameEnv lenv name of
+ Just (ATcId id) -> id
+ other -> pprPanic "tcLookupLocalIds" (ppr name)
\end{code}
= tcLookup_maybe name `thenNF_Tc` \ maybe_thing ->
case maybe_thing of
Just thing -> returnNF_Tc thing
- other -> notFound "tcLookup:" name
+ other -> notFound "tcLookup" name
-- Extract the IdInfo from an IfaceSig imported from an interface file
\end{code}
tcGetGlobalTyVars :: NF_TcM TcTyVarSet
tcGetGlobalTyVars
= tcGetEnv `thenNF_Tc` \ (TcEnv {tcTyVars = gtv_var}) ->
- tcReadMutVar gtv_var `thenNF_Tc` \ global_tvs ->
- zonkTcTyVars (varSetElems global_tvs) `thenNF_Tc` \ global_tys' ->
- let
- global_tvs' = (tyVarsOfTypes global_tys')
- in
- tcWriteMutVar gtv_var global_tvs' `thenNF_Tc_`
- returnNF_Tc global_tvs'
+ tcReadMutVar gtv_var `thenNF_Tc` \ gbl_tvs ->
+ zonkTcTyVarsAndFV (varSetElems gbl_tvs) `thenNF_Tc` \ gbl_tvs' ->
+ tcWriteMutVar gtv_var gbl_tvs' `thenNF_Tc_`
+ returnNF_Tc gbl_tvs'
\end{code}
%************************************************************************
%* *
+\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}
+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))]
+
+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}
%* *
%************************************************************************