+%
+% (c) The University of Glasgow 2006
+%
+
\begin{code}
+{-# OPTIONS -w #-}
+-- The above warning supression flag is a temporary kludge.
+-- While working on this module you are encouraged to remove it and fix
+-- any warnings in the module. See
+-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
+-- for details
+
module TcEnv(
TyThing(..), TcTyThing(..), TcId,
tcExtendGlobalEnv,
tcExtendGlobalValEnv,
tcLookupLocatedGlobal, tcLookupGlobal,
- tcLookupGlobalId, tcLookupTyCon, tcLookupClass, tcLookupDataCon,
+ tcLookupField, tcLookupTyCon, tcLookupClass, tcLookupDataCon,
tcLookupLocatedGlobalId, tcLookupLocatedTyCon,
- tcLookupLocatedClass,
+ tcLookupLocatedClass, tcLookupFamInst,
-- Local environment
tcExtendKindEnv, tcExtendKindEnvTvs,
tcExtendTyVarEnv, tcExtendTyVarEnv2,
+ tcExtendGhciEnv,
tcExtendIdEnv, tcExtendIdEnv1, tcExtendIdEnv2,
- tcLookup, tcLookupLocated, tcLookupLocalIds, tcLookupLocalId_maybe,
+ tcLookup, tcLookupLocated, tcLookupLocalIds,
tcLookupId, tcLookupTyVar, getScopedTyVarBinds,
lclEnvElts, getInLocalScope, findGlobals,
wrongThingErr, pprBinders,
-- Template Haskell stuff
checkWellStaged, spliceOK, bracketOK, tcMetaTy, thLevel,
- topIdLvl,
+ topIdLvl, thTopLevelId,
-- New Ids
- newLocalName, newDFunName
+ newLocalName, newDFunName, newFamInstTyConName,
) where
#include "HsVersions.h"
-import HsSyn ( LRuleDecl, LHsBinds, LSig,
- LHsTyVarBndr, HsTyVarBndr(..), pprLHsBinds )
-import TcIface ( tcImportDecl )
-import IfaceEnv ( newGlobalBinder )
+import HsSyn
+import TcIface
+import IfaceEnv
import TcRnMonad
-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 Id ( idName, isLocalId, setIdType )
-import Var ( TyVar, Id, idType, tyVarName )
+import TcMType
+import TcType
+import TcGadt
+-- import TcSuspension
+import qualified Type
+import Var
import VarSet
import VarEnv
-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 RdrName
+import InstEnv
+import FamInstEnv
+import DataCon
+import TyCon
+import TypeRep
+import Coercion
+import Class
+import Name
+import PrelNames
import NameEnv
-import OccName ( mkDFunOcc, occNameString )
-import HscTypes ( extendTypeEnvList, lookupType,
- TyThing(..), tyThingId, tyThingDataCon,
- ExternalPackageState(..) )
-
-import SrcLoc ( SrcLoc, Located(..) )
+import OccName
+import HscTypes
+import SrcLoc
import Outputable
+import Maybes
\end{code}
= do { env <- getGblEnv
-- Try local envt
- ; case lookupNameEnv (tcg_type_env env) name of {
+ ; 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 {
+ ; dflags <- getDOpts
+ ; case lookupType dflags 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
+ { case nameModule_maybe name of
+ Nothing -> notFound name env -- Internal names can happen in GHCi
+
+ Just mod | mod == tcg_mod env -- Names from this module
+ -> notFound name env -- should be in tcg_type_env
+ | mod == thFAKE -- Names bound in TH declaration brackets
+ -> notFound name env -- should be in tcg_env
+ | otherwise
+ -> tcImportDecl name -- Go find it in an interface
}}}}}
-tcLookupGlobalId :: Name -> TcM Id
--- Never used for Haskell-source DataCons, hence no ADataCon case
-tcLookupGlobalId name
+tcLookupField :: Name -> TcM Id -- Returns the selector Id
+tcLookupField name
= tcLookupGlobal name `thenM` \ thing ->
- return (tyThingId thing)
+ case thing of
+ AnId id -> return id
+ other -> wrongThingErr "field name" (AGlobal thing) name
tcLookupDataCon :: Name -> TcM DataCon
-tcLookupDataCon con_name
- = tcLookupGlobal con_name `thenM` \ thing ->
- return (tyThingDataCon thing)
+tcLookupDataCon name
+ = tcLookupGlobal name `thenM` \ thing ->
+ case thing of
+ ADataCon con -> return con
+ other -> wrongThingErr "data constructor" (AGlobal thing) name
tcLookupClass :: Name -> TcM Class
tcLookupClass name
tcLookupLocatedTyCon :: Located Name -> TcM TyCon
tcLookupLocatedTyCon = addLocM tcLookupTyCon
+
+-- Look up the instance tycon of a family instance.
+--
+-- The match must be unique - ie, match exactly one instance - but the
+-- type arguments used for matching may be more specific than those of
+-- the family instance declaration.
+--
+-- Return the instance tycon and its type instance. For example, if we have
+--
+-- tcLookupFamInst 'T' '[Int]' yields (':R42T', 'Int')
+--
+-- then we have a coercion (ie, type instance of family instance coercion)
+--
+-- :Co:R42T Int :: T [Int] ~ :R42T Int
+--
+-- which implies that :R42T was declared as 'data instance T [a]'.
+--
+tcLookupFamInst :: TyCon -> [Type] -> TcM (Maybe (TyCon, [Type]))
+tcLookupFamInst tycon tys
+ | not (isOpenTyCon tycon)
+ = return Nothing
+ | otherwise
+ = do { env <- getGblEnv
+ ; eps <- getEps
+ ; let instEnv = (eps_fam_inst_env eps, tcg_fam_inst_env env)
+ ; case lookupFamInstEnv instEnv tycon tys of
+ [(fam_inst, rep_tys)] -> return $ Just (famInstTyCon fam_inst,
+ rep_tys)
+ other -> return Nothing
+ }
\end{code}
%************************************************************************
other -> pprPanic "tcLookupTyVar" (ppr name)
tcLookupId :: Name -> TcM Id
--- Used when we aren't interested in the binding level
--- Never a DataCon. (Why does that matter? see TcExpr.tcId)
+-- Used when we aren't interested in the binding level, nor refinement.
+-- The "no refinement" part means that we return the un-refined Id regardless
+--
+-- The Id is 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)
-
-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
+ ATcId { tct_id = id} -> returnM 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
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 { tct_id = id, tct_level = lvl1 })
+ -> ASSERT( lvl == lvl1 ) id
+ other -> pprPanic "tcLookupLocalIds" (ppr name)
lclEnvElts :: TcLclEnv -> [TcTyThing]
lclEnvElts env = nameEnvElts (tcl_env env)
\begin{code}
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
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 = 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' ->
- (traceTc (text "env4") `thenM_`
- setLclEnv (env {tcl_env = le', tcl_tyvars = gtvs', tcl_rdr = rdr_env'}) thing_inside)
+ = do { env <- getLclEnv
+ ; tc_extend_local_id_env env (thLevel (tcl_th_ctxt env)) names_w_ids thing_inside }
+
+tcExtendGhciEnv :: [TcId] -> TcM a -> TcM a
+-- Used to bind Ids for GHCi identifiers bound earlier in the user interaction
+-- Note especially that we bind them at TH level 'impLevel'. That's because it's
+-- OK to use a variable bound earlier in the interaction in a splice, becuase
+-- GHCi has already compiled it to bytecode
+tcExtendGhciEnv ids thing_inside
+ = do { env <- getLclEnv
+ ; tc_extend_local_id_env env impLevel [(idName id, id) | id <- ids] thing_inside }
+
+tc_extend_local_id_env -- This is the guy who does the work
+ :: TcLclEnv
+ -> ThLevel
+ -> [(Name,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
+
+tc_extend_local_id_env env th_lvl names_w_ids thing_inside
+ = do { traceTc (text "env2")
+ ; traceTc (text "env3" <+> ppr extra_env)
+ ; gtvs' <- tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars
+ ; let env' = env {tcl_env = le', tcl_tyvars = gtvs', tcl_rdr = rdr_env'}
+ ; setLclEnv env' thing_inside }
+ where
+ extra_global_tyvars = tcTyVarsOfTypes [idType id | (_,id) <- names_w_ids]
+ extra_env = [ (name, ATcId { tct_id = id,
+ tct_level = th_lvl,
+ tct_type = id_ty,
+ tct_co = case isRefineableTy id_ty of
+ (True,_) -> Unrefineable
+ (_,True) -> Rigid idHsWrapper
+ _ -> Wobbly})
+ | (name,id) <- names_w_ids, let id_ty = idType id]
+ le' = extendNameEnvList (tcl_env env) extra_env
+ rdr_env' = extendLocalRdrEnv (tcl_rdr env) [name | (name,_) <- names_w_ids]
\end{code}
Just d -> go tidy_env1 (d:acc) things
Nothing -> go tidy_env1 acc things
- ignore_it ty = not (tvs `intersectsVarSet` tyVarsOfType ty)
+ ignore_it ty = tvs `disjointVarSet` tyVarsOfType ty
-----------------------
-find_thing ignore_it tidy_env (ATcId id _ _)
+find_thing ignore_it tidy_env (ATcId { tct_id = id })
= zonkTcType (idType id) `thenM` \ id_ty ->
if ignore_it id_ty then
returnM (tidy_env, Nothing)
bound_at = parens $ ptext SLIT("bound at:") <+> ppr (getSrcLoc tv)
in
returnM (tidy_env1, Just msg)
+
+find_thing _ _ thing = pprPanic "find_thing" (ppr thing)
\end{code}
\begin{code}
-refineEnvironment :: TvSubst -> TcM a -> TcM a
-refineEnvironment reft thing_inside
+refineEnvironment
+ :: Refinement
+ -> Bool -- whether type equations are involved
+ -> TcM a
+ -> TcM a
+-- I don't think I have to refine the set of global type variables in scope
+-- Reason: the refinement never increases that set
+refineEnvironment reft otherEquations thing_inside
+ | isEmptyRefinement reft -- Common case
+ , not otherEquations
+ = thing_inside
+ | otherwise
= 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 }
+ ; setLclEnv (env {tcl_env = le'}) 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
+ refine elt@(ATcId { tct_co = Rigid co, tct_type = ty })
+ | Just (co', ty') <- refineType reft ty
+ = elt { tct_co = Rigid (WpCo co' <.> co), tct_type = ty' }
+ refine elt@(ATcId { tct_co = Wobbly})
+-- Main new idea: make wobbly things invisible whenever there
+-- is a refinement of any sort
+-- | otherEquations
+ = elt { tct_co = WobblyInvisible}
+ refine (ATyVar tv ty)
+ | Just (_, ty') <- refineType reft ty
+ = ATyVar tv ty' -- Ignore the coercion that refineType returns
+
+ refine elt = elt -- Common case
\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.
checkWellStaged :: SDoc -- What the stage check is for
- -> ThLevel -- Binding level
+ -> ThLevel -- Binding level (increases inside brackets)
-> ThStage -- Use stage
-> TcM () -- Fail if badly staged, adding an error
checkWellStaged pp_thing bind_lvl use_stage
- | bind_lvl <= use_lvl -- OK!
- = returnM ()
+ | use_lvl >= bind_lvl -- OK! Used later than bound
+ = returnM () -- E.g. \x -> [| $(f x) |]
| bind_lvl == topLevel -- GHC restriction on top level splices
= failWithTc $
nest 2 (ptext SLIT("is used in a top-level splice, and must be imported, not defined locally"))]
| otherwise -- Badly staged
- = failWithTc $
+ = failWithTc $ -- E.g. \x -> $(f x)
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]
tcMetaTy tc_name
= tcLookupTyCon tc_name `thenM` \ t ->
returnM (mkTyConApp t [])
+
+thTopLevelId :: Id -> Bool
+-- See Note [What is a top-level Id?] in TcSplice
+thTopLevelId id = isGlobalId id || isExternalName (idName id)
\end{code}
data InstBindings
= VanillaInst -- The normal case
- (LHsBinds Name) -- Bindings
+ (LHsBinds Name) -- Bindings for the instance methods
[LSig Name] -- User pragmas recorded for generating
-- specialised instances
- | NewTypeDerived -- Used for deriving instances of newtypes, where the
- [Type] -- witness dictionary is identical to the argument
- -- dictionary. Hence no bindings, no pragmas
- -- The [Type] are the representation types
- -- See notes in TcDeriv
+ | NewTypeDerived -- Used for deriving instances of newtypes, where the
+ -- witness dictionary is identical to the argument
+ -- dictionary. Hence no bindings, no pragmas.
pprInstInfo info = vcat [ptext SLIT("InstInfo:") <+> ppr (idType (iDFunId info))]
pprInstInfoDetails info = pprInstInfo info $$ nest 2 (details (iBinds info))
where
- details (VanillaInst b _) = pprLHsBinds b
- details (NewTypeDerived _) = text "Derived from the representation type"
+ details (VanillaInst b _) = pprLHsBinds b
+ details NewTypeDerived = text "Derived from the representation type"
simpleInstInfoClsTy :: InstInfo -> (Class, Type)
simpleInstInfoClsTy info = case instanceHead (iSpec info) of
name, like otber top-level names, and hence must be made with newGlobalBinder.
\begin{code}
-newDFunName :: Class -> [Type] -> SrcLoc -> TcM Name
+newDFunName :: Class -> [Type] -> SrcSpan -> TcM Name
newDFunName clas (ty:_) loc
= do { index <- nextDFunIndex
; is_boot <- tcIsHsBoot
occNameString (getDFunTyKey ty)
dfun_occ = mkDFunOcc info_string is_boot index
- ; newGlobalBinder mod dfun_occ Nothing loc }
+ ; newGlobalBinder mod dfun_occ loc }
newDFunName clas [] loc = pprPanic "newDFunName" (ppr clas <+> ppr loc)
\end{code}
+Make a name for the representation tycon of a family instance. It's an
+*external* name, like otber top-level names, and hence must be made with
+newGlobalBinder.
+
+\begin{code}
+newFamInstTyConName :: Name -> SrcSpan -> TcM Name
+newFamInstTyConName tc_name loc
+ = do { index <- nextDFunIndex
+ ; mod <- getModule
+ ; let occ = nameOccName tc_name
+ ; newGlobalBinder mod (mkInstTyTcOcc index occ) loc }
+\end{code}
+
%************************************************************************
%* *
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"))
+notFound name env
+ = failWithTc (vcat[ptext SLIT("GHC internal error:") <+> quotes (ppr name) <+>
+ ptext SLIT("is not in scope during type checking, but it passed the renamer"),
+ ptext SLIT("tcg_type_env of environment:") <+> ppr (tcg_type_env env)]
+ )
wrongThingErr expected thing name
= failWithTc (pprTcTyThingCategory thing <+> quotes (ppr name) <+>