\begin{code}
module Inst (
- showLIE,
-
Inst,
- pprInst, pprInsts, pprInstsInFull, pprDFuns,
+
+ pprDFuns, pprDictsTheta, pprDictsInFull, -- User error messages
+ showLIE, pprInst, pprInsts, pprInstInFull, -- Debugging messages
+
tidyInsts, tidyMoreInsts,
newDictsFromOld, newDicts, cloneDict,
#include "HsVersions.h"
import {-# SOURCE #-} TcExpr( tcCheckSigma )
+import {-# SOURCE #-} TcUnify ( unifyTauTy ) -- Used in checkKind (sigh)
-import HsSyn ( HsLit(..), HsOverLit(..), HsExpr(..), LHsExpr, nlHsVar, mkHsApp )
+import HsSyn ( HsLit(..), HsOverLit(..), HsExpr(..), LHsExpr, mkHsApp )
import TcHsSyn ( TcId, TcIdSet,
mkHsTyApp, mkHsDictApp, mkHsConApp, zonkId,
mkCoercion, ExprCoFn
zonkTcThetaType, tcInstTyVar, tcInstType, tcInstTyVars
)
import TcType ( Type, TcType, TcThetaType, TcTyVarSet,
- PredType(..), TyVarDetails(VanillaTv),
+ PredType(..), TyVarDetails(VanillaTv), typeKind,
tcSplitForAllTys, tcSplitForAllTys, mkTyConApp,
tcSplitPhiTy, tcIsTyVarTy, tcSplitDFunTy,
isIntTy,isFloatTy, isIntegerTy, isDoubleTy,
getClassPredTys, getClassPredTys_maybe, mkPredName,
isInheritablePred, isIPPred, matchTys,
tidyType, tidyTypes, tidyFreeTyVars, tcSplitSigmaTy,
- pprPred, pprParendType, pprThetaArrow, pprClassPred
+ pprPred, pprParendType, pprThetaArrow, pprTheta, pprClassPred
)
+import Kind ( isSubKind )
import HscTypes ( ExternalPackageState(..) )
import CoreFVs ( idFreeTyVars )
import DataCon ( DataCon,dataConSig )
import PrelInfo ( isStandardClass, isNoDictClass )
import Name ( Name, mkMethodOcc, getOccName, getSrcLoc, isHomePackageName, isInternalName )
import NameSet ( addOneToNameSet )
-import Subst ( substTy, substTyWith, substTheta, mkTyVarSubst )
+import Subst ( substTy, substTyWith, substTheta, mkTopTyVarSubst )
import Literal ( inIntRange )
-import Var ( TyVar )
+import Var ( TyVar, tyVarKind )
import VarEnv ( TidyEnv, emptyTidyEnv, lookupSubstEnv, SubstResult(..) )
import VarSet ( elemVarSet, emptyVarSet, unionVarSet, mkVarSet )
import TysWiredIn ( floatDataCon, doubleDataCon )
in
returnM (mkCoercion inst_fn, tau)
-tcInstDataCon :: InstOrigin -> DataCon
+tcInstDataCon :: InstOrigin
+ -> TyVarDetails -- Use this for the existential tyvars
+ -- ExistTv when pattern-matching,
+ -- VanillaTv at a call of the constructor
+ -> DataCon
-> TcM ([TcType], -- Types to instantiate at
[Inst], -- Existential dictionaries to apply to
[TcType], -- Argument types of constructor
TcType, -- Result type
[TyVar]) -- Existential tyvars
-tcInstDataCon orig data_con
+tcInstDataCon orig ex_tv_details data_con
= let
(tvs, stupid_theta, ex_tvs, ex_theta, arg_tys, tycon) = dataConSig data_con
-- We generate constraints for the stupid theta even when
-- pattern matching (as the Report requires)
in
- tcInstTyVars VanillaTv (tvs ++ ex_tvs) `thenM` \ (all_tvs', ty_args', tenv) ->
+ mappM (tcInstTyVar VanillaTv) tvs `thenM` \ tvs' ->
+ mappM (tcInstTyVar ex_tv_details) ex_tvs `thenM` \ ex_tvs' ->
let
+ tv_tys' = mkTyVarTys tvs'
+ ex_tv_tys' = mkTyVarTys ex_tvs'
+ all_tys' = tv_tys' ++ ex_tv_tys'
+
+ tenv = mkTopTyVarSubst (tvs ++ ex_tvs) all_tys'
stupid_theta' = substTheta tenv stupid_theta
ex_theta' = substTheta tenv ex_theta
arg_tys' = map (substTy tenv) arg_tys
-
- n_normal_tvs = length tvs
- ex_tvs' = drop n_normal_tvs all_tvs'
- result_ty = mkTyConApp tycon (take n_normal_tvs ty_args')
+ result_ty' = mkTyConApp tycon tv_tys'
in
newDicts orig stupid_theta' `thenM` \ stupid_dicts ->
newDicts orig ex_theta' `thenM` \ ex_dicts ->
-- we don't otherwise use it at all
extendLIEs stupid_dicts `thenM_`
- returnM (ty_args', ex_dicts, arg_tys', result_ty, ex_tvs')
+ returnM (all_tys', ex_dicts, arg_tys', result_ty', ex_tvs')
newMethodFromName :: InstOrigin -> TcType -> Name -> TcM TcId
newMethodFromName origin ty name
-- This is important because they are used by TcSimplify
-- to simplify Insts
+-- NB: the kind of the type variable to be instantiated
+-- might be a sub-kind of the type to which it is applied,
+-- notably when the latter is a type variable of kind ??
+-- Hence the call to checkKind
+-- A worry: is this needed anywhere else?
tcInstClassOp :: InstLoc -> Id -> [TcType] -> TcM Inst
tcInstClassOp inst_loc sel_id tys
= let
substTyWith tyvars tys rho
(preds,tau) = tcSplitPhiTy rho_ty
in
+ zipWithM_ checkKind tyvars tys `thenM_`
newMethod inst_loc sel_id tys preds tau
+checkKind :: TyVar -> TcType -> TcM ()
+-- Ensure that the type has a sub-kind of the tyvar
+checkKind tv ty
+ = do { ty1 <- zonkTcType ty
+ ; if typeKind ty1 `isSubKind` tyVarKind tv
+ then return ()
+ else do
+ { traceTc (text "checkKind: adding kind constraint" <+> ppr tv <+> ppr ty)
+ ; tv1 <- tcInstTyVar VanillaTv tv
+ ; unifyTauTy (mkTyVarTy tv1) ty1 }}
+
+
---------------------------
newMethod inst_loc id tys theta tau
= newUnique `thenM` \ new_uniq ->
-- Reason: tcSyntaxName does unification
-- which is very inconvenient in tcSimplify
-- ToDo: noLoc sadness
- = tcSyntaxName orig expected_ty (fromIntegerName, noLoc (HsVar fi)) `thenM` \ (_,expr) ->
- mkIntegerLit i `thenM` \ integer_lit ->
- returnM (mkHsApp expr integer_lit)
-
+ = tcSyntaxName orig expected_ty (fromIntegerName, HsVar fi) `thenM` \ (_,expr) ->
+ mkIntegerLit i `thenM` \ integer_lit ->
+ returnM (mkHsApp (noLoc expr) integer_lit)
+ -- The mkHsApp will get the loc from the literal
| Just expr <- shortCutIntLit i expected_ty
= returnM expr
newOverloadedLit orig lit@(HsFractional r fr) expected_ty
| fr /= fromRationalName -- c.f. HsIntegral case
- = tcSyntaxName orig expected_ty (fromRationalName, noLoc (HsVar fr)) `thenM` \ (_,expr) ->
- mkRatLit r `thenM` \ rat_lit ->
- returnM (mkHsApp expr rat_lit)
+ = tcSyntaxName orig expected_ty (fromRationalName, HsVar fr) `thenM` \ (_,expr) ->
+ mkRatLit r `thenM` \ rat_lit ->
+ returnM (mkHsApp (noLoc expr) rat_lit)
+ -- The mkHsApp will get the loc from the literal
| Just expr <- shortCutFracLit r expected_ty
= returnM expr
instance Outputable Inst where
ppr inst = pprInst inst
-pprInsts :: [Inst] -> SDoc
-pprInsts insts = parens (sep (punctuate comma (map pprInst insts)))
+pprDictsTheta :: [Inst] -> SDoc
+-- Print in type-like fashion (Eq a, Show b)
+pprDictsTheta dicts = pprTheta (map dictPred dicts)
-pprInstsInFull insts
- = vcat (map go insts)
+pprDictsInFull :: [Inst] -> SDoc
+-- Print in type-like fashion, but with source location
+pprDictsInFull dicts
+ = vcat (map go dicts)
where
- go inst = sep [quotes (ppr inst), nest 2 (pprInstLoc (instLoc inst))]
+ go dict = sep [quotes (ppr (dictPred dict)), nest 2 (pprInstLoc (instLoc dict))]
-pprInst (LitInst u lit ty loc)
- = hsep [ppr lit, ptext SLIT("at"), ppr ty, show_uniq u]
+pprInsts :: [Inst] -> SDoc
+-- Debugging: print the evidence :: type
+pprInsts insts = brackets (interpp'SP insts)
-pprInst (Dict u pred loc) = pprPred pred <+> show_uniq u
+pprInst, pprInstInFull :: Inst -> SDoc
+-- Debugging: print the evidence :: type
+pprInst (LitInst id lit ty loc) = ppr id <+> dcolon <+> ppr ty
+pprInst (Dict id pred loc) = ppr id <+> dcolon <+> pprPred pred
-pprInst m@(Method u id tys theta tau loc)
- = hsep [ppr id, ptext SLIT("at"),
- brackets (sep (map pprParendType tys)) {- ,
- ptext SLIT("theta"), ppr theta,
- ptext SLIT("tau"), ppr tau
- show_uniq u,
- ppr (instToId m) -}]
+pprInst m@(Method inst_id id tys theta tau loc)
+ = ppr inst_id <+> dcolon <+>
+ braces (sep [ppr id <+> ptext SLIT("at"),
+ brackets (sep (map pprParendType tys))])
+pprInstInFull inst
+ = sep [quotes (pprInst inst), nest 2 (pprInstLoc (instLoc inst))]
pprDFuns :: [DFunId] -> SDoc
-- Prints the dfun as an instance declaration
showLIE str
= do { lie_var <- getLIEVar ;
lie <- readMutVar lie_var ;
- traceTc (str <+> pprInstsInFull (lieToList lie)) }
+ traceTc (str <+> vcat (map pprInstInFull (lieToList lie))) }
\end{code}
-- Dictionaries
lookupInst dict@(Dict _ pred@(ClassP clas tys) loc)
- = do { dflags <- getDOpts
- ; if all tcIsTyVarTy tys &&
- not (dopt Opt_AllowUndecidableInstances dflags)
- -- Common special case; no lookup
- -- NB: tcIsTyVarTy... don't look through newtypes!
- -- Don't take this short cut if we allow undecidable instances
- -- because we might have "instance T a where ...".
- -- [That means we need -fallow-undecidable-instances in the
- -- client module, as well as the module with the instance decl.]
- then return NoInstance
-
- else do
- { pkg_ie <- loadImportedInsts clas tys
+ = do { pkg_ie <- loadImportedInsts clas tys
-- Suck in any instance decls that may be relevant
; tcg_env <- getGblEnv
+ ; dflags <- getDOpts
; case lookupInstEnv dflags (pkg_ie, tcg_inst_env tcg_env) clas tys of {
([(tenv, (_,_,dfun_id))], []) -> instantiate_dfun tenv dfun_id pred loc ;
(matches, unifs) -> do
- { traceTc (text "lookupInst" <+> vcat [text "matches" <+> ppr matches,
- text "unifs" <+> ppr unifs])
- ; return NoInstance } } } }
+ { traceTc (text "lookupInst fail" <+> vcat [text "dict" <+> ppr pred,
+ text "matches" <+> ppr matches,
+ text "unifs" <+> ppr unifs])
+ ; return NoInstance } } }
-- In the case of overlap (multiple matches) we report
-- NoInstance here. That has the effect of making the
-- context-simplifier return the dict as an irreducible one.
-----------------
instantiate_dfun tenv dfun_id pred loc
- = -- Record that this dfun is needed
+ = traceTc (text "lookupInst success" <+>
+ vcat [text "dict" <+> ppr pred,
+ text "witness" <+> ppr dfun_id <+> ppr (idType dfun_id) ]) `thenM_`
+ -- Record that this dfun is needed
record_dfun_usage dfun_id `thenM_`
-- It's possible that not all the tyvars are in
in
mappM mk_ty_arg tyvars `thenM` \ ty_args ->
let
- dfun_rho = substTy (mkTyVarSubst tyvars ty_args) rho
+ dfun_rho = substTy (mkTopTyVarSubst tyvars ty_args) rho
+ -- Since the tyvars are freshly made,
+ -- they cannot possibly be captured by
+ -- any existing for-alls. Hence mkTopTyVarSubst
(theta, _) = tcSplitPhiTy dfun_rho
ty_app = mkHsTyApp (L (instLocSrcSpan loc) (HsVar dfun_id)) ty_args
in
dfun_name = idName dfun_id
tcGetInstEnvs :: TcM (InstEnv, InstEnv)
--- Gets both the home-pkg inst env (includes module being compiled)
--- and the external-package inst-env
+-- Gets both the external-package inst-env
+-- and the home-pkg inst env (includes module being compiled)
tcGetInstEnvs = do { eps <- getEps; env <- getGblEnv;
- return (tcg_inst_env env, eps_inst_env eps) }
+ return (eps_inst_env eps, tcg_inst_env env) }
\end{code}
\begin{code}
tcSyntaxName :: InstOrigin
-> TcType -- Type to instantiate it at
- -> (Name, LHsExpr Name) -- (Standard name, user name)
- -> TcM (Name, LHsExpr TcId) -- (Standard name, suitable expression)
+ -> (Name, HsExpr Name) -- (Standard name, user name)
+ -> TcM (Name, HsExpr TcId) -- (Standard name, suitable expression)
-- NB: tcSyntaxName calls tcExpr, and hence can do unification.
-- So we do not call it from lookupInst, which is called from tcSimplify
-tcSyntaxName orig ty (std_nm, L span (HsVar user_nm))
+tcSyntaxName orig ty (std_nm, HsVar user_nm)
| std_nm == user_nm
- = addSrcSpan span (tcStdSyntaxName orig ty std_nm)
+ = tcStdSyntaxName orig ty std_nm
tcSyntaxName orig ty (std_nm, user_nm_expr)
= tcLookupId std_nm `thenM` \ std_id ->
let
-- C.f. newMethodAtLoc
([tv], _, tau) = tcSplitSigmaTy (idType std_id)
- tau1 = substTyWith [tv] [ty] tau
+ sigma1 = substTyWith [tv] [ty] tau
-- Actually, the "tau-type" might be a sigma-type in the
-- case of locally-polymorphic methods.
in
- addErrCtxtM (syntaxNameCtxt user_nm_expr orig tau1) $
+ addErrCtxtM (syntaxNameCtxt user_nm_expr orig sigma1) $
-- Check that the user-supplied thing has the
- -- same type as the standard one
- tcCheckSigma user_nm_expr tau1 `thenM` \ expr ->
- returnM (std_nm, expr)
+ -- same type as the standard one.
+ -- Tiresome jiggling because tcCheckSigma takes a located expression
+ getSrcSpanM `thenM` \ span ->
+ tcCheckSigma (L span user_nm_expr) sigma1 `thenM` \ expr ->
+ returnM (std_nm, unLoc expr)
tcStdSyntaxName :: InstOrigin
-> TcType -- Type to instantiate it at
-> Name -- Standard name
- -> TcM (Name, LHsExpr TcId) -- (Standard name, suitable expression)
+ -> TcM (Name, HsExpr TcId) -- (Standard name, suitable expression)
tcStdSyntaxName orig ty std_nm
= newMethodFromName orig ty std_nm `thenM` \ id ->
- getSrcSpanM `thenM` \ span ->
- returnM (std_nm, L span (HsVar id))
+ returnM (std_nm, HsVar id)
syntaxNameCtxt name orig ty tidy_env
= getInstLoc orig `thenM` \ inst_loc ->