{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
module GHC.Tc.Instance.Class (
matchGlobalInst, matchEqualityInst,
ClsInstResult(..),
InstanceWhat(..), safeOverlap, instanceReturnsDictCon,
AssocInstInfo(..), isNotAssociated
) where
import GHC.Prelude
import GHC.Driver.DynFlags
import GHC.Core.TyCo.Rep
import GHC.Tc.Utils.Env
import GHC.Tc.Utils.Monad
import GHC.Tc.Utils.TcType
import GHC.Tc.Utils.Instantiate(instDFunType, tcInstType)
import GHC.Tc.Instance.Typeable
import GHC.Tc.Utils.TcMType
import GHC.Tc.Types.Evidence
import GHC.Tc.Types.Origin (InstanceWhat (..), SafeOverlapping)
import GHC.Tc.Instance.Family( tcGetFamInstEnvs, tcInstNewTyCon_maybe, tcLookupDataFamInst )
import GHC.Rename.Env( addUsedGRE, DeprecationWarnings (..) )
import GHC.Builtin.Types
import GHC.Builtin.Types.Prim
import GHC.Builtin.Names
import GHC.Types.FieldLabel
import GHC.Types.Name.Reader
import GHC.Types.SafeHaskell
import GHC.Types.Name ( Name )
import GHC.Types.Var.Env ( VarEnv )
import GHC.Types.Id
import GHC.Types.Var
import GHC.Core.Predicate
import GHC.Core.Coercion
import GHC.Core.InstEnv
import GHC.Core.Type
import GHC.Core.Make ( mkCharExpr, mkNaturalExpr, mkStringExprFS, mkCoreLams )
import GHC.Core.DataCon
import GHC.Core.TyCon
import GHC.Core.Class
import GHC.Core ( Expr(Var, App, Cast) )
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Utils.Misc( splitAtList, fstOf3 )
import GHC.Data.FastString
import Language.Haskell.Syntax.Basic (FieldLabelString(..))
data AssocInstInfo
= NotAssociated
| InClsInst { AssocInstInfo -> Class
ai_class :: Class
, AssocInstInfo -> [DFunId]
ai_tyvars :: [TyVar]
, AssocInstInfo -> VarEnv PredType
ai_inst_env :: VarEnv Type
}
isNotAssociated :: AssocInstInfo -> Bool
isNotAssociated :: AssocInstInfo -> Bool
isNotAssociated (NotAssociated {}) = Bool
True
isNotAssociated (InClsInst {}) = Bool
False
data ClsInstResult
= NoInstance
| OneInst { ClsInstResult -> [PredType]
cir_new_theta :: [TcPredType]
, ClsInstResult -> [EvExpr] -> EvTerm
cir_mk_ev :: [EvExpr] -> EvTerm
, ClsInstResult -> Bool
cir_canonical :: Canonical
, ClsInstResult -> InstanceWhat
cir_what :: InstanceWhat }
| NotSure
instance Outputable ClsInstResult where
ppr :: ClsInstResult -> SDoc
ppr ClsInstResult
NoInstance = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"NoInstance"
ppr ClsInstResult
NotSure = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"NotSure"
ppr (OneInst { cir_new_theta :: ClsInstResult -> [PredType]
cir_new_theta = [PredType]
ev
, cir_what :: ClsInstResult -> InstanceWhat
cir_what = InstanceWhat
what })
= String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"OneInst" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [[PredType] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [PredType]
ev, InstanceWhat -> SDoc
forall a. Outputable a => a -> SDoc
ppr InstanceWhat
what]
safeOverlap :: InstanceWhat -> Bool
safeOverlap :: InstanceWhat -> Bool
safeOverlap (TopLevInstance { iw_safe_over :: InstanceWhat -> Bool
iw_safe_over = Bool
so }) = Bool
so
safeOverlap InstanceWhat
_ = Bool
True
instanceReturnsDictCon :: InstanceWhat -> Bool
instanceReturnsDictCon :: InstanceWhat -> Bool
instanceReturnsDictCon (TopLevInstance {}) = Bool
True
instanceReturnsDictCon InstanceWhat
BuiltinInstance = Bool
True
instanceReturnsDictCon BuiltinTypeableInstance {} = Bool
True
instanceReturnsDictCon InstanceWhat
BuiltinEqInstance = Bool
False
instanceReturnsDictCon InstanceWhat
LocalInstance = Bool
False
matchGlobalInst :: DynFlags
-> Bool
-> Class -> [Type] -> TcM ClsInstResult
matchGlobalInst :: DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchGlobalInst DynFlags
dflags Bool
short_cut Class
clas [PredType]
tys
| Name
cls_name Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
knownNatClassName = DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchKnownNat DynFlags
dflags Bool
short_cut Class
clas [PredType]
tys
| Name
cls_name Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
knownSymbolClassName = DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchKnownSymbol DynFlags
dflags Bool
short_cut Class
clas [PredType]
tys
| Name
cls_name Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
knownCharClassName = DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchKnownChar DynFlags
dflags Bool
short_cut Class
clas [PredType]
tys
| Class -> Bool
isCTupleClass Class
clas = Class -> [PredType] -> TcM ClsInstResult
matchCTuple Class
clas [PredType]
tys
| Name
cls_name Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
typeableClassName = Class -> [PredType] -> TcM ClsInstResult
matchTypeable Class
clas [PredType]
tys
| Name
cls_name Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
withDictClassName = [PredType] -> TcM ClsInstResult
matchWithDict [PredType]
tys
| Name
cls_name Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
hasFieldClassName = DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchHasField DynFlags
dflags Bool
short_cut Class
clas [PredType]
tys
| Name
cls_name Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
unsatisfiableClassName = ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return ClsInstResult
NoInstance
| Bool
otherwise = DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchInstEnv DynFlags
dflags Bool
short_cut Class
clas [PredType]
tys
where
cls_name :: Name
cls_name = Class -> Name
className Class
clas
matchInstEnv :: DynFlags -> Bool -> Class -> [Type] -> TcM ClsInstResult
matchInstEnv :: DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchInstEnv DynFlags
dflags Bool
short_cut_solver Class
clas [PredType]
tys
= do { InstEnvs
instEnvs <- TcM InstEnvs
tcGetInstEnvs
; let safeOverlapCheck :: Bool
safeOverlapCheck = DynFlags -> SafeHaskellMode
safeHaskell DynFlags
dflags SafeHaskellMode -> [SafeHaskellMode] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [SafeHaskellMode
Sf_Safe, SafeHaskellMode
Sf_Trustworthy]
([InstMatch]
matches, PotentialUnifiers
unify, [InstMatch]
unsafeOverlaps) = Bool
-> InstEnvs
-> Class
-> [PredType]
-> ([InstMatch], PotentialUnifiers, [InstMatch])
lookupInstEnv Bool
True InstEnvs
instEnvs Class
clas [PredType]
tys
safeHaskFail :: Bool
safeHaskFail = Bool
safeOverlapCheck Bool -> Bool -> Bool
&& Bool -> Bool
not ([InstMatch] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [InstMatch]
unsafeOverlaps)
; String -> SDoc -> TcRn ()
traceTc String
"matchInstEnv" (SDoc -> TcRn ()) -> SDoc -> TcRn ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"goal:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Class -> SDoc
forall a. Outputable a => a -> SDoc
ppr Class
clas SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> [PredType] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [PredType]
tys
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"matches:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> [InstMatch] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [InstMatch]
matches
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"unify:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> PotentialUnifiers -> SDoc
forall a. Outputable a => a -> SDoc
ppr PotentialUnifiers
unify ]
; case ([InstMatch]
matches, PotentialUnifiers
unify, Bool
safeHaskFail) of
([], NoUnifiers{}, Bool
_)
-> do { String -> SDoc -> TcRn ()
traceTc String
"matchClass not matching" (PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
pred SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ InstEnv -> SDoc
forall a. Outputable a => a -> SDoc
ppr (InstEnvs -> InstEnv
ie_local InstEnvs
instEnvs))
; ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return ClsInstResult
NoInstance }
([(ClsInst
ispec, [DFunInstType]
inst_tys)], NoUnifiers Bool
canonical, Bool
False)
| Bool
short_cut_solver
, ClsInst -> Bool
isOverlappable ClsInst
ispec
-> do { String -> SDoc -> TcRn ()
traceTc String
"matchClass: ignoring overlappable" (PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
pred)
; ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return ClsInstResult
NotSure }
| Bool
otherwise
-> do { let dfun_id :: DFunId
dfun_id = ClsInst -> DFunId
instanceDFunId ClsInst
ispec
; String -> SDoc -> TcRn ()
traceTc String
"matchClass success" (SDoc -> TcRn ()) -> SDoc -> TcRn ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"dict" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
pred SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
parens (if Bool
canonical then String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"canonical" else String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"non-canonical"),
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"witness" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> DFunId -> SDoc
forall a. Outputable a => a -> SDoc
ppr DFunId
dfun_id
SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (DFunId -> PredType
idType DFunId
dfun_id) ]
; Bool -> Bool -> DFunId -> [DFunInstType] -> TcM ClsInstResult
match_one ([InstMatch] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [InstMatch]
unsafeOverlaps) Bool
canonical DFunId
dfun_id [DFunInstType]
inst_tys }
([InstMatch], PotentialUnifiers, Bool)
_ -> do { String -> SDoc -> TcRn ()
traceTc String
"matchClass multiple matches, deferring choice" (SDoc -> TcRn ()) -> SDoc -> TcRn ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"dict" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
pred,
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"matches" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> [InstMatch] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [InstMatch]
matches]
; ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return ClsInstResult
NotSure } }
where
pred :: PredType
pred = Class -> [PredType] -> PredType
mkClassPred Class
clas [PredType]
tys
match_one :: SafeOverlapping -> Canonical -> DFunId -> [DFunInstType]
-> TcM ClsInstResult
match_one :: Bool -> Bool -> DFunId -> [DFunInstType] -> TcM ClsInstResult
match_one Bool
so Bool
canonical DFunId
dfun_id [DFunInstType]
mb_inst_tys
= do { String -> SDoc -> TcRn ()
traceTc String
"match_one" (DFunId -> SDoc
forall a. Outputable a => a -> SDoc
ppr DFunId
dfun_id SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ [DFunInstType] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [DFunInstType]
mb_inst_tys)
; ([PredType]
tys, [PredType]
theta) <- DFunId -> [DFunInstType] -> TcM ([PredType], [PredType])
instDFunType DFunId
dfun_id [DFunInstType]
mb_inst_tys
; String -> SDoc -> TcRn ()
traceTc String
"match_one 2" (DFunId -> SDoc
forall a. Outputable a => a -> SDoc
ppr DFunId
dfun_id SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ [PredType] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [PredType]
tys SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ [PredType] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [PredType]
theta)
; ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (ClsInstResult -> TcM ClsInstResult)
-> ClsInstResult -> TcM ClsInstResult
forall a b. (a -> b) -> a -> b
$ OneInst { cir_new_theta :: [PredType]
cir_new_theta = [PredType]
theta
, cir_mk_ev :: [EvExpr] -> EvTerm
cir_mk_ev = DFunId -> [PredType] -> [EvExpr] -> EvTerm
evDFunApp DFunId
dfun_id [PredType]
tys
, cir_canonical :: Bool
cir_canonical = Bool
canonical
, cir_what :: InstanceWhat
cir_what = TopLevInstance { iw_dfun_id :: DFunId
iw_dfun_id = DFunId
dfun_id
, iw_safe_over :: Bool
iw_safe_over = Bool
so } } }
matchCTuple :: Class -> [Type] -> TcM ClsInstResult
matchCTuple :: Class -> [PredType] -> TcM ClsInstResult
matchCTuple Class
clas [PredType]
tys
= ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (OneInst { cir_new_theta :: [PredType]
cir_new_theta = [PredType]
tys
, cir_mk_ev :: [EvExpr] -> EvTerm
cir_mk_ev = [EvExpr] -> EvTerm
tuple_ev
, cir_canonical :: Bool
cir_canonical = Bool
True
, cir_what :: InstanceWhat
cir_what = InstanceWhat
BuiltinInstance })
where
data_con :: DataCon
data_con = TyCon -> DataCon
tyConSingleDataCon (Class -> TyCon
classTyCon Class
clas)
tuple_ev :: [EvExpr] -> EvTerm
tuple_ev = DFunId -> [PredType] -> [EvExpr] -> EvTerm
evDFunApp (DataCon -> DFunId
dataConWrapId DataCon
data_con) [PredType]
tys
matchKnownNat :: DynFlags
-> Bool
-> Class -> [Type] -> TcM ClsInstResult
matchKnownNat :: DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchKnownNat DynFlags
dflags Bool
_ Class
clas [PredType
ty]
| Just Integer
n <- PredType -> Maybe Integer
isNumLitTy PredType
ty = Class -> PredType -> EvExpr -> TcM ClsInstResult
makeLitDict Class
clas PredType
ty (Platform -> Integer -> EvExpr
mkNaturalExpr (DynFlags -> Platform
targetPlatform DynFlags
dflags) Integer
n)
matchKnownNat DynFlags
df Bool
sc Class
clas [PredType]
tys = DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchInstEnv DynFlags
df Bool
sc Class
clas [PredType]
tys
matchKnownSymbol :: DynFlags
-> Bool
-> Class -> [Type] -> TcM ClsInstResult
matchKnownSymbol :: DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchKnownSymbol DynFlags
_ Bool
_ Class
clas [PredType
ty]
| Just FastString
s <- PredType -> Maybe FastString
isStrLitTy PredType
ty = do
EvExpr
et <- FastString -> IOEnv (Env TcGblEnv TcLclEnv) EvExpr
forall (m :: * -> *). MonadThings m => FastString -> m EvExpr
mkStringExprFS FastString
s
Class -> PredType -> EvExpr -> TcM ClsInstResult
makeLitDict Class
clas PredType
ty EvExpr
et
matchKnownSymbol DynFlags
df Bool
sc Class
clas [PredType]
tys = DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchInstEnv DynFlags
df Bool
sc Class
clas [PredType]
tys
matchKnownChar :: DynFlags
-> Bool
-> Class -> [Type] -> TcM ClsInstResult
matchKnownChar :: DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchKnownChar DynFlags
_ Bool
_ Class
clas [PredType
ty]
| Just Char
s <- PredType -> Maybe Char
isCharLitTy PredType
ty = Class -> PredType -> EvExpr -> TcM ClsInstResult
makeLitDict Class
clas PredType
ty (Char -> EvExpr
mkCharExpr Char
s)
matchKnownChar DynFlags
df Bool
sc Class
clas [PredType]
tys = DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchInstEnv DynFlags
df Bool
sc Class
clas [PredType]
tys
makeLitDict :: Class -> Type -> EvExpr -> TcM ClsInstResult
makeLitDict :: Class -> PredType -> EvExpr -> TcM ClsInstResult
makeLitDict Class
clas PredType
ty EvExpr
et
| Just (PredType
_, TcCoercion
co_dict) <- TyCon -> [PredType] -> Maybe (PredType, TcCoercion)
tcInstNewTyCon_maybe (Class -> TyCon
classTyCon Class
clas) [PredType
ty]
, [ DFunId
meth ] <- Class -> [DFunId]
classMethods Class
clas
, Just TyCon
tcRep <- PredType -> Maybe TyCon
tyConAppTyCon_maybe (DFunId -> PredType
classMethodTy DFunId
meth)
, Just (PredType
_, TcCoercion
co_rep) <- TyCon -> [PredType] -> Maybe (PredType, TcCoercion)
tcInstNewTyCon_maybe TyCon
tcRep [PredType
ty]
, let ev_tm :: EvTerm
ev_tm = EvExpr -> TcCoercion -> EvTerm
mkEvCast EvExpr
et (TcCoercion -> TcCoercion
mkSymCo (TcCoercion -> TcCoercion -> TcCoercion
mkTransCo TcCoercion
co_dict TcCoercion
co_rep))
= ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (ClsInstResult -> TcM ClsInstResult)
-> ClsInstResult -> TcM ClsInstResult
forall a b. (a -> b) -> a -> b
$ OneInst { cir_new_theta :: [PredType]
cir_new_theta = []
, cir_mk_ev :: [EvExpr] -> EvTerm
cir_mk_ev = \[EvExpr]
_ -> EvTerm
ev_tm
, cir_canonical :: Bool
cir_canonical = Bool
True
, cir_what :: InstanceWhat
cir_what = InstanceWhat
BuiltinInstance }
| Bool
otherwise
= String -> SDoc -> TcM ClsInstResult
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"makeLitDict" (SDoc -> TcM ClsInstResult) -> SDoc -> TcM ClsInstResult
forall a b. (a -> b) -> a -> b
$
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Unexpected evidence for" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Name -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Class -> Name
className Class
clas)
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat ((DFunId -> SDoc) -> [DFunId] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (PredType -> SDoc) -> (DFunId -> PredType) -> DFunId -> SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DFunId -> PredType
idType) (Class -> [DFunId]
classMethods Class
clas))
matchWithDict :: [Type] -> TcM ClsInstResult
matchWithDict :: [PredType] -> TcM ClsInstResult
matchWithDict [PredType
cls, PredType
mty]
| Just (TyCon
dict_tc, [PredType]
dict_args) <- HasCallStack => PredType -> Maybe (TyCon, [PredType])
PredType -> Maybe (TyCon, [PredType])
tcSplitTyConApp_maybe PredType
cls
, Just (PredType
inst_meth_ty, TcCoercion
co) <- TyCon -> [PredType] -> Maybe (PredType, TcCoercion)
tcInstNewTyCon_maybe TyCon
dict_tc [PredType]
dict_args
= do { DFunId
sv <- FastString
-> PredType -> PredType -> IOEnv (Env TcGblEnv TcLclEnv) DFunId
forall (m :: * -> *).
MonadUnique m =>
FastString -> PredType -> PredType -> m DFunId
mkSysLocalM (String -> FastString
fsLit String
"withDict_s") PredType
ManyTy PredType
mty
; DFunId
k <- FastString
-> PredType -> PredType -> IOEnv (Env TcGblEnv TcLclEnv) DFunId
forall (m :: * -> *).
MonadUnique m =>
FastString -> PredType -> PredType -> m DFunId
mkSysLocalM (String -> FastString
fsLit String
"withDict_k") PredType
ManyTy (HasDebugCallStack => PredType -> PredType -> PredType
PredType -> PredType -> PredType
mkInvisFunTy PredType
cls PredType
openAlphaTy)
; let evWithDict :: TcCoercion -> EvExpr
evWithDict TcCoercion
co2 =
[DFunId] -> EvExpr -> EvExpr
mkCoreLams [ DFunId
runtimeRep1TyVar, DFunId
openAlphaTyVar, DFunId
sv, DFunId
k ] (EvExpr -> EvExpr) -> EvExpr -> EvExpr
forall a b. (a -> b) -> a -> b
$
DFunId -> EvExpr
forall b. DFunId -> Expr b
Var DFunId
k
EvExpr -> EvExpr -> EvExpr
forall b. Expr b -> Expr b -> Expr b
`App`
(DFunId -> EvExpr
forall b. DFunId -> Expr b
Var DFunId
sv EvExpr -> TcCoercion -> EvExpr
forall b. Expr b -> TcCoercion -> Expr b
`Cast` TcCoercion -> TcCoercion -> TcCoercion
mkTransCo (HasDebugCallStack => TcCoercion -> TcCoercion
TcCoercion -> TcCoercion
mkSubCo TcCoercion
co2) (TcCoercion -> TcCoercion
mkSymCo TcCoercion
co))
; TyCon
tc <- Name -> TcM TyCon
tcLookupTyCon Name
withDictClassName
; let Just DataCon
withdict_data_con
= TyCon -> Maybe DataCon
tyConSingleDataCon_maybe TyCon
tc
mk_ev :: [EvExpr] -> EvTerm
mk_ev [EvExpr
c] = DataCon -> [PredType] -> [EvExpr] -> EvTerm
evDataConApp DataCon
withdict_data_con
[PredType
cls, PredType
mty] [TcCoercion -> EvExpr
evWithDict (EvTerm -> TcCoercion
evTermCoercion (EvExpr -> EvTerm
EvExpr EvExpr
c))]
mk_ev [EvExpr]
e = String -> SDoc -> EvTerm
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"matchWithDict" ([EvExpr] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [EvExpr]
e)
; ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (ClsInstResult -> TcM ClsInstResult)
-> ClsInstResult -> TcM ClsInstResult
forall a b. (a -> b) -> a -> b
$ OneInst { cir_new_theta :: [PredType]
cir_new_theta = [PredType -> PredType -> PredType
mkPrimEqPred PredType
mty PredType
inst_meth_ty]
, cir_mk_ev :: [EvExpr] -> EvTerm
cir_mk_ev = [EvExpr] -> EvTerm
mk_ev
, cir_canonical :: Bool
cir_canonical = Bool
False
, cir_what :: InstanceWhat
cir_what = InstanceWhat
BuiltinInstance }
}
matchWithDict [PredType]
_
= ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return ClsInstResult
NoInstance
matchTypeable :: Class -> [Type] -> TcM ClsInstResult
matchTypeable :: Class -> [PredType] -> TcM ClsInstResult
matchTypeable Class
clas [PredType
k,PredType
t]
| PredType -> Bool
isForAllTy PredType
k = ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return ClsInstResult
NoInstance
| Just (FunTyFlag
af,PredType
mult,PredType
arg,PredType
ret) <- PredType -> Maybe (FunTyFlag, PredType, PredType, PredType)
splitFunTy_maybe PredType
t
= if FunTyFlag -> Bool
isVisibleFunArg FunTyFlag
af
then Class
-> PredType
-> PredType
-> PredType
-> PredType
-> TcM ClsInstResult
doFunTy Class
clas PredType
t PredType
mult PredType
arg PredType
ret
else ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return ClsInstResult
NoInstance
| PredType
k PredType -> PredType -> Bool
`eqType` PredType
naturalTy = Name -> PredType -> TcM ClsInstResult
doTyLit Name
knownNatClassName PredType
t
| PredType
k PredType -> PredType -> Bool
`eqType` PredType
typeSymbolKind = Name -> PredType -> TcM ClsInstResult
doTyLit Name
knownSymbolClassName PredType
t
| PredType
k PredType -> PredType -> Bool
`eqType` PredType
charTy = Name -> PredType -> TcM ClsInstResult
doTyLit Name
knownCharClassName PredType
t
| Just (TyCon
tc, [PredType]
ks) <- HasDebugCallStack => PredType -> Maybe (TyCon, [PredType])
PredType -> Maybe (TyCon, [PredType])
splitTyConApp_maybe PredType
t
, TyCon -> [PredType] -> Bool
onlyNamedBndrsApplied TyCon
tc [PredType]
ks = Class -> PredType -> TyCon -> [PredType] -> TcM ClsInstResult
doTyConApp Class
clas PredType
t TyCon
tc [PredType]
ks
| Just (PredType
f,PredType
kt) <- PredType -> Maybe (PredType, PredType)
splitAppTy_maybe PredType
t = Class -> PredType -> PredType -> PredType -> TcM ClsInstResult
doTyApp Class
clas PredType
t PredType
f PredType
kt
matchTypeable Class
_ [PredType]
_ = ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return ClsInstResult
NoInstance
doFunTy :: Class -> Type -> Mult -> Type -> Type -> TcM ClsInstResult
doFunTy :: Class
-> PredType
-> PredType
-> PredType
-> PredType
-> TcM ClsInstResult
doFunTy Class
clas PredType
ty PredType
mult PredType
arg_ty PredType
ret_ty
= ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (ClsInstResult -> TcM ClsInstResult)
-> ClsInstResult -> TcM ClsInstResult
forall a b. (a -> b) -> a -> b
$ OneInst { cir_new_theta :: [PredType]
cir_new_theta = [PredType]
preds
, cir_mk_ev :: [EvExpr] -> EvTerm
cir_mk_ev = [EvExpr] -> EvTerm
mk_ev
, cir_canonical :: Bool
cir_canonical = Bool
True
, cir_what :: InstanceWhat
cir_what = InstanceWhat
BuiltinInstance }
where
preds :: [PredType]
preds = (PredType -> PredType) -> [PredType] -> [PredType]
forall a b. (a -> b) -> [a] -> [b]
map (Class -> PredType -> PredType
mk_typeable_pred Class
clas) [PredType
mult, PredType
arg_ty, PredType
ret_ty]
mk_ev :: [EvExpr] -> EvTerm
mk_ev [EvExpr
mult_ev, EvExpr
arg_ev, EvExpr
ret_ev] = PredType -> EvTypeable -> EvTerm
evTypeable PredType
ty (EvTypeable -> EvTerm) -> EvTypeable -> EvTerm
forall a b. (a -> b) -> a -> b
$
EvTerm -> EvTerm -> EvTerm -> EvTypeable
EvTypeableTrFun (EvExpr -> EvTerm
EvExpr EvExpr
mult_ev) (EvExpr -> EvTerm
EvExpr EvExpr
arg_ev) (EvExpr -> EvTerm
EvExpr EvExpr
ret_ev)
mk_ev [EvExpr]
_ = String -> EvTerm
forall a. HasCallStack => String -> a
panic String
"GHC.Tc.Instance.Class.doFunTy"
doTyConApp :: Class -> Type -> TyCon -> [Kind] -> TcM ClsInstResult
doTyConApp :: Class -> PredType -> TyCon -> [PredType] -> TcM ClsInstResult
doTyConApp Class
clas PredType
ty TyCon
tc [PredType]
kind_args
| TyCon -> Bool
tyConIsTypeable TyCon
tc
= ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (ClsInstResult -> TcM ClsInstResult)
-> ClsInstResult -> TcM ClsInstResult
forall a b. (a -> b) -> a -> b
$ OneInst { cir_new_theta :: [PredType]
cir_new_theta = (PredType -> PredType) -> [PredType] -> [PredType]
forall a b. (a -> b) -> [a] -> [b]
map (Class -> PredType -> PredType
mk_typeable_pred Class
clas) [PredType]
kind_args
, cir_mk_ev :: [EvExpr] -> EvTerm
cir_mk_ev = [EvExpr] -> EvTerm
mk_ev
, cir_canonical :: Bool
cir_canonical = Bool
True
, cir_what :: InstanceWhat
cir_what = TyCon -> InstanceWhat
BuiltinTypeableInstance TyCon
tc }
| Bool
otherwise
= ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return ClsInstResult
NoInstance
where
mk_ev :: [EvExpr] -> EvTerm
mk_ev [EvExpr]
kinds = PredType -> EvTypeable -> EvTerm
evTypeable PredType
ty (EvTypeable -> EvTerm) -> EvTypeable -> EvTerm
forall a b. (a -> b) -> a -> b
$ TyCon -> [EvTerm] -> EvTypeable
EvTypeableTyCon TyCon
tc ((EvExpr -> EvTerm) -> [EvExpr] -> [EvTerm]
forall a b. (a -> b) -> [a] -> [b]
map EvExpr -> EvTerm
EvExpr [EvExpr]
kinds)
onlyNamedBndrsApplied :: TyCon -> [KindOrType] -> Bool
onlyNamedBndrsApplied :: TyCon -> [PredType] -> Bool
onlyNamedBndrsApplied TyCon
tc [PredType]
ks
= (TyConBinder -> Bool) -> [TyConBinder] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all TyConBinder -> Bool
isNamedTyConBinder [TyConBinder]
used_bndrs Bool -> Bool -> Bool
&&
Bool -> Bool
not ((TyConBinder -> Bool) -> [TyConBinder] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any TyConBinder -> Bool
isNamedTyConBinder [TyConBinder]
leftover_bndrs)
where
bndrs :: [TyConBinder]
bndrs = TyCon -> [TyConBinder]
tyConBinders TyCon
tc
([TyConBinder]
used_bndrs, [TyConBinder]
leftover_bndrs) = [PredType] -> [TyConBinder] -> ([TyConBinder], [TyConBinder])
forall b a. [b] -> [a] -> ([a], [a])
splitAtList [PredType]
ks [TyConBinder]
bndrs
doTyApp :: Class -> Type -> Type -> KindOrType -> TcM ClsInstResult
doTyApp :: Class -> PredType -> PredType -> PredType -> TcM ClsInstResult
doTyApp Class
clas PredType
ty PredType
f PredType
tk
| PredType -> Bool
isForAllTy (HasDebugCallStack => PredType -> PredType
PredType -> PredType
typeKind PredType
f)
= ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return ClsInstResult
NoInstance
| Bool
otherwise
= ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (ClsInstResult -> TcM ClsInstResult)
-> ClsInstResult -> TcM ClsInstResult
forall a b. (a -> b) -> a -> b
$ OneInst { cir_new_theta :: [PredType]
cir_new_theta = (PredType -> PredType) -> [PredType] -> [PredType]
forall a b. (a -> b) -> [a] -> [b]
map (Class -> PredType -> PredType
mk_typeable_pred Class
clas) [PredType
f, PredType
tk]
, cir_mk_ev :: [EvExpr] -> EvTerm
cir_mk_ev = [EvExpr] -> EvTerm
mk_ev
, cir_canonical :: Bool
cir_canonical = Bool
True
, cir_what :: InstanceWhat
cir_what = InstanceWhat
BuiltinInstance }
where
mk_ev :: [EvExpr] -> EvTerm
mk_ev [EvExpr
t1,EvExpr
t2] = PredType -> EvTypeable -> EvTerm
evTypeable PredType
ty (EvTypeable -> EvTerm) -> EvTypeable -> EvTerm
forall a b. (a -> b) -> a -> b
$ EvTerm -> EvTerm -> EvTypeable
EvTypeableTyApp (EvExpr -> EvTerm
EvExpr EvExpr
t1) (EvExpr -> EvTerm
EvExpr EvExpr
t2)
mk_ev [EvExpr]
_ = String -> EvTerm
forall a. HasCallStack => String -> a
panic String
"doTyApp"
mk_typeable_pred :: Class -> Type -> PredType
mk_typeable_pred :: Class -> PredType -> PredType
mk_typeable_pred Class
clas PredType
ty = Class -> [PredType] -> PredType
mkClassPred Class
clas [ HasDebugCallStack => PredType -> PredType
PredType -> PredType
typeKind PredType
ty, PredType
ty ]
doTyLit :: Name -> Type -> TcM ClsInstResult
doTyLit :: Name -> PredType -> TcM ClsInstResult
doTyLit Name
kc PredType
t = do { Class
kc_clas <- Name -> TcM Class
tcLookupClass Name
kc
; let kc_pred :: PredType
kc_pred = Class -> [PredType] -> PredType
mkClassPred Class
kc_clas [ PredType
t ]
mk_ev :: [EvExpr] -> EvTerm
mk_ev [EvExpr
ev] = PredType -> EvTypeable -> EvTerm
evTypeable PredType
t (EvTypeable -> EvTerm) -> EvTypeable -> EvTerm
forall a b. (a -> b) -> a -> b
$ EvTerm -> EvTypeable
EvTypeableTyLit (EvExpr -> EvTerm
EvExpr EvExpr
ev)
mk_ev [EvExpr]
_ = String -> EvTerm
forall a. HasCallStack => String -> a
panic String
"doTyLit"
; ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (OneInst { cir_new_theta :: [PredType]
cir_new_theta = [PredType
kc_pred]
, cir_mk_ev :: [EvExpr] -> EvTerm
cir_mk_ev = [EvExpr] -> EvTerm
mk_ev
, cir_canonical :: Bool
cir_canonical = Bool
True
, cir_what :: InstanceWhat
cir_what = InstanceWhat
BuiltinInstance }) }
matchEqualityInst :: Class -> [Type] -> (DataCon, Role, Type, Type)
matchEqualityInst :: Class -> [PredType] -> (DataCon, Role, PredType, PredType)
matchEqualityInst Class
cls [PredType]
args
| Class
cls Class -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
eqTyConKey
, [PredType
_,PredType
t1,PredType
t2] <- [PredType]
args
= (DataCon
eqDataCon, Role
Nominal, PredType
t1, PredType
t2)
| Class
cls Class -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
heqTyConKey
, [PredType
_,PredType
_,PredType
t1,PredType
t2] <- [PredType]
args
= (DataCon
heqDataCon, Role
Nominal, PredType
t1, PredType
t2)
| Class
cls Class -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
coercibleTyConKey
, [PredType
_, PredType
t1, PredType
t2] <- [PredType]
args
= (DataCon
coercibleDataCon, Role
Representational, PredType
t1, PredType
t2)
| Bool
otherwise
= String -> SDoc -> (DataCon, Role, PredType, PredType)
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"matchEqualityInst" (PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Class -> [PredType] -> PredType
mkClassPred Class
cls [PredType]
args))
matchHasField :: DynFlags -> Bool -> Class -> [Type] -> TcM ClsInstResult
matchHasField :: DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchHasField DynFlags
dflags Bool
short_cut Class
clas [PredType]
tys
= do { FamInstEnvs
fam_inst_envs <- TcM FamInstEnvs
tcGetFamInstEnvs
; GlobalRdrEnv
rdr_env <- TcRn GlobalRdrEnv
getGlobalRdrEnv
; case [PredType]
tys of
[PredType
_k_ty, PredType
x_ty, PredType
r_ty, PredType
a_ty]
| Just FastString
x <- PredType -> Maybe FastString
isStrLitTy PredType
x_ty
, Just (TyCon
tc, [PredType]
args) <- HasCallStack => PredType -> Maybe (TyCon, [PredType])
PredType -> Maybe (TyCon, [PredType])
tcSplitTyConApp_maybe PredType
r_ty
, let r_tc :: TyCon
r_tc = (TyCon, [PredType], TcCoercion) -> TyCon
forall a b c. (a, b, c) -> a
fstOf3 (FamInstEnvs
-> TyCon -> [PredType] -> (TyCon, [PredType], TcCoercion)
tcLookupDataFamInst FamInstEnvs
fam_inst_envs TyCon
tc [PredType]
args)
, Just FieldLabel
fl <- FieldLabelString -> TyCon -> Maybe FieldLabel
lookupTyConFieldLabel (FastString -> FieldLabelString
FieldLabelString FastString
x) TyCon
r_tc
, Just FieldGlobalRdrElt
gre <- GlobalRdrEnv -> FieldLabel -> Maybe FieldGlobalRdrElt
lookupGRE_FieldLabel GlobalRdrEnv
rdr_env FieldLabel
fl
-> do { DFunId
sel_id <- Name -> IOEnv (Env TcGblEnv TcLclEnv) DFunId
tcLookupId (FieldLabel -> Name
flSelector FieldLabel
fl)
; ([(Name, DFunId)]
tv_prs, [PredType]
preds, PredType
sel_ty) <- ([DFunId] -> TcM (Subst, [DFunId]))
-> DFunId -> TcM ([(Name, DFunId)], [PredType], PredType)
tcInstType [DFunId] -> TcM (Subst, [DFunId])
newMetaTyVars DFunId
sel_id
; let theta :: [PredType]
theta = PredType -> PredType -> PredType
mkPrimEqPred PredType
sel_ty (HasDebugCallStack => PredType -> PredType -> PredType
PredType -> PredType -> PredType
mkVisFunTyMany PredType
r_ty PredType
a_ty) PredType -> [PredType] -> [PredType]
forall a. a -> [a] -> [a]
: [PredType]
preds
mk_ev :: [EvExpr] -> EvTerm
mk_ev (EvExpr
ev1:[EvExpr]
evs) = DFunId -> [PredType] -> [EvExpr] -> EvExpr
evSelector DFunId
sel_id [PredType]
tvs [EvExpr]
evs EvExpr -> TcCoercion -> EvTerm
`evCast` TcCoercion
co
where
co :: TcCoercion
co = HasDebugCallStack => TcCoercion -> TcCoercion
TcCoercion -> TcCoercion
mkSubCo (EvTerm -> TcCoercion
evTermCoercion (EvExpr -> EvTerm
EvExpr EvExpr
ev1))
TcCoercion -> TcCoercion -> TcCoercion
`mkTransCo` TcCoercion -> TcCoercion
mkSymCo TcCoercion
co2
mk_ev [] = String -> EvTerm
forall a. HasCallStack => String -> a
panic String
"matchHasField.mk_ev"
Just (PredType
_, TcCoercion
co2) = TyCon -> [PredType] -> Maybe (PredType, TcCoercion)
tcInstNewTyCon_maybe (Class -> TyCon
classTyCon Class
clas)
[PredType]
tys
tvs :: [PredType]
tvs = [DFunId] -> [PredType]
mkTyVarTys (((Name, DFunId) -> DFunId) -> [(Name, DFunId)] -> [DFunId]
forall a b. (a -> b) -> [a] -> [b]
map (Name, DFunId) -> DFunId
forall a b. (a, b) -> b
snd [(Name, DFunId)]
tv_prs)
; if Bool -> Bool
not (DFunId -> Bool
isNaughtyRecordSelector DFunId
sel_id) Bool -> Bool -> Bool
&& PredType -> Bool
isTauTy PredType
sel_ty
then do {
DeprecationWarnings -> FieldGlobalRdrElt -> TcRn ()
addUsedGRE DeprecationWarnings
AllDeprecationWarnings FieldGlobalRdrElt
gre
; Name -> TcRn ()
keepAlive (FieldGlobalRdrElt -> Name
forall info. GlobalRdrEltX info -> Name
greName FieldGlobalRdrElt
gre)
; ClsInstResult -> TcM ClsInstResult
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return OneInst { cir_new_theta :: [PredType]
cir_new_theta = [PredType]
theta
, cir_mk_ev :: [EvExpr] -> EvTerm
cir_mk_ev = [EvExpr] -> EvTerm
mk_ev
, cir_canonical :: Bool
cir_canonical = Bool
True
, cir_what :: InstanceWhat
cir_what = InstanceWhat
BuiltinInstance } }
else DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchInstEnv DynFlags
dflags Bool
short_cut Class
clas [PredType]
tys }
[PredType]
_ -> DynFlags -> Bool -> Class -> [PredType] -> TcM ClsInstResult
matchInstEnv DynFlags
dflags Bool
short_cut Class
clas [PredType]
tys }