{-# LANGUAGE CPP, GADTs, ScopedTypeVariables, BangPatterns, TupleSections,
DeriveFunctor #-}
module 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, normaliseTcArgs,
reduceTyFamApp_maybe,
flattenTys
) where
#include "GhclibHsVersions.h"
import GhcPrelude
import Unify
import Type
import TyCoRep
import TyCon
import Coercion
import CoAxiom
import VarSet
import VarEnv
import Name
import PrelNames ( eqPrimTyConKey )
import UniqDFM
import Outputable
import Maybes
import CoreMap
import Unique
import Util
import Var
import Pair
import SrcLoc
import 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 -> Int -> 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))
Int
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 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)
emptyFamInstEnvs :: (FamInstEnv, FamInstEnv)
emptyFamInstEnvs :: (FamInstEnv, FamInstEnv)
emptyFamInstEnvs = (FamInstEnv
emptyFamInstEnv, FamInstEnv
emptyFamInstEnv)
emptyFamInstEnv :: FamInstEnv
emptyFamInstEnv :: FamInstEnv
emptyFamInstEnv = FamInstEnv
forall elt. UniqDFM elt
emptyUDFM
famInstEnvElts :: FamInstEnv -> [FamInst]
famInstEnvElts :: FamInstEnv -> [FamInst]
famInstEnvElts FamInstEnv
fi = [FamInst
elt | FamIE [FamInst]
elts <- FamInstEnv -> [FamilyInstEnv]
forall elt. UniqDFM elt -> [elt]
eltsUDFM FamInstEnv
fi, FamInst
elt <- [FamInst]
elts]
famInstEnvSize :: FamInstEnv -> Int
famInstEnvSize :: FamInstEnv -> Int
famInstEnvSize = (FamilyInstEnv -> Int -> Int) -> Int -> FamInstEnv -> Int
forall elt a. (elt -> a -> a) -> a -> UniqDFM elt -> a
nonDetFoldUDFM (\(FamIE [FamInst]
elt) Int
sum -> Int
sum Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [FamInst] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FamInst]
elt) Int
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 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})
= (FamilyInstEnv -> FamilyInstEnv -> FamilyInstEnv)
-> FamInstEnv -> Name -> FamilyInstEnv -> FamInstEnv
forall key elt.
Uniquable key =>
(elt -> elt -> elt) -> UniqDFM elt -> key -> elt -> UniqDFM elt
addToUDFM_C FamilyInstEnv -> FamilyInstEnv -> FamilyInstEnv
add 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 :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
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 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 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 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) = Int -> [Type] -> ([Type], [Type])
forall a. Int -> [a] -> ([a], [a])
splitAt (TyCon -> Int
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 = Pair Type -> Type
forall a. Pair a -> a
pSnd (Coercion -> Pair Type
coercionKind 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 (Int
ind, [Type]
inst_tys, [Coercion]
inst_cos) <- CoAxiom Branched -> [Type] -> Maybe (Int, [Type], [Coercion])
chooseBranch CoAxiom Branched
ax [Type]
tys
= let co :: Coercion
co = Role -> CoAxiom Branched -> Int -> [Type] -> [Coercion] -> Coercion
forall (br :: BranchFlag).
Role -> CoAxiom br -> Int -> [Type] -> [Coercion] -> Coercion
mkAxInstCo Role
role CoAxiom Branched
ax Int
ind [Type]
inst_tys [Coercion]
inst_cos
ty :: Type
ty = Pair Type -> Type
forall a. Pair a -> a
pSnd (Coercion -> Pair Type
coercionKind 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 (Int, [Type], [Coercion])
chooseBranch CoAxiom Branched
axiom [Type]
tys
= do { let num_pats :: Int
num_pats = CoAxiom Branched -> Int
forall (br :: BranchFlag). CoAxiom br -> Int
coAxiomNumPats CoAxiom Branched
axiom
([Type]
target_tys, [Type]
extra_tys) = Int -> [Type] -> ([Type], [Type])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
num_pats [Type]
tys
branches :: Branches Branched
branches = CoAxiom Branched -> Branches Branched
forall (br :: BranchFlag). CoAxiom br -> Branches br
coAxiomBranches CoAxiom Branched
axiom
; (Int
ind, [Type]
inst_tys, [Coercion]
inst_cos)
<- Array Int CoAxBranch -> [Type] -> Maybe (Int, [Type], [Coercion])
findBranch (Branches Branched -> Array Int CoAxBranch
forall (br :: BranchFlag). Branches br -> Array Int CoAxBranch
unMkBranches Branches Branched
branches) [Type]
target_tys
; (Int, [Type], [Coercion]) -> Maybe (Int, [Type], [Coercion])
forall (m :: * -> *) a. Monad m => a -> m a
return ( Int
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 Int CoAxBranch -> [Type] -> Maybe (Int, [Type], [Coercion])
findBranch Array Int CoAxBranch
branches [Type]
target_tys
= ((Int, CoAxBranch)
-> Maybe (Int, [Type], [Coercion])
-> Maybe (Int, [Type], [Coercion]))
-> Maybe (Int, [Type], [Coercion])
-> [(Int, CoAxBranch)]
-> Maybe (Int, [Type], [Coercion])
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Int, CoAxBranch)
-> Maybe (Int, [Type], [Coercion])
-> Maybe (Int, [Type], [Coercion])
go Maybe (Int, [Type], [Coercion])
forall a. Maybe a
Nothing (Array Int CoAxBranch -> [(Int, CoAxBranch)]
forall i e. Ix i => Array i e -> [(i, e)]
assocs Array Int CoAxBranch
branches)
where
go :: (BranchIndex, CoAxBranch)
-> Maybe (BranchIndex, [Type], [Coercion])
-> Maybe (BranchIndex, [Type], [Coercion])
go :: (Int, CoAxBranch)
-> Maybe (Int, [Type], [Coercion])
-> Maybe (Int, [Type], [Coercion])
go (Int
index, CoAxBranch
branch) Maybe (Int, [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 )
(Int, [Type], [Coercion]) -> Maybe (Int, [Type], [Coercion])
forall a. a -> Maybe a
Just (Int
index, TCvSubst -> [TyVar] -> [Type]
substTyVars TCvSubst
subst [TyVar]
tpl_tvs, TCvSubst -> [TyVar] -> [Coercion]
substCoVars TCvSubst
subst [TyVar]
tpl_cvs)
Maybe TCvSubst
_ -> Maybe (Int, [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
= let (Coercion
args_co, [Type]
ntys, Coercion
res_co) = (FamInstEnv, FamInstEnv)
-> Role -> TyCon -> [Type] -> (Coercion, [Type], Coercion)
normaliseTcArgs (FamInstEnv, FamInstEnv)
env Role
Representational TyCon
tc [Type]
tys in
case (FamInstEnv, FamInstEnv)
-> Role -> TyCon -> [Type] -> Maybe (Coercion, Type)
reduceTyFamApp_maybe (FamInstEnv, FamInstEnv)
env Role
Representational TyCon
tc [Type]
ntys of
Just (Coercion
co, Type
rhs) -> RecTcChecker
-> Type
-> (Coercion, MCoercionN)
-> NormaliseStepResult (Coercion, MCoercionN)
forall ev. RecTcChecker -> Type -> ev -> NormaliseStepResult ev
NS_Step RecTcChecker
rec_nts Type
rhs (Coercion
args_co Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
co, Coercion -> MCoercionN
MCo Coercion
res_co)
Maybe (Coercion, Type)
_ -> 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
normaliseTcArgs :: FamInstEnvs
-> Role
-> TyCon
-> [Type]
-> (Coercion, [Type], CoercionN)
normaliseTcArgs :: (FamInstEnv, FamInstEnv)
-> Role -> TyCon -> [Type] -> (Coercion, [Type], Coercion)
normaliseTcArgs (FamInstEnv, FamInstEnv)
env Role
role TyCon
tc [Type]
tys
= (FamInstEnv, FamInstEnv)
-> Role
-> VarSet
-> NormM (Coercion, [Type], Coercion)
-> (Coercion, [Type], Coercion)
forall a.
(FamInstEnv, FamInstEnv) -> Role -> VarSet -> NormM a -> a
initNormM (FamInstEnv, FamInstEnv)
env Role
role ([Type] -> VarSet
tyCoVarsOfTypes [Type]
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
tc [Type]
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_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
; Role
r <- NormM Role
getRole
; (Coercion, Type) -> NormM (Coercion, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Role -> Coercion -> Coercion -> Coercion
mkFunCo Role
r Coercion
co1 Coercion
co2, Type
ty { 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
castCoercionKind 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, Pair Type -> Type
forall a. Pair a -> a
pSnd (Pair Type -> Type) -> Pair Type -> Type
forall a b. (a -> b) -> a -> b
$ Coercion -> Pair Type
coercionKind 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 { NormM a -> (FamInstEnv, FamInstEnv) -> LiftingContext -> Role -> a
runNormM ::
FamInstEnvs -> LiftingContext -> Role -> a }
deriving (a -> NormM b -> NormM a
(a -> b) -> NormM a -> NormM b
(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
<$ :: a -> NormM b -> NormM a
$c<$ :: forall a b. a -> NormM b -> NormM a
fmap :: (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 :: (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 :: 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 :: 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 >>= :: 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 :: 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
<*> :: 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 :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
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_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 in
(FlattenEnv
env2, Type
ty { 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
fresh_name :: Name
fresh_name = Name
mkFlattenFreshCoName
(FlattenEnv
env1, Type
kind') = TvSubstEnv -> FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy TvSubstEnv
subst FlattenEnv
env (Coercion -> Type
coercionType Coercion
co)
covar :: TyVar
covar = InScopeSet -> TyVar -> TyVar
uniqAway (FlattenEnv -> InScopeSet
fe_in_scope FlattenEnv
env1) (Name -> Type -> TyVar
mkCoVar Name
fresh_name 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 :: Int
arity = TyCon -> Int
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 )
Int -> [Type] -> ([Type], [Type])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
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 :: 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")
mkFlattenFreshCoName :: Name
mkFlattenFreshCoName :: Name
mkFlattenFreshCoName
= Unique -> FastString -> Name
mkSystemVarName (Unique -> Int -> Unique
deriveUnique Unique
eqPrimTyConKey Int
71) (String -> FastString
fsLit String
"flc")