{-# LANGUAGE CPP, FlexibleContexts #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Type (
TyThing(..), Type, ArgFlag(..), KindOrType, PredType, ThetaType,
Var, TyVar, isTyVar, TyCoVar, TyBinder, TyVarBinder,
KnotTied,
mkTyVarTy, mkTyVarTys, getTyVar, getTyVar_maybe, repGetTyVar_maybe,
getCastedTyVar_maybe, tyVarKind,
mkAppTy, mkAppTys, splitAppTy, splitAppTys, repSplitAppTys,
splitAppTy_maybe, repSplitAppTy_maybe, tcRepSplitAppTy_maybe,
mkFunTy, mkFunTys, splitFunTy, splitFunTy_maybe,
splitFunTys, funResultTy, funArgTy,
mkTyConApp, mkTyConTy,
tyConAppTyCon_maybe, tyConAppTyConPicky_maybe,
tyConAppArgs_maybe, tyConAppTyCon, tyConAppArgs,
splitTyConApp_maybe, splitTyConApp, tyConAppArgN, nextRole,
tcRepSplitTyConApp_maybe, tcSplitTyConApp_maybe,
splitListTyConApp_maybe,
repSplitTyConApp_maybe,
mkForAllTy, mkForAllTys, mkInvForAllTys, mkSpecForAllTys,
mkVisForAllTys, mkInvForAllTy,
splitForAllTys, splitForAllTyVarBndrs,
splitForAllTy_maybe, splitForAllTy,
splitPiTy_maybe, splitPiTy, splitPiTys,
mkPiTy, mkPiTys, mkTyConBindersPreferAnon,
mkLamType, mkLamTypes,
piResultTy, piResultTys,
applyTysX, dropForAlls,
mkNumLitTy, isNumLitTy,
mkStrLitTy, isStrLitTy,
getRuntimeRep_maybe, getRuntimeRepFromKind_maybe,
mkCastTy, mkCoercionTy, splitCastTy_maybe,
userTypeError_maybe, pprUserTypeErrorTy,
coAxNthLHS,
stripCoercionTy, splitCoercionType_maybe,
splitPiTysInvisible, filterOutInvisibleTypes,
partitionInvisibles,
synTyConResKind,
modifyJoinResTy, setJoinResTy,
TyCoMapper(..), mapType, mapCoercion,
newTyConInstRhs,
mkFamilyTyConApp,
isDictLikeTy,
mkPrimEqPred, mkReprPrimEqPred, mkPrimEqPredRole,
equalityTyCon,
mkHeteroPrimEqPred, mkHeteroReprPrimEqPred,
mkClassPred,
isClassPred, isEqPred, isNomEqPred,
isIPPred, isIPPred_maybe, isIPTyCon, isIPClass,
isCTupleClass,
PredTree(..), EqRel(..), eqRelRole, classifyPredType,
getClassPredTys, getClassPredTys_maybe,
getEqPredTys, getEqPredTys_maybe, getEqPredRole,
predTypeEqRel,
sameVis,
mkTyVarBinder, mkTyVarBinders,
mkAnonBinder,
isAnonTyBinder, isNamedTyBinder,
binderVar, binderVars, binderKind, binderArgFlag,
tyBinderType, tyBinderVar_maybe,
binderRelevantType_maybe, caseBinder,
isVisibleArgFlag, isInvisibleArgFlag, isVisibleBinder, isInvisibleBinder,
tyConBindersTyBinders,
funTyCon,
isTyVarTy, isFunTy, isDictTy, isPredTy, isCoercionTy,
isCoercionTy_maybe, isCoercionType, isForAllTy,
isPiTy, isTauTy, isFamFreeTy,
isValidJoinPointType,
isLiftedType_maybe, isUnliftedType, isUnboxedTupleType, isUnboxedSumType,
isAlgType, isDataFamilyAppType,
isPrimitiveType, isStrictType,
isRuntimeRepTy, isRuntimeRepVar, isRuntimeRepKindedTy,
dropRuntimeRepArgs,
getRuntimeRep, getRuntimeRepFromKind,
Kind,
typeKind, isTypeLevPoly, resultIsLevPoly,
tcIsLiftedTypeKind, tcIsConstraintKind, tcReturnsConstraintKind,
liftedTypeKind,
tyCoFVsOfType, tyCoFVsBndr,
tyCoVarsOfType, tyCoVarsOfTypes,
tyCoVarsOfTypeDSet,
coVarsOfType,
coVarsOfTypes, closeOverKinds, closeOverKindsList,
noFreeVarsOfType,
splitVisVarsOfType, splitVisVarsOfTypes,
expandTypeSynonyms,
typeSize, occCheckExpand,
dVarSetElemsWellScoped, toposortTyVars, tyCoVarsOfTypeWellScoped,
tyCoVarsOfTypesWellScoped,
eqType, eqTypeX, eqTypes, nonDetCmpType, nonDetCmpTypes, nonDetCmpTypeX,
nonDetCmpTypesX, nonDetCmpTc,
eqVarBndrs,
seqType, seqTypes,
coreView, tcView,
tyConsOfType,
TvSubstEnv,
TCvSubst(..),
emptyTvSubstEnv, emptyTCvSubst, mkEmptyTCvSubst,
mkTCvSubst, zipTvSubst, mkTvSubstPrs,
notElemTCvSubst,
getTvSubstEnv, setTvSubstEnv,
zapTCvSubst, getTCvInScope, getTCvSubstRangeFVs,
extendTCvInScope, extendTCvInScopeList, extendTCvInScopeSet,
extendTCvSubst, extendCvSubst,
extendTvSubst, extendTvSubstBinderAndInScope,
extendTvSubstList, extendTvSubstAndInScope,
extendTvSubstWithClone,
isInScope, composeTCvSubstEnv, composeTCvSubst, zipTyEnv, zipCoEnv,
isEmptyTCvSubst, unionTCvSubst,
substTy, substTys, substTyWith, substTysWith, substTheta,
substTyAddInScope,
substTyUnchecked, substTysUnchecked, substThetaUnchecked,
substTyWithUnchecked,
substCoUnchecked, substCoWithUnchecked,
substTyVarBndr, substTyVarBndrs, substTyVar, substTyVars,
cloneTyVarBndr, cloneTyVarBndrs, lookupTyVar,
pprType, pprParendType, pprPrecType,
pprTypeApp, pprTyThingCategory, pprShortTyThing,
pprTvBndr, pprTvBndrs, pprForAll, pprUserForAll,
pprSigmaType, ppSuggestExplicitKinds,
pprTheta, pprThetaArrowTy, pprClassPred,
pprKind, pprParendKind, pprSourceTyCon,
PprPrec(..), topPrec, sigPrec, opPrec, funPrec, appPrec, maybeParen,
pprTyVar, pprTyVars,
pprWithTYPE,
tidyType, tidyTypes,
tidyOpenType, tidyOpenTypes,
tidyOpenKind,
tidyTyCoVarBndr, tidyTyCoVarBndrs, tidyFreeTyCoVars,
tidyOpenTyCoVar, tidyOpenTyCoVars,
tidyTyVarOcc,
tidyTopType,
tidyKind,
tidyTyVarBinder, tidyTyVarBinders
) where
#include "HsVersions.h"
import GhcPrelude
import BasicTypes
import Kind
import TyCoRep
import Var
import VarEnv
import VarSet
import UniqSet
import Class
import TyCon
import TysPrim
import {-# SOURCE #-} TysWiredIn ( listTyCon, typeNatKind
, typeSymbolKind, liftedTypeKind )
import PrelNames
import CoAxiom
import {-# SOURCE #-} Coercion( mkCoherenceCo, mkReflCo
, mkTyConAppCo, mkAppCo, mkCoVarCo, mkAxiomRuleCo
, mkForAllCo, mkFunCo, mkAxiomInstCo, mkUnivCo
, mkSymCo, mkTransCo, mkNthCo, mkLRCo, mkInstCo
, mkKindCo, mkSubCo, mkFunCo, mkAxiomInstCo
, decomposePiCos, coercionKind, coercionType
, isReflexiveCo, seqCo )
import Util
import Outputable
import FastString
import Pair
import DynFlags ( gopt_set, GeneralFlag(Opt_PrintExplicitRuntimeReps) )
import ListSetOps
import Digraph
import Unique ( nonDetCmpUnique )
import Maybes ( orElse )
import Data.Maybe ( isJust, mapMaybe )
import Control.Monad ( guard )
import Control.Arrow ( first, second )
{-# INLINE tcView #-}
tcView :: Type -> Maybe Type
tcView (TyConApp tc tys) | Just (tenv, rhs, tys') <- expandSynTyCon_maybe tc tys
= Just (mkAppTys (substTy (mkTvSubstPrs tenv) rhs) tys')
tcView _ = Nothing
{-# INLINE coreView #-}
coreView :: Type -> Maybe Type
coreView ty@(TyConApp tc tys)
| Just (tenv, rhs, tys') <- expandSynTyCon_maybe tc tys
= Just (mkAppTys (substTy (mkTvSubstPrs tenv) rhs) tys')
| isConstraintKindCon tc
= ASSERT2( null tys, ppr ty )
Just liftedTypeKind
coreView _ = Nothing
expandTypeSynonyms :: Type -> Type
expandTypeSynonyms ty
= go (mkEmptyTCvSubst in_scope) ty
where
in_scope = mkInScopeSet (tyCoVarsOfType ty)
go subst (TyConApp tc tys)
| Just (tenv, rhs, tys') <- expandSynTyCon_maybe tc expanded_tys
= let subst' = mkTvSubst in_scope (mkVarEnv tenv)
in mkAppTys (go subst' rhs) tys'
| otherwise
= TyConApp tc expanded_tys
where
expanded_tys = (map (go subst) tys)
go _ (LitTy l) = LitTy l
go subst (TyVarTy tv) = substTyVar subst tv
go subst (AppTy t1 t2) = mkAppTy (go subst t1) (go subst t2)
go subst (FunTy arg res)
= mkFunTy (go subst arg) (go subst res)
go subst (ForAllTy (TvBndr tv vis) t)
= let (subst', tv') = substTyVarBndrUsing go subst tv in
ForAllTy (TvBndr tv' vis) (go subst' t)
go subst (CastTy ty co) = mkCastTy (go subst ty) (go_co subst co)
go subst (CoercionTy co) = mkCoercionTy (go_co subst co)
go_co subst (Refl r ty)
= mkReflCo r (go subst ty)
go_co subst (TyConAppCo r tc args)
= mkTyConAppCo r tc (map (go_co subst) args)
go_co subst (AppCo co arg)
= mkAppCo (go_co subst co) (go_co subst arg)
go_co subst (ForAllCo tv kind_co co)
= let (subst', tv', kind_co') = go_cobndr subst tv kind_co in
mkForAllCo tv' kind_co' (go_co subst' co)
go_co subst (FunCo r co1 co2)
= mkFunCo r (go_co subst co1) (go_co subst co2)
go_co subst (CoVarCo cv)
= substCoVar subst cv
go_co subst (AxiomInstCo ax ind args)
= mkAxiomInstCo ax ind (map (go_co subst) args)
go_co subst (UnivCo p r t1 t2)
= mkUnivCo (go_prov subst p) r (go subst t1) (go subst t2)
go_co subst (SymCo co)
= mkSymCo (go_co subst co)
go_co subst (TransCo co1 co2)
= mkTransCo (go_co subst co1) (go_co subst co2)
go_co subst (NthCo r n co)
= mkNthCo r n (go_co subst co)
go_co subst (LRCo lr co)
= mkLRCo lr (go_co subst co)
go_co subst (InstCo co arg)
= mkInstCo (go_co subst co) (go_co subst arg)
go_co subst (CoherenceCo co1 co2)
= mkCoherenceCo (go_co subst co1) (go_co subst co2)
go_co subst (KindCo co)
= mkKindCo (go_co subst co)
go_co subst (SubCo co)
= mkSubCo (go_co subst co)
go_co subst (AxiomRuleCo ax cs)
= AxiomRuleCo ax (map (go_co subst) cs)
go_co _ (HoleCo h)
= pprPanic "expandTypeSynonyms hit a hole" (ppr h)
go_prov _ UnsafeCoerceProv = UnsafeCoerceProv
go_prov subst (PhantomProv co) = PhantomProv (go_co subst co)
go_prov subst (ProofIrrelProv co) = ProofIrrelProv (go_co subst co)
go_prov _ p@(PluginProv _) = p
go_cobndr subst = substForAllCoBndrUsing False (go_co subst) subst
data TyCoMapper env m
= TyCoMapper
{ tcm_smart :: Bool
, tcm_tyvar :: env -> TyVar -> m Type
, tcm_covar :: env -> CoVar -> m Coercion
, tcm_hole :: env -> CoercionHole -> m Coercion
, tcm_tybinder :: env -> TyVar -> ArgFlag -> m (env, TyVar)
, tcm_tycon :: TyCon -> m TyCon
}
{-# INLINABLE mapType #-}
mapType :: Monad m => TyCoMapper env m -> env -> Type -> m Type
mapType mapper@(TyCoMapper { tcm_smart = smart, tcm_tyvar = tyvar
, tcm_tybinder = tybinder, tcm_tycon = tycon })
env ty
= go ty
where
go (TyVarTy tv) = tyvar env tv
go (AppTy t1 t2) = mkappty <$> go t1 <*> go t2
go t@(TyConApp tc []) | not (isTcTyCon tc)
= return t
go (TyConApp tc tys)
= do { tc' <- tycon tc
; mktyconapp tc' <$> mapM go tys }
go (FunTy arg res) = FunTy <$> go arg <*> go res
go (ForAllTy (TvBndr tv vis) inner)
= do { (env', tv') <- tybinder env tv vis
; inner' <- mapType mapper env' inner
; return $ ForAllTy (TvBndr tv' vis) inner' }
go ty@(LitTy {}) = return ty
go (CastTy ty co) = mkcastty <$> go ty <*> mapCoercion mapper env co
go (CoercionTy co) = CoercionTy <$> mapCoercion mapper env co
(mktyconapp, mkappty, mkcastty)
| smart = (mkTyConApp, mkAppTy, mkCastTy)
| otherwise = (TyConApp, AppTy, CastTy)
{-# INLINABLE mapCoercion #-}
mapCoercion :: Monad m
=> TyCoMapper env m -> env -> Coercion -> m Coercion
mapCoercion mapper@(TyCoMapper { tcm_smart = smart, tcm_covar = covar
, tcm_hole = cohole, tcm_tybinder = tybinder
, tcm_tycon = tycon })
env co
= go co
where
go (Refl r ty) = Refl r <$> mapType mapper env ty
go (TyConAppCo r tc args)
= do { tc' <- tycon tc
; mktyconappco r tc' <$> mapM go args }
go (AppCo c1 c2) = mkappco <$> go c1 <*> go c2
go (ForAllCo tv kind_co co)
= do { kind_co' <- go kind_co
; (env', tv') <- tybinder env tv Inferred
; co' <- mapCoercion mapper env' co
; return $ mkforallco tv' kind_co' co' }
go (FunCo r c1 c2) = mkFunCo r <$> go c1 <*> go c2
go (CoVarCo cv) = covar env cv
go (AxiomInstCo ax i args)
= mkaxiominstco ax i <$> mapM go args
go (HoleCo hole) = cohole env hole
go (UnivCo p r t1 t2)
= mkunivco <$> go_prov p <*> pure r
<*> mapType mapper env t1 <*> mapType mapper env t2
go (SymCo co) = mksymco <$> go co
go (TransCo c1 c2) = mktransco <$> go c1 <*> go c2
go (AxiomRuleCo r cos) = AxiomRuleCo r <$> mapM go cos
go (NthCo r i co) = mknthco r i <$> go co
go (LRCo lr co) = mklrco lr <$> go co
go (InstCo co arg) = mkinstco <$> go co <*> go arg
go (CoherenceCo c1 c2) = mkcoherenceco <$> go c1 <*> go c2
go (KindCo co) = mkkindco <$> go co
go (SubCo co) = mksubco <$> go co
go_prov UnsafeCoerceProv = return UnsafeCoerceProv
go_prov (PhantomProv co) = PhantomProv <$> go co
go_prov (ProofIrrelProv co) = ProofIrrelProv <$> go co
go_prov p@(PluginProv _) = return p
( mktyconappco, mkappco, mkaxiominstco, mkunivco
, mksymco, mktransco, mknthco, mklrco, mkinstco, mkcoherenceco
, mkkindco, mksubco, mkforallco)
| smart
= ( mkTyConAppCo, mkAppCo, mkAxiomInstCo, mkUnivCo
, mkSymCo, mkTransCo, mkNthCo, mkLRCo, mkInstCo, mkCoherenceCo
, mkKindCo, mkSubCo, mkForAllCo )
| otherwise
= ( TyConAppCo, AppCo, AxiomInstCo, UnivCo
, SymCo, TransCo, NthCo, LRCo, InstCo, CoherenceCo
, KindCo, SubCo, ForAllCo )
getTyVar :: String -> Type -> TyVar
getTyVar msg ty = case getTyVar_maybe ty of
Just tv -> tv
Nothing -> panic ("getTyVar: " ++ msg)
isTyVarTy :: Type -> Bool
isTyVarTy ty = isJust (getTyVar_maybe ty)
getTyVar_maybe :: Type -> Maybe TyVar
getTyVar_maybe ty | Just ty' <- coreView ty = getTyVar_maybe ty'
| otherwise = repGetTyVar_maybe ty
getCastedTyVar_maybe :: Type -> Maybe (TyVar, CoercionN)
getCastedTyVar_maybe ty | Just ty' <- coreView ty = getCastedTyVar_maybe ty'
getCastedTyVar_maybe (CastTy (TyVarTy tv) co) = Just (tv, co)
getCastedTyVar_maybe (TyVarTy tv)
= Just (tv, mkReflCo Nominal (tyVarKind tv))
getCastedTyVar_maybe _ = Nothing
repGetTyVar_maybe :: Type -> Maybe TyVar
repGetTyVar_maybe (TyVarTy tv) = Just tv
repGetTyVar_maybe _ = Nothing
mkAppTy :: Type -> Type -> Type
mkAppTy (CastTy fun_ty co) arg_ty
| ([arg_co], res_co) <- decomposePiCos co (coercionKind co) [arg_ty]
= (fun_ty `mkAppTy` (arg_ty `mkCastTy` arg_co)) `mkCastTy` res_co
mkAppTy (TyConApp tc tys) ty2 = mkTyConApp tc (tys ++ [ty2])
mkAppTy ty1 ty2 = AppTy ty1 ty2
mkAppTys :: Type -> [Type] -> Type
mkAppTys ty1 [] = ty1
mkAppTys (CastTy fun_ty co) arg_tys
= foldl AppTy ((mkAppTys fun_ty casted_arg_tys) `mkCastTy` res_co) leftovers
where
(arg_cos, res_co) = decomposePiCos co (coercionKind co) arg_tys
(args_to_cast, leftovers) = splitAtList arg_cos arg_tys
casted_arg_tys = zipWith mkCastTy args_to_cast arg_cos
mkAppTys (TyConApp tc tys1) tys2 = mkTyConApp tc (tys1 ++ tys2)
mkAppTys ty1 tys2 = foldl AppTy ty1 tys2
splitAppTy_maybe :: Type -> Maybe (Type, Type)
splitAppTy_maybe ty | Just ty' <- coreView ty
= splitAppTy_maybe ty'
splitAppTy_maybe ty = repSplitAppTy_maybe ty
repSplitAppTy_maybe :: HasDebugCallStack => Type -> Maybe (Type,Type)
repSplitAppTy_maybe (FunTy ty1 ty2)
= Just (TyConApp funTyCon [rep1, rep2, ty1], ty2)
where
rep1 = getRuntimeRep ty1
rep2 = getRuntimeRep ty2
repSplitAppTy_maybe (AppTy ty1 ty2)
= Just (ty1, ty2)
repSplitAppTy_maybe (TyConApp tc tys)
| mightBeUnsaturatedTyCon tc || tys `lengthExceeds` tyConArity tc
, Just (tys', ty') <- snocView tys
= Just (TyConApp tc tys', ty')
repSplitAppTy_maybe _other = Nothing
tcRepSplitAppTy_maybe :: Type -> Maybe (Type,Type)
tcRepSplitAppTy_maybe (FunTy ty1 ty2)
| isPredTy ty1
= Nothing
| otherwise
= Just (TyConApp funTyCon [rep1, rep2, ty1], ty2)
where
rep1 = getRuntimeRep ty1
rep2 = getRuntimeRep ty2
tcRepSplitAppTy_maybe (AppTy ty1 ty2) = Just (ty1, ty2)
tcRepSplitAppTy_maybe (TyConApp tc tys)
| mightBeUnsaturatedTyCon tc || tys `lengthExceeds` tyConArity tc
, Just (tys', ty') <- snocView tys
= Just (TyConApp tc tys', ty')
tcRepSplitAppTy_maybe _other = Nothing
tcRepSplitTyConApp_maybe :: HasCallStack => Type -> Maybe (TyCon, [Type])
tcRepSplitTyConApp_maybe (TyConApp tc tys)
= Just (tc, tys)
tcRepSplitTyConApp_maybe (FunTy arg res)
= Just (funTyCon, [arg_rep, res_rep, arg, res])
where
arg_rep = getRuntimeRep arg
res_rep = getRuntimeRep res
tcRepSplitTyConApp_maybe _
= Nothing
splitAppTy :: Type -> (Type, Type)
splitAppTy ty = case splitAppTy_maybe ty of
Just pr -> pr
Nothing -> panic "splitAppTy"
splitAppTys :: Type -> (Type, [Type])
splitAppTys ty = split ty ty []
where
split orig_ty ty args | Just ty' <- coreView ty = split orig_ty ty' args
split _ (AppTy ty arg) args = split ty ty (arg:args)
split _ (TyConApp tc tc_args) args
= let
n | mightBeUnsaturatedTyCon tc = 0
| otherwise = tyConArity tc
(tc_args1, tc_args2) = splitAt n tc_args
in
(TyConApp tc tc_args1, tc_args2 ++ args)
split _ (FunTy ty1 ty2) args
= ASSERT( null args )
(TyConApp funTyCon [], [rep1, rep2, ty1, ty2])
where
rep1 = getRuntimeRep ty1
rep2 = getRuntimeRep ty2
split orig_ty _ args = (orig_ty, args)
repSplitAppTys :: HasDebugCallStack => Type -> (Type, [Type])
repSplitAppTys ty = split ty []
where
split (AppTy ty arg) args = split ty (arg:args)
split (TyConApp tc tc_args) args
= let n | mightBeUnsaturatedTyCon tc = 0
| otherwise = tyConArity tc
(tc_args1, tc_args2) = splitAt n tc_args
in
(TyConApp tc tc_args1, tc_args2 ++ args)
split (FunTy ty1 ty2) args
= ASSERT( null args )
(TyConApp funTyCon [], [rep1, rep2, ty1, ty2])
where
rep1 = getRuntimeRep ty1
rep2 = getRuntimeRep ty2
split ty args = (ty, args)
mkNumLitTy :: Integer -> Type
mkNumLitTy n = LitTy (NumTyLit n)
isNumLitTy :: Type -> Maybe Integer
isNumLitTy ty | Just ty1 <- coreView ty = isNumLitTy ty1
isNumLitTy (LitTy (NumTyLit n)) = Just n
isNumLitTy _ = Nothing
mkStrLitTy :: FastString -> Type
mkStrLitTy s = LitTy (StrTyLit s)
isStrLitTy :: Type -> Maybe FastString
isStrLitTy ty | Just ty1 <- coreView ty = isStrLitTy ty1
isStrLitTy (LitTy (StrTyLit s)) = Just s
isStrLitTy _ = Nothing
userTypeError_maybe :: Type -> Maybe Type
userTypeError_maybe t
= do { (tc, _kind : msg : _) <- splitTyConApp_maybe t
; guard (tyConName tc == errorMessageTypeErrorFamName)
; return msg }
pprUserTypeErrorTy :: Type -> SDoc
pprUserTypeErrorTy ty =
case splitTyConApp_maybe ty of
Just (tc,[txt])
| tyConName tc == typeErrorTextDataConName
, Just str <- isStrLitTy txt -> ftext str
Just (tc,[_k,t])
| tyConName tc == typeErrorShowTypeDataConName -> ppr t
Just (tc,[t1,t2])
| tyConName tc == typeErrorAppendDataConName ->
pprUserTypeErrorTy t1 <> pprUserTypeErrorTy t2
Just (tc,[t1,t2])
| tyConName tc == typeErrorVAppendDataConName ->
pprUserTypeErrorTy t1 $$ pprUserTypeErrorTy t2
_ -> ppr ty
isFunTy :: Type -> Bool
isFunTy ty = isJust (splitFunTy_maybe ty)
splitFunTy :: Type -> (Type, Type)
splitFunTy ty | Just ty' <- coreView ty = splitFunTy ty'
splitFunTy (FunTy arg res) = (arg, res)
splitFunTy other = pprPanic "splitFunTy" (ppr other)
splitFunTy_maybe :: Type -> Maybe (Type, Type)
splitFunTy_maybe ty | Just ty' <- coreView ty = splitFunTy_maybe ty'
splitFunTy_maybe (FunTy arg res) = Just (arg, res)
splitFunTy_maybe _ = Nothing
splitFunTys :: Type -> ([Type], Type)
splitFunTys ty = split [] ty ty
where
split args orig_ty ty | Just ty' <- coreView ty = split args orig_ty ty'
split args _ (FunTy arg res) = split (arg:args) res res
split args orig_ty _ = (reverse args, orig_ty)
funResultTy :: Type -> Type
funResultTy ty | Just ty' <- coreView ty = funResultTy ty'
funResultTy (FunTy _ res) = res
funResultTy ty = pprPanic "funResultTy" (ppr ty)
funArgTy :: Type -> Type
funArgTy ty | Just ty' <- coreView ty = funArgTy ty'
funArgTy (FunTy arg _res) = arg
funArgTy ty = pprPanic "funArgTy" (ppr ty)
piResultTy :: HasDebugCallStack => Type -> Type -> Type
piResultTy ty arg = case piResultTy_maybe ty arg of
Just res -> res
Nothing -> pprPanic "piResultTy" (ppr ty $$ ppr arg)
piResultTy_maybe :: Type -> Type -> Maybe Type
piResultTy_maybe ty arg
| Just ty' <- coreView ty = piResultTy_maybe ty' arg
| FunTy _ res <- ty
= Just res
| ForAllTy (TvBndr tv _) res <- ty
= let empty_subst = mkEmptyTCvSubst $ mkInScopeSet $
tyCoVarsOfTypes [arg,res]
in Just (substTy (extendTvSubst empty_subst tv arg) res)
| otherwise
= Nothing
piResultTys :: HasDebugCallStack => Type -> [Type] -> Type
piResultTys ty [] = ty
piResultTys ty orig_args@(arg:args)
| Just ty' <- coreView ty
= piResultTys ty' orig_args
| FunTy _ res <- ty
= piResultTys res args
| ForAllTy (TvBndr tv _) res <- ty
= go (extendVarEnv emptyTvSubstEnv tv arg) res args
| otherwise
= pprPanic "piResultTys1" (ppr ty $$ ppr orig_args)
where
in_scope = mkInScopeSet (tyCoVarsOfTypes (ty:orig_args))
go :: TvSubstEnv -> Type -> [Type] -> Type
go tv_env ty [] = substTy (mkTvSubst in_scope tv_env) ty
go tv_env ty all_args@(arg:args)
| Just ty' <- coreView ty
= go tv_env ty' all_args
| FunTy _ res <- ty
= go tv_env res args
| ForAllTy (TvBndr tv _) res <- ty
= go (extendVarEnv tv_env tv arg) res args
| not (isEmptyVarEnv tv_env)
= go emptyTvSubstEnv
(substTy (mkTvSubst in_scope tv_env) ty)
all_args
| otherwise
=
pprPanic "piResultTys2" (ppr ty $$ ppr orig_args $$ ppr all_args)
applyTysX :: [TyVar] -> Type -> [Type] -> Type
applyTysX tvs body_ty arg_tys
= ASSERT2( arg_tys `lengthAtLeast` n_tvs, pp_stuff )
ASSERT2( tyCoVarsOfType body_ty `subVarSet` mkVarSet tvs, pp_stuff )
mkAppTys (substTyWith tvs (take n_tvs arg_tys) body_ty)
(drop n_tvs arg_tys)
where
pp_stuff = vcat [ppr tvs, ppr body_ty, ppr arg_tys]
n_tvs = length tvs
mkTyConApp :: TyCon -> [Type] -> Type
mkTyConApp tycon tys
| isFunTyCon tycon
, [_rep1,_rep2,ty1,ty2] <- tys
= FunTy ty1 ty2
| otherwise
= TyConApp tycon tys
tyConAppTyConPicky_maybe :: Type -> Maybe TyCon
tyConAppTyConPicky_maybe (TyConApp tc _) = Just tc
tyConAppTyConPicky_maybe (FunTy {}) = Just funTyCon
tyConAppTyConPicky_maybe _ = Nothing
tyConAppTyCon_maybe :: Type -> Maybe TyCon
tyConAppTyCon_maybe ty | Just ty' <- coreView ty = tyConAppTyCon_maybe ty'
tyConAppTyCon_maybe (TyConApp tc _) = Just tc
tyConAppTyCon_maybe (FunTy {}) = Just funTyCon
tyConAppTyCon_maybe _ = Nothing
tyConAppTyCon :: Type -> TyCon
tyConAppTyCon ty = tyConAppTyCon_maybe ty `orElse` pprPanic "tyConAppTyCon" (ppr ty)
tyConAppArgs_maybe :: Type -> Maybe [Type]
tyConAppArgs_maybe ty | Just ty' <- coreView ty = tyConAppArgs_maybe ty'
tyConAppArgs_maybe (TyConApp _ tys) = Just tys
tyConAppArgs_maybe (FunTy arg res)
| Just rep1 <- getRuntimeRep_maybe arg
, Just rep2 <- getRuntimeRep_maybe res
= Just [rep1, rep2, arg, res]
tyConAppArgs_maybe _ = Nothing
tyConAppArgs :: Type -> [Type]
tyConAppArgs ty = tyConAppArgs_maybe ty `orElse` pprPanic "tyConAppArgs" (ppr ty)
tyConAppArgN :: Int -> Type -> Type
tyConAppArgN n ty
= case tyConAppArgs_maybe ty of
Just tys -> ASSERT2( tys `lengthExceeds` n, ppr n <+> ppr tys ) tys `getNth` n
Nothing -> pprPanic "tyConAppArgN" (ppr n <+> ppr ty)
splitTyConApp :: Type -> (TyCon, [Type])
splitTyConApp ty = case splitTyConApp_maybe ty of
Just stuff -> stuff
Nothing -> pprPanic "splitTyConApp" (ppr ty)
splitTyConApp_maybe :: HasDebugCallStack => Type -> Maybe (TyCon, [Type])
splitTyConApp_maybe ty | Just ty' <- coreView ty = splitTyConApp_maybe ty'
splitTyConApp_maybe ty = repSplitTyConApp_maybe ty
repSplitTyConApp_maybe :: HasDebugCallStack => Type -> Maybe (TyCon, [Type])
repSplitTyConApp_maybe (TyConApp tc tys) = Just (tc, tys)
repSplitTyConApp_maybe (FunTy arg res)
| Just arg_rep <- getRuntimeRep_maybe arg
, Just res_rep <- getRuntimeRep_maybe res
= Just (funTyCon, [arg_rep, res_rep, arg, res])
repSplitTyConApp_maybe _ = Nothing
splitListTyConApp_maybe :: Type -> Maybe Type
splitListTyConApp_maybe ty = case splitTyConApp_maybe ty of
Just (tc,[e]) | tc == listTyCon -> Just e
_other -> Nothing
nextRole :: Type -> Role
nextRole ty
| Just (tc, tys) <- splitTyConApp_maybe ty
, let num_tys = length tys
, num_tys < tyConArity tc
= tyConRoles tc `getNth` num_tys
| otherwise
= Nominal
newTyConInstRhs :: TyCon -> [Type] -> Type
newTyConInstRhs tycon tys
= ASSERT2( tvs `leLength` tys, ppr tycon $$ ppr tys $$ ppr tvs )
applyTysX tvs rhs tys
where
(tvs, rhs) = newTyConEtadRhs tycon
splitCastTy_maybe :: Type -> Maybe (Type, Coercion)
splitCastTy_maybe ty | Just ty' <- coreView ty = splitCastTy_maybe ty'
splitCastTy_maybe (CastTy ty co) = Just (ty, co)
splitCastTy_maybe _ = Nothing
mkCastTy :: Type -> Coercion -> Type
mkCastTy ty co | isReflexiveCo co = ty
mkCastTy (CastTy ty co1) co2 = mkCastTy ty (co1 `mkTransCo` co2)
mkCastTy ty co = CastTy ty co
tyConBindersTyBinders :: [TyConBinder] -> [TyBinder]
tyConBindersTyBinders = map to_tyb
where
to_tyb (TvBndr tv (NamedTCB vis)) = Named (TvBndr tv vis)
to_tyb (TvBndr tv AnonTCB) = Anon (tyVarKind tv)
mkCoercionTy :: Coercion -> Type
mkCoercionTy = CoercionTy
isCoercionTy :: Type -> Bool
isCoercionTy (CoercionTy _) = True
isCoercionTy _ = False
isCoercionTy_maybe :: Type -> Maybe Coercion
isCoercionTy_maybe (CoercionTy co) = Just co
isCoercionTy_maybe _ = Nothing
stripCoercionTy :: Type -> Coercion
stripCoercionTy (CoercionTy co) = co
stripCoercionTy ty = pprPanic "stripCoercionTy" (ppr ty)
mkInvForAllTy :: TyVar -> Type -> Type
mkInvForAllTy tv ty = ASSERT( isTyVar tv )
ForAllTy (TvBndr tv Inferred) ty
mkInvForAllTys :: [TyVar] -> Type -> Type
mkInvForAllTys tvs ty = ASSERT( all isTyVar tvs )
foldr mkInvForAllTy ty tvs
mkSpecForAllTys :: [TyVar] -> Type -> Type
mkSpecForAllTys tvs = ASSERT( all isTyVar tvs )
mkForAllTys [ TvBndr tv Specified | tv <- tvs ]
mkVisForAllTys :: [TyVar] -> Type -> Type
mkVisForAllTys tvs = ASSERT( all isTyVar tvs )
mkForAllTys [ TvBndr tv Required | tv <- tvs ]
mkLamType :: Var -> Type -> Type
mkLamTypes :: [Var] -> Type -> Type
mkLamType v ty
| isTyVar v = ForAllTy (TvBndr v Inferred) ty
| otherwise = FunTy (varType v) ty
mkLamTypes vs ty = foldr mkLamType ty vs
mkTyConBindersPreferAnon :: [TyVar] -> Type -> [TyConBinder]
mkTyConBindersPreferAnon vars inner_ty = fst (go vars)
where
go :: [TyVar] -> ([TyConBinder], VarSet)
go [] = ([], tyCoVarsOfType inner_ty)
go (v:vs) | v `elemVarSet` fvs
= ( TvBndr v (NamedTCB Required) : binders
, fvs `delVarSet` v `unionVarSet` kind_vars )
| otherwise
= ( TvBndr v AnonTCB : binders
, fvs `unionVarSet` kind_vars )
where
(binders, fvs) = go vs
kind_vars = tyCoVarsOfType $ tyVarKind v
splitForAllTys :: Type -> ([TyVar], Type)
splitForAllTys ty = split ty ty []
where
split orig_ty ty tvs | Just ty' <- coreView ty = split orig_ty ty' tvs
split _ (ForAllTy (TvBndr tv _) ty) tvs = split ty ty (tv:tvs)
split orig_ty _ tvs = (reverse tvs, orig_ty)
splitForAllTyVarBndrs :: Type -> ([TyVarBinder], Type)
splitForAllTyVarBndrs ty = split ty ty []
where
split orig_ty ty bs | Just ty' <- coreView ty = split orig_ty ty' bs
split _ (ForAllTy b res) bs = split res res (b:bs)
split orig_ty _ bs = (reverse bs, orig_ty)
{-# INLINE splitForAllTyVarBndrs #-}
isForAllTy :: Type -> Bool
isForAllTy ty | Just ty' <- coreView ty = isForAllTy ty'
isForAllTy (ForAllTy {}) = True
isForAllTy _ = False
isPiTy :: Type -> Bool
isPiTy ty | Just ty' <- coreView ty = isForAllTy ty'
isPiTy (ForAllTy {}) = True
isPiTy (FunTy {}) = True
isPiTy _ = False
splitForAllTy :: Type -> (TyVar, Type)
splitForAllTy ty
| Just answer <- splitForAllTy_maybe ty = answer
| otherwise = pprPanic "splitForAllTy" (ppr ty)
dropForAlls :: Type -> Type
dropForAlls ty = go ty
where
go ty | Just ty' <- coreView ty = go ty'
go (ForAllTy _ res) = go res
go res = res
splitForAllTy_maybe :: Type -> Maybe (TyVar, Type)
splitForAllTy_maybe ty = go ty
where
go ty | Just ty' <- coreView ty = go ty'
go (ForAllTy (TvBndr tv _) ty) = Just (tv, ty)
go _ = Nothing
splitPiTy_maybe :: Type -> Maybe (TyBinder, Type)
splitPiTy_maybe ty = go ty
where
go ty | Just ty' <- coreView ty = go ty'
go (ForAllTy bndr ty) = Just (Named bndr, ty)
go (FunTy arg res) = Just (Anon arg, res)
go _ = Nothing
splitPiTy :: Type -> (TyBinder, Type)
splitPiTy ty
| Just answer <- splitPiTy_maybe ty = answer
| otherwise = pprPanic "splitPiTy" (ppr ty)
splitPiTys :: Type -> ([TyBinder], Type)
splitPiTys ty = split ty ty
where
split orig_ty ty | Just ty' <- coreView ty = split orig_ty ty'
split _ (ForAllTy b res) = let (bs, ty) = split res res
in (Named b : bs, ty)
split _ (FunTy arg res) = let (bs, ty) = split res res
in (Anon arg : bs, ty)
split orig_ty _ = ([], orig_ty)
splitPiTysInvisible :: Type -> ([TyBinder], Type)
splitPiTysInvisible ty = split ty ty []
where
split orig_ty ty bs | Just ty' <- coreView ty = split orig_ty ty' bs
split _ (ForAllTy b@(TvBndr _ vis) res) bs
| isInvisibleArgFlag vis = split res res (Named b : bs)
split _ (FunTy arg res) bs
| isPredTy arg = split res res (Anon arg : bs)
split orig_ty _ bs = (reverse bs, orig_ty)
filterOutInvisibleTypes :: TyCon -> [Type] -> [Type]
filterOutInvisibleTypes tc tys = snd $ partitionInvisibles tc id tys
partitionInvisibles :: TyCon -> (a -> Type) -> [a] -> ([a], [a])
partitionInvisibles tc get_ty = go emptyTCvSubst (tyConKind tc)
where
go _ _ [] = ([], [])
go subst (ForAllTy (TvBndr tv vis) res_ki) (x:xs)
| isVisibleArgFlag vis = second (x :) (go subst' res_ki xs)
| otherwise = first (x :) (go subst' res_ki xs)
where
subst' = extendTvSubst subst tv (get_ty x)
go subst (TyVarTy tv) xs
| Just ki <- lookupTyVar subst tv = go subst ki xs
go _ _ xs = ([], xs)
isTauTy :: Type -> Bool
isTauTy ty | Just ty' <- coreView ty = isTauTy ty'
isTauTy (TyVarTy _) = True
isTauTy (LitTy {}) = True
isTauTy (TyConApp tc tys) = all isTauTy tys && isTauTyCon tc
isTauTy (AppTy a b) = isTauTy a && isTauTy b
isTauTy (FunTy a b) = isTauTy a && isTauTy b
isTauTy (ForAllTy {}) = False
isTauTy (CastTy ty _) = isTauTy ty
isTauTy (CoercionTy _) = False
mkAnonBinder :: Type -> TyBinder
mkAnonBinder = Anon
isAnonTyBinder :: TyBinder -> Bool
isAnonTyBinder (Named {}) = False
isAnonTyBinder (Anon {}) = True
isNamedTyBinder :: TyBinder -> Bool
isNamedTyBinder (Named {}) = True
isNamedTyBinder (Anon {}) = False
tyBinderVar_maybe :: TyBinder -> Maybe TyVar
tyBinderVar_maybe (Named tv) = Just $ binderVar tv
tyBinderVar_maybe _ = Nothing
tyBinderType :: TyBinder -> Type
tyBinderType (Named tvb) = binderKind tvb
tyBinderType (Anon ty) = ty
binderRelevantType_maybe :: TyBinder -> Maybe Type
binderRelevantType_maybe (Named {}) = Nothing
binderRelevantType_maybe (Anon ty) = Just ty
caseBinder :: TyBinder
-> (TyVarBinder -> a)
-> (Type -> a)
-> a
caseBinder (Named v) f _ = f v
caseBinder (Anon t) _ d = d t
tcSplitTyConApp_maybe :: HasCallStack => Type -> Maybe (TyCon, [Type])
tcSplitTyConApp_maybe ty | Just ty' <- tcView ty = tcSplitTyConApp_maybe ty'
tcSplitTyConApp_maybe ty = tcRepSplitTyConApp_maybe ty
tcIsConstraintKind :: Kind -> Bool
tcIsConstraintKind ty
| Just (tc, args) <- tcSplitTyConApp_maybe ty
, isConstraintKindCon tc
= ASSERT2( null args, ppr ty ) True
| otherwise
= False
tcIsLiftedTypeKind :: Kind -> Bool
tcIsLiftedTypeKind ty
| Just (type_tc, [arg]) <- tcSplitTyConApp_maybe ty
, type_tc `hasKey` tYPETyConKey
, Just (lifted_rep_tc, args) <- tcSplitTyConApp_maybe arg
, lifted_rep_tc `hasKey` liftedRepDataConKey
= ASSERT2( null args, ppr ty ) True
| otherwise
= False
tcReturnsConstraintKind :: Kind -> Bool
tcReturnsConstraintKind kind
| Just kind' <- tcView kind = tcReturnsConstraintKind kind'
tcReturnsConstraintKind (ForAllTy _ ty) = tcReturnsConstraintKind ty
tcReturnsConstraintKind (FunTy _ ty) = tcReturnsConstraintKind ty
tcReturnsConstraintKind (TyConApp tc _) = isConstraintKindCon tc
tcReturnsConstraintKind _ = False
isPredTy :: Type -> Bool
isPredTy ty = go ty []
where
go :: Type -> [KindOrType] -> Bool
go (AppTy ty1 ty2) args = go ty1 (ty2 : args)
go (TyVarTy tv) args = go_k (tyVarKind tv) args
go (TyConApp tc tys) args = ASSERT( null args )
go_tc tc tys
go (FunTy arg res) []
| isPredTy arg = isPredTy res
| otherwise = False
go (ForAllTy _ ty) [] = go ty []
go (CastTy _ co) args = go_k (pSnd (coercionKind co)) args
go _ _ = False
go_tc :: TyCon -> [KindOrType] -> Bool
go_tc tc args
| tc `hasKey` eqPrimTyConKey || tc `hasKey` eqReprPrimTyConKey
= args `lengthIs` 4
| otherwise = go_k (tyConKind tc) args
go_k :: Kind -> [KindOrType] -> Bool
go_k k [] = tcIsConstraintKind k
go_k k (arg:args) = case piResultTy_maybe k arg of
Just k' -> go_k k' args
Nothing -> WARN( True, text "isPredTy" <+> ppr ty )
False
isClassPred, isEqPred, isNomEqPred, isIPPred :: PredType -> Bool
isClassPred ty = case tyConAppTyCon_maybe ty of
Just tyCon | isClassTyCon tyCon -> True
_ -> False
isEqPred ty = case tyConAppTyCon_maybe ty of
Just tyCon -> tyCon `hasKey` eqPrimTyConKey
|| tyCon `hasKey` eqReprPrimTyConKey
_ -> False
isNomEqPred ty = case tyConAppTyCon_maybe ty of
Just tyCon -> tyCon `hasKey` eqPrimTyConKey
_ -> False
isIPPred ty = case tyConAppTyCon_maybe ty of
Just tc -> isIPTyCon tc
_ -> False
isIPTyCon :: TyCon -> Bool
isIPTyCon tc = tc `hasKey` ipClassKey
isIPClass :: Class -> Bool
isIPClass cls = cls `hasKey` ipClassKey
isCTupleClass :: Class -> Bool
isCTupleClass cls = isTupleTyCon (classTyCon cls)
isIPPred_maybe :: Type -> Maybe (FastString, Type)
isIPPred_maybe ty =
do (tc,[t1,t2]) <- splitTyConApp_maybe ty
guard (isIPTyCon tc)
x <- isStrLitTy t1
return (x,t2)
mkPrimEqPredRole :: Role -> Type -> Type -> PredType
mkPrimEqPredRole Nominal = mkPrimEqPred
mkPrimEqPredRole Representational = mkReprPrimEqPred
mkPrimEqPredRole Phantom = panic "mkPrimEqPredRole phantom"
mkPrimEqPred :: Type -> Type -> Type
mkPrimEqPred ty1 ty2
= TyConApp eqPrimTyCon [k1, k2, ty1, ty2]
where
k1 = typeKind ty1
k2 = typeKind ty2
mkHeteroPrimEqPred :: Kind -> Kind -> Type -> Type -> Type
mkHeteroPrimEqPred k1 k2 ty1 ty2 = TyConApp eqPrimTyCon [k1, k2, ty1, ty2]
mkHeteroReprPrimEqPred :: Kind -> Kind -> Type -> Type -> Type
mkHeteroReprPrimEqPred k1 k2 ty1 ty2
= TyConApp eqReprPrimTyCon [k1, k2, ty1, ty2]
splitCoercionType_maybe :: Type -> Maybe (Type, Type)
splitCoercionType_maybe ty
= do { (tc, [_, _, ty1, ty2]) <- splitTyConApp_maybe ty
; guard $ tc `hasKey` eqPrimTyConKey || tc `hasKey` eqReprPrimTyConKey
; return (ty1, ty2) }
mkReprPrimEqPred :: Type -> Type -> Type
mkReprPrimEqPred ty1 ty2
= TyConApp eqReprPrimTyCon [k1, k2, ty1, ty2]
where
k1 = typeKind ty1
k2 = typeKind ty2
equalityTyCon :: Role -> TyCon
equalityTyCon Nominal = eqPrimTyCon
equalityTyCon Representational = eqReprPrimTyCon
equalityTyCon Phantom = eqPhantPrimTyCon
mkClassPred :: Class -> [Type] -> PredType
mkClassPred clas tys = TyConApp (classTyCon clas) tys
isDictTy :: Type -> Bool
isDictTy = isClassPred
isDictLikeTy :: Type -> Bool
isDictLikeTy ty | Just ty' <- coreView ty = isDictLikeTy ty'
isDictLikeTy ty = case splitTyConApp_maybe ty of
Just (tc, tys) | isClassTyCon tc -> True
| isTupleTyCon tc -> all isDictLikeTy tys
_other -> False
data EqRel = NomEq | ReprEq
deriving (Eq, Ord)
instance Outputable EqRel where
ppr NomEq = text "nominal equality"
ppr ReprEq = text "representational equality"
eqRelRole :: EqRel -> Role
eqRelRole NomEq = Nominal
eqRelRole ReprEq = Representational
data PredTree
= ClassPred Class [Type]
| EqPred EqRel Type Type
| IrredPred PredType
| ForAllPred [TyVarBinder] [PredType] PredType
classifyPredType :: PredType -> PredTree
classifyPredType ev_ty = case splitTyConApp_maybe ev_ty of
Just (tc, [_, _, ty1, ty2])
| tc `hasKey` eqReprPrimTyConKey -> EqPred ReprEq ty1 ty2
| tc `hasKey` eqPrimTyConKey -> EqPred NomEq ty1 ty2
Just (tc, tys)
| Just clas <- tyConClass_maybe tc
-> ClassPred clas tys
_ | (tvs, rho) <- splitForAllTyVarBndrs ev_ty
, (theta, pred) <- splitFunTys rho
, not (null tvs && null theta)
-> ForAllPred tvs theta pred
| otherwise
-> IrredPred ev_ty
getClassPredTys :: HasDebugCallStack => PredType -> (Class, [Type])
getClassPredTys ty = case getClassPredTys_maybe ty of
Just (clas, tys) -> (clas, tys)
Nothing -> pprPanic "getClassPredTys" (ppr ty)
getClassPredTys_maybe :: PredType -> Maybe (Class, [Type])
getClassPredTys_maybe ty = case splitTyConApp_maybe ty of
Just (tc, tys) | Just clas <- tyConClass_maybe tc -> Just (clas, tys)
_ -> Nothing
getEqPredTys :: PredType -> (Type, Type)
getEqPredTys ty
= case splitTyConApp_maybe ty of
Just (tc, [_, _, ty1, ty2])
| tc `hasKey` eqPrimTyConKey
|| tc `hasKey` eqReprPrimTyConKey
-> (ty1, ty2)
_ -> pprPanic "getEqPredTys" (ppr ty)
getEqPredTys_maybe :: PredType -> Maybe (Role, Type, Type)
getEqPredTys_maybe ty
= case splitTyConApp_maybe ty of
Just (tc, [_, _, ty1, ty2])
| tc `hasKey` eqPrimTyConKey -> Just (Nominal, ty1, ty2)
| tc `hasKey` eqReprPrimTyConKey -> Just (Representational, ty1, ty2)
_ -> Nothing
getEqPredRole :: PredType -> Role
getEqPredRole ty = eqRelRole (predTypeEqRel ty)
predTypeEqRel :: PredType -> EqRel
predTypeEqRel ty
| Just (tc, _) <- splitTyConApp_maybe ty
, tc `hasKey` eqReprPrimTyConKey
= ReprEq
| otherwise
= NomEq
toposortTyVars :: [TyCoVar] -> [TyCoVar]
toposortTyVars tvs = reverse $
[ node_payload node | node <- topologicalSortG $
graphFromEdgedVerticesOrd nodes ]
where
var_ids :: VarEnv Int
var_ids = mkVarEnv (zip tvs [1..])
nodes :: [ Node Int TyVar ]
nodes = [ DigraphNode
tv
(lookupVarEnv_NF var_ids tv)
(mapMaybe (lookupVarEnv var_ids)
(tyCoVarsOfTypeList (tyVarKind tv)))
| tv <- tvs ]
dVarSetElemsWellScoped :: DVarSet -> [Var]
dVarSetElemsWellScoped = toposortTyVars . dVarSetElems
tyCoVarsOfTypeWellScoped :: Type -> [TyVar]
tyCoVarsOfTypeWellScoped = toposortTyVars . tyCoVarsOfTypeList
tyCoVarsOfTypesWellScoped :: [Type] -> [TyVar]
tyCoVarsOfTypesWellScoped = toposortTyVars . tyCoVarsOfTypesList
mkFamilyTyConApp :: TyCon -> [Type] -> Type
mkFamilyTyConApp tc tys
| Just (fam_tc, fam_tys) <- tyConFamInst_maybe tc
, let tvs = tyConTyVars tc
fam_subst = ASSERT2( tvs `equalLength` tys, ppr tc <+> ppr tys )
zipTvSubst tvs tys
= mkTyConApp fam_tc (substTys fam_subst fam_tys)
| otherwise
= mkTyConApp tc tys
coAxNthLHS :: CoAxiom br -> Int -> Type
coAxNthLHS ax ind =
mkTyConApp (coAxiomTyCon ax) (coAxBranchLHS (coAxiomNthBranch ax ind))
pprSourceTyCon :: TyCon -> SDoc
pprSourceTyCon tycon
| Just (fam_tc, tys) <- tyConFamInst_maybe tycon
= ppr $ fam_tc `TyConApp` tys
| otherwise
= ppr tycon
isFamFreeTy :: Type -> Bool
isFamFreeTy ty | Just ty' <- coreView ty = isFamFreeTy ty'
isFamFreeTy (TyVarTy _) = True
isFamFreeTy (LitTy {}) = True
isFamFreeTy (TyConApp tc tys) = all isFamFreeTy tys && isFamFreeTyCon tc
isFamFreeTy (AppTy a b) = isFamFreeTy a && isFamFreeTy b
isFamFreeTy (FunTy a b) = isFamFreeTy a && isFamFreeTy b
isFamFreeTy (ForAllTy _ ty) = isFamFreeTy ty
isFamFreeTy (CastTy ty _) = isFamFreeTy ty
isFamFreeTy (CoercionTy _) = False
isLiftedType_maybe :: HasDebugCallStack => Type -> Maybe Bool
isLiftedType_maybe ty = go (getRuntimeRep ty)
where
go rr | Just rr' <- coreView rr = go rr'
go (TyConApp lifted_rep [])
| lifted_rep `hasKey` liftedRepDataConKey = Just True
go (TyConApp {}) = Just False
go _ = Nothing
isUnliftedType :: HasDebugCallStack => Type -> Bool
isUnliftedType ty
= not (isLiftedType_maybe ty `orElse`
pprPanic "isUnliftedType" (ppr ty <+> dcolon <+> ppr (typeKind ty)))
isRuntimeRepKindedTy :: Type -> Bool
isRuntimeRepKindedTy = isRuntimeRepTy . typeKind
dropRuntimeRepArgs :: [Type] -> [Type]
dropRuntimeRepArgs = dropWhile isRuntimeRepKindedTy
getRuntimeRep_maybe :: HasDebugCallStack
=> Type -> Maybe Type
getRuntimeRep_maybe = getRuntimeRepFromKind_maybe . typeKind
getRuntimeRep :: HasDebugCallStack => Type -> Type
getRuntimeRep ty
= case getRuntimeRep_maybe ty of
Just r -> r
Nothing -> pprPanic "getRuntimeRep" (ppr ty <+> dcolon <+> ppr (typeKind ty))
getRuntimeRepFromKind :: HasDebugCallStack
=> Type -> Type
getRuntimeRepFromKind k =
case getRuntimeRepFromKind_maybe k of
Just r -> r
Nothing -> pprPanic "getRuntimeRepFromKind"
(ppr k <+> dcolon <+> ppr (typeKind k))
getRuntimeRepFromKind_maybe :: HasDebugCallStack
=> Type -> Maybe Type
getRuntimeRepFromKind_maybe = go
where
go k | Just k' <- coreView k = go k'
go k
| Just (_tc, [arg]) <- splitTyConApp_maybe k
= ASSERT2( _tc `hasKey` tYPETyConKey, ppr k )
Just arg
go _ = Nothing
isUnboxedTupleType :: Type -> Bool
isUnboxedTupleType ty
= tyConAppTyCon (getRuntimeRep ty) `hasKey` tupleRepDataConKey
isUnboxedSumType :: Type -> Bool
isUnboxedSumType ty
= tyConAppTyCon (getRuntimeRep ty) `hasKey` sumRepDataConKey
isAlgType :: Type -> Bool
isAlgType ty
= case splitTyConApp_maybe ty of
Just (tc, ty_args) -> ASSERT( ty_args `lengthIs` tyConArity tc )
isAlgTyCon tc
_other -> False
isDataFamilyAppType :: Type -> Bool
isDataFamilyAppType ty = case tyConAppTyCon_maybe ty of
Just tc -> isDataFamilyTyCon tc
_ -> False
isStrictType :: HasDebugCallStack => Type -> Bool
isStrictType = isUnliftedType
isPrimitiveType :: Type -> Bool
isPrimitiveType ty = case splitTyConApp_maybe ty of
Just (tc, ty_args) -> ASSERT( ty_args `lengthIs` tyConArity tc )
isPrimTyCon tc
_ -> False
isValidJoinPointType :: JoinArity -> Type -> Bool
isValidJoinPointType arity ty
= valid_under emptyVarSet arity ty
where
valid_under tvs arity ty
| arity == 0
= isEmptyVarSet (tvs `intersectVarSet` tyCoVarsOfType ty)
| Just (t, ty') <- splitForAllTy_maybe ty
= valid_under (tvs `extendVarSet` t) (arity-1) ty'
| Just (_, res_ty) <- splitFunTy_maybe ty
= valid_under tvs (arity-1) res_ty
| otherwise
= False
seqType :: Type -> ()
seqType (LitTy n) = n `seq` ()
seqType (TyVarTy tv) = tv `seq` ()
seqType (AppTy t1 t2) = seqType t1 `seq` seqType t2
seqType (FunTy t1 t2) = seqType t1 `seq` seqType t2
seqType (TyConApp tc tys) = tc `seq` seqTypes tys
seqType (ForAllTy (TvBndr tv _) ty) = seqType (tyVarKind tv) `seq` seqType ty
seqType (CastTy ty co) = seqType ty `seq` seqCo co
seqType (CoercionTy co) = seqCo co
seqTypes :: [Type] -> ()
seqTypes [] = ()
seqTypes (ty:tys) = seqType ty `seq` seqTypes tys
eqType :: Type -> Type -> Bool
eqType t1 t2 = isEqual $ nonDetCmpType t1 t2
eqTypeX :: RnEnv2 -> Type -> Type -> Bool
eqTypeX env t1 t2 = isEqual $ nonDetCmpTypeX env t1 t2
eqTypes :: [Type] -> [Type] -> Bool
eqTypes tys1 tys2 = isEqual $ nonDetCmpTypes tys1 tys2
eqVarBndrs :: RnEnv2 -> [Var] -> [Var] -> Maybe RnEnv2
eqVarBndrs env [] []
= Just env
eqVarBndrs env (tv1:tvs1) (tv2:tvs2)
| eqTypeX env (tyVarKind tv1) (tyVarKind tv2)
= eqVarBndrs (rnBndr2 env tv1 tv2) tvs1 tvs2
eqVarBndrs _ _ _= Nothing
nonDetCmpType :: Type -> Type -> Ordering
nonDetCmpType t1 t2
= nonDetCmpTypeX rn_env t1 t2
where
rn_env = mkRnEnv2 (mkInScopeSet (tyCoVarsOfTypes [t1, t2]))
nonDetCmpTypes :: [Type] -> [Type] -> Ordering
nonDetCmpTypes ts1 ts2 = nonDetCmpTypesX rn_env ts1 ts2
where
rn_env = mkRnEnv2 (mkInScopeSet (tyCoVarsOfTypes (ts1 ++ ts2)))
data TypeOrdering = TLT
| TEQ
| TEQX
| TGT
deriving (Eq, Ord, Enum, Bounded)
nonDetCmpTypeX :: RnEnv2 -> Type -> Type -> Ordering
nonDetCmpTypeX env orig_t1 orig_t2 =
case go env orig_t1 orig_t2 of
TEQX -> toOrdering $ go env k1 k2
ty_ordering -> toOrdering ty_ordering
where
k1 = typeKind orig_t1
k2 = typeKind orig_t2
toOrdering :: TypeOrdering -> Ordering
toOrdering TLT = LT
toOrdering TEQ = EQ
toOrdering TEQX = EQ
toOrdering TGT = GT
liftOrdering :: Ordering -> TypeOrdering
liftOrdering LT = TLT
liftOrdering EQ = TEQ
liftOrdering GT = TGT
thenCmpTy :: TypeOrdering -> TypeOrdering -> TypeOrdering
thenCmpTy TEQ rel = rel
thenCmpTy TEQX rel = hasCast rel
thenCmpTy rel _ = rel
hasCast :: TypeOrdering -> TypeOrdering
hasCast TEQ = TEQX
hasCast rel = rel
go :: RnEnv2 -> Type -> Type -> TypeOrdering
go env t1 t2
| Just t1' <- coreView t1 = go env t1' t2
| Just t2' <- coreView t2 = go env t1 t2'
go env (TyVarTy tv1) (TyVarTy tv2)
= liftOrdering $ rnOccL env tv1 `nonDetCmpVar` rnOccR env tv2
go env (ForAllTy (TvBndr tv1 _) t1) (ForAllTy (TvBndr tv2 _) t2)
= go env (tyVarKind tv1) (tyVarKind tv2)
`thenCmpTy` go (rnBndr2 env tv1 tv2) t1 t2
go env (AppTy s1 t1) ty2
| Just (s2, t2) <- repSplitAppTy_maybe ty2
= go env s1 s2 `thenCmpTy` go env t1 t2
go env ty1 (AppTy s2 t2)
| Just (s1, t1) <- repSplitAppTy_maybe ty1
= go env s1 s2 `thenCmpTy` go env t1 t2
go env (FunTy s1 t1) (FunTy s2 t2)
= go env s1 s2 `thenCmpTy` go env t1 t2
go env (TyConApp tc1 tys1) (TyConApp tc2 tys2)
= liftOrdering (tc1 `nonDetCmpTc` tc2) `thenCmpTy` gos env tys1 tys2
go _ (LitTy l1) (LitTy l2) = liftOrdering (compare l1 l2)
go env (CastTy t1 _) t2 = hasCast $ go env t1 t2
go env t1 (CastTy t2 _) = hasCast $ go env t1 t2
go _ (CoercionTy {}) (CoercionTy {}) = TEQ
go _ ty1 ty2
= liftOrdering $ (get_rank ty1) `compare` (get_rank ty2)
where get_rank :: Type -> Int
get_rank (CastTy {})
= pprPanic "nonDetCmpTypeX.get_rank" (ppr [ty1,ty2])
get_rank (TyVarTy {}) = 0
get_rank (CoercionTy {}) = 1
get_rank (AppTy {}) = 3
get_rank (LitTy {}) = 4
get_rank (TyConApp {}) = 5
get_rank (FunTy {}) = 6
get_rank (ForAllTy {}) = 7
gos :: RnEnv2 -> [Type] -> [Type] -> TypeOrdering
gos _ [] [] = TEQ
gos _ [] _ = TLT
gos _ _ [] = TGT
gos env (ty1:tys1) (ty2:tys2) = go env ty1 ty2 `thenCmpTy` gos env tys1 tys2
nonDetCmpTypesX :: RnEnv2 -> [Type] -> [Type] -> Ordering
nonDetCmpTypesX _ [] [] = EQ
nonDetCmpTypesX env (t1:tys1) (t2:tys2) = nonDetCmpTypeX env t1 t2
`thenCmp` nonDetCmpTypesX env tys1 tys2
nonDetCmpTypesX _ [] _ = LT
nonDetCmpTypesX _ _ [] = GT
nonDetCmpTc :: TyCon -> TyCon -> Ordering
nonDetCmpTc tc1 tc2
= ASSERT( not (isConstraintKindCon tc1) && not (isConstraintKindCon tc2) )
u1 `nonDetCmpUnique` u2
where
u1 = tyConUnique tc1
u2 = tyConUnique tc2
typeKind :: HasDebugCallStack => Type -> Kind
typeKind (TyConApp tc tys) = piResultTys (tyConKind tc) tys
typeKind (AppTy fun arg) = typeKind_apps fun [arg]
typeKind (LitTy l) = typeLiteralKind l
typeKind (FunTy {}) = liftedTypeKind
typeKind (TyVarTy tyvar) = tyVarKind tyvar
typeKind (CastTy _ty co) = pSnd $ coercionKind co
typeKind (CoercionTy co) = coercionType co
typeKind ty@(ForAllTy {}) = case occCheckExpand tvs k of
Just k' -> k'
Nothing -> pprPanic "typeKind"
(ppr ty $$ ppr k $$ ppr tvs $$ ppr body)
where
(tvs, body) = splitForAllTys ty
k = typeKind body
typeKind_apps :: HasDebugCallStack => Type -> [Type] -> Kind
typeKind_apps (AppTy fun arg) args = typeKind_apps fun (arg:args)
typeKind_apps fun args = piResultTys (typeKind fun) args
typeLiteralKind :: TyLit -> Kind
typeLiteralKind l =
case l of
NumTyLit _ -> typeNatKind
StrTyLit _ -> typeSymbolKind
isTypeLevPoly :: Type -> Bool
isTypeLevPoly = go
where
go ty@(TyVarTy {}) = check_kind ty
go ty@(AppTy {}) = check_kind ty
go ty@(TyConApp tc _) | not (isTcLevPoly tc) = False
| otherwise = check_kind ty
go (ForAllTy _ ty) = go ty
go (FunTy {}) = False
go (LitTy {}) = False
go ty@(CastTy {}) = check_kind ty
go ty@(CoercionTy {}) = pprPanic "isTypeLevPoly co" (ppr ty)
check_kind = isKindLevPoly . typeKind
resultIsLevPoly :: Type -> Bool
resultIsLevPoly = isTypeLevPoly . snd . splitPiTys
occCheckExpand :: [Var] -> Type -> Maybe Type
occCheckExpand vs_to_avoid ty
= go (mkVarSet vs_to_avoid, emptyVarEnv) ty
where
go :: (VarSet, VarEnv TyVar) -> Type -> Maybe Type
go cxt@(as, env) (TyVarTy tv')
| tv' `elemVarSet` as = Nothing
| Just tv'' <- lookupVarEnv env tv' = return (mkTyVarTy tv'')
| otherwise = do { tv'' <- go_var cxt tv'
; return (mkTyVarTy tv'') }
go _ ty@(LitTy {}) = return ty
go cxt (AppTy ty1 ty2) = do { ty1' <- go cxt ty1
; ty2' <- go cxt ty2
; return (mkAppTy ty1' ty2') }
go cxt (FunTy ty1 ty2) = do { ty1' <- go cxt ty1
; ty2' <- go cxt ty2
; return (mkFunTy ty1' ty2') }
go cxt@(as, env) (ForAllTy (TvBndr tv vis) body_ty)
= do { ki' <- go cxt (tyVarKind tv)
; let tv' = setTyVarKind tv ki'
env' = extendVarEnv env tv tv'
as' = as `delVarSet` tv
; body' <- go (as', env') body_ty
; return (ForAllTy (TvBndr tv' vis) body') }
go cxt ty@(TyConApp tc tys)
= case mapM (go cxt) tys of
Just tys' -> return (mkTyConApp tc tys')
Nothing | Just ty' <- tcView ty -> go cxt ty'
| otherwise -> Nothing
go cxt (CastTy ty co) = do { ty' <- go cxt ty
; co' <- go_co cxt co
; return (mkCastTy ty' co') }
go cxt (CoercionTy co) = do { co' <- go_co cxt co
; return (mkCoercionTy co') }
go_var cxt v = do { k' <- go cxt (varType v)
; return (setVarType v k') }
go_co cxt (Refl r ty) = do { ty' <- go cxt ty
; return (mkReflCo r ty') }
go_co cxt (TyConAppCo r tc args) = do { args' <- mapM (go_co cxt) args
; return (mkTyConAppCo r tc args') }
go_co cxt (AppCo co arg) = do { co' <- go_co cxt co
; arg' <- go_co cxt arg
; return (mkAppCo co' arg') }
go_co cxt@(as, env) (ForAllCo tv kind_co body_co)
= do { kind_co' <- go_co cxt kind_co
; let tv' = setTyVarKind tv $
pFst (coercionKind kind_co')
env' = extendVarEnv env tv tv'
as' = as `delVarSet` tv
; body' <- go_co (as', env') body_co
; return (ForAllCo tv' kind_co' body') }
go_co cxt (FunCo r co1 co2) = do { co1' <- go_co cxt co1
; co2' <- go_co cxt co2
; return (mkFunCo r co1' co2') }
go_co cxt (CoVarCo c) = do { c' <- go_var cxt c
; return (mkCoVarCo c') }
go_co cxt (HoleCo h) = do { c' <- go_var cxt (ch_co_var h)
; return (HoleCo (h { ch_co_var = c' })) }
go_co cxt (AxiomInstCo ax ind args) = do { args' <- mapM (go_co cxt) args
; return (mkAxiomInstCo ax ind args') }
go_co cxt (UnivCo p r ty1 ty2) = do { p' <- go_prov cxt p
; ty1' <- go cxt ty1
; ty2' <- go cxt ty2
; return (mkUnivCo p' r ty1' ty2') }
go_co cxt (SymCo co) = do { co' <- go_co cxt co
; return (mkSymCo co') }
go_co cxt (TransCo co1 co2) = do { co1' <- go_co cxt co1
; co2' <- go_co cxt co2
; return (mkTransCo co1' co2') }
go_co cxt (NthCo r n co) = do { co' <- go_co cxt co
; return (mkNthCo r n co') }
go_co cxt (LRCo lr co) = do { co' <- go_co cxt co
; return (mkLRCo lr co') }
go_co cxt (InstCo co arg) = do { co' <- go_co cxt co
; arg' <- go_co cxt arg
; return (mkInstCo co' arg') }
go_co cxt (CoherenceCo co1 co2) = do { co1' <- go_co cxt co1
; co2' <- go_co cxt co2
; return (mkCoherenceCo co1' co2') }
go_co cxt (KindCo co) = do { co' <- go_co cxt co
; return (mkKindCo co') }
go_co cxt (SubCo co) = do { co' <- go_co cxt co
; return (mkSubCo co') }
go_co cxt (AxiomRuleCo ax cs) = do { cs' <- mapM (go_co cxt) cs
; return (mkAxiomRuleCo ax cs') }
go_prov _ UnsafeCoerceProv = return UnsafeCoerceProv
go_prov cxt (PhantomProv co) = PhantomProv <$> go_co cxt co
go_prov cxt (ProofIrrelProv co) = ProofIrrelProv <$> go_co cxt co
go_prov _ p@(PluginProv _) = return p
tyConsOfType :: Type -> UniqSet TyCon
tyConsOfType ty
= go ty
where
go :: Type -> UniqSet TyCon
go ty | Just ty' <- coreView ty = go ty'
go (TyVarTy {}) = emptyUniqSet
go (LitTy {}) = emptyUniqSet
go (TyConApp tc tys) = go_tc tc `unionUniqSets` go_s tys
go (AppTy a b) = go a `unionUniqSets` go b
go (FunTy a b) = go a `unionUniqSets` go b `unionUniqSets` go_tc funTyCon
go (ForAllTy (TvBndr tv _) ty) = go ty `unionUniqSets` go (tyVarKind tv)
go (CastTy ty co) = go ty `unionUniqSets` go_co co
go (CoercionTy co) = go_co co
go_co (Refl _ ty) = go ty
go_co (TyConAppCo _ tc args) = go_tc tc `unionUniqSets` go_cos args
go_co (AppCo co arg) = go_co co `unionUniqSets` go_co arg
go_co (ForAllCo _ kind_co co) = go_co kind_co `unionUniqSets` go_co co
go_co (FunCo _ co1 co2) = go_co co1 `unionUniqSets` go_co co2
go_co (AxiomInstCo ax _ args) = go_ax ax `unionUniqSets` go_cos args
go_co (UnivCo p _ t1 t2) = go_prov p `unionUniqSets` go t1 `unionUniqSets` go t2
go_co (CoVarCo {}) = emptyUniqSet
go_co (HoleCo {}) = emptyUniqSet
go_co (SymCo co) = go_co co
go_co (TransCo co1 co2) = go_co co1 `unionUniqSets` go_co co2
go_co (NthCo _ _ co) = go_co co
go_co (LRCo _ co) = go_co co
go_co (InstCo co arg) = go_co co `unionUniqSets` go_co arg
go_co (CoherenceCo co1 co2) = go_co co1 `unionUniqSets` go_co co2
go_co (KindCo co) = go_co co
go_co (SubCo co) = go_co co
go_co (AxiomRuleCo _ cs) = go_cos cs
go_prov UnsafeCoerceProv = emptyUniqSet
go_prov (PhantomProv co) = go_co co
go_prov (ProofIrrelProv co) = go_co co
go_prov (PluginProv _) = emptyUniqSet
go_s tys = foldr (unionUniqSets . go) emptyUniqSet tys
go_cos cos = foldr (unionUniqSets . go_co) emptyUniqSet cos
go_tc tc = unitUniqSet tc
go_ax ax = go_tc $ coAxiomTyCon ax
synTyConResKind :: TyCon -> Kind
synTyConResKind tycon = piResultTys (tyConKind tycon) (mkTyVarTys (tyConTyVars tycon))
splitVisVarsOfType :: Type -> Pair TyCoVarSet
splitVisVarsOfType orig_ty = Pair invis_vars vis_vars
where
Pair invis_vars1 vis_vars = go orig_ty
invis_vars = invis_vars1 `minusVarSet` vis_vars
go (TyVarTy tv) = Pair (tyCoVarsOfType $ tyVarKind tv) (unitVarSet tv)
go (AppTy t1 t2) = go t1 `mappend` go t2
go (TyConApp tc tys) = go_tc tc tys
go (FunTy t1 t2) = go t1 `mappend` go t2
go (ForAllTy (TvBndr tv _) ty)
= ((`delVarSet` tv) <$> go ty) `mappend`
(invisible (tyCoVarsOfType $ tyVarKind tv))
go (LitTy {}) = mempty
go (CastTy ty co) = go ty `mappend` invisible (tyCoVarsOfCo co)
go (CoercionTy co) = invisible $ tyCoVarsOfCo co
invisible vs = Pair vs emptyVarSet
go_tc tc tys = let (invis, vis) = partitionInvisibles tc id tys in
invisible (tyCoVarsOfTypes invis) `mappend` foldMap go vis
splitVisVarsOfTypes :: [Type] -> Pair TyCoVarSet
splitVisVarsOfTypes = foldMap splitVisVarsOfType
modifyJoinResTy :: Int
-> (Type -> Type)
-> Type
-> Type
modifyJoinResTy orig_ar f orig_ty
= go orig_ar orig_ty
where
go 0 ty = f ty
go n ty | Just (arg_bndr, res_ty) <- splitPiTy_maybe ty
= mkPiTy arg_bndr (go (n-1) res_ty)
| otherwise
= pprPanic "modifyJoinResTy" (ppr orig_ar <+> ppr orig_ty)
setJoinResTy :: Int
-> Type
-> Type
-> Type
setJoinResTy ar new_res_ty ty
= modifyJoinResTy ar (const new_res_ty) ty
pprWithTYPE :: Type -> SDoc
pprWithTYPE ty = updSDocDynFlags (flip gopt_set Opt_PrintExplicitRuntimeReps) $
ppr ty