{-# LANGUAGE CPP, GADTs, ScopedTypeVariables, BangPatterns, TupleSections,
DeriveFunctor #-}
{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}
module GHC.Core.FamInstEnv (
FamInst(..), FamFlavor(..), famInstAxiom, famInstTyCon, famInstRHS,
famInstsRepTyCons, famInstRepTyCon_maybe, dataFamInstRepTyCon,
pprFamInst, pprFamInsts,
mkImportedFamInst,
FamInstEnvs, FamInstEnv, emptyFamInstEnv, emptyFamInstEnvs,
extendFamInstEnv, extendFamInstEnvList,
famInstEnvElts, famInstEnvSize, familyInstances,
mkCoAxBranch, mkBranchedCoAxiom, mkUnbranchedCoAxiom, mkSingleCoAxiom,
mkNewTypeCoAxiom,
FamInstMatch(..),
lookupFamInstEnv, lookupFamInstEnvConflicts, lookupFamInstEnvByTyCon,
isDominatedBy, apartnessCheck,
InjectivityCheckResult(..),
lookupFamInstEnvInjectivityConflicts, injectiveBranches,
topNormaliseType, topNormaliseType_maybe,
normaliseType, normaliseTcApp,
topReduceTyFamApp_maybe, reduceTyFamApp_maybe,
flattenTys
) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Core.Unify
import GHC.Core.Type as Type
import GHC.Core.TyCo.Rep
import GHC.Core.TyCon
import GHC.Core.Coercion
import GHC.Core.Coercion.Axiom
import GHC.Types.Var.Set
import GHC.Types.Var.Env
import GHC.Types.Name
import GHC.Types.Unique.DFM
import GHC.Utils.Outputable
import GHC.Data.Maybe
import GHC.Core.Map
import GHC.Types.Unique
import GHC.Utils.Misc
import GHC.Types.Var
import GHC.Types.SrcLoc
import GHC.Data.FastString
import Control.Monad
import Data.List( mapAccumL )
import Data.Array( Array, assocs )
data FamInst
= FamInst { FamInst -> CoAxiom Unbranched
fi_axiom :: CoAxiom Unbranched
, FamInst -> FamFlavor
fi_flavor :: FamFlavor
, FamInst -> Name
fi_fam :: Name
, FamInst -> [Maybe Name]
fi_tcs :: [Maybe Name]
, FamInst -> [TyVar]
fi_tvs :: [TyVar]
, FamInst -> [TyVar]
fi_cvs :: [CoVar]
, FamInst -> [Type]
fi_tys :: [Type]
, FamInst -> Type
fi_rhs :: Type
}
data FamFlavor
= SynFamilyInst
| DataFamilyInst TyCon
famInstAxiom :: FamInst -> CoAxiom Unbranched
famInstAxiom :: FamInst -> CoAxiom Unbranched
famInstAxiom = FamInst -> CoAxiom Unbranched
fi_axiom
famInstSplitLHS :: FamInst -> (TyCon, [Type])
famInstSplitLHS :: FamInst -> (TyCon, [Type])
famInstSplitLHS (FamInst { fi_axiom :: FamInst -> CoAxiom Unbranched
fi_axiom = CoAxiom Unbranched
axiom, fi_tys :: FamInst -> [Type]
fi_tys = [Type]
lhs })
= (CoAxiom Unbranched -> TyCon
forall (br :: BranchFlag). CoAxiom br -> TyCon
coAxiomTyCon CoAxiom Unbranched
axiom, [Type]
lhs)
famInstRHS :: FamInst -> Type
famInstRHS :: FamInst -> Type
famInstRHS = FamInst -> Type
fi_rhs
famInstTyCon :: FamInst -> TyCon
famInstTyCon :: FamInst -> TyCon
famInstTyCon = CoAxiom Unbranched -> TyCon
forall (br :: BranchFlag). CoAxiom br -> TyCon
coAxiomTyCon (CoAxiom Unbranched -> TyCon)
-> (FamInst -> CoAxiom Unbranched) -> FamInst -> TyCon
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FamInst -> CoAxiom Unbranched
famInstAxiom
famInstsRepTyCons :: [FamInst] -> [TyCon]
famInstsRepTyCons :: [FamInst] -> [TyCon]
famInstsRepTyCons [FamInst]
fis = [TyCon
tc | FamInst { fi_flavor :: FamInst -> FamFlavor
fi_flavor = DataFamilyInst TyCon
tc } <- [FamInst]
fis]
famInstRepTyCon_maybe :: FamInst -> Maybe TyCon
famInstRepTyCon_maybe :: FamInst -> Maybe TyCon
famInstRepTyCon_maybe FamInst
fi
= case FamInst -> FamFlavor
fi_flavor FamInst
fi of
DataFamilyInst TyCon
tycon -> TyCon -> Maybe TyCon
forall a. a -> Maybe a
Just TyCon
tycon
FamFlavor
SynFamilyInst -> Maybe TyCon
forall a. Maybe a
Nothing
dataFamInstRepTyCon :: FamInst -> TyCon
dataFamInstRepTyCon :: FamInst -> TyCon
dataFamInstRepTyCon FamInst
fi
= case FamInst -> FamFlavor
fi_flavor FamInst
fi of
DataFamilyInst TyCon
tycon -> TyCon
tycon
FamFlavor
SynFamilyInst -> String -> SDoc -> TyCon
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"dataFamInstRepTyCon" (FamInst -> SDoc
forall a. Outputable a => a -> SDoc
ppr FamInst
fi)
instance NamedThing FamInst where
getName :: FamInst -> Name
getName = CoAxiom Unbranched -> Name
forall (br :: BranchFlag). CoAxiom br -> Name
coAxiomName (CoAxiom Unbranched -> Name)
-> (FamInst -> CoAxiom Unbranched) -> FamInst -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FamInst -> CoAxiom Unbranched
fi_axiom
instance Outputable FamInst where
ppr :: FamInst -> SDoc
ppr = FamInst -> SDoc
pprFamInst
pprFamInst :: FamInst -> SDoc
pprFamInst :: FamInst -> SDoc
pprFamInst (FamInst { fi_flavor :: FamInst -> FamFlavor
fi_flavor = FamFlavor
flavor, fi_axiom :: FamInst -> CoAxiom Unbranched
fi_axiom = CoAxiom Unbranched
ax
, fi_tvs :: FamInst -> [TyVar]
fi_tvs = [TyVar]
tvs, fi_tys :: FamInst -> [Type]
fi_tys = [Type]
tys, fi_rhs :: FamInst -> Type
fi_rhs = Type
rhs })
= SDoc -> Arity -> SDoc -> SDoc
hang (SDoc
ppr_tc_sort SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"instance"
SDoc -> SDoc -> SDoc
<+> TyCon -> CoAxBranch -> SDoc
pprCoAxBranchUser (CoAxiom Unbranched -> TyCon
forall (br :: BranchFlag). CoAxiom br -> TyCon
coAxiomTyCon CoAxiom Unbranched
ax) (CoAxiom Unbranched -> CoAxBranch
coAxiomSingleBranch CoAxiom Unbranched
ax))
Arity
2 (SDoc -> SDoc
whenPprDebug SDoc
debug_stuff)
where
ppr_tc_sort :: SDoc
ppr_tc_sort = case FamFlavor
flavor of
FamFlavor
SynFamilyInst -> String -> SDoc
text String
"type"
DataFamilyInst TyCon
tycon
| TyCon -> Bool
isDataTyCon TyCon
tycon -> String -> SDoc
text String
"data"
| TyCon -> Bool
isNewTyCon TyCon
tycon -> String -> SDoc
text String
"newtype"
| TyCon -> Bool
isAbstractTyCon TyCon
tycon -> String -> SDoc
text String
"data"
| Bool
otherwise -> String -> SDoc
text String
"WEIRD" SDoc -> SDoc -> SDoc
<+> TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
tycon
debug_stuff :: SDoc
debug_stuff = [SDoc] -> SDoc
vcat [ String -> SDoc
text String
"Coercion axiom:" SDoc -> SDoc -> SDoc
<+> CoAxiom Unbranched -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoAxiom Unbranched
ax
, String -> SDoc
text String
"Tvs:" SDoc -> SDoc -> SDoc
<+> [TyVar] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [TyVar]
tvs
, String -> SDoc
text String
"LHS:" SDoc -> SDoc -> SDoc
<+> [Type] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Type]
tys
, String -> SDoc
text String
"RHS:" SDoc -> SDoc -> SDoc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
rhs ]
pprFamInsts :: [FamInst] -> SDoc
pprFamInsts :: [FamInst] -> SDoc
pprFamInsts [FamInst]
finsts = [SDoc] -> SDoc
vcat ((FamInst -> SDoc) -> [FamInst] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map FamInst -> SDoc
pprFamInst [FamInst]
finsts)
mkImportedFamInst :: Name
-> [Maybe Name]
-> CoAxiom Unbranched
-> FamInst
mkImportedFamInst :: Name -> [Maybe Name] -> CoAxiom Unbranched -> FamInst
mkImportedFamInst Name
fam [Maybe Name]
mb_tcs CoAxiom Unbranched
axiom
= FamInst :: CoAxiom Unbranched
-> FamFlavor
-> Name
-> [Maybe Name]
-> [TyVar]
-> [TyVar]
-> [Type]
-> Type
-> FamInst
FamInst {
fi_fam :: Name
fi_fam = Name
fam,
fi_tcs :: [Maybe Name]
fi_tcs = [Maybe Name]
mb_tcs,
fi_tvs :: [TyVar]
fi_tvs = [TyVar]
tvs,
fi_cvs :: [TyVar]
fi_cvs = [TyVar]
cvs,
fi_tys :: [Type]
fi_tys = [Type]
tys,
fi_rhs :: Type
fi_rhs = Type
rhs,
fi_axiom :: CoAxiom Unbranched
fi_axiom = CoAxiom Unbranched
axiom,
fi_flavor :: FamFlavor
fi_flavor = FamFlavor
flavor }
where
~(CoAxBranch { cab_lhs :: CoAxBranch -> [Type]
cab_lhs = [Type]
tys
, cab_tvs :: CoAxBranch -> [TyVar]
cab_tvs = [TyVar]
tvs
, cab_cvs :: CoAxBranch -> [TyVar]
cab_cvs = [TyVar]
cvs
, cab_rhs :: CoAxBranch -> Type
cab_rhs = Type
rhs }) = CoAxiom Unbranched -> CoAxBranch
coAxiomSingleBranch CoAxiom Unbranched
axiom
flavor :: FamFlavor
flavor = case HasDebugCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
splitTyConApp_maybe Type
rhs of
Just (TyCon
tc, [Type]
_)
| Just CoAxiom Unbranched
ax' <- TyCon -> Maybe (CoAxiom Unbranched)
tyConFamilyCoercion_maybe TyCon
tc
, CoAxiom Unbranched
ax' CoAxiom Unbranched -> CoAxiom Unbranched -> Bool
forall a. Eq a => a -> a -> Bool
== CoAxiom Unbranched
axiom
-> TyCon -> FamFlavor
DataFamilyInst TyCon
tc
Maybe (TyCon, [Type])
_ -> FamFlavor
SynFamilyInst
type FamInstEnv = UniqDFM TyCon FamilyInstEnv
type FamInstEnvs = (FamInstEnv, FamInstEnv)
newtype FamilyInstEnv
= FamIE [FamInst]
instance Outputable FamilyInstEnv where
ppr :: FamilyInstEnv -> SDoc
ppr (FamIE [FamInst]
fs) = String -> SDoc
text String
"FamIE" SDoc -> SDoc -> SDoc
<+> [SDoc] -> SDoc
vcat ((FamInst -> SDoc) -> [FamInst] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map FamInst -> SDoc
forall a. Outputable a => a -> SDoc
ppr [FamInst]
fs)
toNameInstEnv :: FamInstEnv -> UniqDFM Name FamilyInstEnv
toNameInstEnv :: FamInstEnv -> UniqDFM Name FamilyInstEnv
toNameInstEnv = FamInstEnv -> UniqDFM Name FamilyInstEnv
forall key1 elt key2. UniqDFM key1 elt -> UniqDFM key2 elt
unsafeCastUDFMKey
fromNameInstEnv :: UniqDFM Name FamilyInstEnv -> FamInstEnv
fromNameInstEnv :: UniqDFM Name FamilyInstEnv -> FamInstEnv
fromNameInstEnv = UniqDFM Name FamilyInstEnv -> FamInstEnv
forall key1 elt key2. UniqDFM key1 elt -> UniqDFM key2 elt
unsafeCastUDFMKey
emptyFamInstEnvs :: (FamInstEnv, FamInstEnv)
emptyFamInstEnvs :: (FamInstEnv, FamInstEnv)
emptyFamInstEnvs = (FamInstEnv
emptyFamInstEnv, FamInstEnv
emptyFamInstEnv)
emptyFamInstEnv :: FamInstEnv
emptyFamInstEnv :: FamInstEnv
emptyFamInstEnv = FamInstEnv
forall key elt. UniqDFM key elt
emptyUDFM
famInstEnvElts :: FamInstEnv -> [FamInst]
famInstEnvElts :: FamInstEnv -> [FamInst]
famInstEnvElts FamInstEnv
fi = [FamInst
elt | FamIE [FamInst]
elts <- FamInstEnv -> [FamilyInstEnv]
forall key elt. UniqDFM key elt -> [elt]
eltsUDFM FamInstEnv
fi, FamInst
elt <- [FamInst]
elts]
famInstEnvSize :: FamInstEnv -> Int
famInstEnvSize :: FamInstEnv -> Arity
famInstEnvSize = (FamilyInstEnv -> Arity -> Arity) -> Arity -> FamInstEnv -> Arity
forall elt a key. (elt -> a -> a) -> a -> UniqDFM key elt -> a
nonDetStrictFoldUDFM (\(FamIE [FamInst]
elt) Arity
sum -> Arity
sum Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ [FamInst] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [FamInst]
elt) Arity
0
familyInstances :: (FamInstEnv, FamInstEnv) -> TyCon -> [FamInst]
familyInstances :: (FamInstEnv, FamInstEnv) -> TyCon -> [FamInst]
familyInstances (FamInstEnv
pkg_fie, FamInstEnv
home_fie) TyCon
fam
= FamInstEnv -> [FamInst]
get FamInstEnv
home_fie [FamInst] -> [FamInst] -> [FamInst]
forall a. [a] -> [a] -> [a]
++ FamInstEnv -> [FamInst]
get FamInstEnv
pkg_fie
where
get :: FamInstEnv -> [FamInst]
get FamInstEnv
env = case FamInstEnv -> TyCon -> Maybe FamilyInstEnv
forall key elt.
Uniquable key =>
UniqDFM key elt -> key -> Maybe elt
lookupUDFM FamInstEnv
env TyCon
fam of
Just (FamIE [FamInst]
insts) -> [FamInst]
insts
Maybe FamilyInstEnv
Nothing -> []
extendFamInstEnvList :: FamInstEnv -> [FamInst] -> FamInstEnv
extendFamInstEnvList :: FamInstEnv -> [FamInst] -> FamInstEnv
extendFamInstEnvList FamInstEnv
inst_env [FamInst]
fis = (FamInstEnv -> FamInst -> FamInstEnv)
-> FamInstEnv -> [FamInst] -> FamInstEnv
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' FamInstEnv -> FamInst -> FamInstEnv
extendFamInstEnv FamInstEnv
inst_env [FamInst]
fis
extendFamInstEnv :: FamInstEnv -> FamInst -> FamInstEnv
extendFamInstEnv :: FamInstEnv -> FamInst -> FamInstEnv
extendFamInstEnv FamInstEnv
inst_env
ins_item :: FamInst
ins_item@(FamInst {fi_fam :: FamInst -> Name
fi_fam = Name
cls_nm})
= UniqDFM Name FamilyInstEnv -> FamInstEnv
fromNameInstEnv (UniqDFM Name FamilyInstEnv -> FamInstEnv)
-> UniqDFM Name FamilyInstEnv -> FamInstEnv
forall a b. (a -> b) -> a -> b
$ (FamilyInstEnv -> FamilyInstEnv -> FamilyInstEnv)
-> UniqDFM Name FamilyInstEnv
-> Name
-> FamilyInstEnv
-> UniqDFM Name FamilyInstEnv
forall key elt.
Uniquable key =>
(elt -> elt -> elt)
-> UniqDFM key elt -> key -> elt -> UniqDFM key elt
addToUDFM_C FamilyInstEnv -> FamilyInstEnv -> FamilyInstEnv
add (FamInstEnv -> UniqDFM Name FamilyInstEnv
toNameInstEnv FamInstEnv
inst_env) Name
cls_nm ([FamInst] -> FamilyInstEnv
FamIE [FamInst
ins_item])
where
add :: FamilyInstEnv -> FamilyInstEnv -> FamilyInstEnv
add (FamIE [FamInst]
items) FamilyInstEnv
_ = [FamInst] -> FamilyInstEnv
FamIE (FamInst
ins_itemFamInst -> [FamInst] -> [FamInst]
forall a. a -> [a] -> [a]
:[FamInst]
items)
compatibleBranches :: CoAxBranch -> CoAxBranch -> Bool
compatibleBranches :: CoAxBranch -> CoAxBranch -> Bool
compatibleBranches (CoAxBranch { cab_lhs :: CoAxBranch -> [Type]
cab_lhs = [Type]
lhs1, cab_rhs :: CoAxBranch -> Type
cab_rhs = Type
rhs1 })
(CoAxBranch { cab_lhs :: CoAxBranch -> [Type]
cab_lhs = [Type]
lhs2, cab_rhs :: CoAxBranch -> Type
cab_rhs = Type
rhs2 })
= let ([Type]
commonlhs1, [Type]
commonlhs2) = [Type] -> [Type] -> ([Type], [Type])
forall a b. [a] -> [b] -> ([a], [b])
zipAndUnzip [Type]
lhs1 [Type]
lhs2
in case (TyVar -> BindFlag) -> [Type] -> [Type] -> UnifyResult
tcUnifyTysFG (BindFlag -> TyVar -> BindFlag
forall a b. a -> b -> a
const BindFlag
BindMe) [Type]
commonlhs1 [Type]
commonlhs2 of
UnifyResult
SurelyApart -> Bool
True
Unifiable TCvSubst
subst
| TCvSubst -> Type -> Type
Type.substTyAddInScope TCvSubst
subst Type
rhs1 Type -> Type -> Bool
`eqType`
TCvSubst -> Type -> Type
Type.substTyAddInScope TCvSubst
subst Type
rhs2
-> Bool
True
UnifyResult
_ -> Bool
False
data InjectivityCheckResult
= InjectivityAccepted
| InjectivityUnified CoAxBranch CoAxBranch
injectiveBranches :: [Bool] -> CoAxBranch -> CoAxBranch
-> InjectivityCheckResult
injectiveBranches :: [Bool] -> CoAxBranch -> CoAxBranch -> InjectivityCheckResult
injectiveBranches [Bool]
injectivity
ax1 :: CoAxBranch
ax1@(CoAxBranch { cab_lhs :: CoAxBranch -> [Type]
cab_lhs = [Type]
lhs1, cab_rhs :: CoAxBranch -> Type
cab_rhs = Type
rhs1 })
ax2 :: CoAxBranch
ax2@(CoAxBranch { cab_lhs :: CoAxBranch -> [Type]
cab_lhs = [Type]
lhs2, cab_rhs :: CoAxBranch -> Type
cab_rhs = Type
rhs2 })
= let getInjArgs :: [Type] -> [Type]
getInjArgs = [Bool] -> [Type] -> [Type]
forall a. [Bool] -> [a] -> [a]
filterByList [Bool]
injectivity
in case Bool -> Type -> Type -> Maybe TCvSubst
tcUnifyTyWithTFs Bool
True Type
rhs1 Type
rhs2 of
Maybe TCvSubst
Nothing -> InjectivityCheckResult
InjectivityAccepted
Just TCvSubst
subst ->
let lhs1Subst :: [Type]
lhs1Subst = HasCallStack => TCvSubst -> [Type] -> [Type]
TCvSubst -> [Type] -> [Type]
Type.substTys TCvSubst
subst ([Type] -> [Type]
getInjArgs [Type]
lhs1)
lhs2Subst :: [Type]
lhs2Subst = HasCallStack => TCvSubst -> [Type] -> [Type]
TCvSubst -> [Type] -> [Type]
Type.substTys TCvSubst
subst ([Type] -> [Type]
getInjArgs [Type]
lhs2)
in if [Type] -> [Type] -> Bool
eqTypes [Type]
lhs1Subst [Type]
lhs2Subst
then InjectivityCheckResult
InjectivityAccepted
else CoAxBranch -> CoAxBranch -> InjectivityCheckResult
InjectivityUnified ( CoAxBranch
ax1 { cab_lhs :: [Type]
cab_lhs = HasCallStack => TCvSubst -> [Type] -> [Type]
TCvSubst -> [Type] -> [Type]
Type.substTys TCvSubst
subst [Type]
lhs1
, cab_rhs :: Type
cab_rhs = HasCallStack => TCvSubst -> Type -> Type
TCvSubst -> Type -> Type
Type.substTy TCvSubst
subst Type
rhs1 })
( CoAxBranch
ax2 { cab_lhs :: [Type]
cab_lhs = HasCallStack => TCvSubst -> [Type] -> [Type]
TCvSubst -> [Type] -> [Type]
Type.substTys TCvSubst
subst [Type]
lhs2
, cab_rhs :: Type
cab_rhs = HasCallStack => TCvSubst -> Type -> Type
TCvSubst -> Type -> Type
Type.substTy TCvSubst
subst Type
rhs2 })
computeAxiomIncomps :: [CoAxBranch] -> [CoAxBranch]
computeAxiomIncomps :: [CoAxBranch] -> [CoAxBranch]
computeAxiomIncomps [CoAxBranch]
branches
= ([CoAxBranch], [CoAxBranch]) -> [CoAxBranch]
forall a b. (a, b) -> b
snd (([CoAxBranch] -> CoAxBranch -> ([CoAxBranch], CoAxBranch))
-> [CoAxBranch] -> [CoAxBranch] -> ([CoAxBranch], [CoAxBranch])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL [CoAxBranch] -> CoAxBranch -> ([CoAxBranch], CoAxBranch)
go [] [CoAxBranch]
branches)
where
go :: [CoAxBranch] -> CoAxBranch -> ([CoAxBranch], CoAxBranch)
go :: [CoAxBranch] -> CoAxBranch -> ([CoAxBranch], CoAxBranch)
go [CoAxBranch]
prev_brs CoAxBranch
cur_br
= (CoAxBranch
cur_br CoAxBranch -> [CoAxBranch] -> [CoAxBranch]
forall a. a -> [a] -> [a]
: [CoAxBranch]
prev_brs, CoAxBranch
new_br)
where
new_br :: CoAxBranch
new_br = CoAxBranch
cur_br { cab_incomps :: [CoAxBranch]
cab_incomps = [CoAxBranch] -> CoAxBranch -> [CoAxBranch]
mk_incomps [CoAxBranch]
prev_brs CoAxBranch
cur_br }
mk_incomps :: [CoAxBranch] -> CoAxBranch -> [CoAxBranch]
mk_incomps :: [CoAxBranch] -> CoAxBranch -> [CoAxBranch]
mk_incomps [CoAxBranch]
prev_brs CoAxBranch
cur_br
= (CoAxBranch -> Bool) -> [CoAxBranch] -> [CoAxBranch]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (CoAxBranch -> Bool) -> CoAxBranch -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoAxBranch -> CoAxBranch -> Bool
compatibleBranches CoAxBranch
cur_br) [CoAxBranch]
prev_brs
mkCoAxBranch :: [TyVar]
-> [TyVar]
-> [CoVar]
-> [Type]
-> Type
-> [Role]
-> SrcSpan
-> CoAxBranch
mkCoAxBranch :: [TyVar]
-> [TyVar]
-> [TyVar]
-> [Type]
-> Type
-> [Role]
-> SrcSpan
-> CoAxBranch
mkCoAxBranch [TyVar]
tvs [TyVar]
eta_tvs [TyVar]
cvs [Type]
lhs Type
rhs [Role]
roles SrcSpan
loc
= CoAxBranch :: SrcSpan
-> [TyVar]
-> [TyVar]
-> [TyVar]
-> [Role]
-> [Type]
-> Type
-> [CoAxBranch]
-> CoAxBranch
CoAxBranch { cab_tvs :: [TyVar]
cab_tvs = [TyVar]
tvs'
, cab_eta_tvs :: [TyVar]
cab_eta_tvs = [TyVar]
eta_tvs'
, cab_cvs :: [TyVar]
cab_cvs = [TyVar]
cvs'
, cab_lhs :: [Type]
cab_lhs = TidyEnv -> [Type] -> [Type]
tidyTypes TidyEnv
env [Type]
lhs
, cab_roles :: [Role]
cab_roles = [Role]
roles
, cab_rhs :: Type
cab_rhs = TidyEnv -> Type -> Type
tidyType TidyEnv
env Type
rhs
, cab_loc :: SrcSpan
cab_loc = SrcSpan
loc
, cab_incomps :: [CoAxBranch]
cab_incomps = [CoAxBranch]
placeHolderIncomps }
where
(TidyEnv
env1, [TyVar]
tvs') = TidyEnv -> [TyVar] -> (TidyEnv, [TyVar])
tidyVarBndrs TidyEnv
init_tidy_env [TyVar]
tvs
(TidyEnv
env2, [TyVar]
eta_tvs') = TidyEnv -> [TyVar] -> (TidyEnv, [TyVar])
tidyVarBndrs TidyEnv
env1 [TyVar]
eta_tvs
(TidyEnv
env, [TyVar]
cvs') = TidyEnv -> [TyVar] -> (TidyEnv, [TyVar])
tidyVarBndrs TidyEnv
env2 [TyVar]
cvs
init_occ_env :: TidyOccEnv
init_occ_env = [OccName] -> TidyOccEnv
initTidyOccEnv [String -> OccName
mkTyVarOcc String
"_"]
init_tidy_env :: TidyEnv
init_tidy_env = TidyOccEnv -> TidyEnv
mkEmptyTidyEnv TidyOccEnv
init_occ_env
mkBranchedCoAxiom :: Name -> TyCon -> [CoAxBranch] -> CoAxiom Branched
mkBranchedCoAxiom :: Name -> TyCon -> [CoAxBranch] -> CoAxiom Branched
mkBranchedCoAxiom Name
ax_name TyCon
fam_tc [CoAxBranch]
branches
= CoAxiom :: forall (br :: BranchFlag).
Unique
-> Name -> Role -> TyCon -> Branches br -> Bool -> CoAxiom br
CoAxiom { co_ax_unique :: Unique
co_ax_unique = Name -> Unique
nameUnique Name
ax_name
, co_ax_name :: Name
co_ax_name = Name
ax_name
, co_ax_tc :: TyCon
co_ax_tc = TyCon
fam_tc
, co_ax_role :: Role
co_ax_role = Role
Nominal
, co_ax_implicit :: Bool
co_ax_implicit = Bool
False
, co_ax_branches :: Branches Branched
co_ax_branches = [CoAxBranch] -> Branches Branched
manyBranches ([CoAxBranch] -> [CoAxBranch]
computeAxiomIncomps [CoAxBranch]
branches) }
mkUnbranchedCoAxiom :: Name -> TyCon -> CoAxBranch -> CoAxiom Unbranched
mkUnbranchedCoAxiom :: Name -> TyCon -> CoAxBranch -> CoAxiom Unbranched
mkUnbranchedCoAxiom Name
ax_name TyCon
fam_tc CoAxBranch
branch
= CoAxiom :: forall (br :: BranchFlag).
Unique
-> Name -> Role -> TyCon -> Branches br -> Bool -> CoAxiom br
CoAxiom { co_ax_unique :: Unique
co_ax_unique = Name -> Unique
nameUnique Name
ax_name
, co_ax_name :: Name
co_ax_name = Name
ax_name
, co_ax_tc :: TyCon
co_ax_tc = TyCon
fam_tc
, co_ax_role :: Role
co_ax_role = Role
Nominal
, co_ax_implicit :: Bool
co_ax_implicit = Bool
False
, co_ax_branches :: Branches Unbranched
co_ax_branches = CoAxBranch -> Branches Unbranched
unbranched (CoAxBranch
branch { cab_incomps :: [CoAxBranch]
cab_incomps = [] }) }
mkSingleCoAxiom :: Role -> Name
-> [TyVar] -> [TyVar] -> [CoVar]
-> TyCon -> [Type] -> Type
-> CoAxiom Unbranched
mkSingleCoAxiom :: Role
-> Name
-> [TyVar]
-> [TyVar]
-> [TyVar]
-> TyCon
-> [Type]
-> Type
-> CoAxiom Unbranched
mkSingleCoAxiom Role
role Name
ax_name [TyVar]
tvs [TyVar]
eta_tvs [TyVar]
cvs TyCon
fam_tc [Type]
lhs_tys Type
rhs_ty
= CoAxiom :: forall (br :: BranchFlag).
Unique
-> Name -> Role -> TyCon -> Branches br -> Bool -> CoAxiom br
CoAxiom { co_ax_unique :: Unique
co_ax_unique = Name -> Unique
nameUnique Name
ax_name
, co_ax_name :: Name
co_ax_name = Name
ax_name
, co_ax_tc :: TyCon
co_ax_tc = TyCon
fam_tc
, co_ax_role :: Role
co_ax_role = Role
role
, co_ax_implicit :: Bool
co_ax_implicit = Bool
False
, co_ax_branches :: Branches Unbranched
co_ax_branches = CoAxBranch -> Branches Unbranched
unbranched (CoAxBranch
branch { cab_incomps :: [CoAxBranch]
cab_incomps = [] }) }
where
branch :: CoAxBranch
branch = [TyVar]
-> [TyVar]
-> [TyVar]
-> [Type]
-> Type
-> [Role]
-> SrcSpan
-> CoAxBranch
mkCoAxBranch [TyVar]
tvs [TyVar]
eta_tvs [TyVar]
cvs [Type]
lhs_tys Type
rhs_ty
((TyVar -> Role) -> [TyVar] -> [Role]
forall a b. (a -> b) -> [a] -> [b]
map (Role -> TyVar -> Role
forall a b. a -> b -> a
const Role
Nominal) [TyVar]
tvs)
(Name -> SrcSpan
forall a. NamedThing a => a -> SrcSpan
getSrcSpan Name
ax_name)
mkNewTypeCoAxiom :: Name -> TyCon -> [TyVar] -> [Role] -> Type -> CoAxiom Unbranched
mkNewTypeCoAxiom :: Name -> TyCon -> [TyVar] -> [Role] -> Type -> CoAxiom Unbranched
mkNewTypeCoAxiom Name
name TyCon
tycon [TyVar]
tvs [Role]
roles Type
rhs_ty
= CoAxiom :: forall (br :: BranchFlag).
Unique
-> Name -> Role -> TyCon -> Branches br -> Bool -> CoAxiom br
CoAxiom { co_ax_unique :: Unique
co_ax_unique = Name -> Unique
nameUnique Name
name
, co_ax_name :: Name
co_ax_name = Name
name
, co_ax_implicit :: Bool
co_ax_implicit = Bool
True
, co_ax_role :: Role
co_ax_role = Role
Representational
, co_ax_tc :: TyCon
co_ax_tc = TyCon
tycon
, co_ax_branches :: Branches Unbranched
co_ax_branches = CoAxBranch -> Branches Unbranched
unbranched (CoAxBranch
branch { cab_incomps :: [CoAxBranch]
cab_incomps = [] }) }
where
branch :: CoAxBranch
branch = [TyVar]
-> [TyVar]
-> [TyVar]
-> [Type]
-> Type
-> [Role]
-> SrcSpan
-> CoAxBranch
mkCoAxBranch [TyVar]
tvs [] [] ([TyVar] -> [Type]
mkTyVarTys [TyVar]
tvs) Type
rhs_ty
[Role]
roles (Name -> SrcSpan
forall a. NamedThing a => a -> SrcSpan
getSrcSpan Name
name)
data FamInstMatch = FamInstMatch { FamInstMatch -> FamInst
fim_instance :: FamInst
, FamInstMatch -> [Type]
fim_tys :: [Type]
, FamInstMatch -> [Coercion]
fim_cos :: [Coercion]
}
instance Outputable FamInstMatch where
ppr :: FamInstMatch -> SDoc
ppr (FamInstMatch { fim_instance :: FamInstMatch -> FamInst
fim_instance = FamInst
inst
, fim_tys :: FamInstMatch -> [Type]
fim_tys = [Type]
tys
, fim_cos :: FamInstMatch -> [Coercion]
fim_cos = [Coercion]
cos })
= String -> SDoc
text String
"match with" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
parens (FamInst -> SDoc
forall a. Outputable a => a -> SDoc
ppr FamInst
inst) SDoc -> SDoc -> SDoc
<+> [Type] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Type]
tys SDoc -> SDoc -> SDoc
<+> [Coercion] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Coercion]
cos
lookupFamInstEnvByTyCon :: FamInstEnvs -> TyCon -> [FamInst]
lookupFamInstEnvByTyCon :: (FamInstEnv, FamInstEnv) -> TyCon -> [FamInst]
lookupFamInstEnvByTyCon (FamInstEnv
pkg_ie, FamInstEnv
home_ie) TyCon
fam_tc
= FamInstEnv -> [FamInst]
get FamInstEnv
pkg_ie [FamInst] -> [FamInst] -> [FamInst]
forall a. [a] -> [a] -> [a]
++ FamInstEnv -> [FamInst]
get FamInstEnv
home_ie
where
get :: FamInstEnv -> [FamInst]
get FamInstEnv
ie = case FamInstEnv -> TyCon -> Maybe FamilyInstEnv
forall key elt.
Uniquable key =>
UniqDFM key elt -> key -> Maybe elt
lookupUDFM FamInstEnv
ie TyCon
fam_tc of
Maybe FamilyInstEnv
Nothing -> []
Just (FamIE [FamInst]
fis) -> [FamInst]
fis
lookupFamInstEnv
:: FamInstEnvs
-> TyCon -> [Type]
-> [FamInstMatch]
lookupFamInstEnv :: (FamInstEnv, FamInstEnv) -> TyCon -> [Type] -> [FamInstMatch]
lookupFamInstEnv
= MatchFun
-> (FamInstEnv, FamInstEnv) -> TyCon -> [Type] -> [FamInstMatch]
lookup_fam_inst_env MatchFun
forall {p} {p}. p -> p -> [Type] -> [Type] -> Maybe TCvSubst
match
where
match :: p -> p -> [Type] -> [Type] -> Maybe TCvSubst
match p
_ p
_ [Type]
tpl_tys [Type]
tys = [Type] -> [Type] -> Maybe TCvSubst
tcMatchTys [Type]
tpl_tys [Type]
tys
lookupFamInstEnvConflicts
:: FamInstEnvs
-> FamInst
-> [FamInstMatch]
lookupFamInstEnvConflicts :: (FamInstEnv, FamInstEnv) -> FamInst -> [FamInstMatch]
lookupFamInstEnvConflicts (FamInstEnv, FamInstEnv)
envs fam_inst :: FamInst
fam_inst@(FamInst { fi_axiom :: FamInst -> CoAxiom Unbranched
fi_axiom = CoAxiom Unbranched
new_axiom })
= MatchFun
-> (FamInstEnv, FamInstEnv) -> TyCon -> [Type] -> [FamInstMatch]
lookup_fam_inst_env MatchFun
my_unify (FamInstEnv, FamInstEnv)
envs TyCon
fam [Type]
tys
where
(TyCon
fam, [Type]
tys) = FamInst -> (TyCon, [Type])
famInstSplitLHS FamInst
fam_inst
my_unify :: MatchFun
my_unify (FamInst { fi_axiom :: FamInst -> CoAxiom Unbranched
fi_axiom = CoAxiom Unbranched
old_axiom }) VarSet
tpl_tvs [Type]
tpl_tys [Type]
_
= ASSERT2( tyCoVarsOfTypes tys `disjointVarSet` tpl_tvs,
(ppr fam <+> ppr tys) $$
(ppr tpl_tvs <+> ppr tpl_tys) )
if CoAxBranch -> CoAxBranch -> Bool
compatibleBranches (CoAxiom Unbranched -> CoAxBranch
coAxiomSingleBranch CoAxiom Unbranched
old_axiom) CoAxBranch
new_branch
then Maybe TCvSubst
forall a. Maybe a
Nothing
else TCvSubst -> Maybe TCvSubst
forall a. a -> Maybe a
Just TCvSubst
forall {a}. a
noSubst
noSubst :: a
noSubst = String -> a
forall a. String -> a
panic String
"lookupFamInstEnvConflicts noSubst"
new_branch :: CoAxBranch
new_branch = CoAxiom Unbranched -> CoAxBranch
coAxiomSingleBranch CoAxiom Unbranched
new_axiom
lookupFamInstEnvInjectivityConflicts
:: [Bool]
-> FamInstEnvs
-> FamInst
-> [CoAxBranch]
lookupFamInstEnvInjectivityConflicts :: [Bool] -> (FamInstEnv, FamInstEnv) -> FamInst -> [CoAxBranch]
lookupFamInstEnvInjectivityConflicts [Bool]
injList (FamInstEnv
pkg_ie, FamInstEnv
home_ie)
fam_inst :: FamInst
fam_inst@(FamInst { fi_axiom :: FamInst -> CoAxiom Unbranched
fi_axiom = CoAxiom Unbranched
new_axiom })
= FamInstEnv -> [CoAxBranch]
lookup_inj_fam_conflicts FamInstEnv
home_ie [CoAxBranch] -> [CoAxBranch] -> [CoAxBranch]
forall a. [a] -> [a] -> [a]
++ FamInstEnv -> [CoAxBranch]
lookup_inj_fam_conflicts FamInstEnv
pkg_ie
where
fam :: TyCon
fam = FamInst -> TyCon
famInstTyCon FamInst
fam_inst
new_branch :: CoAxBranch
new_branch = CoAxiom Unbranched -> CoAxBranch
coAxiomSingleBranch CoAxiom Unbranched
new_axiom
isInjConflict :: FamInst -> Bool
isInjConflict (FamInst { fi_axiom :: FamInst -> CoAxiom Unbranched
fi_axiom = CoAxiom Unbranched
old_axiom })
| InjectivityCheckResult
InjectivityAccepted <-
[Bool] -> CoAxBranch -> CoAxBranch -> InjectivityCheckResult
injectiveBranches [Bool]
injList (CoAxiom Unbranched -> CoAxBranch
coAxiomSingleBranch CoAxiom Unbranched
old_axiom) CoAxBranch
new_branch
= Bool
False
| Bool
otherwise = Bool
True
lookup_inj_fam_conflicts :: FamInstEnv -> [CoAxBranch]
lookup_inj_fam_conflicts FamInstEnv
ie
| TyCon -> Bool
isOpenFamilyTyCon TyCon
fam, Just (FamIE [FamInst]
insts) <- FamInstEnv -> TyCon -> Maybe FamilyInstEnv
forall key elt.
Uniquable key =>
UniqDFM key elt -> key -> Maybe elt
lookupUDFM FamInstEnv
ie TyCon
fam
= (FamInst -> CoAxBranch) -> [FamInst] -> [CoAxBranch]
forall a b. (a -> b) -> [a] -> [b]
map (CoAxiom Unbranched -> CoAxBranch
coAxiomSingleBranch (CoAxiom Unbranched -> CoAxBranch)
-> (FamInst -> CoAxiom Unbranched) -> FamInst -> CoAxBranch
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FamInst -> CoAxiom Unbranched
fi_axiom) ([FamInst] -> [CoAxBranch]) -> [FamInst] -> [CoAxBranch]
forall a b. (a -> b) -> a -> b
$
(FamInst -> Bool) -> [FamInst] -> [FamInst]
forall a. (a -> Bool) -> [a] -> [a]
filter FamInst -> Bool
isInjConflict [FamInst]
insts
| Bool
otherwise = []
type MatchFun = FamInst
-> TyVarSet -> [Type]
-> [Type]
-> Maybe TCvSubst
lookup_fam_inst_env'
:: MatchFun
-> FamInstEnv
-> TyCon -> [Type]
-> [FamInstMatch]
lookup_fam_inst_env' :: MatchFun -> FamInstEnv -> TyCon -> [Type] -> [FamInstMatch]
lookup_fam_inst_env' MatchFun
match_fun FamInstEnv
ie TyCon
fam [Type]
match_tys
| TyCon -> Bool
isOpenFamilyTyCon TyCon
fam
, Just (FamIE [FamInst]
insts) <- FamInstEnv -> TyCon -> Maybe FamilyInstEnv
forall key elt.
Uniquable key =>
UniqDFM key elt -> key -> Maybe elt
lookupUDFM FamInstEnv
ie TyCon
fam
= [FamInst] -> [FamInstMatch]
find [FamInst]
insts
| Bool
otherwise = []
where
find :: [FamInst] -> [FamInstMatch]
find [] = []
find (item :: FamInst
item@(FamInst { fi_tcs :: FamInst -> [Maybe Name]
fi_tcs = [Maybe Name]
mb_tcs, fi_tvs :: FamInst -> [TyVar]
fi_tvs = [TyVar]
tpl_tvs, fi_cvs :: FamInst -> [TyVar]
fi_cvs = [TyVar]
tpl_cvs
, fi_tys :: FamInst -> [Type]
fi_tys = [Type]
tpl_tys }) : [FamInst]
rest)
| [Maybe Name] -> [Maybe Name] -> Bool
instanceCantMatch [Maybe Name]
rough_tcs [Maybe Name]
mb_tcs
= [FamInst] -> [FamInstMatch]
find [FamInst]
rest
| Just TCvSubst
subst <- MatchFun
match_fun FamInst
item ([TyVar] -> VarSet
mkVarSet [TyVar]
tpl_tvs) [Type]
tpl_tys [Type]
match_tys1
= (FamInstMatch :: FamInst -> [Type] -> [Coercion] -> FamInstMatch
FamInstMatch { fim_instance :: FamInst
fim_instance = FamInst
item
, fim_tys :: [Type]
fim_tys = TCvSubst -> [TyVar] -> [Type]
substTyVars TCvSubst
subst [TyVar]
tpl_tvs [Type] -> [Type] -> [Type]
forall a. [a] -> [a] -> [a]
`chkAppend` [Type]
match_tys2
, fim_cos :: [Coercion]
fim_cos = ASSERT( all (isJust . lookupCoVar subst) tpl_cvs )
TCvSubst -> [TyVar] -> [Coercion]
substCoVars TCvSubst
subst [TyVar]
tpl_cvs
})
FamInstMatch -> [FamInstMatch] -> [FamInstMatch]
forall a. a -> [a] -> [a]
: [FamInst] -> [FamInstMatch]
find [FamInst]
rest
| Bool
otherwise
= [FamInst] -> [FamInstMatch]
find [FamInst]
rest
where
([Maybe Name]
rough_tcs, [Type]
match_tys1, [Type]
match_tys2) = [Type] -> ([Maybe Name], [Type], [Type])
split_tys [Type]
tpl_tys
split_tys :: [Type] -> ([Maybe Name], [Type], [Type])
split_tys [Type]
tpl_tys
| TyCon -> Bool
isTypeFamilyTyCon TyCon
fam
= ([Maybe Name], [Type], [Type])
pre_rough_split_tys
| Bool
otherwise
= let ([Type]
match_tys1, [Type]
match_tys2) = [Type] -> [Type] -> ([Type], [Type])
forall b a. [b] -> [a] -> ([a], [a])
splitAtList [Type]
tpl_tys [Type]
match_tys
rough_tcs :: [Maybe Name]
rough_tcs = [Type] -> [Maybe Name]
roughMatchTcs [Type]
match_tys1
in ([Maybe Name]
rough_tcs, [Type]
match_tys1, [Type]
match_tys2)
([Type]
pre_match_tys1, [Type]
pre_match_tys2) = Arity -> [Type] -> ([Type], [Type])
forall a. Arity -> [a] -> ([a], [a])
splitAt (TyCon -> Arity
tyConArity TyCon
fam) [Type]
match_tys
pre_rough_split_tys :: ([Maybe Name], [Type], [Type])
pre_rough_split_tys
= ([Type] -> [Maybe Name]
roughMatchTcs [Type]
pre_match_tys1, [Type]
pre_match_tys1, [Type]
pre_match_tys2)
lookup_fam_inst_env
:: MatchFun
-> FamInstEnvs
-> TyCon -> [Type]
-> [FamInstMatch]
lookup_fam_inst_env :: MatchFun
-> (FamInstEnv, FamInstEnv) -> TyCon -> [Type] -> [FamInstMatch]
lookup_fam_inst_env MatchFun
match_fun (FamInstEnv
pkg_ie, FamInstEnv
home_ie) TyCon
fam [Type]
tys
= MatchFun -> FamInstEnv -> TyCon -> [Type] -> [FamInstMatch]
lookup_fam_inst_env' MatchFun
match_fun FamInstEnv
home_ie TyCon
fam [Type]
tys
[FamInstMatch] -> [FamInstMatch] -> [FamInstMatch]
forall a. [a] -> [a] -> [a]
++ MatchFun -> FamInstEnv -> TyCon -> [Type] -> [FamInstMatch]
lookup_fam_inst_env' MatchFun
match_fun FamInstEnv
pkg_ie TyCon
fam [Type]
tys
isDominatedBy :: CoAxBranch -> [CoAxBranch] -> Bool
isDominatedBy :: CoAxBranch -> [CoAxBranch] -> Bool
isDominatedBy CoAxBranch
branch [CoAxBranch]
branches
= [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ([Bool] -> Bool) -> [Bool] -> Bool
forall a b. (a -> b) -> a -> b
$ (CoAxBranch -> Bool) -> [CoAxBranch] -> [Bool]
forall a b. (a -> b) -> [a] -> [b]
map CoAxBranch -> Bool
match [CoAxBranch]
branches
where
lhs :: [Type]
lhs = CoAxBranch -> [Type]
coAxBranchLHS CoAxBranch
branch
match :: CoAxBranch -> Bool
match (CoAxBranch { cab_lhs :: CoAxBranch -> [Type]
cab_lhs = [Type]
tys })
= Maybe TCvSubst -> Bool
forall a. Maybe a -> Bool
isJust (Maybe TCvSubst -> Bool) -> Maybe TCvSubst -> Bool
forall a b. (a -> b) -> a -> b
$ [Type] -> [Type] -> Maybe TCvSubst
tcMatchTys [Type]
tys [Type]
lhs
reduceTyFamApp_maybe :: FamInstEnvs
-> Role
-> TyCon -> [Type]
-> Maybe (Coercion, Type)
reduceTyFamApp_maybe :: (FamInstEnv, FamInstEnv)
-> Role -> TyCon -> [Type] -> Maybe (Coercion, Type)
reduceTyFamApp_maybe (FamInstEnv, FamInstEnv)
envs Role
role TyCon
tc [Type]
tys
| Role
Phantom <- Role
role
= Maybe (Coercion, Type)
forall a. Maybe a
Nothing
| case Role
role of
Role
Representational -> TyCon -> Bool
isOpenFamilyTyCon TyCon
tc
Role
_ -> TyCon -> Bool
isOpenTypeFamilyTyCon TyCon
tc
, FamInstMatch { fim_instance :: FamInstMatch -> FamInst
fim_instance = FamInst { fi_axiom :: FamInst -> CoAxiom Unbranched
fi_axiom = CoAxiom Unbranched
ax }
, fim_tys :: FamInstMatch -> [Type]
fim_tys = [Type]
inst_tys
, fim_cos :: FamInstMatch -> [Coercion]
fim_cos = [Coercion]
inst_cos } : [FamInstMatch]
_ <- (FamInstEnv, FamInstEnv) -> TyCon -> [Type] -> [FamInstMatch]
lookupFamInstEnv (FamInstEnv, FamInstEnv)
envs TyCon
tc [Type]
tys
= let co :: Coercion
co = Role -> CoAxiom Unbranched -> [Type] -> [Coercion] -> Coercion
mkUnbranchedAxInstCo Role
role CoAxiom Unbranched
ax [Type]
inst_tys [Coercion]
inst_cos
ty :: Type
ty = Coercion -> Type
coercionRKind Coercion
co
in (Coercion, Type) -> Maybe (Coercion, Type)
forall a. a -> Maybe a
Just (Coercion
co, Type
ty)
| Just CoAxiom Branched
ax <- TyCon -> Maybe (CoAxiom Branched)
isClosedSynFamilyTyConWithAxiom_maybe TyCon
tc
, Just (Arity
ind, [Type]
inst_tys, [Coercion]
inst_cos) <- CoAxiom Branched -> [Type] -> Maybe (Arity, [Type], [Coercion])
chooseBranch CoAxiom Branched
ax [Type]
tys
= let co :: Coercion
co = Role
-> CoAxiom Branched -> Arity -> [Type] -> [Coercion] -> Coercion
forall (br :: BranchFlag).
Role -> CoAxiom br -> Arity -> [Type] -> [Coercion] -> Coercion
mkAxInstCo Role
role CoAxiom Branched
ax Arity
ind [Type]
inst_tys [Coercion]
inst_cos
ty :: Type
ty = Coercion -> Type
coercionRKind Coercion
co
in (Coercion, Type) -> Maybe (Coercion, Type)
forall a. a -> Maybe a
Just (Coercion
co, Type
ty)
| Just BuiltInSynFamily
ax <- TyCon -> Maybe BuiltInSynFamily
isBuiltInSynFamTyCon_maybe TyCon
tc
, Just (CoAxiomRule
coax,[Type]
ts,Type
ty) <- BuiltInSynFamily -> [Type] -> Maybe (CoAxiomRule, [Type], Type)
sfMatchFam BuiltInSynFamily
ax [Type]
tys
= let co :: Coercion
co = CoAxiomRule -> [Coercion] -> Coercion
mkAxiomRuleCo CoAxiomRule
coax ((Role -> Type -> Coercion) -> [Role] -> [Type] -> [Coercion]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Role -> Type -> Coercion
mkReflCo (CoAxiomRule -> [Role]
coaxrAsmpRoles CoAxiomRule
coax) [Type]
ts)
in (Coercion, Type) -> Maybe (Coercion, Type)
forall a. a -> Maybe a
Just (Coercion
co, Type
ty)
| Bool
otherwise
= Maybe (Coercion, Type)
forall a. Maybe a
Nothing
chooseBranch :: CoAxiom Branched -> [Type]
-> Maybe (BranchIndex, [Type], [Coercion])
chooseBranch :: CoAxiom Branched -> [Type] -> Maybe (Arity, [Type], [Coercion])
chooseBranch CoAxiom Branched
axiom [Type]
tys
= do { let num_pats :: Arity
num_pats = CoAxiom Branched -> Arity
forall (br :: BranchFlag). CoAxiom br -> Arity
coAxiomNumPats CoAxiom Branched
axiom
([Type]
target_tys, [Type]
extra_tys) = Arity -> [Type] -> ([Type], [Type])
forall a. Arity -> [a] -> ([a], [a])
splitAt Arity
num_pats [Type]
tys
branches :: Branches Branched
branches = CoAxiom Branched -> Branches Branched
forall (br :: BranchFlag). CoAxiom br -> Branches br
coAxiomBranches CoAxiom Branched
axiom
; (Arity
ind, [Type]
inst_tys, [Coercion]
inst_cos)
<- Array Arity CoAxBranch
-> [Type] -> Maybe (Arity, [Type], [Coercion])
findBranch (Branches Branched -> Array Arity CoAxBranch
forall (br :: BranchFlag). Branches br -> Array Arity CoAxBranch
unMkBranches Branches Branched
branches) [Type]
target_tys
; (Arity, [Type], [Coercion]) -> Maybe (Arity, [Type], [Coercion])
forall (m :: * -> *) a. Monad m => a -> m a
return ( Arity
ind, [Type]
inst_tys [Type] -> [Type] -> [Type]
forall a. [a] -> [a] -> [a]
`chkAppend` [Type]
extra_tys, [Coercion]
inst_cos ) }
findBranch :: Array BranchIndex CoAxBranch
-> [Type]
-> Maybe (BranchIndex, [Type], [Coercion])
findBranch :: Array Arity CoAxBranch
-> [Type] -> Maybe (Arity, [Type], [Coercion])
findBranch Array Arity CoAxBranch
branches [Type]
target_tys
= ((Arity, CoAxBranch)
-> Maybe (Arity, [Type], [Coercion])
-> Maybe (Arity, [Type], [Coercion]))
-> Maybe (Arity, [Type], [Coercion])
-> [(Arity, CoAxBranch)]
-> Maybe (Arity, [Type], [Coercion])
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Arity, CoAxBranch)
-> Maybe (Arity, [Type], [Coercion])
-> Maybe (Arity, [Type], [Coercion])
go Maybe (Arity, [Type], [Coercion])
forall a. Maybe a
Nothing (Array Arity CoAxBranch -> [(Arity, CoAxBranch)]
forall i e. Ix i => Array i e -> [(i, e)]
assocs Array Arity CoAxBranch
branches)
where
go :: (BranchIndex, CoAxBranch)
-> Maybe (BranchIndex, [Type], [Coercion])
-> Maybe (BranchIndex, [Type], [Coercion])
go :: (Arity, CoAxBranch)
-> Maybe (Arity, [Type], [Coercion])
-> Maybe (Arity, [Type], [Coercion])
go (Arity
index, CoAxBranch
branch) Maybe (Arity, [Type], [Coercion])
other
= let (CoAxBranch { cab_tvs :: CoAxBranch -> [TyVar]
cab_tvs = [TyVar]
tpl_tvs, cab_cvs :: CoAxBranch -> [TyVar]
cab_cvs = [TyVar]
tpl_cvs
, cab_lhs :: CoAxBranch -> [Type]
cab_lhs = [Type]
tpl_lhs
, cab_incomps :: CoAxBranch -> [CoAxBranch]
cab_incomps = [CoAxBranch]
incomps }) = CoAxBranch
branch
in_scope :: InScopeSet
in_scope = VarSet -> InScopeSet
mkInScopeSet ([VarSet] -> VarSet
unionVarSets ([VarSet] -> VarSet) -> [VarSet] -> VarSet
forall a b. (a -> b) -> a -> b
$
(CoAxBranch -> VarSet) -> [CoAxBranch] -> [VarSet]
forall a b. (a -> b) -> [a] -> [b]
map ([Type] -> VarSet
tyCoVarsOfTypes ([Type] -> VarSet)
-> (CoAxBranch -> [Type]) -> CoAxBranch -> VarSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoAxBranch -> [Type]
coAxBranchLHS) [CoAxBranch]
incomps)
flattened_target :: [Type]
flattened_target = InScopeSet -> [Type] -> [Type]
flattenTys InScopeSet
in_scope [Type]
target_tys
in case [Type] -> [Type] -> Maybe TCvSubst
tcMatchTys [Type]
tpl_lhs [Type]
target_tys of
Just TCvSubst
subst
| [Type] -> CoAxBranch -> Bool
apartnessCheck [Type]
flattened_target CoAxBranch
branch
->
ASSERT( all (isJust . lookupCoVar subst) tpl_cvs )
(Arity, [Type], [Coercion]) -> Maybe (Arity, [Type], [Coercion])
forall a. a -> Maybe a
Just (Arity
index, TCvSubst -> [TyVar] -> [Type]
substTyVars TCvSubst
subst [TyVar]
tpl_tvs, TCvSubst -> [TyVar] -> [Coercion]
substCoVars TCvSubst
subst [TyVar]
tpl_cvs)
Maybe TCvSubst
_ -> Maybe (Arity, [Type], [Coercion])
other
apartnessCheck :: [Type]
-> CoAxBranch
-> Bool
apartnessCheck :: [Type] -> CoAxBranch -> Bool
apartnessCheck [Type]
flattened_target (CoAxBranch { cab_incomps :: CoAxBranch -> [CoAxBranch]
cab_incomps = [CoAxBranch]
incomps })
= (CoAxBranch -> Bool) -> [CoAxBranch] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (UnifyResult -> Bool
forall {a}. UnifyResultM a -> Bool
isSurelyApart
(UnifyResult -> Bool)
-> (CoAxBranch -> UnifyResult) -> CoAxBranch -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TyVar -> BindFlag) -> [Type] -> [Type] -> UnifyResult
tcUnifyTysFG (BindFlag -> TyVar -> BindFlag
forall a b. a -> b -> a
const BindFlag
BindMe) [Type]
flattened_target
([Type] -> UnifyResult)
-> (CoAxBranch -> [Type]) -> CoAxBranch -> UnifyResult
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoAxBranch -> [Type]
coAxBranchLHS) [CoAxBranch]
incomps
where
isSurelyApart :: UnifyResultM a -> Bool
isSurelyApart UnifyResultM a
SurelyApart = Bool
True
isSurelyApart UnifyResultM a
_ = Bool
False
topNormaliseType :: FamInstEnvs -> Type -> Type
topNormaliseType :: (FamInstEnv, FamInstEnv) -> Type -> Type
topNormaliseType (FamInstEnv, FamInstEnv)
env Type
ty = case (FamInstEnv, FamInstEnv) -> Type -> Maybe (Coercion, Type)
topNormaliseType_maybe (FamInstEnv, FamInstEnv)
env Type
ty of
Just (Coercion
_co, Type
ty') -> Type
ty'
Maybe (Coercion, Type)
Nothing -> Type
ty
topNormaliseType_maybe :: FamInstEnvs -> Type -> Maybe (Coercion, Type)
topNormaliseType_maybe :: (FamInstEnv, FamInstEnv) -> Type -> Maybe (Coercion, Type)
topNormaliseType_maybe (FamInstEnv, FamInstEnv)
env Type
ty
= do { ((Coercion
co, MCoercionN
mkind_co), Type
nty) <- NormaliseStepper (Coercion, MCoercionN)
-> ((Coercion, MCoercionN)
-> (Coercion, MCoercionN) -> (Coercion, MCoercionN))
-> Type
-> Maybe ((Coercion, MCoercionN), Type)
forall ev.
NormaliseStepper ev -> (ev -> ev -> ev) -> Type -> Maybe (ev, Type)
topNormaliseTypeX NormaliseStepper (Coercion, MCoercionN)
stepper (Coercion, MCoercionN)
-> (Coercion, MCoercionN) -> (Coercion, MCoercionN)
combine Type
ty
; (Coercion, Type) -> Maybe (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Coercion, Type) -> Maybe (Coercion, Type))
-> (Coercion, Type) -> Maybe (Coercion, Type)
forall a b. (a -> b) -> a -> b
$ case MCoercionN
mkind_co of
MCoercionN
MRefl -> (Coercion
co, Type
nty)
MCo Coercion
kind_co -> let nty_casted :: Type
nty_casted = Type
nty Type -> Coercion -> Type
`mkCastTy` Coercion -> Coercion
mkSymCo Coercion
kind_co
final_co :: Coercion
final_co = Role -> Type -> Coercion -> Coercion -> Coercion
mkCoherenceRightCo Role
Representational Type
nty
(Coercion -> Coercion
mkSymCo Coercion
kind_co) Coercion
co
in (Coercion
final_co, Type
nty_casted) }
where
stepper :: NormaliseStepper (Coercion, MCoercionN)
stepper = NormaliseStepper (Coercion, MCoercionN)
unwrapNewTypeStepper' NormaliseStepper (Coercion, MCoercionN)
-> NormaliseStepper (Coercion, MCoercionN)
-> NormaliseStepper (Coercion, MCoercionN)
forall ev.
NormaliseStepper ev -> NormaliseStepper ev -> NormaliseStepper ev
`composeSteppers` NormaliseStepper (Coercion, MCoercionN)
tyFamStepper
combine :: (Coercion, MCoercionN)
-> (Coercion, MCoercionN) -> (Coercion, MCoercionN)
combine (Coercion
c1, MCoercionN
mc1) (Coercion
c2, MCoercionN
mc2) = (Coercion
c1 Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
c2, MCoercionN
mc1 MCoercionN -> MCoercionN -> MCoercionN
`mkTransMCo` MCoercionN
mc2)
unwrapNewTypeStepper' :: NormaliseStepper (Coercion, MCoercionN)
unwrapNewTypeStepper' :: NormaliseStepper (Coercion, MCoercionN)
unwrapNewTypeStepper' RecTcChecker
rec_nts TyCon
tc [Type]
tys
= (Coercion -> (Coercion, MCoercionN))
-> NormaliseStepResult Coercion
-> NormaliseStepResult (Coercion, MCoercionN)
forall ev1 ev2.
(ev1 -> ev2) -> NormaliseStepResult ev1 -> NormaliseStepResult ev2
mapStepResult (, MCoercionN
MRefl) (NormaliseStepResult Coercion
-> NormaliseStepResult (Coercion, MCoercionN))
-> NormaliseStepResult Coercion
-> NormaliseStepResult (Coercion, MCoercionN)
forall a b. (a -> b) -> a -> b
$ NormaliseStepper Coercion
unwrapNewTypeStepper RecTcChecker
rec_nts TyCon
tc [Type]
tys
tyFamStepper :: NormaliseStepper (Coercion, MCoercionN)
tyFamStepper :: NormaliseStepper (Coercion, MCoercionN)
tyFamStepper RecTcChecker
rec_nts TyCon
tc [Type]
tys
= case (FamInstEnv, FamInstEnv)
-> TyCon -> [Type] -> Maybe (Coercion, Type, Coercion)
topReduceTyFamApp_maybe (FamInstEnv, FamInstEnv)
env TyCon
tc [Type]
tys of
Just (Coercion
co, Type
rhs, Coercion
res_co) -> RecTcChecker
-> Type
-> (Coercion, MCoercionN)
-> NormaliseStepResult (Coercion, MCoercionN)
forall ev. RecTcChecker -> Type -> ev -> NormaliseStepResult ev
NS_Step RecTcChecker
rec_nts Type
rhs (Coercion
co, Coercion -> MCoercionN
MCo Coercion
res_co)
Maybe (Coercion, Type, Coercion)
_ -> NormaliseStepResult (Coercion, MCoercionN)
forall ev. NormaliseStepResult ev
NS_Done
normaliseTcApp :: FamInstEnvs -> Role -> TyCon -> [Type] -> (Coercion, Type)
normaliseTcApp :: (FamInstEnv, FamInstEnv)
-> Role -> TyCon -> [Type] -> (Coercion, Type)
normaliseTcApp (FamInstEnv, FamInstEnv)
env Role
role TyCon
tc [Type]
tys
= (FamInstEnv, FamInstEnv)
-> Role -> VarSet -> NormM (Coercion, Type) -> (Coercion, Type)
forall a.
(FamInstEnv, FamInstEnv) -> Role -> VarSet -> NormM a -> a
initNormM (FamInstEnv, FamInstEnv)
env Role
role ([Type] -> VarSet
tyCoVarsOfTypes [Type]
tys) (NormM (Coercion, Type) -> (Coercion, Type))
-> NormM (Coercion, Type) -> (Coercion, Type)
forall a b. (a -> b) -> a -> b
$
TyCon -> [Type] -> NormM (Coercion, Type)
normalise_tc_app TyCon
tc [Type]
tys
normalise_tc_app :: TyCon -> [Type] -> NormM (Coercion, Type)
normalise_tc_app :: TyCon -> [Type] -> NormM (Coercion, Type)
normalise_tc_app TyCon
tc [Type]
tys
| Just ([(TyVar, Type)]
tenv, Type
rhs, [Type]
tys') <- TyCon -> [Type] -> Maybe ([(TyVar, Type)], Type, [Type])
forall tyco.
TyCon -> [tyco] -> Maybe ([(TyVar, tyco)], Type, [tyco])
expandSynTyCon_maybe TyCon
tc [Type]
tys
, Bool -> Bool
not (TyCon -> Bool
isFamFreeTyCon TyCon
tc)
=
Type -> NormM (Coercion, Type)
normalise_type (Type -> [Type] -> Type
mkAppTys (HasCallStack => TCvSubst -> Type -> Type
TCvSubst -> Type -> Type
substTy ([(TyVar, Type)] -> TCvSubst
mkTvSubstPrs [(TyVar, Type)]
tenv) Type
rhs) [Type]
tys')
| TyCon -> Bool
isFamilyTyCon TyCon
tc
=
do { (FamInstEnv, FamInstEnv)
env <- NormM (FamInstEnv, FamInstEnv)
getEnv
; Role
role <- NormM Role
getRole
; (Coercion
args_co, [Type]
ntys, Coercion
res_co) <- TyCon -> [Type] -> NormM (Coercion, [Type], Coercion)
normalise_tc_args TyCon
tc [Type]
tys
; case (FamInstEnv, FamInstEnv)
-> Role -> TyCon -> [Type] -> Maybe (Coercion, Type)
reduceTyFamApp_maybe (FamInstEnv, FamInstEnv)
env Role
role TyCon
tc [Type]
ntys of
Just (Coercion
first_co, Type
ty')
-> do { (Coercion
rest_co,Type
nty) <- Type -> NormM (Coercion, Type)
normalise_type Type
ty'
; (Coercion, Type) -> NormM (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Role -> Type -> Coercion -> Coercion -> (Coercion, Type)
assemble_result Role
role Type
nty
(Coercion
args_co Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
first_co Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
rest_co)
Coercion
res_co) }
Maybe (Coercion, Type)
_ ->
(Coercion, Type) -> NormM (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Role -> Type -> Coercion -> Coercion -> (Coercion, Type)
assemble_result Role
role (TyCon -> [Type] -> Type
mkTyConApp TyCon
tc [Type]
ntys) Coercion
args_co Coercion
res_co) }
| Bool
otherwise
=
do { (Coercion
args_co, [Type]
ntys, Coercion
res_co) <- TyCon -> [Type] -> NormM (Coercion, [Type], Coercion)
normalise_tc_args TyCon
tc [Type]
tys
; Role
role <- NormM Role
getRole
; (Coercion, Type) -> NormM (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Role -> Type -> Coercion -> Coercion -> (Coercion, Type)
assemble_result Role
role (TyCon -> [Type] -> Type
mkTyConApp TyCon
tc [Type]
ntys) Coercion
args_co Coercion
res_co) }
where
assemble_result :: Role
-> Type
-> Coercion
-> CoercionN
-> (Coercion, Type)
assemble_result :: Role -> Type -> Coercion -> Coercion -> (Coercion, Type)
assemble_result Role
r Type
nty Coercion
orig_to_nty Coercion
kind_co
= ( Coercion
final_co, Type
nty_old_kind )
where
nty_old_kind :: Type
nty_old_kind = Type
nty Type -> Coercion -> Type
`mkCastTy` Coercion -> Coercion
mkSymCo Coercion
kind_co
final_co :: Coercion
final_co = Role -> Type -> Coercion -> Coercion -> Coercion
mkCoherenceRightCo Role
r Type
nty (Coercion -> Coercion
mkSymCo Coercion
kind_co) Coercion
orig_to_nty
topReduceTyFamApp_maybe :: FamInstEnvs -> TyCon -> [Type]
-> Maybe (Coercion, Type, Coercion)
topReduceTyFamApp_maybe :: (FamInstEnv, FamInstEnv)
-> TyCon -> [Type] -> Maybe (Coercion, Type, Coercion)
topReduceTyFamApp_maybe (FamInstEnv, FamInstEnv)
envs TyCon
fam_tc [Type]
arg_tys
| TyCon -> Bool
isFamilyTyCon TyCon
fam_tc
, Just (Coercion
co, Type
rhs) <- (FamInstEnv, FamInstEnv)
-> Role -> TyCon -> [Type] -> Maybe (Coercion, Type)
reduceTyFamApp_maybe (FamInstEnv, FamInstEnv)
envs Role
role TyCon
fam_tc [Type]
ntys
= (Coercion, Type, Coercion) -> Maybe (Coercion, Type, Coercion)
forall a. a -> Maybe a
Just (Coercion
args_co Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
co, Type
rhs, Coercion
res_co)
| Bool
otherwise
= Maybe (Coercion, Type, Coercion)
forall a. Maybe a
Nothing
where
role :: Role
role = Role
Representational
(Coercion
args_co, [Type]
ntys, Coercion
res_co) = (FamInstEnv, FamInstEnv)
-> Role
-> VarSet
-> NormM (Coercion, [Type], Coercion)
-> (Coercion, [Type], Coercion)
forall a.
(FamInstEnv, FamInstEnv) -> Role -> VarSet -> NormM a -> a
initNormM (FamInstEnv, FamInstEnv)
envs Role
role ([Type] -> VarSet
tyCoVarsOfTypes [Type]
arg_tys) (NormM (Coercion, [Type], Coercion)
-> (Coercion, [Type], Coercion))
-> NormM (Coercion, [Type], Coercion)
-> (Coercion, [Type], Coercion)
forall a b. (a -> b) -> a -> b
$
TyCon -> [Type] -> NormM (Coercion, [Type], Coercion)
normalise_tc_args TyCon
fam_tc [Type]
arg_tys
normalise_tc_args :: TyCon -> [Type]
-> NormM (Coercion, [Type], CoercionN)
normalise_tc_args :: TyCon -> [Type] -> NormM (Coercion, [Type], Coercion)
normalise_tc_args TyCon
tc [Type]
tys
= do { Role
role <- NormM Role
getRole
; ([Coercion]
args_cos, [Type]
nargs, Coercion
res_co) <- Type -> [Role] -> [Type] -> NormM ([Coercion], [Type], Coercion)
normalise_args (TyCon -> Type
tyConKind TyCon
tc) (Role -> TyCon -> [Role]
tyConRolesX Role
role TyCon
tc) [Type]
tys
; (Coercion, [Type], Coercion) -> NormM (Coercion, [Type], Coercion)
forall (m :: * -> *) a. Monad m => a -> m a
return (HasDebugCallStack => Role -> TyCon -> [Coercion] -> Coercion
Role -> TyCon -> [Coercion] -> Coercion
mkTyConAppCo Role
role TyCon
tc [Coercion]
args_cos, [Type]
nargs, Coercion
res_co) }
normaliseType :: FamInstEnvs
-> Role
-> Type -> (Coercion, Type)
normaliseType :: (FamInstEnv, FamInstEnv) -> Role -> Type -> (Coercion, Type)
normaliseType (FamInstEnv, FamInstEnv)
env Role
role Type
ty
= (FamInstEnv, FamInstEnv)
-> Role -> VarSet -> NormM (Coercion, Type) -> (Coercion, Type)
forall a.
(FamInstEnv, FamInstEnv) -> Role -> VarSet -> NormM a -> a
initNormM (FamInstEnv, FamInstEnv)
env Role
role (Type -> VarSet
tyCoVarsOfType Type
ty) (NormM (Coercion, Type) -> (Coercion, Type))
-> NormM (Coercion, Type) -> (Coercion, Type)
forall a b. (a -> b) -> a -> b
$ Type -> NormM (Coercion, Type)
normalise_type Type
ty
normalise_type :: Type
-> NormM (Coercion, Type)
normalise_type :: Type -> NormM (Coercion, Type)
normalise_type Type
ty
= Type -> NormM (Coercion, Type)
go Type
ty
where
go :: Type -> NormM (Coercion, Type)
go (TyConApp TyCon
tc [Type]
tys) = TyCon -> [Type] -> NormM (Coercion, Type)
normalise_tc_app TyCon
tc [Type]
tys
go ty :: Type
ty@(LitTy {}) = do { Role
r <- NormM Role
getRole
; (Coercion, Type) -> NormM (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Role -> Type -> Coercion
mkReflCo Role
r Type
ty, Type
ty) }
go (AppTy Type
ty1 Type
ty2) = Type -> [Type] -> NormM (Coercion, Type)
go_app_tys Type
ty1 [Type
ty2]
go ty :: Type
ty@(FunTy { ft_mult :: Type -> Type
ft_mult = Type
w, ft_arg :: Type -> Type
ft_arg = Type
ty1, ft_res :: Type -> Type
ft_res = Type
ty2 })
= do { (Coercion
co1, Type
nty1) <- Type -> NormM (Coercion, Type)
go Type
ty1
; (Coercion
co2, Type
nty2) <- Type -> NormM (Coercion, Type)
go Type
ty2
; (Coercion
wco, Type
wty) <- Role -> NormM (Coercion, Type) -> NormM (Coercion, Type)
forall a. Role -> NormM a -> NormM a
withRole Role
Nominal (NormM (Coercion, Type) -> NormM (Coercion, Type))
-> NormM (Coercion, Type) -> NormM (Coercion, Type)
forall a b. (a -> b) -> a -> b
$ Type -> NormM (Coercion, Type)
go Type
w
; Role
r <- NormM Role
getRole
; (Coercion, Type) -> NormM (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Role -> Coercion -> Coercion -> Coercion -> Coercion
mkFunCo Role
r Coercion
wco Coercion
co1 Coercion
co2, Type
ty { ft_mult :: Type
ft_mult = Type
wty, ft_arg :: Type
ft_arg = Type
nty1, ft_res :: Type
ft_res = Type
nty2 }) }
go (ForAllTy (Bndr TyVar
tcvar ArgFlag
vis) Type
ty)
= do { (LiftingContext
lc', TyVar
tv', Coercion
h, Type
ki') <- TyVar -> NormM (LiftingContext, TyVar, Coercion, Type)
normalise_var_bndr TyVar
tcvar
; (Coercion
co, Type
nty) <- LiftingContext -> NormM (Coercion, Type) -> NormM (Coercion, Type)
forall a. LiftingContext -> NormM a -> NormM a
withLC LiftingContext
lc' (NormM (Coercion, Type) -> NormM (Coercion, Type))
-> NormM (Coercion, Type) -> NormM (Coercion, Type)
forall a b. (a -> b) -> a -> b
$ Type -> NormM (Coercion, Type)
normalise_type Type
ty
; let tv2 :: TyVar
tv2 = TyVar -> Type -> TyVar
setTyVarKind TyVar
tv' Type
ki'
; (Coercion, Type) -> NormM (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (TyVar -> Coercion -> Coercion -> Coercion
mkForAllCo TyVar
tv' Coercion
h Coercion
co, VarBndr TyVar ArgFlag -> Type -> Type
ForAllTy (TyVar -> ArgFlag -> VarBndr TyVar ArgFlag
forall var argf. var -> argf -> VarBndr var argf
Bndr TyVar
tv2 ArgFlag
vis) Type
nty) }
go (TyVarTy TyVar
tv) = TyVar -> NormM (Coercion, Type)
normalise_tyvar TyVar
tv
go (CastTy Type
ty Coercion
co)
= do { (Coercion
nco, Type
nty) <- Type -> NormM (Coercion, Type)
go Type
ty
; LiftingContext
lc <- NormM LiftingContext
getLC
; let co' :: Coercion
co' = LiftingContext -> Coercion -> Coercion
substRightCo LiftingContext
lc Coercion
co
; (Coercion, Type) -> NormM (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Coercion
-> Role -> Type -> Type -> Coercion -> Coercion -> Coercion
castCoercionKind2 Coercion
nco Role
Nominal Type
ty Type
nty Coercion
co Coercion
co'
, Type -> Coercion -> Type
mkCastTy Type
nty Coercion
co') }
go (CoercionTy Coercion
co)
= do { LiftingContext
lc <- NormM LiftingContext
getLC
; Role
r <- NormM Role
getRole
; let right_co :: Coercion
right_co = LiftingContext -> Coercion -> Coercion
substRightCo LiftingContext
lc Coercion
co
; (Coercion, Type) -> NormM (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return ( Role -> Coercion -> Coercion -> Coercion -> Coercion
mkProofIrrelCo Role
r
(HasDebugCallStack => Role -> LiftingContext -> Type -> Coercion
Role -> LiftingContext -> Type -> Coercion
liftCoSubst Role
Nominal LiftingContext
lc (Coercion -> Type
coercionType Coercion
co))
Coercion
co Coercion
right_co
, Coercion -> Type
mkCoercionTy Coercion
right_co ) }
go_app_tys :: Type
-> [Type]
-> NormM (Coercion, Type)
go_app_tys :: Type -> [Type] -> NormM (Coercion, Type)
go_app_tys (AppTy Type
ty1 Type
ty2) [Type]
tys = Type -> [Type] -> NormM (Coercion, Type)
go_app_tys Type
ty1 (Type
ty2 Type -> [Type] -> [Type]
forall a. a -> [a] -> [a]
: [Type]
tys)
go_app_tys Type
fun_ty [Type]
arg_tys
= do { (Coercion
fun_co, Type
nfun) <- Type -> NormM (Coercion, Type)
go Type
fun_ty
; case HasCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
tcSplitTyConApp_maybe Type
nfun of
Just (TyCon
tc, [Type]
xis) ->
do { (Coercion
second_co, Type
nty) <- Type -> NormM (Coercion, Type)
go (TyCon -> [Type] -> Type
mkTyConApp TyCon
tc ([Type]
xis [Type] -> [Type] -> [Type]
forall a. [a] -> [a] -> [a]
++ [Type]
arg_tys))
; (Coercion, Type) -> NormM (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Coercion -> [Coercion] -> Coercion
mkAppCos Coercion
fun_co ((Type -> Coercion) -> [Type] -> [Coercion]
forall a b. (a -> b) -> [a] -> [b]
map Type -> Coercion
mkNomReflCo [Type]
arg_tys) Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
second_co, Type
nty) }
Maybe (TyCon, [Type])
Nothing ->
do { ([Coercion]
args_cos, [Type]
nargs, Coercion
res_co) <- Type -> [Role] -> [Type] -> NormM ([Coercion], [Type], Coercion)
normalise_args (HasDebugCallStack => Type -> Type
Type -> Type
typeKind Type
nfun)
(Role -> [Role]
forall a. a -> [a]
repeat Role
Nominal)
[Type]
arg_tys
; Role
role <- NormM Role
getRole
; let nty :: Type
nty = Type -> [Type] -> Type
mkAppTys Type
nfun [Type]
nargs
nco :: Coercion
nco = Coercion -> [Coercion] -> Coercion
mkAppCos Coercion
fun_co [Coercion]
args_cos
nty_casted :: Type
nty_casted = Type
nty Type -> Coercion -> Type
`mkCastTy` Coercion -> Coercion
mkSymCo Coercion
res_co
final_co :: Coercion
final_co = Role -> Type -> Coercion -> Coercion -> Coercion
mkCoherenceRightCo Role
role Type
nty (Coercion -> Coercion
mkSymCo Coercion
res_co) Coercion
nco
; (Coercion, Type) -> NormM (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Coercion
final_co, Type
nty_casted) } }
normalise_args :: Kind
-> [Role]
-> [Type]
-> NormM ([Coercion], [Type], Coercion)
normalise_args :: Type -> [Role] -> [Type] -> NormM ([Coercion], [Type], Coercion)
normalise_args Type
fun_ki [Role]
roles [Type]
args
= do { [(Type, Coercion)]
normed_args <- (Role -> Type -> NormM (Type, Coercion))
-> [Role] -> [Type] -> NormM [(Type, Coercion)]
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM Role -> Type -> NormM (Type, Coercion)
normalise1 [Role]
roles [Type]
args
; let ([Type]
xis, [Coercion]
cos, Coercion
res_co) = [TyCoBinder]
-> Type
-> VarSet
-> [Role]
-> [(Type, Coercion)]
-> ([Type], [Coercion], Coercion)
simplifyArgsWorker [TyCoBinder]
ki_binders Type
inner_ki VarSet
fvs [Role]
roles [(Type, Coercion)]
normed_args
; ([Coercion], [Type], Coercion)
-> NormM ([Coercion], [Type], Coercion)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Coercion -> Coercion) -> [Coercion] -> [Coercion]
forall a b. (a -> b) -> [a] -> [b]
map Coercion -> Coercion
mkSymCo [Coercion]
cos, [Type]
xis, Coercion -> Coercion
mkSymCo Coercion
res_co) }
where
([TyCoBinder]
ki_binders, Type
inner_ki) = Type -> ([TyCoBinder], Type)
splitPiTys Type
fun_ki
fvs :: VarSet
fvs = [Type] -> VarSet
tyCoVarsOfTypes [Type]
args
impedance_match :: NormM (Coercion, Type) -> NormM (Type, Coercion)
impedance_match :: NormM (Coercion, Type) -> NormM (Type, Coercion)
impedance_match NormM (Coercion, Type)
action = do { (Coercion
co, Type
ty) <- NormM (Coercion, Type)
action
; (Type, Coercion) -> NormM (Type, Coercion)
forall (m :: * -> *) a. Monad m => a -> m a
return (Type
ty, Coercion -> Coercion
mkSymCo Coercion
co) }
normalise1 :: Role -> Type -> NormM (Type, Coercion)
normalise1 Role
role Type
ty
= NormM (Coercion, Type) -> NormM (Type, Coercion)
impedance_match (NormM (Coercion, Type) -> NormM (Type, Coercion))
-> NormM (Coercion, Type) -> NormM (Type, Coercion)
forall a b. (a -> b) -> a -> b
$ Role -> NormM (Coercion, Type) -> NormM (Coercion, Type)
forall a. Role -> NormM a -> NormM a
withRole Role
role (NormM (Coercion, Type) -> NormM (Coercion, Type))
-> NormM (Coercion, Type) -> NormM (Coercion, Type)
forall a b. (a -> b) -> a -> b
$ Type -> NormM (Coercion, Type)
normalise_type Type
ty
normalise_tyvar :: TyVar -> NormM (Coercion, Type)
normalise_tyvar :: TyVar -> NormM (Coercion, Type)
normalise_tyvar TyVar
tv
= ASSERT( isTyVar tv )
do { LiftingContext
lc <- NormM LiftingContext
getLC
; Role
r <- NormM Role
getRole
; (Coercion, Type) -> NormM (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Coercion, Type) -> NormM (Coercion, Type))
-> (Coercion, Type) -> NormM (Coercion, Type)
forall a b. (a -> b) -> a -> b
$ case LiftingContext -> Role -> TyVar -> Maybe Coercion
liftCoSubstTyVar LiftingContext
lc Role
r TyVar
tv of
Just Coercion
co -> (Coercion
co, Coercion -> Type
coercionRKind Coercion
co)
Maybe Coercion
Nothing -> (Role -> Type -> Coercion
mkReflCo Role
r Type
ty, Type
ty) }
where ty :: Type
ty = TyVar -> Type
mkTyVarTy TyVar
tv
normalise_var_bndr :: TyCoVar -> NormM (LiftingContext, TyCoVar, Coercion, Kind)
normalise_var_bndr :: TyVar -> NormM (LiftingContext, TyVar, Coercion, Type)
normalise_var_bndr TyVar
tcvar
= do { LiftingContext
lc1 <- NormM LiftingContext
getLC
; (FamInstEnv, FamInstEnv)
env <- NormM (FamInstEnv, FamInstEnv)
getEnv
; let callback :: LiftingContext -> Type -> (Coercion, Type)
callback LiftingContext
lc Type
ki = NormM (Coercion, Type)
-> (FamInstEnv, FamInstEnv)
-> LiftingContext
-> Role
-> (Coercion, Type)
forall a.
NormM a -> (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a
runNormM (Type -> NormM (Coercion, Type)
normalise_type Type
ki) (FamInstEnv, FamInstEnv)
env LiftingContext
lc Role
Nominal
; (LiftingContext, TyVar, Coercion, Type)
-> NormM (LiftingContext, TyVar, Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return ((LiftingContext, TyVar, Coercion, Type)
-> NormM (LiftingContext, TyVar, Coercion, Type))
-> (LiftingContext, TyVar, Coercion, Type)
-> NormM (LiftingContext, TyVar, Coercion, Type)
forall a b. (a -> b) -> a -> b
$ (LiftingContext -> Type -> (Coercion, Type))
-> LiftingContext
-> TyVar
-> (LiftingContext, TyVar, Coercion, Type)
forall a.
(LiftingContext -> Type -> (Coercion, a))
-> LiftingContext -> TyVar -> (LiftingContext, TyVar, Coercion, a)
liftCoSubstVarBndrUsing LiftingContext -> Type -> (Coercion, Type)
callback LiftingContext
lc1 TyVar
tcvar }
newtype NormM a = NormM { forall a.
NormM a -> (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a
runNormM ::
FamInstEnvs -> LiftingContext -> Role -> a }
deriving ((forall a b. (a -> b) -> NormM a -> NormM b)
-> (forall a b. a -> NormM b -> NormM a) -> Functor NormM
forall a b. a -> NormM b -> NormM a
forall a b. (a -> b) -> NormM a -> NormM b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> NormM b -> NormM a
$c<$ :: forall a b. a -> NormM b -> NormM a
fmap :: forall a b. (a -> b) -> NormM a -> NormM b
$cfmap :: forall a b. (a -> b) -> NormM a -> NormM b
Functor)
initNormM :: FamInstEnvs -> Role
-> TyCoVarSet
-> NormM a -> a
initNormM :: forall a.
(FamInstEnv, FamInstEnv) -> Role -> VarSet -> NormM a -> a
initNormM (FamInstEnv, FamInstEnv)
env Role
role VarSet
vars (NormM (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a
thing_inside)
= (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a
thing_inside (FamInstEnv, FamInstEnv)
env LiftingContext
lc Role
role
where
in_scope :: InScopeSet
in_scope = VarSet -> InScopeSet
mkInScopeSet VarSet
vars
lc :: LiftingContext
lc = InScopeSet -> LiftingContext
emptyLiftingContext InScopeSet
in_scope
getRole :: NormM Role
getRole :: NormM Role
getRole = ((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> Role)
-> NormM Role
forall a.
((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
NormM (\ (FamInstEnv, FamInstEnv)
_ LiftingContext
_ Role
r -> Role
r)
getLC :: NormM LiftingContext
getLC :: NormM LiftingContext
getLC = ((FamInstEnv, FamInstEnv)
-> LiftingContext -> Role -> LiftingContext)
-> NormM LiftingContext
forall a.
((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
NormM (\ (FamInstEnv, FamInstEnv)
_ LiftingContext
lc Role
_ -> LiftingContext
lc)
getEnv :: NormM FamInstEnvs
getEnv :: NormM (FamInstEnv, FamInstEnv)
getEnv = ((FamInstEnv, FamInstEnv)
-> LiftingContext -> Role -> (FamInstEnv, FamInstEnv))
-> NormM (FamInstEnv, FamInstEnv)
forall a.
((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
NormM (\ (FamInstEnv, FamInstEnv)
env LiftingContext
_ Role
_ -> (FamInstEnv, FamInstEnv)
env)
withRole :: Role -> NormM a -> NormM a
withRole :: forall a. Role -> NormM a -> NormM a
withRole Role
r NormM a
thing = ((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
forall a.
((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
NormM (((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a)
-> ((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
forall a b. (a -> b) -> a -> b
$ \ (FamInstEnv, FamInstEnv)
envs LiftingContext
lc Role
_old_r -> NormM a -> (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a
forall a.
NormM a -> (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a
runNormM NormM a
thing (FamInstEnv, FamInstEnv)
envs LiftingContext
lc Role
r
withLC :: LiftingContext -> NormM a -> NormM a
withLC :: forall a. LiftingContext -> NormM a -> NormM a
withLC LiftingContext
lc NormM a
thing = ((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
forall a.
((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
NormM (((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a)
-> ((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
forall a b. (a -> b) -> a -> b
$ \ (FamInstEnv, FamInstEnv)
envs LiftingContext
_old_lc Role
r -> NormM a -> (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a
forall a.
NormM a -> (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a
runNormM NormM a
thing (FamInstEnv, FamInstEnv)
envs LiftingContext
lc Role
r
instance Monad NormM where
NormM a
ma >>= :: forall a b. NormM a -> (a -> NormM b) -> NormM b
>>= a -> NormM b
fmb = ((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> b)
-> NormM b
forall a.
((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
NormM (((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> b)
-> NormM b)
-> ((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> b)
-> NormM b
forall a b. (a -> b) -> a -> b
$ \(FamInstEnv, FamInstEnv)
env LiftingContext
lc Role
r ->
let a :: a
a = NormM a -> (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a
forall a.
NormM a -> (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a
runNormM NormM a
ma (FamInstEnv, FamInstEnv)
env LiftingContext
lc Role
r in
NormM b -> (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> b
forall a.
NormM a -> (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a
runNormM (a -> NormM b
fmb a
a) (FamInstEnv, FamInstEnv)
env LiftingContext
lc Role
r
instance Applicative NormM where
pure :: forall a. a -> NormM a
pure a
x = ((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
forall a.
((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
NormM (((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a)
-> ((FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a)
-> NormM a
forall a b. (a -> b) -> a -> b
$ \ (FamInstEnv, FamInstEnv)
_ LiftingContext
_ Role
_ -> a
x
<*> :: forall a b. NormM (a -> b) -> NormM a -> NormM b
(<*>) = NormM (a -> b) -> NormM a -> NormM b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
data FlattenEnv
= FlattenEnv { FlattenEnv -> TypeMap TyVar
fe_type_map :: TypeMap TyVar
, FlattenEnv -> InScopeSet
fe_in_scope :: InScopeSet }
emptyFlattenEnv :: InScopeSet -> FlattenEnv
emptyFlattenEnv :: InScopeSet -> FlattenEnv
emptyFlattenEnv InScopeSet
in_scope
= FlattenEnv :: TypeMap TyVar -> InScopeSet -> FlattenEnv
FlattenEnv { fe_type_map :: TypeMap TyVar
fe_type_map = TypeMap TyVar
forall a. TypeMap a
emptyTypeMap
, fe_in_scope :: InScopeSet
fe_in_scope = InScopeSet
in_scope }
updateInScopeSet :: FlattenEnv -> (InScopeSet -> InScopeSet) -> FlattenEnv
updateInScopeSet :: FlattenEnv -> (InScopeSet -> InScopeSet) -> FlattenEnv
updateInScopeSet FlattenEnv
env InScopeSet -> InScopeSet
upd = FlattenEnv
env { fe_in_scope :: InScopeSet
fe_in_scope = InScopeSet -> InScopeSet
upd (FlattenEnv -> InScopeSet
fe_in_scope FlattenEnv
env) }
flattenTys :: InScopeSet -> [Type] -> [Type]
flattenTys :: InScopeSet -> [Type] -> [Type]
flattenTys InScopeSet
in_scope [Type]
tys
= (FlattenEnv, [Type]) -> [Type]
forall a b. (a, b) -> b
snd ((FlattenEnv, [Type]) -> [Type]) -> (FlattenEnv, [Type]) -> [Type]
forall a b. (a -> b) -> a -> b
$ TvSubstEnv -> FlattenEnv -> [Type] -> (FlattenEnv, [Type])
coreFlattenTys TvSubstEnv
emptyTvSubstEnv (InScopeSet -> FlattenEnv
emptyFlattenEnv InScopeSet
in_scope) [Type]
tys
coreFlattenTys :: TvSubstEnv -> FlattenEnv
-> [Type] -> (FlattenEnv, [Type])
coreFlattenTys :: TvSubstEnv -> FlattenEnv -> [Type] -> (FlattenEnv, [Type])
coreFlattenTys TvSubstEnv
subst = (FlattenEnv -> Type -> (FlattenEnv, Type))
-> FlattenEnv -> [Type] -> (FlattenEnv, [Type])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL (TvSubstEnv -> FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy TvSubstEnv
subst)
coreFlattenTy :: TvSubstEnv -> FlattenEnv
-> Type -> (FlattenEnv, Type)
coreFlattenTy :: TvSubstEnv -> FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy TvSubstEnv
subst = FlattenEnv -> Type -> (FlattenEnv, Type)
go
where
go :: FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty | Just Type
ty' <- Type -> Maybe Type
coreView Type
ty = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty'
go FlattenEnv
env (TyVarTy TyVar
tv)
| Just Type
ty <- TvSubstEnv -> TyVar -> Maybe Type
forall a. VarEnv a -> TyVar -> Maybe a
lookupVarEnv TvSubstEnv
subst TyVar
tv = (FlattenEnv
env, Type
ty)
| Bool
otherwise = let (FlattenEnv
env', Type
ki) = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env (TyVar -> Type
tyVarKind TyVar
tv) in
(FlattenEnv
env', TyVar -> Type
mkTyVarTy (TyVar -> Type) -> TyVar -> Type
forall a b. (a -> b) -> a -> b
$ TyVar -> Type -> TyVar
setTyVarKind TyVar
tv Type
ki)
go FlattenEnv
env (AppTy Type
ty1 Type
ty2) = let (FlattenEnv
env1, Type
ty1') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty1
(FlattenEnv
env2, Type
ty2') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env1 Type
ty2 in
(FlattenEnv
env2, Type -> Type -> Type
AppTy Type
ty1' Type
ty2')
go FlattenEnv
env (TyConApp TyCon
tc [Type]
tys)
| Bool -> Bool
not (TyCon -> Role -> Bool
isGenerativeTyCon TyCon
tc Role
Nominal)
= TvSubstEnv -> FlattenEnv -> TyCon -> [Type] -> (FlattenEnv, Type)
coreFlattenTyFamApp TvSubstEnv
subst FlattenEnv
env TyCon
tc [Type]
tys
| Bool
otherwise
= let (FlattenEnv
env', [Type]
tys') = TvSubstEnv -> FlattenEnv -> [Type] -> (FlattenEnv, [Type])
coreFlattenTys TvSubstEnv
subst FlattenEnv
env [Type]
tys in
(FlattenEnv
env', TyCon -> [Type] -> Type
mkTyConApp TyCon
tc [Type]
tys')
go FlattenEnv
env ty :: Type
ty@(FunTy { ft_mult :: Type -> Type
ft_mult = Type
mult, ft_arg :: Type -> Type
ft_arg = Type
ty1, ft_res :: Type -> Type
ft_res = Type
ty2 })
= let (FlattenEnv
env1, Type
ty1') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty1
(FlattenEnv
env2, Type
ty2') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env1 Type
ty2
(FlattenEnv
env3, Type
mult') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env2 Type
mult in
(FlattenEnv
env3, Type
ty { ft_mult :: Type
ft_mult = Type
mult', ft_arg :: Type
ft_arg = Type
ty1', ft_res :: Type
ft_res = Type
ty2' })
go FlattenEnv
env (ForAllTy (Bndr TyVar
tv ArgFlag
vis) Type
ty)
= let (FlattenEnv
env1, TvSubstEnv
subst', TyVar
tv') = TvSubstEnv
-> FlattenEnv -> TyVar -> (FlattenEnv, TvSubstEnv, TyVar)
coreFlattenVarBndr TvSubstEnv
subst FlattenEnv
env TyVar
tv
(FlattenEnv
env2, Type
ty') = TvSubstEnv -> FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy TvSubstEnv
subst' FlattenEnv
env1 Type
ty in
(FlattenEnv
env2, VarBndr TyVar ArgFlag -> Type -> Type
ForAllTy (TyVar -> ArgFlag -> VarBndr TyVar ArgFlag
forall var argf. var -> argf -> VarBndr var argf
Bndr TyVar
tv' ArgFlag
vis) Type
ty')
go FlattenEnv
env ty :: Type
ty@(LitTy {}) = (FlattenEnv
env, Type
ty)
go FlattenEnv
env (CastTy Type
ty Coercion
co)
= let (FlattenEnv
env1, Type
ty') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty
(FlattenEnv
env2, Coercion
co') = TvSubstEnv -> FlattenEnv -> Coercion -> (FlattenEnv, Coercion)
coreFlattenCo TvSubstEnv
subst FlattenEnv
env1 Coercion
co in
(FlattenEnv
env2, Type -> Coercion -> Type
CastTy Type
ty' Coercion
co')
go FlattenEnv
env (CoercionTy Coercion
co)
= let (FlattenEnv
env', Coercion
co') = TvSubstEnv -> FlattenEnv -> Coercion -> (FlattenEnv, Coercion)
coreFlattenCo TvSubstEnv
subst FlattenEnv
env Coercion
co in
(FlattenEnv
env', Coercion -> Type
CoercionTy Coercion
co')
coreFlattenCo :: TvSubstEnv -> FlattenEnv
-> Coercion -> (FlattenEnv, Coercion)
coreFlattenCo :: TvSubstEnv -> FlattenEnv -> Coercion -> (FlattenEnv, Coercion)
coreFlattenCo TvSubstEnv
subst FlattenEnv
env Coercion
co
= (FlattenEnv
env2, TyVar -> Coercion
mkCoVarCo TyVar
covar)
where
(FlattenEnv
env1, Type
kind') = TvSubstEnv -> FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy TvSubstEnv
subst FlattenEnv
env (Coercion -> Type
coercionType Coercion
co)
covar :: TyVar
covar = InScopeSet -> Type -> TyVar
mkFlattenFreshCoVar (FlattenEnv -> InScopeSet
fe_in_scope FlattenEnv
env1) Type
kind'
env2 :: FlattenEnv
env2 = FlattenEnv -> (InScopeSet -> InScopeSet) -> FlattenEnv
updateInScopeSet FlattenEnv
env1 ((InScopeSet -> TyVar -> InScopeSet)
-> TyVar -> InScopeSet -> InScopeSet
forall a b c. (a -> b -> c) -> b -> a -> c
flip InScopeSet -> TyVar -> InScopeSet
extendInScopeSet TyVar
covar)
coreFlattenVarBndr :: TvSubstEnv -> FlattenEnv
-> TyCoVar -> (FlattenEnv, TvSubstEnv, TyVar)
coreFlattenVarBndr :: TvSubstEnv
-> FlattenEnv -> TyVar -> (FlattenEnv, TvSubstEnv, TyVar)
coreFlattenVarBndr TvSubstEnv
subst FlattenEnv
env TyVar
tv
= (FlattenEnv
env2, TvSubstEnv
subst', TyVar
tv')
where
kind :: Type
kind = TyVar -> Type
varType TyVar
tv
(FlattenEnv
env1, Type
kind') = TvSubstEnv -> FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy TvSubstEnv
subst FlattenEnv
env Type
kind
tv' :: TyVar
tv' = InScopeSet -> TyVar -> TyVar
uniqAway (FlattenEnv -> InScopeSet
fe_in_scope FlattenEnv
env1) (TyVar -> Type -> TyVar
setVarType TyVar
tv Type
kind')
subst' :: TvSubstEnv
subst' = TvSubstEnv -> TyVar -> Type -> TvSubstEnv
forall a. VarEnv a -> TyVar -> a -> VarEnv a
extendVarEnv TvSubstEnv
subst TyVar
tv (TyVar -> Type
mkTyVarTy TyVar
tv')
env2 :: FlattenEnv
env2 = FlattenEnv -> (InScopeSet -> InScopeSet) -> FlattenEnv
updateInScopeSet FlattenEnv
env1 ((InScopeSet -> TyVar -> InScopeSet)
-> TyVar -> InScopeSet -> InScopeSet
forall a b c. (a -> b -> c) -> b -> a -> c
flip InScopeSet -> TyVar -> InScopeSet
extendInScopeSet TyVar
tv')
coreFlattenTyFamApp :: TvSubstEnv -> FlattenEnv
-> TyCon
-> [Type]
-> (FlattenEnv, Type)
coreFlattenTyFamApp :: TvSubstEnv -> FlattenEnv -> TyCon -> [Type] -> (FlattenEnv, Type)
coreFlattenTyFamApp TvSubstEnv
tv_subst FlattenEnv
env TyCon
fam_tc [Type]
fam_args
= case TypeMap TyVar -> Type -> Maybe TyVar
forall a. TypeMap a -> Type -> Maybe a
lookupTypeMap TypeMap TyVar
type_map Type
fam_ty of
Just TyVar
tv -> (FlattenEnv
env', Type -> [Type] -> Type
mkAppTys (TyVar -> Type
mkTyVarTy TyVar
tv) [Type]
leftover_args')
Maybe TyVar
Nothing -> let tyvar_name :: Name
tyvar_name = TyCon -> Name
forall a. Uniquable a => a -> Name
mkFlattenFreshTyName TyCon
fam_tc
tv :: TyVar
tv = InScopeSet -> TyVar -> TyVar
uniqAway InScopeSet
in_scope (TyVar -> TyVar) -> TyVar -> TyVar
forall a b. (a -> b) -> a -> b
$
Name -> Type -> TyVar
mkTyVar Name
tyvar_name (HasDebugCallStack => Type -> Type
Type -> Type
typeKind Type
fam_ty)
ty' :: Type
ty' = Type -> [Type] -> Type
mkAppTys (TyVar -> Type
mkTyVarTy TyVar
tv) [Type]
leftover_args'
env'' :: FlattenEnv
env'' = FlattenEnv
env' { fe_type_map :: TypeMap TyVar
fe_type_map = TypeMap TyVar -> Type -> TyVar -> TypeMap TyVar
forall a. TypeMap a -> Type -> a -> TypeMap a
extendTypeMap TypeMap TyVar
type_map Type
fam_ty TyVar
tv
, fe_in_scope :: InScopeSet
fe_in_scope = InScopeSet -> TyVar -> InScopeSet
extendInScopeSet InScopeSet
in_scope TyVar
tv }
in (FlattenEnv
env'', Type
ty')
where
arity :: Arity
arity = TyCon -> Arity
tyConArity TyCon
fam_tc
tcv_subst :: TCvSubst
tcv_subst = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
TCvSubst (FlattenEnv -> InScopeSet
fe_in_scope FlattenEnv
env) TvSubstEnv
tv_subst CvSubstEnv
forall a. VarEnv a
emptyVarEnv
([Type]
sat_fam_args, [Type]
leftover_args) = ASSERT( arity <= length fam_args )
Arity -> [Type] -> ([Type], [Type])
forall a. Arity -> [a] -> ([a], [a])
splitAt Arity
arity [Type]
fam_args
sat_fam_args' :: [Type]
sat_fam_args' = HasCallStack => TCvSubst -> [Type] -> [Type]
TCvSubst -> [Type] -> [Type]
substTys TCvSubst
tcv_subst [Type]
sat_fam_args
(FlattenEnv
env', [Type]
leftover_args') = TvSubstEnv -> FlattenEnv -> [Type] -> (FlattenEnv, [Type])
coreFlattenTys TvSubstEnv
tv_subst FlattenEnv
env [Type]
leftover_args
fam_ty :: Type
fam_ty = TyCon -> [Type] -> Type
mkTyConApp TyCon
fam_tc [Type]
sat_fam_args'
FlattenEnv { fe_type_map :: FlattenEnv -> TypeMap TyVar
fe_type_map = TypeMap TyVar
type_map
, fe_in_scope :: FlattenEnv -> InScopeSet
fe_in_scope = InScopeSet
in_scope } = FlattenEnv
env'
mkFlattenFreshTyName :: Uniquable a => a -> Name
mkFlattenFreshTyName :: forall a. Uniquable a => a -> Name
mkFlattenFreshTyName a
unq
= Unique -> FastString -> Name
mkSysTvName (a -> Unique
forall a. Uniquable a => a -> Unique
getUnique a
unq) (String -> FastString
fsLit String
"flt")
mkFlattenFreshCoVar :: InScopeSet -> Kind -> CoVar
mkFlattenFreshCoVar :: InScopeSet -> Type -> TyVar
mkFlattenFreshCoVar InScopeSet
in_scope Type
kind
= let uniq :: Unique
uniq = InScopeSet -> Unique
unsafeGetFreshLocalUnique InScopeSet
in_scope
name :: Name
name = Unique -> FastString -> Name
mkSystemVarName Unique
uniq (String -> FastString
fsLit String
"flc")
in Name -> Type -> TyVar
mkCoVar Name
name Type
kind