{-# LANGUAGE ScopedTypeVariables, PatternSynonyms #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveFunctor, DeriveDataTypeable #-}
module GHC.Core.Unify (
tcMatchTy, tcMatchTyKi,
tcMatchTys, tcMatchTyKis,
tcMatchTyX, tcMatchTysX, tcMatchTyKisX,
tcMatchTyX_BM, ruleMatchTyKiX,
RoughMatchTc(..), roughMatchTcs, instanceCantMatch,
typesCantMatch, isRoughOtherTc,
tcUnifyTy, tcUnifyTyKi, tcUnifyTys, tcUnifyTyKis,
tcUnifyTysFG, tcUnifyTyWithTFs,
BindFun, BindFlag(..), matchBindFun, alwaysBindFun,
UnifyResult, UnifyResultM(..), MaybeApartReason(..),
liftCoMatch,
flattenTys, flattenTysX
) where
#include "GhclibHsVersions.h"
import GHC.Prelude
import GHC.Types.Var
import GHC.Types.Var.Env
import GHC.Types.Var.Set
import GHC.Types.Name( Name, mkSysTvName, mkSystemVarName )
import GHC.Core.Type hiding ( getTvSubstEnv )
import GHC.Core.Coercion hiding ( getCvSubstEnv )
import GHC.Core.TyCon
import GHC.Core.TyCo.Rep
import GHC.Core.TyCo.FVs ( tyCoVarsOfCoList, tyCoFVsOfTypes )
import GHC.Core.TyCo.Subst ( mkTvSubst )
import GHC.Core.Map.Type
import GHC.Utils.FV( FV, fvVarSet, fvVarList )
import GHC.Utils.Misc
import GHC.Data.Pair
import GHC.Utils.Outputable
import GHC.Types.Unique
import GHC.Types.Unique.FM
import GHC.Types.Unique.Set
import GHC.Exts( oneShot )
import GHC.Utils.Panic
import GHC.Data.FastString
import Data.Data ( Data )
import Data.List ( mapAccumL )
import Control.Monad
import qualified Data.Semigroup as S
type BindFun = TyCoVar -> Type -> BindFlag
tcMatchTy :: Type -> Type -> Maybe TCvSubst
tcMatchTy :: Type -> Type -> Maybe TCvSubst
tcMatchTy Type
ty1 Type
ty2 = [Type] -> [Type] -> Maybe TCvSubst
tcMatchTys [Type
ty1] [Type
ty2]
tcMatchTyX_BM :: BindFun -> TCvSubst
-> Type -> Type -> Maybe TCvSubst
tcMatchTyX_BM :: BindFun -> TCvSubst -> Type -> Type -> Maybe TCvSubst
tcMatchTyX_BM BindFun
bind_me TCvSubst
subst Type
ty1 Type
ty2
= BindFun -> Bool -> TCvSubst -> [Type] -> [Type] -> Maybe TCvSubst
tc_match_tys_x BindFun
bind_me Bool
False TCvSubst
subst [Type
ty1] [Type
ty2]
tcMatchTyKi :: Type -> Type -> Maybe TCvSubst
tcMatchTyKi :: Type -> Type -> Maybe TCvSubst
tcMatchTyKi Type
ty1 Type
ty2
= BindFun -> Bool -> [Type] -> [Type] -> Maybe TCvSubst
tc_match_tys BindFun
alwaysBindFun Bool
True [Type
ty1] [Type
ty2]
tcMatchTyX :: TCvSubst
-> Type
-> Type
-> Maybe TCvSubst
tcMatchTyX :: TCvSubst -> Type -> Type -> Maybe TCvSubst
tcMatchTyX TCvSubst
subst Type
ty1 Type
ty2
= BindFun -> Bool -> TCvSubst -> [Type] -> [Type] -> Maybe TCvSubst
tc_match_tys_x BindFun
alwaysBindFun Bool
False TCvSubst
subst [Type
ty1] [Type
ty2]
tcMatchTys :: [Type]
-> [Type]
-> Maybe TCvSubst
tcMatchTys :: [Type] -> [Type] -> Maybe TCvSubst
tcMatchTys [Type]
tys1 [Type]
tys2
= BindFun -> Bool -> [Type] -> [Type] -> Maybe TCvSubst
tc_match_tys BindFun
alwaysBindFun Bool
False [Type]
tys1 [Type]
tys2
tcMatchTyKis :: [Type]
-> [Type]
-> Maybe TCvSubst
tcMatchTyKis :: [Type] -> [Type] -> Maybe TCvSubst
tcMatchTyKis [Type]
tys1 [Type]
tys2
= BindFun -> Bool -> [Type] -> [Type] -> Maybe TCvSubst
tc_match_tys BindFun
alwaysBindFun Bool
True [Type]
tys1 [Type]
tys2
tcMatchTysX :: TCvSubst
-> [Type]
-> [Type]
-> Maybe TCvSubst
tcMatchTysX :: TCvSubst -> [Type] -> [Type] -> Maybe TCvSubst
tcMatchTysX TCvSubst
subst [Type]
tys1 [Type]
tys2
= BindFun -> Bool -> TCvSubst -> [Type] -> [Type] -> Maybe TCvSubst
tc_match_tys_x BindFun
alwaysBindFun Bool
False TCvSubst
subst [Type]
tys1 [Type]
tys2
tcMatchTyKisX :: TCvSubst
-> [Type]
-> [Type]
-> Maybe TCvSubst
tcMatchTyKisX :: TCvSubst -> [Type] -> [Type] -> Maybe TCvSubst
tcMatchTyKisX TCvSubst
subst [Type]
tys1 [Type]
tys2
= BindFun -> Bool -> TCvSubst -> [Type] -> [Type] -> Maybe TCvSubst
tc_match_tys_x BindFun
alwaysBindFun Bool
True TCvSubst
subst [Type]
tys1 [Type]
tys2
tc_match_tys :: BindFun
-> Bool
-> [Type]
-> [Type]
-> Maybe TCvSubst
tc_match_tys :: BindFun -> Bool -> [Type] -> [Type] -> Maybe TCvSubst
tc_match_tys BindFun
bind_me Bool
match_kis [Type]
tys1 [Type]
tys2
= BindFun -> Bool -> TCvSubst -> [Type] -> [Type] -> Maybe TCvSubst
tc_match_tys_x BindFun
bind_me Bool
match_kis (InScopeSet -> TCvSubst
mkEmptyTCvSubst InScopeSet
in_scope) [Type]
tys1 [Type]
tys2
where
in_scope :: InScopeSet
in_scope = VarSet -> InScopeSet
mkInScopeSet ([Type] -> VarSet
tyCoVarsOfTypes [Type]
tys1 VarSet -> VarSet -> VarSet
`unionVarSet` [Type] -> VarSet
tyCoVarsOfTypes [Type]
tys2)
tc_match_tys_x :: BindFun
-> Bool
-> TCvSubst
-> [Type]
-> [Type]
-> Maybe TCvSubst
tc_match_tys_x :: BindFun -> Bool -> TCvSubst -> [Type] -> [Type] -> Maybe TCvSubst
tc_match_tys_x BindFun
bind_me Bool
match_kis (TCvSubst InScopeSet
in_scope TvSubstEnv
tv_env CvSubstEnv
cv_env) [Type]
tys1 [Type]
tys2
= case BindFun
-> Bool
-> Bool
-> Bool
-> RnEnv2
-> TvSubstEnv
-> CvSubstEnv
-> [Type]
-> [Type]
-> UnifyResultM (TvSubstEnv, CvSubstEnv)
tc_unify_tys BindFun
bind_me
Bool
False
Bool
False
Bool
match_kis
(InScopeSet -> RnEnv2
mkRnEnv2 InScopeSet
in_scope) TvSubstEnv
tv_env CvSubstEnv
cv_env [Type]
tys1 [Type]
tys2 of
Unifiable (TvSubstEnv
tv_env', CvSubstEnv
cv_env')
-> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
TCvSubst InScopeSet
in_scope TvSubstEnv
tv_env' CvSubstEnv
cv_env'
UnifyResultM (TvSubstEnv, CvSubstEnv)
_ -> forall a. Maybe a
Nothing
ruleMatchTyKiX
:: TyCoVarSet
-> RnEnv2
-> TvSubstEnv
-> Type
-> Type
-> Maybe TvSubstEnv
ruleMatchTyKiX :: VarSet -> RnEnv2 -> TvSubstEnv -> Type -> Type -> Maybe TvSubstEnv
ruleMatchTyKiX VarSet
tmpl_tvs RnEnv2
rn_env TvSubstEnv
tenv Type
tmpl Type
target
= case BindFun
-> Bool
-> Bool
-> Bool
-> RnEnv2
-> TvSubstEnv
-> CvSubstEnv
-> [Type]
-> [Type]
-> UnifyResultM (TvSubstEnv, CvSubstEnv)
tc_unify_tys (VarSet -> BindFun
matchBindFun VarSet
tmpl_tvs) Bool
False Bool
False
Bool
True
RnEnv2
rn_env TvSubstEnv
tenv CvSubstEnv
emptyCvSubstEnv [Type
tmpl] [Type
target] of
Unifiable (TvSubstEnv
tenv', CvSubstEnv
_) -> forall a. a -> Maybe a
Just TvSubstEnv
tenv'
UnifyResultM (TvSubstEnv, CvSubstEnv)
_ -> forall a. Maybe a
Nothing
matchBindFun :: TyCoVarSet -> BindFun
matchBindFun :: VarSet -> BindFun
matchBindFun VarSet
tvs OutTyVar
tv Type
_ty
| OutTyVar
tv OutTyVar -> VarSet -> Bool
`elemVarSet` VarSet
tvs = BindFlag
BindMe
| Bool
otherwise = BindFlag
Apart
alwaysBindFun :: BindFun
alwaysBindFun :: BindFun
alwaysBindFun OutTyVar
_tv Type
_ty = BindFlag
BindMe
data RoughMatchTc
= KnownTc Name
| OtherTc
deriving( Typeable RoughMatchTc
RoughMatchTc -> DataType
RoughMatchTc -> Constr
(forall b. Data b => b -> b) -> RoughMatchTc -> RoughMatchTc
forall a.
Typeable a
-> (forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Arity -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u.
Arity -> (forall d. Data d => d -> u) -> RoughMatchTc -> u
forall u. (forall d. Data d => d -> u) -> RoughMatchTc -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> RoughMatchTc -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> RoughMatchTc -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> RoughMatchTc -> m RoughMatchTc
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> RoughMatchTc -> m RoughMatchTc
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c RoughMatchTc
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> RoughMatchTc -> c RoughMatchTc
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c RoughMatchTc)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c RoughMatchTc)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> RoughMatchTc -> m RoughMatchTc
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> RoughMatchTc -> m RoughMatchTc
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> RoughMatchTc -> m RoughMatchTc
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> RoughMatchTc -> m RoughMatchTc
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> RoughMatchTc -> m RoughMatchTc
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> RoughMatchTc -> m RoughMatchTc
gmapQi :: forall u.
Arity -> (forall d. Data d => d -> u) -> RoughMatchTc -> u
$cgmapQi :: forall u.
Arity -> (forall d. Data d => d -> u) -> RoughMatchTc -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> RoughMatchTc -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> RoughMatchTc -> [u]
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> RoughMatchTc -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> RoughMatchTc -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> RoughMatchTc -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> RoughMatchTc -> r
gmapT :: (forall b. Data b => b -> b) -> RoughMatchTc -> RoughMatchTc
$cgmapT :: (forall b. Data b => b -> b) -> RoughMatchTc -> RoughMatchTc
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c RoughMatchTc)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c RoughMatchTc)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c RoughMatchTc)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c RoughMatchTc)
dataTypeOf :: RoughMatchTc -> DataType
$cdataTypeOf :: RoughMatchTc -> DataType
toConstr :: RoughMatchTc -> Constr
$ctoConstr :: RoughMatchTc -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c RoughMatchTc
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c RoughMatchTc
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> RoughMatchTc -> c RoughMatchTc
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> RoughMatchTc -> c RoughMatchTc
Data )
isRoughOtherTc :: RoughMatchTc -> Bool
isRoughOtherTc :: RoughMatchTc -> Bool
isRoughOtherTc RoughMatchTc
OtherTc = Bool
True
isRoughOtherTc (KnownTc {}) = Bool
False
roughMatchTcs :: [Type] -> [RoughMatchTc]
roughMatchTcs :: [Type] -> [RoughMatchTc]
roughMatchTcs [Type]
tys = forall a b. (a -> b) -> [a] -> [b]
map Type -> RoughMatchTc
rough [Type]
tys
where
rough :: Type -> RoughMatchTc
rough Type
ty
| Just (Type
ty', Coercion
_) <- Type -> Maybe (Type, Coercion)
splitCastTy_maybe Type
ty = Type -> RoughMatchTc
rough Type
ty'
| Just (TyCon
tc,[Type]
_) <- HasDebugCallStack => Type -> Maybe (TyCon, [Type])
splitTyConApp_maybe Type
ty
, Bool -> Bool
not (TyCon -> Bool
isTypeFamilyTyCon TyCon
tc) = ASSERT2( isGenerativeTyCon tc Nominal, ppr tc )
Name -> RoughMatchTc
KnownTc (TyCon -> Name
tyConName TyCon
tc)
| Bool
otherwise = RoughMatchTc
OtherTc
instanceCantMatch :: [RoughMatchTc] -> [RoughMatchTc] -> Bool
instanceCantMatch :: [RoughMatchTc] -> [RoughMatchTc] -> Bool
instanceCantMatch (RoughMatchTc
mt : [RoughMatchTc]
ts) (RoughMatchTc
ma : [RoughMatchTc]
as) = RoughMatchTc -> RoughMatchTc -> Bool
itemCantMatch RoughMatchTc
mt RoughMatchTc
ma Bool -> Bool -> Bool
|| [RoughMatchTc] -> [RoughMatchTc] -> Bool
instanceCantMatch [RoughMatchTc]
ts [RoughMatchTc]
as
instanceCantMatch [RoughMatchTc]
_ [RoughMatchTc]
_ = Bool
False
itemCantMatch :: RoughMatchTc -> RoughMatchTc -> Bool
itemCantMatch :: RoughMatchTc -> RoughMatchTc -> Bool
itemCantMatch (KnownTc Name
t) (KnownTc Name
a) = Name
t forall a. Eq a => a -> a -> Bool
/= Name
a
itemCantMatch RoughMatchTc
_ RoughMatchTc
_ = Bool
False
typesCantMatch :: [(Type,Type)] -> Bool
typesCantMatch :: [(Type, Type)] -> Bool
typesCantMatch [(Type, Type)]
prs = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Type -> Type -> Bool
cant_match) [(Type, Type)]
prs
where
cant_match :: Type -> Type -> Bool
cant_match :: Type -> Type -> Bool
cant_match Type
t1 Type
t2 = case BindFun -> [Type] -> [Type] -> UnifyResult
tcUnifyTysFG BindFun
alwaysBindFun [Type
t1] [Type
t2] of
UnifyResult
SurelyApart -> Bool
True
UnifyResult
_ -> Bool
False
tcUnifyTy :: Type -> Type
-> Maybe TCvSubst
tcUnifyTy :: Type -> Type -> Maybe TCvSubst
tcUnifyTy Type
t1 Type
t2 = BindFun -> [Type] -> [Type] -> Maybe TCvSubst
tcUnifyTys BindFun
alwaysBindFun [Type
t1] [Type
t2]
tcUnifyTyKi :: Type -> Type -> Maybe TCvSubst
tcUnifyTyKi :: Type -> Type -> Maybe TCvSubst
tcUnifyTyKi Type
t1 Type
t2 = BindFun -> [Type] -> [Type] -> Maybe TCvSubst
tcUnifyTyKis BindFun
alwaysBindFun [Type
t1] [Type
t2]
tcUnifyTyWithTFs :: Bool
-> Type -> Type -> Maybe TCvSubst
tcUnifyTyWithTFs :: Bool -> Type -> Type -> Maybe TCvSubst
tcUnifyTyWithTFs Bool
twoWay Type
t1 Type
t2
= case BindFun
-> Bool
-> Bool
-> Bool
-> RnEnv2
-> TvSubstEnv
-> CvSubstEnv
-> [Type]
-> [Type]
-> UnifyResultM (TvSubstEnv, CvSubstEnv)
tc_unify_tys BindFun
alwaysBindFun Bool
twoWay Bool
True Bool
False
RnEnv2
rn_env TvSubstEnv
emptyTvSubstEnv CvSubstEnv
emptyCvSubstEnv
[Type
t1] [Type
t2] of
Unifiable (TvSubstEnv
subst, CvSubstEnv
_) -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ TvSubstEnv -> TCvSubst
maybe_fix TvSubstEnv
subst
MaybeApart MaybeApartReason
_reason (TvSubstEnv
subst, CvSubstEnv
_) -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ TvSubstEnv -> TCvSubst
maybe_fix TvSubstEnv
subst
UnifyResultM (TvSubstEnv, CvSubstEnv)
SurelyApart -> forall a. Maybe a
Nothing
where
in_scope :: InScopeSet
in_scope = VarSet -> InScopeSet
mkInScopeSet forall a b. (a -> b) -> a -> b
$ [Type] -> VarSet
tyCoVarsOfTypes [Type
t1, Type
t2]
rn_env :: RnEnv2
rn_env = InScopeSet -> RnEnv2
mkRnEnv2 InScopeSet
in_scope
maybe_fix :: TvSubstEnv -> TCvSubst
maybe_fix | Bool
twoWay = TvSubstEnv -> TCvSubst
niFixTCvSubst
| Bool
otherwise = InScopeSet -> TvSubstEnv -> TCvSubst
mkTvSubst InScopeSet
in_scope
tcUnifyTys :: BindFun
-> [Type] -> [Type]
-> Maybe TCvSubst
tcUnifyTys :: BindFun -> [Type] -> [Type] -> Maybe TCvSubst
tcUnifyTys BindFun
bind_fn [Type]
tys1 [Type]
tys2
= case BindFun -> [Type] -> [Type] -> UnifyResult
tcUnifyTysFG BindFun
bind_fn [Type]
tys1 [Type]
tys2 of
Unifiable TCvSubst
result -> forall a. a -> Maybe a
Just TCvSubst
result
UnifyResult
_ -> forall a. Maybe a
Nothing
tcUnifyTyKis :: BindFun
-> [Type] -> [Type]
-> Maybe TCvSubst
tcUnifyTyKis :: BindFun -> [Type] -> [Type] -> Maybe TCvSubst
tcUnifyTyKis BindFun
bind_fn [Type]
tys1 [Type]
tys2
= case BindFun -> [Type] -> [Type] -> UnifyResult
tcUnifyTyKisFG BindFun
bind_fn [Type]
tys1 [Type]
tys2 of
Unifiable TCvSubst
result -> forall a. a -> Maybe a
Just TCvSubst
result
UnifyResult
_ -> forall a. Maybe a
Nothing
type UnifyResult = UnifyResultM TCvSubst
data UnifyResultM a = Unifiable a
| MaybeApart MaybeApartReason
a
| SurelyApart
deriving forall a b. a -> UnifyResultM b -> UnifyResultM a
forall a b. (a -> b) -> UnifyResultM a -> UnifyResultM b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> UnifyResultM b -> UnifyResultM a
$c<$ :: forall a b. a -> UnifyResultM b -> UnifyResultM a
fmap :: forall a b. (a -> b) -> UnifyResultM a -> UnifyResultM b
$cfmap :: forall a b. (a -> b) -> UnifyResultM a -> UnifyResultM b
Functor
data MaybeApartReason = MARTypeFamily
| MARInfinite
instance Outputable MaybeApartReason where
ppr :: MaybeApartReason -> SDoc
ppr MaybeApartReason
MARTypeFamily = String -> SDoc
text String
"MARTypeFamily"
ppr MaybeApartReason
MARInfinite = String -> SDoc
text String
"MARInfinite"
instance Semigroup MaybeApartReason where
MaybeApartReason
MARTypeFamily <> :: MaybeApartReason -> MaybeApartReason -> MaybeApartReason
<> MaybeApartReason
r = MaybeApartReason
r
MaybeApartReason
MARInfinite <> MaybeApartReason
_ = MaybeApartReason
MARInfinite
instance Applicative UnifyResultM where
pure :: forall a. a -> UnifyResultM a
pure = forall a. a -> UnifyResultM a
Unifiable
<*> :: forall a b.
UnifyResultM (a -> b) -> UnifyResultM a -> UnifyResultM b
(<*>) = forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance Monad UnifyResultM where
UnifyResultM a
SurelyApart >>= :: forall a b.
UnifyResultM a -> (a -> UnifyResultM b) -> UnifyResultM b
>>= a -> UnifyResultM b
_ = forall a. UnifyResultM a
SurelyApart
MaybeApart MaybeApartReason
r1 a
x >>= a -> UnifyResultM b
f = case a -> UnifyResultM b
f a
x of
Unifiable b
y -> forall a. MaybeApartReason -> a -> UnifyResultM a
MaybeApart MaybeApartReason
r1 b
y
MaybeApart MaybeApartReason
r2 b
y -> forall a. MaybeApartReason -> a -> UnifyResultM a
MaybeApart (MaybeApartReason
r1 forall a. Semigroup a => a -> a -> a
S.<> MaybeApartReason
r2) b
y
UnifyResultM b
SurelyApart -> forall a. UnifyResultM a
SurelyApart
Unifiable a
x >>= a -> UnifyResultM b
f = a -> UnifyResultM b
f a
x
tcUnifyTysFG :: BindFun
-> [Type] -> [Type]
-> UnifyResult
tcUnifyTysFG :: BindFun -> [Type] -> [Type] -> UnifyResult
tcUnifyTysFG BindFun
bind_fn [Type]
tys1 [Type]
tys2
= Bool -> BindFun -> [Type] -> [Type] -> UnifyResult
tc_unify_tys_fg Bool
False BindFun
bind_fn [Type]
tys1 [Type]
tys2
tcUnifyTyKisFG :: BindFun
-> [Type] -> [Type]
-> UnifyResult
tcUnifyTyKisFG :: BindFun -> [Type] -> [Type] -> UnifyResult
tcUnifyTyKisFG BindFun
bind_fn [Type]
tys1 [Type]
tys2
= Bool -> BindFun -> [Type] -> [Type] -> UnifyResult
tc_unify_tys_fg Bool
True BindFun
bind_fn [Type]
tys1 [Type]
tys2
tc_unify_tys_fg :: Bool
-> BindFun
-> [Type] -> [Type]
-> UnifyResult
tc_unify_tys_fg :: Bool -> BindFun -> [Type] -> [Type] -> UnifyResult
tc_unify_tys_fg Bool
match_kis BindFun
bind_fn [Type]
tys1 [Type]
tys2
= do { (TvSubstEnv
env, CvSubstEnv
_) <- BindFun
-> Bool
-> Bool
-> Bool
-> RnEnv2
-> TvSubstEnv
-> CvSubstEnv
-> [Type]
-> [Type]
-> UnifyResultM (TvSubstEnv, CvSubstEnv)
tc_unify_tys BindFun
bind_fn Bool
True Bool
False Bool
match_kis RnEnv2
env
TvSubstEnv
emptyTvSubstEnv CvSubstEnv
emptyCvSubstEnv
[Type]
tys1 [Type]
tys2
; forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ TvSubstEnv -> TCvSubst
niFixTCvSubst TvSubstEnv
env }
where
vars :: VarSet
vars = [Type] -> VarSet
tyCoVarsOfTypes [Type]
tys1 VarSet -> VarSet -> VarSet
`unionVarSet` [Type] -> VarSet
tyCoVarsOfTypes [Type]
tys2
env :: RnEnv2
env = InScopeSet -> RnEnv2
mkRnEnv2 forall a b. (a -> b) -> a -> b
$ VarSet -> InScopeSet
mkInScopeSet VarSet
vars
tc_unify_tys :: BindFun
-> AmIUnifying
-> Bool
-> Bool
-> RnEnv2
-> TvSubstEnv
-> CvSubstEnv
-> [Type] -> [Type]
-> UnifyResultM (TvSubstEnv, CvSubstEnv)
tc_unify_tys :: BindFun
-> Bool
-> Bool
-> Bool
-> RnEnv2
-> TvSubstEnv
-> CvSubstEnv
-> [Type]
-> [Type]
-> UnifyResultM (TvSubstEnv, CvSubstEnv)
tc_unify_tys BindFun
bind_fn Bool
unif Bool
inj_check Bool
match_kis RnEnv2
rn_env TvSubstEnv
tv_env CvSubstEnv
cv_env [Type]
tys1 [Type]
tys2
= forall a. TvSubstEnv -> CvSubstEnv -> UM a -> UnifyResultM a
initUM TvSubstEnv
tv_env CvSubstEnv
cv_env forall a b. (a -> b) -> a -> b
$
do { forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
match_kis forall a b. (a -> b) -> a -> b
$
UMEnv -> [Type] -> [Type] -> UM ()
unify_tys UMEnv
env [Type]
kis1 [Type]
kis2
; UMEnv -> [Type] -> [Type] -> UM ()
unify_tys UMEnv
env [Type]
tys1 [Type]
tys2
; (,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> UM TvSubstEnv
getTvSubstEnv forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> UM CvSubstEnv
getCvSubstEnv }
where
env :: UMEnv
env = UMEnv { um_bind_fun :: BindFun
um_bind_fun = BindFun
bind_fn
, um_skols :: VarSet
um_skols = VarSet
emptyVarSet
, um_unif :: Bool
um_unif = Bool
unif
, um_inj_tf :: Bool
um_inj_tf = Bool
inj_check
, um_rn_env :: RnEnv2
um_rn_env = RnEnv2
rn_env }
kis1 :: [Type]
kis1 = forall a b. (a -> b) -> [a] -> [b]
map HasDebugCallStack => Type -> Type
typeKind [Type]
tys1
kis2 :: [Type]
kis2 = forall a b. (a -> b) -> [a] -> [b]
map HasDebugCallStack => Type -> Type
typeKind [Type]
tys2
instance Outputable a => Outputable (UnifyResultM a) where
ppr :: UnifyResultM a -> SDoc
ppr UnifyResultM a
SurelyApart = String -> SDoc
text String
"SurelyApart"
ppr (Unifiable a
x) = String -> SDoc
text String
"Unifiable" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr a
x
ppr (MaybeApart MaybeApartReason
r a
x) = String -> SDoc
text String
"MaybeApart" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr MaybeApartReason
r SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr a
x
niFixTCvSubst :: TvSubstEnv -> TCvSubst
niFixTCvSubst :: TvSubstEnv -> TCvSubst
niFixTCvSubst TvSubstEnv
tenv
| Bool
not_fixpoint = TvSubstEnv -> TCvSubst
niFixTCvSubst (forall a b. (a -> b) -> VarEnv a -> VarEnv b
mapVarEnv (HasCallStack => TCvSubst -> Type -> Type
substTy TCvSubst
subst) TvSubstEnv
tenv)
| Bool
otherwise = TCvSubst
subst
where
range_fvs :: FV
range_fvs :: FV
range_fvs = [Type] -> FV
tyCoFVsOfTypes (forall key elt. UniqFM key elt -> [elt]
nonDetEltsUFM TvSubstEnv
tenv)
range_tvs :: [TyVar]
range_tvs :: [OutTyVar]
range_tvs = FV -> [OutTyVar]
fvVarList FV
range_fvs
not_fixpoint :: Bool
not_fixpoint = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any OutTyVar -> Bool
in_domain [OutTyVar]
range_tvs
in_domain :: OutTyVar -> Bool
in_domain OutTyVar
tv = OutTyVar
tv forall a. OutTyVar -> VarEnv a -> Bool
`elemVarEnv` TvSubstEnv
tenv
free_tvs :: [OutTyVar]
free_tvs = [OutTyVar] -> [OutTyVar]
scopedSort (forall a. (a -> Bool) -> [a] -> [a]
filterOut OutTyVar -> Bool
in_domain [OutTyVar]
range_tvs)
init_in_scope :: InScopeSet
init_in_scope = VarSet -> InScopeSet
mkInScopeSet (FV -> VarSet
fvVarSet FV
range_fvs)
subst :: TCvSubst
subst = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' TCvSubst -> OutTyVar -> TCvSubst
add_free_tv
(InScopeSet -> TvSubstEnv -> TCvSubst
mkTvSubst InScopeSet
init_in_scope TvSubstEnv
tenv)
[OutTyVar]
free_tvs
add_free_tv :: TCvSubst -> TyVar -> TCvSubst
add_free_tv :: TCvSubst -> OutTyVar -> TCvSubst
add_free_tv TCvSubst
subst OutTyVar
tv
= TCvSubst -> OutTyVar -> Type -> TCvSubst
extendTvSubst TCvSubst
subst OutTyVar
tv (OutTyVar -> Type
mkTyVarTy OutTyVar
tv')
where
tv' :: OutTyVar
tv' = (Type -> Type) -> OutTyVar -> OutTyVar
updateTyVarKind (HasCallStack => TCvSubst -> Type -> Type
substTy TCvSubst
subst) OutTyVar
tv
niSubstTvSet :: TvSubstEnv -> TyCoVarSet -> TyCoVarSet
niSubstTvSet :: TvSubstEnv -> VarSet -> VarSet
niSubstTvSet TvSubstEnv
tsubst VarSet
tvs
= forall elt a. (elt -> a -> a) -> a -> UniqSet elt -> a
nonDetStrictFoldUniqSet (VarSet -> VarSet -> VarSet
unionVarSet forall b c a. (b -> c) -> (a -> b) -> a -> c
. OutTyVar -> VarSet
get) VarSet
emptyVarSet VarSet
tvs
where
get :: OutTyVar -> VarSet
get OutTyVar
tv
| Just Type
ty <- forall a. VarEnv a -> OutTyVar -> Maybe a
lookupVarEnv TvSubstEnv
tsubst OutTyVar
tv
= TvSubstEnv -> VarSet -> VarSet
niSubstTvSet TvSubstEnv
tsubst (Type -> VarSet
tyCoVarsOfType Type
ty)
| Bool
otherwise
= OutTyVar -> VarSet
unitVarSet OutTyVar
tv
type AmIUnifying = Bool
unify_ty :: UMEnv
-> Type -> Type
-> CoercionN
-> UM ()
unify_ty :: UMEnv -> Type -> Type -> Coercion -> UM ()
unify_ty UMEnv
env Type
ty1 Type
ty2 Coercion
kco
| TyConApp TyCon
tc1 [] <- Type
ty1
, TyConApp TyCon
tc2 [] <- Type
ty2
, TyCon
tc1 forall a. Eq a => a -> a -> Bool
== TyCon
tc2 = forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Just Type
ty1' <- Type -> Maybe Type
tcView Type
ty1 = UMEnv -> Type -> Type -> Coercion -> UM ()
unify_ty UMEnv
env Type
ty1' Type
ty2 Coercion
kco
| Just Type
ty2' <- Type -> Maybe Type
tcView Type
ty2 = UMEnv -> Type -> Type -> Coercion -> UM ()
unify_ty UMEnv
env Type
ty1 Type
ty2' Coercion
kco
| CastTy Type
ty1' Coercion
co <- Type
ty1 = if UMEnv -> Bool
um_unif UMEnv
env
then UMEnv -> Type -> Type -> Coercion -> UM ()
unify_ty UMEnv
env Type
ty1' Type
ty2 (Coercion
co Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
kco)
else
do { TCvSubst
subst <- UMEnv -> UM TCvSubst
getSubst UMEnv
env
; let co' :: Coercion
co' = HasCallStack => TCvSubst -> Coercion -> Coercion
substCo TCvSubst
subst Coercion
co
; UMEnv -> Type -> Type -> Coercion -> UM ()
unify_ty UMEnv
env Type
ty1' Type
ty2 (Coercion
co' Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
kco) }
| CastTy Type
ty2' Coercion
co <- Type
ty2 = UMEnv -> Type -> Type -> Coercion -> UM ()
unify_ty UMEnv
env Type
ty1 Type
ty2' (Coercion
kco Coercion -> Coercion -> Coercion
`mkTransCo` Coercion -> Coercion
mkSymCo Coercion
co)
unify_ty UMEnv
env (TyVarTy OutTyVar
tv1) Type
ty2 Coercion
kco
= UMEnv -> OutTyVar -> Type -> Coercion -> UM ()
uVar UMEnv
env OutTyVar
tv1 Type
ty2 Coercion
kco
unify_ty UMEnv
env Type
ty1 (TyVarTy OutTyVar
tv2) Coercion
kco
| UMEnv -> Bool
um_unif UMEnv
env
= UMEnv -> OutTyVar -> Type -> Coercion -> UM ()
uVar (UMEnv -> UMEnv
umSwapRn UMEnv
env) OutTyVar
tv2 Type
ty1 (Coercion -> Coercion
mkSymCo Coercion
kco)
unify_ty UMEnv
env Type
ty1 Type
ty2 Coercion
_kco
| Just (TyCon
tc1, [Type]
tys1) <- Maybe (TyCon, [Type])
mb_tc_app1
, Just (TyCon
tc2, [Type]
tys2) <- Maybe (TyCon, [Type])
mb_tc_app2
, TyCon
tc1 forall a. Eq a => a -> a -> Bool
== TyCon
tc2
= if TyCon -> Role -> Bool
isInjectiveTyCon TyCon
tc1 Role
Nominal
then UMEnv -> [Type] -> [Type] -> UM ()
unify_tys UMEnv
env [Type]
tys1 [Type]
tys2
else do { let inj :: [Bool]
inj | TyCon -> Bool
isTypeFamilyTyCon TyCon
tc1
= case TyCon -> Injectivity
tyConInjectivityInfo TyCon
tc1 of
Injectivity
NotInjective -> forall a. a -> [a]
repeat Bool
False
Injective [Bool]
bs -> [Bool]
bs
| Bool
otherwise
= forall a. a -> [a]
repeat Bool
False
([Type]
inj_tys1, [Type]
noninj_tys1) = forall a. [Bool] -> [a] -> ([a], [a])
partitionByList [Bool]
inj [Type]
tys1
([Type]
inj_tys2, [Type]
noninj_tys2) = forall a. [Bool] -> [a] -> ([a], [a])
partitionByList [Bool]
inj [Type]
tys2
; UMEnv -> [Type] -> [Type] -> UM ()
unify_tys UMEnv
env [Type]
inj_tys1 [Type]
inj_tys2
; forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (UMEnv -> Bool
um_inj_tf UMEnv
env) forall a b. (a -> b) -> a -> b
$
MaybeApartReason -> UM () -> UM ()
don'tBeSoSure MaybeApartReason
MARTypeFamily forall a b. (a -> b) -> a -> b
$ UMEnv -> [Type] -> [Type] -> UM ()
unify_tys UMEnv
env [Type]
noninj_tys1 [Type]
noninj_tys2 }
| Maybe (TyCon, [Type]) -> Bool
isTyFamApp Maybe (TyCon, [Type])
mb_tc_app1
= MaybeApartReason -> UM ()
maybeApart MaybeApartReason
MARTypeFamily
| Maybe (TyCon, [Type]) -> Bool
isTyFamApp Maybe (TyCon, [Type])
mb_tc_app2
, UMEnv -> Bool
um_unif UMEnv
env
= MaybeApartReason -> UM ()
maybeApart MaybeApartReason
MARTypeFamily
where
mb_tc_app1 :: Maybe (TyCon, [Type])
mb_tc_app1 = HasCallStack => Type -> Maybe (TyCon, [Type])
tcSplitTyConApp_maybe Type
ty1
mb_tc_app2 :: Maybe (TyCon, [Type])
mb_tc_app2 = HasCallStack => Type -> Maybe (TyCon, [Type])
tcSplitTyConApp_maybe Type
ty2
unify_ty UMEnv
env (AppTy Type
ty1a Type
ty1b) Type
ty2 Coercion
_kco
| Just (Type
ty2a, Type
ty2b) <- Type -> Maybe (Type, Type)
tcRepSplitAppTy_maybe Type
ty2
= UMEnv -> Type -> [Type] -> Type -> [Type] -> UM ()
unify_ty_app UMEnv
env Type
ty1a [Type
ty1b] Type
ty2a [Type
ty2b]
unify_ty UMEnv
env Type
ty1 (AppTy Type
ty2a Type
ty2b) Coercion
_kco
| Just (Type
ty1a, Type
ty1b) <- Type -> Maybe (Type, Type)
tcRepSplitAppTy_maybe Type
ty1
= UMEnv -> Type -> [Type] -> Type -> [Type] -> UM ()
unify_ty_app UMEnv
env Type
ty1a [Type
ty1b] Type
ty2a [Type
ty2b]
unify_ty UMEnv
env (FunTy AnonArgFlag
InvisArg Type
_w1 Type
arg1 Type
res1) (FunTy AnonArgFlag
InvisArg Type
_w2 Type
arg2 Type
res2) Coercion
_kco
| Just Type
res_rep1 <- HasDebugCallStack => Type -> Maybe Type
getRuntimeRep_maybe Type
res1
, Just Type
res_rep2 <- HasDebugCallStack => Type -> Maybe Type
getRuntimeRep_maybe Type
res2
= UMEnv -> [Type] -> [Type] -> UM ()
unify_tys UMEnv
env [Type
res_rep1, Type
arg1, Type
res1] [Type
res_rep2, Type
arg2, Type
res2]
unify_ty UMEnv
_ (LitTy TyLit
x) (LitTy TyLit
y) Coercion
_kco | TyLit
x forall a. Eq a => a -> a -> Bool
== TyLit
y = forall (m :: * -> *) a. Monad m => a -> m a
return ()
unify_ty UMEnv
env (ForAllTy (Bndr OutTyVar
tv1 ArgFlag
_) Type
ty1) (ForAllTy (Bndr OutTyVar
tv2 ArgFlag
_) Type
ty2) Coercion
kco
= do { UMEnv -> Type -> Type -> Coercion -> UM ()
unify_ty UMEnv
env (OutTyVar -> Type
varType OutTyVar
tv1) (OutTyVar -> Type
varType OutTyVar
tv2) (Type -> Coercion
mkNomReflCo Type
liftedTypeKind)
; let env' :: UMEnv
env' = UMEnv -> OutTyVar -> OutTyVar -> UMEnv
umRnBndr2 UMEnv
env OutTyVar
tv1 OutTyVar
tv2
; UMEnv -> Type -> Type -> Coercion -> UM ()
unify_ty UMEnv
env' Type
ty1 Type
ty2 Coercion
kco }
unify_ty UMEnv
env (CoercionTy Coercion
co1) (CoercionTy Coercion
co2) Coercion
kco
= do { CvSubstEnv
c_subst <- UM CvSubstEnv
getCvSubstEnv
; case Coercion
co1 of
CoVarCo OutTyVar
cv
| Bool -> Bool
not (UMEnv -> Bool
um_unif UMEnv
env)
, Bool -> Bool
not (OutTyVar
cv forall a. OutTyVar -> VarEnv a -> Bool
`elemVarEnv` CvSubstEnv
c_subst)
, let (Coercion
_, Coercion
co_l, Coercion
co_r) = HasDebugCallStack =>
Role -> Coercion -> (Coercion, Coercion, Coercion)
decomposeFunCo Role
Nominal Coercion
kco
rhs_co :: Coercion
rhs_co = Coercion
co_l Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
co2 Coercion -> Coercion -> Coercion
`mkTransCo` Coercion -> Coercion
mkSymCo Coercion
co_r
, BindFlag
BindMe <- UMEnv -> BindFun
tvBindFlag UMEnv
env OutTyVar
cv (Coercion -> Type
CoercionTy Coercion
rhs_co)
-> do { UMEnv -> VarSet -> UM ()
checkRnEnv UMEnv
env (Coercion -> VarSet
tyCoVarsOfCo Coercion
co2)
; OutTyVar -> Coercion -> UM ()
extendCvEnv OutTyVar
cv Coercion
rhs_co }
Coercion
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return () }
unify_ty UMEnv
_ Type
_ Type
_ Coercion
_ = forall a. UM a
surelyApart
unify_ty_app :: UMEnv -> Type -> [Type] -> Type -> [Type] -> UM ()
unify_ty_app :: UMEnv -> Type -> [Type] -> Type -> [Type] -> UM ()
unify_ty_app UMEnv
env Type
ty1 [Type]
ty1args Type
ty2 [Type]
ty2args
| Just (Type
ty1', Type
ty1a) <- HasDebugCallStack => Type -> Maybe (Type, Type)
repSplitAppTy_maybe Type
ty1
, Just (Type
ty2', Type
ty2a) <- HasDebugCallStack => Type -> Maybe (Type, Type)
repSplitAppTy_maybe Type
ty2
= UMEnv -> Type -> [Type] -> Type -> [Type] -> UM ()
unify_ty_app UMEnv
env Type
ty1' (Type
ty1a forall a. a -> [a] -> [a]
: [Type]
ty1args) Type
ty2' (Type
ty2a forall a. a -> [a] -> [a]
: [Type]
ty2args)
| Bool
otherwise
= do { let ki1 :: Type
ki1 = HasDebugCallStack => Type -> Type
typeKind Type
ty1
ki2 :: Type
ki2 = HasDebugCallStack => Type -> Type
typeKind Type
ty2
; UMEnv -> Type -> Type -> Coercion -> UM ()
unify_ty UMEnv
env Type
ki1 Type
ki2 (Type -> Coercion
mkNomReflCo Type
liftedTypeKind)
; UMEnv -> Type -> Type -> Coercion -> UM ()
unify_ty UMEnv
env Type
ty1 Type
ty2 (Type -> Coercion
mkNomReflCo Type
ki2)
; UMEnv -> [Type] -> [Type] -> UM ()
unify_tys UMEnv
env [Type]
ty1args [Type]
ty2args }
unify_tys :: UMEnv -> [Type] -> [Type] -> UM ()
unify_tys :: UMEnv -> [Type] -> [Type] -> UM ()
unify_tys UMEnv
env [Type]
orig_xs [Type]
orig_ys
= [Type] -> [Type] -> UM ()
go [Type]
orig_xs [Type]
orig_ys
where
go :: [Type] -> [Type] -> UM ()
go [] [] = forall (m :: * -> *) a. Monad m => a -> m a
return ()
go (Type
x:[Type]
xs) (Type
y:[Type]
ys)
= do { UMEnv -> Type -> Type -> Coercion -> UM ()
unify_ty UMEnv
env Type
x Type
y (Type -> Coercion
mkNomReflCo forall a b. (a -> b) -> a -> b
$ HasDebugCallStack => Type -> Type
typeKind Type
y)
; [Type] -> [Type] -> UM ()
go [Type]
xs [Type]
ys }
go [Type]
_ [Type]
_ = forall a. UM a
surelyApart
isTyFamApp :: Maybe (TyCon, [Type]) -> Bool
isTyFamApp :: Maybe (TyCon, [Type]) -> Bool
isTyFamApp (Just (TyCon
tc, [Type]
tys))
= Bool -> Bool
not (TyCon -> Role -> Bool
isGenerativeTyCon TyCon
tc Role
Nominal)
Bool -> Bool -> Bool
&& Bool -> Bool
not ([Type]
tys forall a. [a] -> Arity -> Bool
`lengthExceeds` TyCon -> Arity
tyConArity TyCon
tc)
isTyFamApp Maybe (TyCon, [Type])
Nothing
= Bool
False
uVar :: UMEnv
-> InTyVar
-> Type
-> Coercion
-> UM ()
uVar :: UMEnv -> OutTyVar -> Type -> Coercion -> UM ()
uVar UMEnv
env OutTyVar
tv1 Type
ty Coercion
kco
= do {
let tv1' :: OutTyVar
tv1' = UMEnv -> OutTyVar -> OutTyVar
umRnOccL UMEnv
env OutTyVar
tv1
; TvSubstEnv
subst <- UM TvSubstEnv
getTvSubstEnv
; case (forall a. VarEnv a -> OutTyVar -> Maybe a
lookupVarEnv TvSubstEnv
subst OutTyVar
tv1') of
Just Type
ty' | UMEnv -> Bool
um_unif UMEnv
env
-> UMEnv -> Type -> Type -> Coercion -> UM ()
unify_ty UMEnv
env Type
ty' Type
ty Coercion
kco
| Bool
otherwise
->
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ((Type
ty' Type -> Coercion -> Type
`mkCastTy` Coercion
kco) Type -> Type -> Bool
`eqType` Type
ty) forall a b. (a -> b) -> a -> b
$
forall a. UM a
surelyApart
Maybe Type
Nothing -> UMEnv -> OutTyVar -> Type -> Type -> Coercion -> UM ()
uUnrefined UMEnv
env OutTyVar
tv1' Type
ty Type
ty Coercion
kco }
uUnrefined :: UMEnv
-> OutTyVar
-> Type
-> Type
-> Coercion
-> UM ()
uUnrefined :: UMEnv -> OutTyVar -> Type -> Type -> Coercion -> UM ()
uUnrefined UMEnv
env OutTyVar
tv1' Type
ty2 Type
ty2' Coercion
kco
| Just Type
ty2'' <- Type -> Maybe Type
tcView Type
ty2'
= UMEnv -> OutTyVar -> Type -> Type -> Coercion -> UM ()
uUnrefined UMEnv
env OutTyVar
tv1' Type
ty2 Type
ty2'' Coercion
kco
| TyVarTy OutTyVar
tv2 <- Type
ty2'
= do { let tv2' :: OutTyVar
tv2' = UMEnv -> OutTyVar -> OutTyVar
umRnOccR UMEnv
env OutTyVar
tv2
; forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (OutTyVar
tv1' forall a. Eq a => a -> a -> Bool
== OutTyVar
tv2' Bool -> Bool -> Bool
&& UMEnv -> Bool
um_unif UMEnv
env) forall a b. (a -> b) -> a -> b
$ do
{ TvSubstEnv
subst <- UM TvSubstEnv
getTvSubstEnv
; case forall a. VarEnv a -> OutTyVar -> Maybe a
lookupVarEnv TvSubstEnv
subst OutTyVar
tv2 of
{ Just Type
ty' | UMEnv -> Bool
um_unif UMEnv
env -> UMEnv -> OutTyVar -> Type -> Type -> Coercion -> UM ()
uUnrefined UMEnv
env OutTyVar
tv1' Type
ty' Type
ty' Coercion
kco
; Maybe Type
_ ->
do {
; let rhs1 :: Type
rhs1 = Type
ty2 Type -> Coercion -> Type
`mkCastTy` Coercion -> Coercion
mkSymCo Coercion
kco
rhs2 :: Type
rhs2 = Type
ty1 Type -> Coercion -> Type
`mkCastTy` Coercion
kco
b1 :: BindFlag
b1 = UMEnv -> BindFun
tvBindFlag UMEnv
env OutTyVar
tv1' Type
rhs1
b2 :: BindFlag
b2 = UMEnv -> BindFun
tvBindFlag UMEnv
env OutTyVar
tv2' Type
rhs2
ty1 :: Type
ty1 = OutTyVar -> Type
mkTyVarTy OutTyVar
tv1'
; case (BindFlag
b1, BindFlag
b2) of
(BindFlag
BindMe, BindFlag
_) -> UMEnv -> OutTyVar -> Type -> UM ()
bindTv UMEnv
env OutTyVar
tv1' Type
rhs1
(BindFlag
_, BindFlag
BindMe) | UMEnv -> Bool
um_unif UMEnv
env
-> UMEnv -> OutTyVar -> Type -> UM ()
bindTv (UMEnv -> UMEnv
umSwapRn UMEnv
env) OutTyVar
tv2 Type
rhs2
(BindFlag, BindFlag)
_ | OutTyVar
tv1' forall a. Eq a => a -> a -> Bool
== OutTyVar
tv2' -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
(BindFlag, BindFlag)
_ -> forall a. UM a
surelyApart
}}}}
uUnrefined UMEnv
env OutTyVar
tv1' Type
ty2 Type
_ Coercion
kco
= case UMEnv -> BindFun
tvBindFlag UMEnv
env OutTyVar
tv1' Type
rhs of
BindFlag
Apart -> forall a. UM a
surelyApart
BindFlag
BindMe -> UMEnv -> OutTyVar -> Type -> UM ()
bindTv UMEnv
env OutTyVar
tv1' Type
rhs
where
rhs :: Type
rhs = Type
ty2 Type -> Coercion -> Type
`mkCastTy` Coercion -> Coercion
mkSymCo Coercion
kco
bindTv :: UMEnv -> OutTyVar -> Type -> UM ()
bindTv :: UMEnv -> OutTyVar -> Type -> UM ()
bindTv UMEnv
env OutTyVar
tv1 Type
ty2
= do { let free_tvs2 :: VarSet
free_tvs2 = Type -> VarSet
tyCoVarsOfType Type
ty2
; UMEnv -> VarSet -> UM ()
checkRnEnv UMEnv
env VarSet
free_tvs2
; Bool
occurs <- UMEnv -> OutTyVar -> VarSet -> UM Bool
occursCheck UMEnv
env OutTyVar
tv1 VarSet
free_tvs2
; if Bool
occurs then MaybeApartReason -> UM ()
maybeApart MaybeApartReason
MARInfinite
else OutTyVar -> Type -> UM ()
extendTvEnv OutTyVar
tv1 Type
ty2 }
occursCheck :: UMEnv -> TyVar -> VarSet -> UM Bool
occursCheck :: UMEnv -> OutTyVar -> VarSet -> UM Bool
occursCheck UMEnv
env OutTyVar
tv VarSet
free_tvs
| UMEnv -> Bool
um_unif UMEnv
env
= do { TvSubstEnv
tsubst <- UM TvSubstEnv
getTvSubstEnv
; forall (m :: * -> *) a. Monad m => a -> m a
return (OutTyVar
tv OutTyVar -> VarSet -> Bool
`elemVarSet` TvSubstEnv -> VarSet -> VarSet
niSubstTvSet TvSubstEnv
tsubst VarSet
free_tvs) }
| Bool
otherwise
= forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
data BindFlag
= BindMe
| Apart
deriving BindFlag -> BindFlag -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BindFlag -> BindFlag -> Bool
$c/= :: BindFlag -> BindFlag -> Bool
== :: BindFlag -> BindFlag -> Bool
$c== :: BindFlag -> BindFlag -> Bool
Eq
data UMEnv
= UMEnv { UMEnv -> Bool
um_unif :: AmIUnifying
, UMEnv -> Bool
um_inj_tf :: Bool
, UMEnv -> RnEnv2
um_rn_env :: RnEnv2
, UMEnv -> VarSet
um_skols :: TyVarSet
, UMEnv -> BindFun
um_bind_fun :: BindFun
}
data UMState = UMState
{ UMState -> TvSubstEnv
um_tv_env :: TvSubstEnv
, UMState -> CvSubstEnv
um_cv_env :: CvSubstEnv }
newtype UM a
= UM' { forall a. UM a -> UMState -> UnifyResultM (UMState, a)
unUM :: UMState -> UnifyResultM (UMState, a) }
deriving (forall a b. a -> UM b -> UM a
forall a b. (a -> b) -> UM a -> UM b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> UM b -> UM a
$c<$ :: forall a b. a -> UM b -> UM a
fmap :: forall a b. (a -> b) -> UM a -> UM b
$cfmap :: forall a b. (a -> b) -> UM a -> UM b
Functor)
pattern UM :: (UMState -> UnifyResultM (UMState, a)) -> UM a
pattern $bUM :: forall a. (UMState -> UnifyResultM (UMState, a)) -> UM a
$mUM :: forall {r} {a}.
UM a
-> ((UMState -> UnifyResultM (UMState, a)) -> r)
-> ((# #) -> r)
-> r
UM m <- UM' m
where
UM UMState -> UnifyResultM (UMState, a)
m = forall a. (UMState -> UnifyResultM (UMState, a)) -> UM a
UM' (oneShot :: forall a b. (a -> b) -> a -> b
oneShot UMState -> UnifyResultM (UMState, a)
m)
instance Applicative UM where
pure :: forall a. a -> UM a
pure a
a = forall a. (UMState -> UnifyResultM (UMState, a)) -> UM a
UM (\UMState
s -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (UMState
s, a
a))
<*> :: forall a b. UM (a -> b) -> UM a -> UM b
(<*>) = forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance Monad UM where
UM a
m >>= :: forall a b. UM a -> (a -> UM b) -> UM b
>>= a -> UM b
k = forall a. (UMState -> UnifyResultM (UMState, a)) -> UM a
UM (\UMState
state ->
do { (UMState
state', a
v) <- forall a. UM a -> UMState -> UnifyResultM (UMState, a)
unUM UM a
m UMState
state
; forall a. UM a -> UMState -> UnifyResultM (UMState, a)
unUM (a -> UM b
k a
v) UMState
state' })
instance MonadFail UM where
fail :: forall a. String -> UM a
fail String
_ = forall a. (UMState -> UnifyResultM (UMState, a)) -> UM a
UM (\UMState
_ -> forall a. UnifyResultM a
SurelyApart)
initUM :: TvSubstEnv
-> CvSubstEnv
-> UM a -> UnifyResultM a
initUM :: forall a. TvSubstEnv -> CvSubstEnv -> UM a -> UnifyResultM a
initUM TvSubstEnv
subst_env CvSubstEnv
cv_subst_env UM a
um
= case forall a. UM a -> UMState -> UnifyResultM (UMState, a)
unUM UM a
um UMState
state of
Unifiable (UMState
_, a
subst) -> forall a. a -> UnifyResultM a
Unifiable a
subst
MaybeApart MaybeApartReason
r (UMState
_, a
subst) -> forall a. MaybeApartReason -> a -> UnifyResultM a
MaybeApart MaybeApartReason
r a
subst
UnifyResultM (UMState, a)
SurelyApart -> forall a. UnifyResultM a
SurelyApart
where
state :: UMState
state = UMState { um_tv_env :: TvSubstEnv
um_tv_env = TvSubstEnv
subst_env
, um_cv_env :: CvSubstEnv
um_cv_env = CvSubstEnv
cv_subst_env }
tvBindFlag :: UMEnv -> OutTyVar -> Type -> BindFlag
tvBindFlag :: UMEnv -> BindFun
tvBindFlag UMEnv
env OutTyVar
tv Type
rhs
| OutTyVar
tv OutTyVar -> VarSet -> Bool
`elemVarSet` UMEnv -> VarSet
um_skols UMEnv
env = BindFlag
Apart
| Bool
otherwise = UMEnv -> BindFun
um_bind_fun UMEnv
env OutTyVar
tv Type
rhs
getTvSubstEnv :: UM TvSubstEnv
getTvSubstEnv :: UM TvSubstEnv
getTvSubstEnv = forall a. (UMState -> UnifyResultM (UMState, a)) -> UM a
UM forall a b. (a -> b) -> a -> b
$ \UMState
state -> forall a. a -> UnifyResultM a
Unifiable (UMState
state, UMState -> TvSubstEnv
um_tv_env UMState
state)
getCvSubstEnv :: UM CvSubstEnv
getCvSubstEnv :: UM CvSubstEnv
getCvSubstEnv = forall a. (UMState -> UnifyResultM (UMState, a)) -> UM a
UM forall a b. (a -> b) -> a -> b
$ \UMState
state -> forall a. a -> UnifyResultM a
Unifiable (UMState
state, UMState -> CvSubstEnv
um_cv_env UMState
state)
getSubst :: UMEnv -> UM TCvSubst
getSubst :: UMEnv -> UM TCvSubst
getSubst UMEnv
env = do { TvSubstEnv
tv_env <- UM TvSubstEnv
getTvSubstEnv
; CvSubstEnv
cv_env <- UM CvSubstEnv
getCvSubstEnv
; let in_scope :: InScopeSet
in_scope = RnEnv2 -> InScopeSet
rnInScopeSet (UMEnv -> RnEnv2
um_rn_env UMEnv
env)
; forall (m :: * -> *) a. Monad m => a -> m a
return (InScopeSet -> (TvSubstEnv, CvSubstEnv) -> TCvSubst
mkTCvSubst InScopeSet
in_scope (TvSubstEnv
tv_env, CvSubstEnv
cv_env)) }
extendTvEnv :: TyVar -> Type -> UM ()
extendTvEnv :: OutTyVar -> Type -> UM ()
extendTvEnv OutTyVar
tv Type
ty = forall a. (UMState -> UnifyResultM (UMState, a)) -> UM a
UM forall a b. (a -> b) -> a -> b
$ \UMState
state ->
forall a. a -> UnifyResultM a
Unifiable (UMState
state { um_tv_env :: TvSubstEnv
um_tv_env = forall a. VarEnv a -> OutTyVar -> a -> VarEnv a
extendVarEnv (UMState -> TvSubstEnv
um_tv_env UMState
state) OutTyVar
tv Type
ty }, ())
extendCvEnv :: CoVar -> Coercion -> UM ()
extendCvEnv :: OutTyVar -> Coercion -> UM ()
extendCvEnv OutTyVar
cv Coercion
co = forall a. (UMState -> UnifyResultM (UMState, a)) -> UM a
UM forall a b. (a -> b) -> a -> b
$ \UMState
state ->
forall a. a -> UnifyResultM a
Unifiable (UMState
state { um_cv_env :: CvSubstEnv
um_cv_env = forall a. VarEnv a -> OutTyVar -> a -> VarEnv a
extendVarEnv (UMState -> CvSubstEnv
um_cv_env UMState
state) OutTyVar
cv Coercion
co }, ())
umRnBndr2 :: UMEnv -> TyCoVar -> TyCoVar -> UMEnv
umRnBndr2 :: UMEnv -> OutTyVar -> OutTyVar -> UMEnv
umRnBndr2 UMEnv
env OutTyVar
v1 OutTyVar
v2
= UMEnv
env { um_rn_env :: RnEnv2
um_rn_env = RnEnv2
rn_env', um_skols :: VarSet
um_skols = UMEnv -> VarSet
um_skols UMEnv
env VarSet -> OutTyVar -> VarSet
`extendVarSet` OutTyVar
v' }
where
(RnEnv2
rn_env', OutTyVar
v') = RnEnv2 -> OutTyVar -> OutTyVar -> (RnEnv2, OutTyVar)
rnBndr2_var (UMEnv -> RnEnv2
um_rn_env UMEnv
env) OutTyVar
v1 OutTyVar
v2
checkRnEnv :: UMEnv -> VarSet -> UM ()
checkRnEnv :: UMEnv -> VarSet -> UM ()
checkRnEnv UMEnv
env VarSet
varset
| VarSet -> Bool
isEmptyVarSet VarSet
skol_vars = forall (m :: * -> *) a. Monad m => a -> m a
return ()
| VarSet
varset VarSet -> VarSet -> Bool
`disjointVarSet` VarSet
skol_vars = forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise = forall a. UM a
surelyApart
where
skol_vars :: VarSet
skol_vars = UMEnv -> VarSet
um_skols UMEnv
env
don'tBeSoSure :: MaybeApartReason -> UM () -> UM ()
don'tBeSoSure :: MaybeApartReason -> UM () -> UM ()
don'tBeSoSure MaybeApartReason
r UM ()
um = forall a. (UMState -> UnifyResultM (UMState, a)) -> UM a
UM forall a b. (a -> b) -> a -> b
$ \ UMState
state ->
case forall a. UM a -> UMState -> UnifyResultM (UMState, a)
unUM UM ()
um UMState
state of
UnifyResultM (UMState, ())
SurelyApart -> forall a. MaybeApartReason -> a -> UnifyResultM a
MaybeApart MaybeApartReason
r (UMState
state, ())
UnifyResultM (UMState, ())
other -> UnifyResultM (UMState, ())
other
umRnOccL :: UMEnv -> TyVar -> TyVar
umRnOccL :: UMEnv -> OutTyVar -> OutTyVar
umRnOccL UMEnv
env OutTyVar
v = RnEnv2 -> OutTyVar -> OutTyVar
rnOccL (UMEnv -> RnEnv2
um_rn_env UMEnv
env) OutTyVar
v
umRnOccR :: UMEnv -> TyVar -> TyVar
umRnOccR :: UMEnv -> OutTyVar -> OutTyVar
umRnOccR UMEnv
env OutTyVar
v = RnEnv2 -> OutTyVar -> OutTyVar
rnOccR (UMEnv -> RnEnv2
um_rn_env UMEnv
env) OutTyVar
v
umSwapRn :: UMEnv -> UMEnv
umSwapRn :: UMEnv -> UMEnv
umSwapRn UMEnv
env = UMEnv
env { um_rn_env :: RnEnv2
um_rn_env = RnEnv2 -> RnEnv2
rnSwap (UMEnv -> RnEnv2
um_rn_env UMEnv
env) }
maybeApart :: MaybeApartReason -> UM ()
maybeApart :: MaybeApartReason -> UM ()
maybeApart MaybeApartReason
r = forall a. (UMState -> UnifyResultM (UMState, a)) -> UM a
UM (\UMState
state -> forall a. MaybeApartReason -> a -> UnifyResultM a
MaybeApart MaybeApartReason
r (UMState
state, ()))
surelyApart :: UM a
surelyApart :: forall a. UM a
surelyApart = forall a. (UMState -> UnifyResultM (UMState, a)) -> UM a
UM (\UMState
_ -> forall a. UnifyResultM a
SurelyApart)
data MatchEnv = ME { MatchEnv -> VarSet
me_tmpls :: TyVarSet
, MatchEnv -> RnEnv2
me_env :: RnEnv2 }
liftCoMatch :: TyCoVarSet -> Type -> Coercion -> Maybe LiftingContext
liftCoMatch :: VarSet -> Type -> Coercion -> Maybe LiftingContext
liftCoMatch VarSet
tmpls Type
ty Coercion
co
= do { CvSubstEnv
cenv1 <- MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv forall a. VarEnv a
emptyVarEnv Type
ki Coercion
ki_co Coercion
ki_ki_co Coercion
ki_ki_co
; CvSubstEnv
cenv2 <- MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv CvSubstEnv
cenv1 Type
ty Coercion
co
(Type -> Coercion
mkNomReflCo Type
co_lkind) (Type -> Coercion
mkNomReflCo Type
co_rkind)
; forall (m :: * -> *) a. Monad m => a -> m a
return (TCvSubst -> CvSubstEnv -> LiftingContext
LC (InScopeSet -> TCvSubst
mkEmptyTCvSubst InScopeSet
in_scope) CvSubstEnv
cenv2) }
where
menv :: MatchEnv
menv = ME { me_tmpls :: VarSet
me_tmpls = VarSet
tmpls, me_env :: RnEnv2
me_env = InScopeSet -> RnEnv2
mkRnEnv2 InScopeSet
in_scope }
in_scope :: InScopeSet
in_scope = VarSet -> InScopeSet
mkInScopeSet (VarSet
tmpls VarSet -> VarSet -> VarSet
`unionVarSet` Coercion -> VarSet
tyCoVarsOfCo Coercion
co)
ki :: Type
ki = HasDebugCallStack => Type -> Type
typeKind Type
ty
ki_co :: Coercion
ki_co = Coercion -> Coercion
promoteCoercion Coercion
co
ki_ki_co :: Coercion
ki_ki_co = Type -> Coercion
mkNomReflCo Type
liftedTypeKind
Pair Type
co_lkind Type
co_rkind = Coercion -> Pair Type
coercionKind Coercion
ki_co
ty_co_match :: MatchEnv
-> LiftCoEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe LiftCoEnv
ty_co_match :: MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty Coercion
co Coercion
lkco Coercion
rkco
| Just Type
ty' <- Type -> Maybe Type
coreView Type
ty = MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty' Coercion
co Coercion
lkco Coercion
rkco
| Type -> VarSet
tyCoVarsOfType Type
ty forall a. VarSet -> VarEnv a -> Bool
`isNotInDomainOf` CvSubstEnv
subst
, Just (Type
ty', Role
_) <- Coercion -> Maybe (Type, Role)
isReflCo_maybe Coercion
co
, Type
ty Type -> Type -> Bool
`eqType` Type
ty'
= forall a. a -> Maybe a
Just CvSubstEnv
subst
where
isNotInDomainOf :: VarSet -> VarEnv a -> Bool
isNotInDomainOf :: forall a. VarSet -> VarEnv a -> Bool
isNotInDomainOf VarSet
set VarEnv a
env
= (OutTyVar -> Bool) -> VarSet -> Bool
noneSet (\OutTyVar
v -> forall a. OutTyVar -> VarEnv a -> Bool
elemVarEnv OutTyVar
v VarEnv a
env) VarSet
set
noneSet :: (Var -> Bool) -> VarSet -> Bool
noneSet :: (OutTyVar -> Bool) -> VarSet -> Bool
noneSet OutTyVar -> Bool
f = (OutTyVar -> Bool) -> VarSet -> Bool
allVarSet (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. OutTyVar -> Bool
f)
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty Coercion
co Coercion
lkco Coercion
rkco
| CastTy Type
ty' Coercion
co' <- Type
ty
= let empty_subst :: TCvSubst
empty_subst = InScopeSet -> TCvSubst
mkEmptyTCvSubst (RnEnv2 -> InScopeSet
rnInScopeSet (MatchEnv -> RnEnv2
me_env MatchEnv
menv))
substed_co_l :: Coercion
substed_co_l = HasCallStack => TCvSubst -> Coercion -> Coercion
substCo (TCvSubst -> CvSubstEnv -> TCvSubst
liftEnvSubstLeft TCvSubst
empty_subst CvSubstEnv
subst) Coercion
co'
substed_co_r :: Coercion
substed_co_r = HasCallStack => TCvSubst -> Coercion -> Coercion
substCo (TCvSubst -> CvSubstEnv -> TCvSubst
liftEnvSubstRight TCvSubst
empty_subst CvSubstEnv
subst) Coercion
co'
in
MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty' Coercion
co (Coercion
substed_co_l Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
lkco)
(Coercion
substed_co_r Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
rkco)
| SymCo Coercion
co' <- Coercion
co
= CvSubstEnv -> CvSubstEnv
swapLiftCoEnv forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv (CvSubstEnv -> CvSubstEnv
swapLiftCoEnv CvSubstEnv
subst) Type
ty Coercion
co' Coercion
rkco Coercion
lkco
ty_co_match MatchEnv
menv CvSubstEnv
subst (TyVarTy OutTyVar
tv1) Coercion
co Coercion
lkco Coercion
rkco
| Just Coercion
co1' <- forall a. VarEnv a -> OutTyVar -> Maybe a
lookupVarEnv CvSubstEnv
subst OutTyVar
tv1'
= if RnEnv2 -> Coercion -> Coercion -> Bool
eqCoercionX (RnEnv2 -> RnEnv2
nukeRnEnvL RnEnv2
rn_env) Coercion
co1' Coercion
co
then forall a. a -> Maybe a
Just CvSubstEnv
subst
else forall a. Maybe a
Nothing
| OutTyVar
tv1' OutTyVar -> VarSet -> Bool
`elemVarSet` MatchEnv -> VarSet
me_tmpls MatchEnv
menv
= if forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (RnEnv2 -> OutTyVar -> Bool
inRnEnvR RnEnv2
rn_env) (Coercion -> [OutTyVar]
tyCoVarsOfCoList Coercion
co)
then forall a. Maybe a
Nothing
else forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. VarEnv a -> OutTyVar -> a -> VarEnv a
extendVarEnv CvSubstEnv
subst OutTyVar
tv1' forall a b. (a -> b) -> a -> b
$
Coercion -> Coercion -> Coercion -> Coercion
castCoercionKind Coercion
co (Coercion -> Coercion
mkSymCo Coercion
lkco) (Coercion -> Coercion
mkSymCo Coercion
rkco)
| Bool
otherwise
= forall a. Maybe a
Nothing
where
rn_env :: RnEnv2
rn_env = MatchEnv -> RnEnv2
me_env MatchEnv
menv
tv1' :: OutTyVar
tv1' = RnEnv2 -> OutTyVar -> OutTyVar
rnOccL RnEnv2
rn_env OutTyVar
tv1
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty (SubCo Coercion
co) Coercion
lkco Coercion
rkco
= MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty Coercion
co Coercion
lkco Coercion
rkco
ty_co_match MatchEnv
menv CvSubstEnv
subst (AppTy Type
ty1a Type
ty1b) Coercion
co Coercion
_lkco Coercion
_rkco
| Just (Coercion
co2, Coercion
arg2) <- Coercion -> Maybe (Coercion, Coercion)
splitAppCo_maybe Coercion
co
= MatchEnv
-> CvSubstEnv
-> Type
-> [Type]
-> Coercion
-> [Coercion]
-> Maybe CvSubstEnv
ty_co_match_app MatchEnv
menv CvSubstEnv
subst Type
ty1a [Type
ty1b] Coercion
co2 [Coercion
arg2]
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty1 (AppCo Coercion
co2 Coercion
arg2) Coercion
_lkco Coercion
_rkco
| Just (Type
ty1a, Type
ty1b) <- HasDebugCallStack => Type -> Maybe (Type, Type)
repSplitAppTy_maybe Type
ty1
= MatchEnv
-> CvSubstEnv
-> Type
-> [Type]
-> Coercion
-> [Coercion]
-> Maybe CvSubstEnv
ty_co_match_app MatchEnv
menv CvSubstEnv
subst Type
ty1a [Type
ty1b] Coercion
co2 [Coercion
arg2]
ty_co_match MatchEnv
menv CvSubstEnv
subst (TyConApp TyCon
tc1 [Type]
tys) (TyConAppCo Role
_ TyCon
tc2 [Coercion]
cos) Coercion
_lkco Coercion
_rkco
= MatchEnv
-> CvSubstEnv
-> TyCon
-> [Type]
-> TyCon
-> [Coercion]
-> Maybe CvSubstEnv
ty_co_match_tc MatchEnv
menv CvSubstEnv
subst TyCon
tc1 [Type]
tys TyCon
tc2 [Coercion]
cos
ty_co_match MatchEnv
menv CvSubstEnv
subst (FunTy AnonArgFlag
_ Type
w Type
ty1 Type
ty2) Coercion
co Coercion
_lkco Coercion
_rkco
| Just (TyCon
tc, [Coercion
co_mult, Coercion
_,Coercion
_,Coercion
co1,Coercion
co2]) <- Coercion -> Maybe (TyCon, [Coercion])
splitTyConAppCo_maybe Coercion
co
, TyCon
tc forall a. Eq a => a -> a -> Bool
== TyCon
funTyCon
= let Pair [Coercion]
lkcos [Coercion]
rkcos = forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Type -> Coercion
mkNomReflCo forall b c a. (b -> c) -> (a -> b) -> a -> c
. Coercion -> Pair Type
coercionKind) [Coercion
co_mult,Coercion
co1,Coercion
co2]
in MatchEnv
-> CvSubstEnv
-> [Type]
-> [Coercion]
-> [Coercion]
-> [Coercion]
-> Maybe CvSubstEnv
ty_co_match_args MatchEnv
menv CvSubstEnv
subst [Type
w, Type
ty1, Type
ty2] [Coercion
co_mult, Coercion
co1, Coercion
co2] [Coercion]
lkcos [Coercion]
rkcos
ty_co_match MatchEnv
menv CvSubstEnv
subst (ForAllTy (Bndr OutTyVar
tv1 ArgFlag
_) Type
ty1)
(ForAllCo OutTyVar
tv2 Coercion
kind_co2 Coercion
co2)
Coercion
lkco Coercion
rkco
| OutTyVar -> Bool
isTyVar OutTyVar
tv1 Bool -> Bool -> Bool
&& OutTyVar -> Bool
isTyVar OutTyVar
tv2
= do { CvSubstEnv
subst1 <- MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv CvSubstEnv
subst (OutTyVar -> Type
tyVarKind OutTyVar
tv1) Coercion
kind_co2
Coercion
ki_ki_co Coercion
ki_ki_co
; let rn_env0 :: RnEnv2
rn_env0 = MatchEnv -> RnEnv2
me_env MatchEnv
menv
rn_env1 :: RnEnv2
rn_env1 = RnEnv2 -> OutTyVar -> OutTyVar -> RnEnv2
rnBndr2 RnEnv2
rn_env0 OutTyVar
tv1 OutTyVar
tv2
menv' :: MatchEnv
menv' = MatchEnv
menv { me_env :: RnEnv2
me_env = RnEnv2
rn_env1 }
; MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv' CvSubstEnv
subst1 Type
ty1 Coercion
co2 Coercion
lkco Coercion
rkco }
where
ki_ki_co :: Coercion
ki_ki_co = Type -> Coercion
mkNomReflCo Type
liftedTypeKind
ty_co_match MatchEnv
_ CvSubstEnv
subst (CoercionTy {}) Coercion
_ Coercion
_ Coercion
_
= forall a. a -> Maybe a
Just CvSubstEnv
subst
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty (GRefl Role
r Type
t (MCo Coercion
co)) Coercion
lkco Coercion
rkco
= MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty (Role -> Type -> MCoercion -> Coercion
GRefl Role
r Type
t MCoercion
MRefl) Coercion
lkco (Coercion
rkco Coercion -> Coercion -> Coercion
`mkTransCo` Coercion -> Coercion
mkSymCo Coercion
co)
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty Coercion
co1 Coercion
lkco Coercion
rkco
| Just (CastTy Type
t Coercion
co, Role
r) <- Coercion -> Maybe (Type, Role)
isReflCo_maybe Coercion
co1
= let kco' :: Coercion
kco' = Coercion -> Coercion
mkSymCo Coercion
co
in MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty (Role -> Type -> Coercion
mkReflCo Role
r Type
t) (Coercion
lkco Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
kco')
(Coercion
rkco Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
kco')
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty Coercion
co Coercion
lkco Coercion
rkco
| Just Coercion
co' <- Coercion -> Maybe Coercion
pushRefl Coercion
co = MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty Coercion
co' Coercion
lkco Coercion
rkco
| Bool
otherwise = forall a. Maybe a
Nothing
ty_co_match_tc :: MatchEnv -> LiftCoEnv
-> TyCon -> [Type]
-> TyCon -> [Coercion]
-> Maybe LiftCoEnv
ty_co_match_tc :: MatchEnv
-> CvSubstEnv
-> TyCon
-> [Type]
-> TyCon
-> [Coercion]
-> Maybe CvSubstEnv
ty_co_match_tc MatchEnv
menv CvSubstEnv
subst TyCon
tc1 [Type]
tys1 TyCon
tc2 [Coercion]
cos2
= do { forall (f :: * -> *). Alternative f => Bool -> f ()
guard (TyCon
tc1 forall a. Eq a => a -> a -> Bool
== TyCon
tc2)
; MatchEnv
-> CvSubstEnv
-> [Type]
-> [Coercion]
-> [Coercion]
-> [Coercion]
-> Maybe CvSubstEnv
ty_co_match_args MatchEnv
menv CvSubstEnv
subst [Type]
tys1 [Coercion]
cos2 [Coercion]
lkcos [Coercion]
rkcos }
where
Pair [Coercion]
lkcos [Coercion]
rkcos
= forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Type -> Coercion
mkNomReflCo forall b c a. (b -> c) -> (a -> b) -> a -> c
. Coercion -> Pair Type
coercionKind) [Coercion]
cos2
ty_co_match_app :: MatchEnv -> LiftCoEnv
-> Type -> [Type] -> Coercion -> [Coercion]
-> Maybe LiftCoEnv
ty_co_match_app :: MatchEnv
-> CvSubstEnv
-> Type
-> [Type]
-> Coercion
-> [Coercion]
-> Maybe CvSubstEnv
ty_co_match_app MatchEnv
menv CvSubstEnv
subst Type
ty1 [Type]
ty1args Coercion
co2 [Coercion]
co2args
| Just (Type
ty1', Type
ty1a) <- HasDebugCallStack => Type -> Maybe (Type, Type)
repSplitAppTy_maybe Type
ty1
, Just (Coercion
co2', Coercion
co2a) <- Coercion -> Maybe (Coercion, Coercion)
splitAppCo_maybe Coercion
co2
= MatchEnv
-> CvSubstEnv
-> Type
-> [Type]
-> Coercion
-> [Coercion]
-> Maybe CvSubstEnv
ty_co_match_app MatchEnv
menv CvSubstEnv
subst Type
ty1' (Type
ty1a forall a. a -> [a] -> [a]
: [Type]
ty1args) Coercion
co2' (Coercion
co2a forall a. a -> [a] -> [a]
: [Coercion]
co2args)
| Bool
otherwise
= do { CvSubstEnv
subst1 <- MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ki1 Coercion
ki2 Coercion
ki_ki_co Coercion
ki_ki_co
; let Pair Coercion
lkco Coercion
rkco = Type -> Coercion
mkNomReflCo forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Coercion -> Pair Type
coercionKind Coercion
ki2
; CvSubstEnv
subst2 <- MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv CvSubstEnv
subst1 Type
ty1 Coercion
co2 Coercion
lkco Coercion
rkco
; let Pair [Coercion]
lkcos [Coercion]
rkcos = forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Type -> Coercion
mkNomReflCo forall b c a. (b -> c) -> (a -> b) -> a -> c
. Coercion -> Pair Type
coercionKind) [Coercion]
co2args
; MatchEnv
-> CvSubstEnv
-> [Type]
-> [Coercion]
-> [Coercion]
-> [Coercion]
-> Maybe CvSubstEnv
ty_co_match_args MatchEnv
menv CvSubstEnv
subst2 [Type]
ty1args [Coercion]
co2args [Coercion]
lkcos [Coercion]
rkcos }
where
ki1 :: Type
ki1 = HasDebugCallStack => Type -> Type
typeKind Type
ty1
ki2 :: Coercion
ki2 = Coercion -> Coercion
promoteCoercion Coercion
co2
ki_ki_co :: Coercion
ki_ki_co = Type -> Coercion
mkNomReflCo Type
liftedTypeKind
ty_co_match_args :: MatchEnv -> LiftCoEnv -> [Type]
-> [Coercion] -> [Coercion] -> [Coercion]
-> Maybe LiftCoEnv
ty_co_match_args :: MatchEnv
-> CvSubstEnv
-> [Type]
-> [Coercion]
-> [Coercion]
-> [Coercion]
-> Maybe CvSubstEnv
ty_co_match_args MatchEnv
_ CvSubstEnv
subst [] [] [Coercion]
_ [Coercion]
_ = forall a. a -> Maybe a
Just CvSubstEnv
subst
ty_co_match_args MatchEnv
menv CvSubstEnv
subst (Type
ty:[Type]
tys) (Coercion
arg:[Coercion]
args) (Coercion
lkco:[Coercion]
lkcos) (Coercion
rkco:[Coercion]
rkcos)
= do { CvSubstEnv
subst' <- MatchEnv
-> CvSubstEnv
-> Type
-> Coercion
-> Coercion
-> Coercion
-> Maybe CvSubstEnv
ty_co_match MatchEnv
menv CvSubstEnv
subst Type
ty Coercion
arg Coercion
lkco Coercion
rkco
; MatchEnv
-> CvSubstEnv
-> [Type]
-> [Coercion]
-> [Coercion]
-> [Coercion]
-> Maybe CvSubstEnv
ty_co_match_args MatchEnv
menv CvSubstEnv
subst' [Type]
tys [Coercion]
args [Coercion]
lkcos [Coercion]
rkcos }
ty_co_match_args MatchEnv
_ CvSubstEnv
_ [Type]
_ [Coercion]
_ [Coercion]
_ [Coercion]
_ = forall a. Maybe a
Nothing
pushRefl :: Coercion -> Maybe Coercion
pushRefl :: Coercion -> Maybe Coercion
pushRefl Coercion
co =
case (Coercion -> Maybe (Type, Role)
isReflCo_maybe Coercion
co) of
Just (AppTy Type
ty1 Type
ty2, Role
Nominal)
-> forall a. a -> Maybe a
Just (Coercion -> Coercion -> Coercion
AppCo (Role -> Type -> Coercion
mkReflCo Role
Nominal Type
ty1) (Type -> Coercion
mkNomReflCo Type
ty2))
Just (FunTy AnonArgFlag
_ Type
w Type
ty1 Type
ty2, Role
r)
| Just Type
rep1 <- HasDebugCallStack => Type -> Maybe Type
getRuntimeRep_maybe Type
ty1
, Just Type
rep2 <- HasDebugCallStack => Type -> Maybe Type
getRuntimeRep_maybe Type
ty2
-> forall a. a -> Maybe a
Just (Role -> TyCon -> [Coercion] -> Coercion
TyConAppCo Role
r TyCon
funTyCon [ Type -> Coercion
multToCo Type
w, Role -> Type -> Coercion
mkReflCo Role
r Type
rep1, Role -> Type -> Coercion
mkReflCo Role
r Type
rep2
, Role -> Type -> Coercion
mkReflCo Role
r Type
ty1, Role -> Type -> Coercion
mkReflCo Role
r Type
ty2 ])
Just (TyConApp TyCon
tc [Type]
tys, Role
r)
-> forall a. a -> Maybe a
Just (Role -> TyCon -> [Coercion] -> Coercion
TyConAppCo Role
r TyCon
tc (forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Role -> Type -> Coercion
mkReflCo (Role -> TyCon -> [Role]
tyConRolesX Role
r TyCon
tc) [Type]
tys))
Just (ForAllTy (Bndr OutTyVar
tv ArgFlag
_) Type
ty, Role
r)
-> forall a. a -> Maybe a
Just (OutTyVar -> Coercion -> Coercion -> Coercion
ForAllCo OutTyVar
tv (Type -> Coercion
mkNomReflCo (OutTyVar -> Type
varType OutTyVar
tv)) (Role -> Type -> Coercion
mkReflCo Role
r Type
ty))
Maybe (Type, Role)
_ -> forall a. Maybe a
Nothing
data FlattenEnv
= FlattenEnv { FlattenEnv -> TypeMap (OutTyVar, TyCon, [Type])
fe_type_map :: TypeMap (TyVar, TyCon, [Type])
, FlattenEnv -> InScopeSet
fe_in_scope :: InScopeSet }
emptyFlattenEnv :: InScopeSet -> FlattenEnv
emptyFlattenEnv :: InScopeSet -> FlattenEnv
emptyFlattenEnv InScopeSet
in_scope
= FlattenEnv { fe_type_map :: TypeMap (OutTyVar, TyCon, [Type])
fe_type_map = 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 = forall a b. (a, b) -> a
fst (InScopeSet -> [Type] -> ([Type], TyVarEnv (TyCon, [Type]))
flattenTysX InScopeSet
in_scope [Type]
tys)
flattenTysX :: InScopeSet -> [Type] -> ([Type], TyVarEnv (TyCon, [Type]))
flattenTysX :: InScopeSet -> [Type] -> ([Type], TyVarEnv (TyCon, [Type]))
flattenTysX InScopeSet
in_scope [Type]
tys
= let (FlattenEnv
env, [Type]
result) = TvSubstEnv -> FlattenEnv -> [Type] -> (FlattenEnv, [Type])
coreFlattenTys TvSubstEnv
emptyTvSubstEnv (InScopeSet -> FlattenEnv
emptyFlattenEnv InScopeSet
in_scope) [Type]
tys in
([Type]
result, TypeMap (OutTyVar, TyCon, [Type]) -> TyVarEnv (TyCon, [Type])
build_env (FlattenEnv -> TypeMap (OutTyVar, TyCon, [Type])
fe_type_map FlattenEnv
env))
where
build_env :: TypeMap (TyVar, TyCon, [Type]) -> TyVarEnv (TyCon, [Type])
build_env :: TypeMap (OutTyVar, TyCon, [Type]) -> TyVarEnv (TyCon, [Type])
build_env TypeMap (OutTyVar, TyCon, [Type])
env_in
= forall (m :: * -> *) a b.
TrieMap m =>
(a -> b -> b) -> m a -> b -> b
foldTM (\(OutTyVar
tv, TyCon
tc, [Type]
tys) TyVarEnv (TyCon, [Type])
env_out -> forall a. VarEnv a -> OutTyVar -> a -> VarEnv a
extendVarEnv TyVarEnv (TyCon, [Type])
env_out OutTyVar
tv (TyCon
tc, [Type]
tys))
TypeMap (OutTyVar, TyCon, [Type])
env_in forall a. VarEnv a
emptyVarEnv
coreFlattenTys :: TvSubstEnv -> FlattenEnv
-> [Type] -> (FlattenEnv, [Type])
coreFlattenTys :: TvSubstEnv -> FlattenEnv -> [Type] -> (FlattenEnv, [Type])
coreFlattenTys TvSubstEnv
subst = forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL (TvSubstEnv -> FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy TvSubstEnv
subst)
coreFlattenTy :: TvSubstEnv -> FlattenEnv
-> Type -> (FlattenEnv, Type)
coreFlattenTy :: TvSubstEnv -> FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy TvSubstEnv
subst = FlattenEnv -> Type -> (FlattenEnv, Type)
go
where
go :: FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty | Just Type
ty' <- Type -> Maybe Type
coreView Type
ty = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty'
go FlattenEnv
env (TyVarTy OutTyVar
tv)
| Just Type
ty <- forall a. VarEnv a -> OutTyVar -> Maybe a
lookupVarEnv TvSubstEnv
subst OutTyVar
tv = (FlattenEnv
env, Type
ty)
| Bool
otherwise = let (FlattenEnv
env', Type
ki) = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env (OutTyVar -> Type
tyVarKind OutTyVar
tv) in
(FlattenEnv
env', OutTyVar -> Type
mkTyVarTy forall a b. (a -> b) -> a -> b
$ OutTyVar -> Type -> OutTyVar
setTyVarKind OutTyVar
tv Type
ki)
go FlattenEnv
env (AppTy Type
ty1 Type
ty2) = let (FlattenEnv
env1, Type
ty1') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty1
(FlattenEnv
env2, Type
ty2') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env1 Type
ty2 in
(FlattenEnv
env2, Type -> Type -> Type
AppTy Type
ty1' Type
ty2')
go FlattenEnv
env (TyConApp TyCon
tc [Type]
tys)
| Bool -> Bool
not (TyCon -> Role -> Bool
isGenerativeTyCon TyCon
tc Role
Nominal)
= TvSubstEnv -> FlattenEnv -> TyCon -> [Type] -> (FlattenEnv, Type)
coreFlattenTyFamApp TvSubstEnv
subst FlattenEnv
env TyCon
tc [Type]
tys
| Bool
otherwise
= let (FlattenEnv
env', [Type]
tys') = TvSubstEnv -> FlattenEnv -> [Type] -> (FlattenEnv, [Type])
coreFlattenTys TvSubstEnv
subst FlattenEnv
env [Type]
tys in
(FlattenEnv
env', TyCon -> [Type] -> Type
mkTyConApp TyCon
tc [Type]
tys')
go FlattenEnv
env ty :: Type
ty@(FunTy { ft_mult :: Type -> Type
ft_mult = Type
mult, ft_arg :: Type -> Type
ft_arg = Type
ty1, ft_res :: Type -> Type
ft_res = Type
ty2 })
= let (FlattenEnv
env1, Type
ty1') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env Type
ty1
(FlattenEnv
env2, Type
ty2') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env1 Type
ty2
(FlattenEnv
env3, Type
mult') = FlattenEnv -> Type -> (FlattenEnv, Type)
go FlattenEnv
env2 Type
mult in
(FlattenEnv
env3, Type
ty { ft_mult :: Type
ft_mult = Type
mult', ft_arg :: Type
ft_arg = Type
ty1', ft_res :: Type
ft_res = Type
ty2' })
go FlattenEnv
env (ForAllTy (Bndr OutTyVar
tv ArgFlag
vis) Type
ty)
= let (FlattenEnv
env1, TvSubstEnv
subst', OutTyVar
tv') = TvSubstEnv
-> FlattenEnv -> OutTyVar -> (FlattenEnv, TvSubstEnv, OutTyVar)
coreFlattenVarBndr TvSubstEnv
subst FlattenEnv
env OutTyVar
tv
(FlattenEnv
env2, Type
ty') = TvSubstEnv -> FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy TvSubstEnv
subst' FlattenEnv
env1 Type
ty in
(FlattenEnv
env2, VarBndr OutTyVar ArgFlag -> Type -> Type
ForAllTy (forall var argf. var -> argf -> VarBndr var argf
Bndr OutTyVar
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, OutTyVar -> Coercion
mkCoVarCo OutTyVar
covar)
where
(FlattenEnv
env1, Type
kind') = TvSubstEnv -> FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy TvSubstEnv
subst FlattenEnv
env (Coercion -> Type
coercionType Coercion
co)
covar :: OutTyVar
covar = InScopeSet -> Type -> OutTyVar
mkFlattenFreshCoVar (FlattenEnv -> InScopeSet
fe_in_scope FlattenEnv
env1) Type
kind'
env2 :: FlattenEnv
env2 = FlattenEnv -> (InScopeSet -> InScopeSet) -> FlattenEnv
updateInScopeSet FlattenEnv
env1 (forall a b c. (a -> b -> c) -> b -> a -> c
flip InScopeSet -> OutTyVar -> InScopeSet
extendInScopeSet OutTyVar
covar)
coreFlattenVarBndr :: TvSubstEnv -> FlattenEnv
-> TyCoVar -> (FlattenEnv, TvSubstEnv, TyVar)
coreFlattenVarBndr :: TvSubstEnv
-> FlattenEnv -> OutTyVar -> (FlattenEnv, TvSubstEnv, OutTyVar)
coreFlattenVarBndr TvSubstEnv
subst FlattenEnv
env OutTyVar
tv
= (FlattenEnv
env2, TvSubstEnv
subst', OutTyVar
tv')
where
kind :: Type
kind = OutTyVar -> Type
varType OutTyVar
tv
(FlattenEnv
env1, Type
kind') = TvSubstEnv -> FlattenEnv -> Type -> (FlattenEnv, Type)
coreFlattenTy TvSubstEnv
subst FlattenEnv
env Type
kind
tv' :: OutTyVar
tv' = InScopeSet -> OutTyVar -> OutTyVar
uniqAway (FlattenEnv -> InScopeSet
fe_in_scope FlattenEnv
env1) (OutTyVar -> Type -> OutTyVar
setVarType OutTyVar
tv Type
kind')
subst' :: TvSubstEnv
subst' = forall a. VarEnv a -> OutTyVar -> a -> VarEnv a
extendVarEnv TvSubstEnv
subst OutTyVar
tv (OutTyVar -> Type
mkTyVarTy OutTyVar
tv')
env2 :: FlattenEnv
env2 = FlattenEnv -> (InScopeSet -> InScopeSet) -> FlattenEnv
updateInScopeSet FlattenEnv
env1 (forall a b c. (a -> b -> c) -> b -> a -> c
flip InScopeSet -> OutTyVar -> InScopeSet
extendInScopeSet OutTyVar
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 forall a. TypeMap a -> Type -> Maybe a
lookupTypeMap TypeMap (OutTyVar, TyCon, [Type])
type_map Type
fam_ty of
Just (OutTyVar
tv, TyCon
_, [Type]
_) -> (FlattenEnv
env', Type -> [Type] -> Type
mkAppTys (OutTyVar -> Type
mkTyVarTy OutTyVar
tv) [Type]
leftover_args')
Maybe (OutTyVar, TyCon, [Type])
Nothing ->
let tyvar_name :: Name
tyvar_name = forall a. Uniquable a => a -> Name
mkFlattenFreshTyName TyCon
fam_tc
tv :: OutTyVar
tv = InScopeSet -> OutTyVar -> OutTyVar
uniqAway InScopeSet
in_scope forall a b. (a -> b) -> a -> b
$
Name -> Type -> OutTyVar
mkTyVar Name
tyvar_name (HasDebugCallStack => Type -> Type
typeKind Type
fam_ty)
ty' :: Type
ty' = Type -> [Type] -> Type
mkAppTys (OutTyVar -> Type
mkTyVarTy OutTyVar
tv) [Type]
leftover_args'
env'' :: FlattenEnv
env'' = FlattenEnv
env' { fe_type_map :: TypeMap (OutTyVar, TyCon, [Type])
fe_type_map = forall a. TypeMap a -> Type -> a -> TypeMap a
extendTypeMap TypeMap (OutTyVar, TyCon, [Type])
type_map Type
fam_ty
(OutTyVar
tv, TyCon
fam_tc, [Type]
sat_fam_args)
, fe_in_scope :: InScopeSet
fe_in_scope = InScopeSet -> OutTyVar -> InScopeSet
extendInScopeSet InScopeSet
in_scope OutTyVar
tv }
in (FlattenEnv
env'', Type
ty')
where
arity :: Arity
arity = TyCon -> Arity
tyConArity TyCon
fam_tc
tcv_subst :: TCvSubst
tcv_subst = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
TCvSubst (FlattenEnv -> InScopeSet
fe_in_scope FlattenEnv
env) TvSubstEnv
tv_subst forall a. VarEnv a
emptyVarEnv
([Type]
sat_fam_args, [Type]
leftover_args) = ASSERT( arity <= length fam_args )
forall a. Arity -> [a] -> ([a], [a])
splitAt Arity
arity [Type]
fam_args
sat_fam_args' :: [Type]
sat_fam_args' = HasCallStack => 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 (OutTyVar, TyCon, [Type])
fe_type_map = TypeMap (OutTyVar, TyCon, [Type])
type_map
, fe_in_scope :: FlattenEnv -> InScopeSet
fe_in_scope = InScopeSet
in_scope } = FlattenEnv
env'
mkFlattenFreshTyName :: Uniquable a => a -> Name
mkFlattenFreshTyName :: forall a. Uniquable a => a -> Name
mkFlattenFreshTyName a
unq
= Unique -> FastString -> Name
mkSysTvName (forall a. Uniquable a => a -> Unique
getUnique a
unq) (String -> FastString
fsLit String
"flt")
mkFlattenFreshCoVar :: InScopeSet -> Kind -> CoVar
mkFlattenFreshCoVar :: InScopeSet -> Type -> OutTyVar
mkFlattenFreshCoVar InScopeSet
in_scope Type
kind
= let uniq :: Unique
uniq = InScopeSet -> Unique
unsafeGetFreshLocalUnique InScopeSet
in_scope
name :: Name
name = Unique -> FastString -> Name
mkSystemVarName Unique
uniq (String -> FastString
fsLit String
"flc")
in Name -> Type -> OutTyVar
mkCoVar Name
name Type
kind