{-# LANGUAGE CPP, GADTs, ScopedTypeVariables, BangPatterns, TupleSections #-}
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 "HsVersions.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 fis :: [FamInst]
fis = [TyCon
tc | FamInst { fi_flavor :: FamInst -> FamFlavor
fi_flavor = DataFamilyInst tc :: TyCon
tc } <- [FamInst]
fis]
famInstRepTyCon_maybe :: FamInst -> Maybe TyCon
famInstRepTyCon_maybe :: FamInst -> Maybe TyCon
famInstRepTyCon_maybe fi :: FamInst
fi
= case FamInst -> FamFlavor
fi_flavor FamInst
fi of
DataFamilyInst tycon :: TyCon
tycon -> TyCon -> Maybe TyCon
forall a. a -> Maybe a
Just TyCon
tycon
SynFamilyInst -> Maybe TyCon
forall a. Maybe a
Nothing
dataFamInstRepTyCon :: FamInst -> TyCon
dataFamInstRepTyCon :: FamInst -> TyCon
dataFamInstRepTyCon fi :: FamInst
fi
= case FamInst -> FamFlavor
fi_flavor FamInst
fi of
DataFamilyInst tycon :: TyCon
tycon -> TyCon
tycon
SynFamilyInst -> String -> SDoc -> TyCon
forall a. HasCallStack => String -> SDoc -> a
pprPanic "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 "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))
2 (SDoc -> SDoc
whenPprDebug SDoc
debug_stuff)
where
ppr_tc_sort :: SDoc
ppr_tc_sort = case FamFlavor
flavor of
SynFamilyInst -> String -> SDoc
text "type"
DataFamilyInst tycon :: TyCon
tycon
| TyCon -> Bool
isDataTyCon TyCon
tycon -> String -> SDoc
text "data"
| TyCon -> Bool
isNewTyCon TyCon
tycon -> String -> SDoc
text "newtype"
| TyCon -> Bool
isAbstractTyCon TyCon
tycon -> String -> SDoc
text "data"
| Bool
otherwise -> String -> SDoc
text "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 "Coercion axiom:" SDoc -> SDoc -> SDoc
<+> CoAxiom Unbranched -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoAxiom Unbranched
ax
, String -> SDoc
text "Tvs:" SDoc -> SDoc -> SDoc
<+> [TyVar] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [TyVar]
tvs
, String -> SDoc
text "LHS:" SDoc -> SDoc -> SDoc
<+> [Type] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Type]
tys
, String -> SDoc
text "RHS:" SDoc -> SDoc -> SDoc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
rhs ]
pprFamInsts :: [FamInst] -> SDoc
pprFamInsts :: [FamInst] -> SDoc
pprFamInsts finsts :: [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 fam :: Name
fam mb_tcs :: [Maybe Name]
mb_tcs axiom :: 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 (tc :: TyCon
tc, _)
| Just ax' :: 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
_ -> FamFlavor
SynFamilyInst
type FamInstEnv = UniqDFM FamilyInstEnv
type FamInstEnvs = (FamInstEnv, FamInstEnv)
newtype FamilyInstEnv
= FamIE [FamInst]
instance Outputable FamilyInstEnv where
ppr :: FamilyInstEnv -> SDoc
ppr (FamIE fs :: [FamInst]
fs) = String -> SDoc
text "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 fi :: FamInstEnv
fi = [FamInst
elt | FamIE elts :: [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 elt :: [FamInst]
elt) sum :: 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) 0
familyInstances :: (FamInstEnv, FamInstEnv) -> TyCon -> [FamInst]
familyInstances :: (FamInstEnv, FamInstEnv) -> TyCon -> [FamInst]
familyInstances (pkg_fie :: FamInstEnv
pkg_fie, home_fie :: FamInstEnv
home_fie) fam :: 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 env :: 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 insts :: [FamInst]
insts) -> [FamInst]
insts
Nothing -> []
extendFamInstEnvList :: FamInstEnv -> [FamInst] -> FamInstEnv
extendFamInstEnvList :: FamInstEnv -> [FamInst] -> FamInstEnv
extendFamInstEnvList inst_env :: FamInstEnv
inst_env fis :: [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 inst_env :: 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 items :: [FamInst]
items) _ = [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 (commonlhs1 :: [Type]
commonlhs1, commonlhs2 :: [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
SurelyApart -> Bool
True
Unifiable subst :: 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
_ -> Bool
False
data InjectivityCheckResult
= InjectivityAccepted
| InjectivityUnified CoAxBranch CoAxBranch
injectiveBranches :: [Bool] -> CoAxBranch -> CoAxBranch
-> InjectivityCheckResult
injectiveBranches :: [Bool] -> CoAxBranch -> CoAxBranch -> InjectivityCheckResult
injectiveBranches injectivity :: [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
Nothing -> InjectivityCheckResult
InjectivityAccepted
Just subst :: 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 branches :: [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 prev_brs :: [CoAxBranch]
prev_brs cur_br :: 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 prev_brs :: [CoAxBranch]
prev_brs cur_br :: 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 tvs :: [TyVar]
tvs eta_tvs :: [TyVar]
eta_tvs cvs :: [TyVar]
cvs lhs :: [Type]
lhs rhs :: Type
rhs roles :: [Role]
roles loc :: 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
(env1 :: TidyEnv
env1, tvs' :: [TyVar]
tvs') = TidyEnv -> [TyVar] -> (TidyEnv, [TyVar])
tidyVarBndrs TidyEnv
init_tidy_env [TyVar]
tvs
(env2 :: TidyEnv
env2, eta_tvs' :: [TyVar]
eta_tvs') = TidyEnv -> [TyVar] -> (TidyEnv, [TyVar])
tidyVarBndrs TidyEnv
env1 [TyVar]
eta_tvs
(env :: TidyEnv
env, cvs' :: [TyVar]
cvs') = TidyEnv -> [TyVar] -> (TidyEnv, [TyVar])
tidyVarBndrs TidyEnv
env2 [TyVar]
cvs
init_occ_env :: TidyOccEnv
init_occ_env = [OccName] -> TidyOccEnv
initTidyOccEnv [String -> OccName
mkTyVarOcc "_"]
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 ax_name :: Name
ax_name fam_tc :: TyCon
fam_tc branches :: [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 ax_name :: Name
ax_name fam_tc :: TyCon
fam_tc branch :: 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
role ax_name :: Name
ax_name tvs :: [TyVar]
tvs eta_tvs :: [TyVar]
eta_tvs cvs :: [TyVar]
cvs fam_tc :: TyCon
fam_tc lhs_tys :: [Type]
lhs_tys rhs_ty :: 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
name tycon :: TyCon
tycon tvs :: [TyVar]
tvs roles :: [Role]
roles rhs_ty :: 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 "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 (pkg_ie :: FamInstEnv
pkg_ie, home_ie :: FamInstEnv
home_ie) fam_tc :: 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 ie :: FamInstEnv
ie = case FamInstEnv -> TyCon -> Maybe FamilyInstEnv
forall key elt. Uniquable key => UniqDFM elt -> key -> Maybe elt
lookupUDFM FamInstEnv
ie TyCon
fam_tc of
Nothing -> []
Just (FamIE fis :: [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 _ _ tpl_tys :: [Type]
tpl_tys tys :: [Type]
tys = [Type] -> [Type] -> Maybe TCvSubst
tcMatchTys [Type]
tpl_tys [Type]
tys
lookupFamInstEnvConflicts
:: FamInstEnvs
-> FamInst
-> [FamInstMatch]
lookupFamInstEnvConflicts :: (FamInstEnv, FamInstEnv) -> FamInst -> [FamInstMatch]
lookupFamInstEnvConflicts envs :: (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
(fam :: TyCon
fam, tys :: [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 }) tpl_tvs :: VarSet
tpl_tvs tpl_tys :: [Type]
tpl_tys _
= 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 "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 injList :: [Bool]
injList (pkg_ie :: FamInstEnv
pkg_ie, home_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 ie :: FamInstEnv
ie
| TyCon -> Bool
isOpenFamilyTyCon TyCon
fam, Just (FamIE insts :: [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' match_fun :: MatchFun
match_fun ie :: FamInstEnv
ie fam :: TyCon
fam match_tys :: [Type]
match_tys
| TyCon -> Bool
isOpenFamilyTyCon TyCon
fam
, Just (FamIE insts :: [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 }) : rest :: [FamInst]
rest)
| [Maybe Name] -> [Maybe Name] -> Bool
instanceCantMatch [Maybe Name]
rough_tcs [Maybe Name]
mb_tcs
= [FamInst] -> [FamInstMatch]
find [FamInst]
rest
| Just subst :: 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
(rough_tcs :: [Maybe Name]
rough_tcs, match_tys1 :: [Type]
match_tys1, match_tys2 :: [Type]
match_tys2) = [Type] -> ([Maybe Name], [Type], [Type])
split_tys [Type]
tpl_tys
split_tys :: [Type] -> ([Maybe Name], [Type], [Type])
split_tys tpl_tys :: [Type]
tpl_tys
| TyCon -> Bool
isTypeFamilyTyCon TyCon
fam
= ([Maybe Name], [Type], [Type])
pre_rough_split_tys
| Bool
otherwise
= let (match_tys1 :: [Type]
match_tys1, match_tys2 :: [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)
(pre_match_tys1 :: [Type]
pre_match_tys1, pre_match_tys2 :: [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 match_fun :: MatchFun
match_fun (pkg_ie :: FamInstEnv
pkg_ie, home_ie :: FamInstEnv
home_ie) fam :: TyCon
fam tys :: [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 branch :: CoAxBranch
branch branches :: [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 envs :: (FamInstEnv, FamInstEnv)
envs role :: Role
role tc :: TyCon
tc tys :: [Type]
tys
| Role
Phantom <- Role
role
= Maybe (Coercion, Type)
forall a. Maybe a
Nothing
| case Role
role of
Representational -> TyCon -> Bool
isOpenFamilyTyCon TyCon
tc
_ -> 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 } : _ <- (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 ax :: CoAxiom Branched
ax <- TyCon -> Maybe (CoAxiom Branched)
isClosedSynFamilyTyConWithAxiom_maybe TyCon
tc
, Just (ind :: Int
ind, inst_tys :: [Type]
inst_tys, inst_cos :: [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 ax :: BuiltInSynFamily
ax <- TyCon -> Maybe BuiltInSynFamily
isBuiltInSynFamTyCon_maybe TyCon
tc
, Just (coax :: CoAxiomRule
coax,ts :: [Type]
ts,ty :: 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 axiom :: CoAxiom Branched
axiom tys :: [Type]
tys
= do { let num_pats :: Int
num_pats = CoAxiom Branched -> Int
forall (br :: BranchFlag). CoAxiom br -> Int
coAxiomNumPats CoAxiom Branched
axiom
(target_tys :: [Type]
target_tys, extra_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
; (ind :: Int
ind, inst_tys :: [Type]
inst_tys, inst_cos :: [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 branches :: Array Int CoAxBranch
branches target_tys :: [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 (index :: Int
index, branch :: CoAxBranch
branch) other :: 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 subst :: 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 (Int, [Type], [Coercion])
other
apartnessCheck :: [Type]
-> CoAxBranch
-> Bool
apartnessCheck :: [Type] -> CoAxBranch -> Bool
apartnessCheck flattened_target :: [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 SurelyApart = Bool
True
isSurelyApart _ = Bool
False
topNormaliseType :: FamInstEnvs -> Type -> Type
topNormaliseType :: (FamInstEnv, FamInstEnv) -> Type -> Type
topNormaliseType env :: (FamInstEnv, FamInstEnv)
env ty :: Type
ty = case (FamInstEnv, FamInstEnv) -> Type -> Maybe (Coercion, Type)
topNormaliseType_maybe (FamInstEnv, FamInstEnv)
env Type
ty of
Just (_co :: Coercion
_co, ty' :: Type
ty') -> Type
ty'
Nothing -> Type
ty
topNormaliseType_maybe :: FamInstEnvs -> Type -> Maybe (Coercion, Type)
topNormaliseType_maybe :: (FamInstEnv, FamInstEnv) -> Type -> Maybe (Coercion, Type)
topNormaliseType_maybe env :: (FamInstEnv, FamInstEnv)
env ty :: Type
ty
= do { ((co :: Coercion
co, mkind_co :: MCoercionN
mkind_co), nty :: 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
MRefl -> (Coercion
co, Type
nty)
MCo kind_co :: 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 (c1 :: Coercion
c1, mc1 :: MCoercionN
mc1) (c2 :: Coercion
c2, mc2 :: 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' rec_nts :: RecTcChecker
rec_nts tc :: TyCon
tc tys :: [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 rec_nts :: RecTcChecker
rec_nts tc :: TyCon
tc tys :: [Type]
tys
= let (args_co :: Coercion
args_co, ntys :: [Type]
ntys, res_co :: 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 (co :: Coercion
co, rhs :: 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)
_ -> 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 env :: (FamInstEnv, FamInstEnv)
env role :: Role
role tc :: TyCon
tc tys :: [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 tc :: TyCon
tc tys :: [Type]
tys
| Just (tenv :: [(TyVar, Type)]
tenv, rhs :: Type
rhs, tys' :: [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
; (args_co :: Coercion
args_co, ntys :: [Type]
ntys, res_co :: 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 (first_co :: Coercion
first_co, ty' :: Type
ty')
-> do { (rest_co :: Coercion
rest_co,nty :: 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) }
_ ->
(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 { (args_co :: Coercion
args_co, ntys :: [Type]
ntys, res_co :: 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 r :: Role
r nty :: Type
nty orig_to_nty :: Coercion
orig_to_nty kind_co :: 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 env :: (FamInstEnv, FamInstEnv)
env role :: Role
role tc :: TyCon
tc tys :: [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 tc :: TyCon
tc tys :: [Type]
tys
= do { Role
role <- NormM Role
getRole
; (args_cos :: [Coercion]
args_cos, nargs :: [Type]
nargs, res_co :: 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 env :: (FamInstEnv, FamInstEnv)
env role :: Role
role ty :: 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 ty :: Type
ty
= Type -> NormM (Coercion, Type)
go Type
ty
where
go :: Type -> NormM (Coercion, Type)
go (TyConApp tc :: TyCon
tc tys :: [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 ty1 :: Type
ty1 ty2 :: Type
ty2) = Type -> [Type] -> NormM (Coercion, Type)
go_app_tys Type
ty1 [Type
ty2]
go (FunTy ty1 :: Type
ty1 ty2 :: Type
ty2)
= do { (co1 :: Coercion
co1, nty1 :: Type
nty1) <- Type -> NormM (Coercion, Type)
go Type
ty1
; (co2 :: Coercion
co2, nty2 :: 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 -> Type -> Type
mkFunTy Type
nty1 Type
nty2) }
go (ForAllTy (Bndr tcvar :: TyVar
tcvar vis :: ArgFlag
vis) ty :: Type
ty)
= do { (lc' :: LiftingContext
lc', tv' :: TyVar
tv', h :: Coercion
h, ki' :: Type
ki') <- TyVar -> NormM (LiftingContext, TyVar, Coercion, Type)
normalise_var_bndr TyVar
tcvar
; (co :: Coercion
co, nty :: 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 tv :: TyVar
tv) = TyVar -> NormM (Coercion, Type)
normalise_tyvar TyVar
tv
go (CastTy ty :: Type
ty co :: Coercion
co)
= do { (nco :: Coercion
nco, nty :: 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 co :: 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 ty1 :: Type
ty1 ty2 :: Type
ty2) tys :: [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 fun_ty :: Type
fun_ty arg_tys :: [Type]
arg_tys
= do { (fun_co :: Coercion
fun_co, nfun :: 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 (tc :: TyCon
tc, xis :: [Type]
xis) ->
do { (second_co :: Coercion
second_co, nty :: 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) }
Nothing ->
do { (args_cos :: [Coercion]
args_cos, nargs :: [Type]
nargs, res_co :: 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 fun_ki :: Type
fun_ki roles :: [Role]
roles args :: [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 (xis :: [Type]
xis, cos :: [Coercion]
cos, res_co :: 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
(ki_binders :: [TyCoBinder]
ki_binders, inner_ki :: 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 action :: NormM (Coercion, Type)
action = do { (co :: Coercion
co, ty :: 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
role ty :: 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 tv :: 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 co :: 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)
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 tcvar :: TyVar
tcvar
= do { LiftingContext
lc1 <- NormM LiftingContext
getLC
; (FamInstEnv, FamInstEnv)
env <- NormM (FamInstEnv, FamInstEnv)
getEnv
; let callback :: LiftingContext -> Type -> (Coercion, Type)
callback lc :: LiftingContext
lc ki :: 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 }
initNormM :: FamInstEnvs -> Role
-> TyCoVarSet
-> NormM a -> a
initNormM :: (FamInstEnv, FamInstEnv) -> Role -> VarSet -> NormM a -> a
initNormM env :: (FamInstEnv, FamInstEnv)
env role :: Role
role vars :: VarSet
vars (NormM thing_inside :: (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 (\ _ _ r :: 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 (\ _ lc :: LiftingContext
lc _ -> 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 (\ env :: (FamInstEnv, FamInstEnv)
env _ _ -> (FamInstEnv, FamInstEnv)
env)
withRole :: Role -> NormM a -> NormM a
withRole :: Role -> NormM a -> NormM a
withRole r :: Role
r thing :: 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
$ \ envs :: (FamInstEnv, FamInstEnv)
envs lc :: LiftingContext
lc _old_r :: 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 lc :: LiftingContext
lc thing :: 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
$ \ envs :: (FamInstEnv, FamInstEnv)
envs _old_lc :: LiftingContext
_old_lc r :: 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
ma :: NormM a
ma >>= :: NormM a -> (a -> NormM b) -> NormM b
>>= fmb :: 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
$ \env :: (FamInstEnv, FamInstEnv)
env lc :: LiftingContext
lc r :: 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 Functor NormM where
fmap :: (a -> b) -> NormM a -> NormM b
fmap = (a -> b) -> NormM a -> NormM b
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM
instance Applicative NormM where
pure :: a -> NormM a
pure x :: 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
$ \ _ _ _ -> 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 -> TCvSubst
fe_subst :: TCvSubst }
emptyFlattenEnv :: InScopeSet -> FlattenEnv
emptyFlattenEnv :: InScopeSet -> FlattenEnv
emptyFlattenEnv in_scope :: InScopeSet
in_scope
= FlattenEnv :: TypeMap TyVar -> TCvSubst -> FlattenEnv
FlattenEnv { fe_type_map :: TypeMap TyVar
fe_type_map = TypeMap TyVar
forall a. TypeMap a
emptyTypeMap
, fe_subst :: TCvSubst
fe_subst = InScopeSet -> TCvSubst
mkEmptyTCvSubst InScopeSet
in_scope }
flattenTys :: InScopeSet -> [Type] -> [Type]
flattenTys :: InScopeSet -> [Type] -> [Type]
flattenTys in_scope :: InScopeSet
in_scope tys :: [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
$ FlattenEnv -> [Type] -> (FlattenEnv, [Type])
coreFlattenTys FlattenEnv
env [Type]
tys
where
all_in_scope :: InScopeSet
all_in_scope = InScopeSet
in_scope InScopeSet -> VarSet -> InScopeSet
`extendInScopeSetSet` [Type] -> VarSet
allTyCoVarsInTys [Type]
tys
env :: FlattenEnv
env = InScopeSet -> FlattenEnv
emptyFlattenEnv InScopeSet
all_in_scope
coreFlattenTys :: FlattenEnv -> [Type] -> (FlattenEnv, [Type])
coreFlattenTys :: FlattenEnv -> [Type] -> (FlattenEnv, [Type])
coreFlattenTys = [Type] -> FlattenEnv -> [Type] -> (FlattenEnv, [Type])
go []
where
go :: [Type] -> FlattenEnv -> [Type] -> (FlattenEnv, [Type])
go rtys :: [Type]
rtys env :: FlattenEnv
env [] = (FlattenEnv
env, [Type] -> [Type]
forall a. [a] -> [a]
reverse [Type]
rtys)
go rtys :: [Type]
rtys env :: FlattenEnv
env (ty :: Type
ty : tys :: [Type]
tys)
= let (env' :: FlattenEnv
env', ty' :: Type
ty') = FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy FlattenEnv
env Type
ty in
[Type] -> FlattenEnv -> [Type] -> (FlattenEnv, [Type])
go (Type
ty' Type -> [Type] -> [Type]
forall a. a -> [a] -> [a]
: [Type]
rtys) FlattenEnv
env' [Type]
tys
coreFlattenTy :: FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy :: FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy = FlattenEnv -> Type -> (FlattenEnv, Type)
go
where
go :: FlattenEnv -> Type -> (FlattenEnv, Type)
go env :: FlattenEnv
env ty :: Type
ty | Just ty' :: Type
ty' <- Type -> Maybe Type
coreView Type
ty = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty'
go env :: FlattenEnv
env (TyVarTy tv :: TyVar
tv) = (FlattenEnv
env, TCvSubst -> TyVar -> Type
substTyVar (FlattenEnv -> TCvSubst
fe_subst FlattenEnv
env) TyVar
tv)
go env :: FlattenEnv
env (AppTy ty1 :: Type
ty1 ty2 :: Type
ty2) = let (env1 :: FlattenEnv
env1, ty1' :: Type
ty1') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty1
(env2 :: FlattenEnv
env2, ty2' :: Type
ty2') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env1 Type
ty2 in
(FlattenEnv
env2, Type -> Type -> Type
AppTy Type
ty1' Type
ty2')
go env :: FlattenEnv
env (TyConApp tc :: TyCon
tc tys :: [Type]
tys)
| Bool -> Bool
not (TyCon -> Role -> Bool
isGenerativeTyCon TyCon
tc Role
Nominal)
= let (env' :: FlattenEnv
env', tv :: TyVar
tv) = FlattenEnv -> TyCon -> [Type] -> (FlattenEnv, TyVar)
coreFlattenTyFamApp FlattenEnv
env TyCon
tc [Type]
tys in
(FlattenEnv
env', TyVar -> Type
mkTyVarTy TyVar
tv)
| Bool
otherwise
= let (env' :: FlattenEnv
env', tys' :: [Type]
tys') = FlattenEnv -> [Type] -> (FlattenEnv, [Type])
coreFlattenTys FlattenEnv
env [Type]
tys in
(FlattenEnv
env', TyCon -> [Type] -> Type
mkTyConApp TyCon
tc [Type]
tys')
go env :: FlattenEnv
env (FunTy ty1 :: Type
ty1 ty2 :: Type
ty2) = let (env1 :: FlattenEnv
env1, ty1' :: Type
ty1') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty1
(env2 :: FlattenEnv
env2, ty2' :: Type
ty2') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env1 Type
ty2 in
(FlattenEnv
env2, Type -> Type -> Type
mkFunTy Type
ty1' Type
ty2')
go env :: FlattenEnv
env (ForAllTy (Bndr tv :: TyVar
tv vis :: ArgFlag
vis) ty :: Type
ty)
= let (env1 :: FlattenEnv
env1, tv' :: TyVar
tv') = FlattenEnv -> TyVar -> (FlattenEnv, TyVar)
coreFlattenVarBndr FlattenEnv
env TyVar
tv
(env2 :: FlattenEnv
env2, ty' :: Type
ty') = FlattenEnv -> Type -> (FlattenEnv, Type)
go 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 env :: FlattenEnv
env ty :: Type
ty@(LitTy {}) = (FlattenEnv
env, Type
ty)
go env :: FlattenEnv
env (CastTy ty :: Type
ty co :: Coercion
co) = let (env1 :: FlattenEnv
env1, ty' :: Type
ty') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty
(env2 :: FlattenEnv
env2, co' :: Coercion
co') = FlattenEnv -> Coercion -> (FlattenEnv, Coercion)
coreFlattenCo FlattenEnv
env1 Coercion
co in
(FlattenEnv
env2, Type -> Coercion -> Type
CastTy Type
ty' Coercion
co')
go env :: FlattenEnv
env (CoercionTy co :: Coercion
co) = let (env' :: FlattenEnv
env', co' :: Coercion
co') = FlattenEnv -> Coercion -> (FlattenEnv, Coercion)
coreFlattenCo FlattenEnv
env Coercion
co in
(FlattenEnv
env', Coercion -> Type
CoercionTy Coercion
co')
coreFlattenCo :: FlattenEnv -> Coercion -> (FlattenEnv, Coercion)
coreFlattenCo :: FlattenEnv -> Coercion -> (FlattenEnv, Coercion)
coreFlattenCo env :: FlattenEnv
env co :: Coercion
co
= (FlattenEnv
env2, TyVar -> Coercion
mkCoVarCo TyVar
covar)
where
(env1 :: FlattenEnv
env1, kind' :: Type
kind') = FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy FlattenEnv
env (Coercion -> Type
coercionType Coercion
co)
fresh_name :: Name
fresh_name = Name
mkFlattenFreshCoName
subst1 :: TCvSubst
subst1 = FlattenEnv -> TCvSubst
fe_subst FlattenEnv
env1
in_scope :: InScopeSet
in_scope = TCvSubst -> InScopeSet
getTCvInScope TCvSubst
subst1
covar :: TyVar
covar = InScopeSet -> TyVar -> TyVar
uniqAway InScopeSet
in_scope (Name -> Type -> TyVar
mkCoVar Name
fresh_name Type
kind')
env2 :: FlattenEnv
env2 = FlattenEnv
env1 { fe_subst :: TCvSubst
fe_subst = TCvSubst
subst1 TCvSubst -> TyVar -> TCvSubst
`extendTCvInScope` TyVar
covar }
coreFlattenVarBndr :: FlattenEnv -> TyCoVar -> (FlattenEnv, TyCoVar)
coreFlattenVarBndr :: FlattenEnv -> TyVar -> (FlattenEnv, TyVar)
coreFlattenVarBndr env :: FlattenEnv
env tv :: TyVar
tv
| Type
kind' Type -> Type -> Bool
`eqType` Type
kind
= ( FlattenEnv
env { fe_subst :: TCvSubst
fe_subst = TCvSubst -> TyVar -> Type -> TCvSubst
extendTCvSubst TCvSubst
old_subst TyVar
tv (TyVar -> Type
mkTyCoVarTy TyVar
tv) }
, TyVar
tv)
| Bool
otherwise
= let new_tv :: TyVar
new_tv = InScopeSet -> TyVar -> TyVar
uniqAway (TCvSubst -> InScopeSet
getTCvInScope TCvSubst
old_subst) (TyVar -> Type -> TyVar
setVarType TyVar
tv Type
kind')
new_subst :: TCvSubst
new_subst = TCvSubst -> TyVar -> TyVar -> TCvSubst
extendTCvSubstWithClone TCvSubst
old_subst TyVar
tv TyVar
new_tv
in
(FlattenEnv
env' { fe_subst :: TCvSubst
fe_subst = TCvSubst
new_subst }, TyVar
new_tv)
where
kind :: Type
kind = TyVar -> Type
varType TyVar
tv
(env' :: FlattenEnv
env', kind' :: Type
kind') = FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy FlattenEnv
env Type
kind
old_subst :: TCvSubst
old_subst = FlattenEnv -> TCvSubst
fe_subst FlattenEnv
env
coreFlattenTyFamApp :: FlattenEnv
-> TyCon
-> [Type]
-> (FlattenEnv, TyVar)
coreFlattenTyFamApp :: FlattenEnv -> TyCon -> [Type] -> (FlattenEnv, TyVar)
coreFlattenTyFamApp env :: FlattenEnv
env fam_tc :: TyCon
fam_tc fam_args :: [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 tv :: TyVar
tv -> (FlattenEnv
env, TyVar
tv)
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 (TCvSubst -> InScopeSet
getTCvInScope TCvSubst
subst) (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)
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_subst :: TCvSubst
fe_subst = TCvSubst -> TyVar -> TCvSubst
extendTCvInScope TCvSubst
subst TyVar
tv }
in (FlattenEnv
env', TyVar
tv)
where fam_ty :: Type
fam_ty = TyCon -> [Type] -> Type
mkTyConApp TyCon
fam_tc [Type]
fam_args
FlattenEnv { fe_type_map :: FlattenEnv -> TypeMap TyVar
fe_type_map = TypeMap TyVar
type_map
, fe_subst :: FlattenEnv -> TCvSubst
fe_subst = TCvSubst
subst } = FlattenEnv
env
allTyCoVarsInTys :: [Type] -> VarSet
allTyCoVarsInTys :: [Type] -> VarSet
allTyCoVarsInTys [] = VarSet
emptyVarSet
allTyCoVarsInTys (ty :: Type
ty:tys :: [Type]
tys) = Type -> VarSet
allTyCoVarsInTy Type
ty VarSet -> VarSet -> VarSet
`unionVarSet` [Type] -> VarSet
allTyCoVarsInTys [Type]
tys
allTyCoVarsInTy :: Type -> VarSet
allTyCoVarsInTy :: Type -> VarSet
allTyCoVarsInTy = Type -> VarSet
go
where
go :: Type -> VarSet
go (TyVarTy tv :: TyVar
tv) = TyVar -> VarSet
unitVarSet TyVar
tv
go (TyConApp _ tys :: [Type]
tys) = [Type] -> VarSet
allTyCoVarsInTys [Type]
tys
go (AppTy ty1 :: Type
ty1 ty2 :: Type
ty2) = (Type -> VarSet
go Type
ty1) VarSet -> VarSet -> VarSet
`unionVarSet` (Type -> VarSet
go Type
ty2)
go (FunTy ty1 :: Type
ty1 ty2 :: Type
ty2) = (Type -> VarSet
go Type
ty1) VarSet -> VarSet -> VarSet
`unionVarSet` (Type -> VarSet
go Type
ty2)
go (ForAllTy (Bndr tv :: TyVar
tv _) ty :: Type
ty) = TyVar -> VarSet
unitVarSet TyVar
tv VarSet -> VarSet -> VarSet
`unionVarSet`
Type -> VarSet
go (TyVar -> Type
tyVarKind TyVar
tv) VarSet -> VarSet -> VarSet
`unionVarSet`
Type -> VarSet
go Type
ty
go (LitTy {}) = VarSet
emptyVarSet
go (CastTy ty :: Type
ty co :: Coercion
co) = Type -> VarSet
go Type
ty VarSet -> VarSet -> VarSet
`unionVarSet` Coercion -> VarSet
go_co Coercion
co
go (CoercionTy co :: Coercion
co) = Coercion -> VarSet
go_co Coercion
co
go_mco :: MCoercionN -> VarSet
go_mco MRefl = VarSet
emptyVarSet
go_mco (MCo co :: Coercion
co) = Coercion -> VarSet
go_co Coercion
co
go_co :: Coercion -> VarSet
go_co (Refl ty :: Type
ty) = Type -> VarSet
go Type
ty
go_co (GRefl _ ty :: Type
ty mco :: MCoercionN
mco) = Type -> VarSet
go Type
ty VarSet -> VarSet -> VarSet
`unionVarSet` MCoercionN -> VarSet
go_mco MCoercionN
mco
go_co (TyConAppCo _ _ args :: [Coercion]
args) = [Coercion] -> VarSet
go_cos [Coercion]
args
go_co (AppCo co :: Coercion
co arg :: Coercion
arg) = Coercion -> VarSet
go_co Coercion
co VarSet -> VarSet -> VarSet
`unionVarSet` Coercion -> VarSet
go_co Coercion
arg
go_co (ForAllCo tv :: TyVar
tv h :: Coercion
h co :: Coercion
co)
= [VarSet] -> VarSet
unionVarSets [TyVar -> VarSet
unitVarSet TyVar
tv, Coercion -> VarSet
go_co Coercion
co, Coercion -> VarSet
go_co Coercion
h]
go_co (FunCo _ c1 :: Coercion
c1 c2 :: Coercion
c2) = Coercion -> VarSet
go_co Coercion
c1 VarSet -> VarSet -> VarSet
`unionVarSet` Coercion -> VarSet
go_co Coercion
c2
go_co (CoVarCo cv :: TyVar
cv) = TyVar -> VarSet
unitVarSet TyVar
cv
go_co (HoleCo h :: CoercionHole
h) = TyVar -> VarSet
unitVarSet (CoercionHole -> TyVar
coHoleCoVar CoercionHole
h)
go_co (AxiomInstCo _ _ cos :: [Coercion]
cos) = [Coercion] -> VarSet
go_cos [Coercion]
cos
go_co (UnivCo p :: UnivCoProvenance
p _ t1 :: Type
t1 t2 :: Type
t2) = UnivCoProvenance -> VarSet
go_prov UnivCoProvenance
p VarSet -> VarSet -> VarSet
`unionVarSet` Type -> VarSet
go Type
t1 VarSet -> VarSet -> VarSet
`unionVarSet` Type -> VarSet
go Type
t2
go_co (SymCo co :: Coercion
co) = Coercion -> VarSet
go_co Coercion
co
go_co (TransCo c1 :: Coercion
c1 c2 :: Coercion
c2) = Coercion -> VarSet
go_co Coercion
c1 VarSet -> VarSet -> VarSet
`unionVarSet` Coercion -> VarSet
go_co Coercion
c2
go_co (NthCo _ _ co :: Coercion
co) = Coercion -> VarSet
go_co Coercion
co
go_co (LRCo _ co :: Coercion
co) = Coercion -> VarSet
go_co Coercion
co
go_co (InstCo co :: Coercion
co arg :: Coercion
arg) = Coercion -> VarSet
go_co Coercion
co VarSet -> VarSet -> VarSet
`unionVarSet` Coercion -> VarSet
go_co Coercion
arg
go_co (KindCo co :: Coercion
co) = Coercion -> VarSet
go_co Coercion
co
go_co (SubCo co :: Coercion
co) = Coercion -> VarSet
go_co Coercion
co
go_co (AxiomRuleCo _ cs :: [Coercion]
cs) = [Coercion] -> VarSet
go_cos [Coercion]
cs
go_cos :: [Coercion] -> VarSet
go_cos = (Coercion -> VarSet -> VarSet) -> VarSet -> [Coercion] -> VarSet
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (VarSet -> VarSet -> VarSet
unionVarSet (VarSet -> VarSet -> VarSet)
-> (Coercion -> VarSet) -> Coercion -> VarSet -> VarSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Coercion -> VarSet
go_co) VarSet
emptyVarSet
go_prov :: UnivCoProvenance -> VarSet
go_prov UnsafeCoerceProv = VarSet
emptyVarSet
go_prov (PhantomProv co :: Coercion
co) = Coercion -> VarSet
go_co Coercion
co
go_prov (ProofIrrelProv co :: Coercion
co) = Coercion -> VarSet
go_co Coercion
co
go_prov (PluginProv _) = VarSet
emptyVarSet
mkFlattenFreshTyName :: Uniquable a => a -> Name
mkFlattenFreshTyName :: a -> Name
mkFlattenFreshTyName unq :: a
unq
= Unique -> FastString -> Name
mkSysTvName (a -> Unique
forall a. Uniquable a => a -> Unique
getUnique a
unq) (String -> FastString
fsLit "flt")
mkFlattenFreshCoName :: Name
mkFlattenFreshCoName :: Name
mkFlattenFreshCoName
= Unique -> FastString -> Name
mkSystemVarName (Unique -> Int -> Unique
deriveUnique Unique
eqPrimTyConKey 71) (String -> FastString
fsLit "flc")