{-# LANGUAGE CPP #-}
{-# LANGUAGE MultiWayIf #-}
module GHC.Tc.Solver.Equality(
solveEquality
) where
import GHC.Prelude
import GHC.Tc.Solver.Irred( solveIrred )
import GHC.Tc.Solver.Dict( matchLocalInst, chooseInstance )
import GHC.Tc.Solver.Rewrite
import GHC.Tc.Solver.Monad
import GHC.Tc.Solver.InertSet
import GHC.Tc.Solver.Types( findFunEqsByTyCon )
import GHC.Tc.Types.Evidence
import GHC.Tc.Types.Constraint
import GHC.Tc.Types.Origin
import GHC.Tc.Utils.Unify
import GHC.Tc.Utils.TcType
import GHC.Tc.Instance.Family ( tcTopNormaliseNewTypeTF_maybe )
import GHC.Tc.Instance.FunDeps( FunDepEqn(..) )
import GHC.Core.Type
import GHC.Core.Predicate
import GHC.Core.Class
import GHC.Core.DataCon ( dataConName )
import GHC.Core.TyCon
import GHC.Core.TyCo.Rep
import GHC.Core.Coercion
import GHC.Core.Coercion.Axiom
import GHC.Core.Reduction
import GHC.Core.Unify( tcUnifyTyWithTFs )
import GHC.Core.FamInstEnv ( FamInstEnvs, FamInst(..), apartnessCheck
, lookupFamInstEnvByTyCon )
import GHC.Core
import GHC.Types.Var
import GHC.Types.Var.Env
import GHC.Types.Var.Set( anyVarSet )
import GHC.Types.Name.Reader
import GHC.Types.Basic
import GHC.Builtin.Types ( anyTypeOfKind )
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Utils.Panic.Plain
import GHC.Utils.Misc
import GHC.Utils.Monad
import GHC.Utils.Constants( debugIsOn )
import GHC.Data.Pair
import GHC.Data.Bag
import Control.Monad
import Data.Maybe ( isJust, isNothing )
import Data.List ( zip4 )
import qualified Data.Semigroup as S
import Data.Bifunctor ( bimap )
import Data.Void( Void )
solveEquality :: CtEvidence -> EqRel -> Type -> Type
-> SolverStage Void
solveEquality :: CtEvidence -> EqRel -> Type -> Type -> SolverStage Void
solveEquality CtEvidence
ev EqRel
eq_rel Type
ty1 Type
ty2
= do { Pair Type
ty1' Type
ty2' <- CtEvidence -> EqRel -> Type -> Type -> SolverStage TypeEqn
zonkEqTypes CtEvidence
ev EqRel
eq_rel Type
ty1 Type
ty2
; let ev' :: CtEvidence
ev' | Bool
debugIsOn = HasDebugCallStack => CtEvidence -> Type -> CtEvidence
CtEvidence -> Type -> CtEvidence
setCtEvPredType CtEvidence
ev (Type -> CtEvidence) -> Type -> CtEvidence
forall a b. (a -> b) -> a -> b
$
Role -> Type -> Type -> Type
mkPrimEqPredRole (EqRel -> Role
eqRelRole EqRel
eq_rel) Type
ty1' Type
ty2'
| Bool
otherwise = CtEvidence
ev
; Either IrredCt EqCt
mb_canon <- CtEvidence
-> EqRel -> Type -> Type -> SolverStage (Either IrredCt EqCt)
canonicaliseEquality CtEvidence
ev' EqRel
eq_rel Type
ty1' Type
ty2'
; case Either IrredCt EqCt
mb_canon of {
Left IrredCt
irred_ct -> do { IrredCt -> SolverStage ()
tryQCsIrredEqCt IrredCt
irred_ct
; IrredCt -> SolverStage Void
solveIrred IrredCt
irred_ct } ;
Right EqCt
eq_ct -> do { EqCt -> SolverStage ()
tryInertEqs EqCt
eq_ct
; EqCt -> SolverStage ()
tryFunDeps EqCt
eq_ct
; EqCt -> SolverStage ()
tryQCsEqCt EqCt
eq_ct
; TcS () -> SolverStage ()
forall a. TcS a -> SolverStage a
simpleStage (EqCt -> TcS ()
updInertEqs EqCt
eq_ct)
; CtEvidence -> String -> SolverStage Void
forall a. CtEvidence -> String -> SolverStage a
stopWithStage (EqCt -> CtEvidence
eqCtEvidence EqCt
eq_ct) String
"Kept inert EqCt" } } }
updInertEqs :: EqCt -> TcS ()
updInertEqs :: EqCt -> TcS ()
updInertEqs EqCt
eq_ct
= do { KickOutSpec -> CtFlavourRole -> TcS ()
kickOutRewritable (CanEqLHS -> KickOutSpec
KOAfterAdding (EqCt -> CanEqLHS
eqCtLHS EqCt
eq_ct)) (EqCt -> CtFlavourRole
eqCtFlavourRole EqCt
eq_ct)
; TcLevel
tc_lvl <- TcS TcLevel
getTcLevel
; (InertCans -> InertCans) -> TcS ()
updInertCans (TcLevel -> EqCt -> InertCans -> InertCans
addEqToCans TcLevel
tc_lvl EqCt
eq_ct) }
zonkEqTypes :: CtEvidence -> EqRel -> TcType -> TcType -> SolverStage (Pair TcType)
zonkEqTypes :: CtEvidence -> EqRel -> Type -> Type -> SolverStage TypeEqn
zonkEqTypes CtEvidence
ev EqRel
eq_rel Type
ty1 Type
ty2
= TcS (StopOrContinue TypeEqn) -> SolverStage TypeEqn
forall a. TcS (StopOrContinue a) -> SolverStage a
Stage (TcS (StopOrContinue TypeEqn) -> SolverStage TypeEqn)
-> TcS (StopOrContinue TypeEqn) -> SolverStage TypeEqn
forall a b. (a -> b) -> a -> b
$ do { Either TypeEqn Type
res <- Type -> Type -> TcS (Either TypeEqn Type)
go Type
ty1 Type
ty2
; case Either TypeEqn Type
res of
Left TypeEqn
pair -> TypeEqn -> TcS (StopOrContinue TypeEqn)
forall a. a -> TcS (StopOrContinue a)
continueWith TypeEqn
pair
Right Type
ty -> CtEvidence -> EqRel -> Type -> TcS (StopOrContinue TypeEqn)
forall a. CtEvidence -> EqRel -> Type -> TcS (StopOrContinue a)
canEqReflexive CtEvidence
ev EqRel
eq_rel Type
ty }
where
go :: TcType -> TcType -> TcS (Either (Pair TcType) TcType)
go :: Type -> Type -> TcS (Either TypeEqn Type)
go (TyVarTy TyVar
tv1) (TyVarTy TyVar
tv2) = TyVar -> TyVar -> TcS (Either TypeEqn Type)
tyvar_tyvar TyVar
tv1 TyVar
tv2
go (TyVarTy TyVar
tv1) Type
ty2 = SwapFlag -> TyVar -> Type -> TcS (Either TypeEqn Type)
tyvar SwapFlag
NotSwapped TyVar
tv1 Type
ty2
go Type
ty1 (TyVarTy TyVar
tv2) = SwapFlag -> TyVar -> Type -> TcS (Either TypeEqn Type)
tyvar SwapFlag
IsSwapped TyVar
tv2 Type
ty1
go (FunTy FunTyFlag
af1 Type
w1 Type
arg1 Type
res1) (FunTy FunTyFlag
af2 Type
w2 Type
arg2 Type
res2)
| FunTyFlag
af1 FunTyFlag -> FunTyFlag -> Bool
forall a. Eq a => a -> a -> Bool
== FunTyFlag
af2
, Type -> Type -> Bool
eqType Type
w1 Type
w2
= do { Either TypeEqn Type
res_a <- Type -> Type -> TcS (Either TypeEqn Type)
go Type
arg1 Type
arg2
; Either TypeEqn Type
res_b <- Type -> Type -> TcS (Either TypeEqn Type)
go Type
res1 Type
res2
; Either TypeEqn Type -> TcS (Either TypeEqn Type)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either TypeEqn Type -> TcS (Either TypeEqn Type))
-> Either TypeEqn Type -> TcS (Either TypeEqn Type)
forall a b. (a -> b) -> a -> b
$ (Type -> Type -> Type)
-> Either TypeEqn Type
-> Either TypeEqn Type
-> Either TypeEqn Type
forall a b c.
(a -> b -> c)
-> Either (Pair b) b -> Either (Pair a) a -> Either (Pair c) c
combine_rev (FunTyFlag -> Type -> Type -> Type -> Type
FunTy FunTyFlag
af1 Type
w1) Either TypeEqn Type
res_b Either TypeEqn Type
res_a }
go ty1 :: Type
ty1@(FunTy {}) Type
ty2 = Type -> Type -> TcS (Either TypeEqn Type)
forall {m :: * -> *} {a} {b}.
Monad m =>
a -> a -> m (Either (Pair a) b)
bale_out Type
ty1 Type
ty2
go Type
ty1 ty2 :: Type
ty2@(FunTy {}) = Type -> Type -> TcS (Either TypeEqn Type)
forall {m :: * -> *} {a} {b}.
Monad m =>
a -> a -> m (Either (Pair a) b)
bale_out Type
ty1 Type
ty2
go Type
ty1 Type
ty2
| Just (TyCon
tc1, [Type]
tys1) <- Type -> Maybe (TyCon, [Type])
splitTyConAppNoView_maybe Type
ty1
, Just (TyCon
tc2, [Type]
tys2) <- Type -> Maybe (TyCon, [Type])
splitTyConAppNoView_maybe Type
ty2
= if TyCon
tc1 TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
tc2 Bool -> Bool -> Bool
&& [Type]
tys1 [Type] -> [Type] -> Bool
forall a b. [a] -> [b] -> Bool
`equalLength` [Type]
tys2
then TyCon -> [Type] -> [Type] -> TcS (Either TypeEqn Type)
tycon TyCon
tc1 [Type]
tys1 [Type]
tys2
else Type -> Type -> TcS (Either TypeEqn Type)
forall {m :: * -> *} {a} {b}.
Monad m =>
a -> a -> m (Either (Pair a) b)
bale_out Type
ty1 Type
ty2
go Type
ty1 Type
ty2
| Just (Type
ty1a, Type
ty1b) <- Type -> Maybe (Type, Type)
tcSplitAppTyNoView_maybe Type
ty1
, Just (Type
ty2a, Type
ty2b) <- Type -> Maybe (Type, Type)
tcSplitAppTyNoView_maybe Type
ty2
= do { Either TypeEqn Type
res_a <- Type -> Type -> TcS (Either TypeEqn Type)
go Type
ty1a Type
ty2a
; Either TypeEqn Type
res_b <- Type -> Type -> TcS (Either TypeEqn Type)
go Type
ty1b Type
ty2b
; Either TypeEqn Type -> TcS (Either TypeEqn Type)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either TypeEqn Type -> TcS (Either TypeEqn Type))
-> Either TypeEqn Type -> TcS (Either TypeEqn Type)
forall a b. (a -> b) -> a -> b
$ (Type -> Type -> Type)
-> Either TypeEqn Type
-> Either TypeEqn Type
-> Either TypeEqn Type
forall a b c.
(a -> b -> c)
-> Either (Pair b) b -> Either (Pair a) a -> Either (Pair c) c
combine_rev Type -> Type -> Type
mkAppTy Either TypeEqn Type
res_b Either TypeEqn Type
res_a }
go ty1 :: Type
ty1@(LitTy TyLit
lit1) (LitTy TyLit
lit2)
| TyLit
lit1 TyLit -> TyLit -> Bool
forall a. Eq a => a -> a -> Bool
== TyLit
lit2
= Either TypeEqn Type -> TcS (Either TypeEqn Type)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (Type -> Either TypeEqn Type
forall a b. b -> Either a b
Right Type
ty1)
go Type
ty1 Type
ty2 = Type -> Type -> TcS (Either TypeEqn Type)
forall {m :: * -> *} {a} {b}.
Monad m =>
a -> a -> m (Either (Pair a) b)
bale_out Type
ty1 Type
ty2
bale_out :: a -> a -> m (Either (Pair a) b)
bale_out a
ty1 a
ty2 = Either (Pair a) b -> m (Either (Pair a) b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either (Pair a) b -> m (Either (Pair a) b))
-> Either (Pair a) b -> m (Either (Pair a) b)
forall a b. (a -> b) -> a -> b
$ Pair a -> Either (Pair a) b
forall a b. a -> Either a b
Left (a -> a -> Pair a
forall a. a -> a -> Pair a
Pair a
ty1 a
ty2)
tyvar :: SwapFlag -> TcTyVar -> TcType
-> TcS (Either (Pair TcType) TcType)
tyvar :: SwapFlag -> TyVar -> Type -> TcS (Either TypeEqn Type)
tyvar SwapFlag
swapped TyVar
tv Type
ty
= case TyVar -> TcTyVarDetails
tcTyVarDetails TyVar
tv of
MetaTv { mtv_ref :: TcTyVarDetails -> IORef MetaDetails
mtv_ref = IORef MetaDetails
ref }
-> do { MetaDetails
cts <- IORef MetaDetails -> TcS MetaDetails
forall a. TcRef a -> TcS a
readTcRef IORef MetaDetails
ref
; case MetaDetails
cts of
MetaDetails
Flexi -> TcS (Either TypeEqn Type)
give_up
Indirect Type
ty' -> do { TyVar -> Type -> TcS ()
forall {a} {a}. (Outputable a, Outputable a) => a -> a -> TcS ()
trace_indirect TyVar
tv Type
ty'
; SwapFlag
-> (Type -> Type -> TcS (Either TypeEqn Type))
-> Type
-> Type
-> TcS (Either TypeEqn Type)
forall a b. SwapFlag -> (a -> a -> b) -> a -> a -> b
unSwap SwapFlag
swapped Type -> Type -> TcS (Either TypeEqn Type)
go Type
ty' Type
ty } }
TcTyVarDetails
_ -> TcS (Either TypeEqn Type)
give_up
where
give_up :: TcS (Either TypeEqn Type)
give_up = Either TypeEqn Type -> TcS (Either TypeEqn Type)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either TypeEqn Type -> TcS (Either TypeEqn Type))
-> Either TypeEqn Type -> TcS (Either TypeEqn Type)
forall a b. (a -> b) -> a -> b
$ TypeEqn -> Either TypeEqn Type
forall a b. a -> Either a b
Left (TypeEqn -> Either TypeEqn Type) -> TypeEqn -> Either TypeEqn Type
forall a b. (a -> b) -> a -> b
$ SwapFlag -> (Type -> Type -> TypeEqn) -> Type -> Type -> TypeEqn
forall a b. SwapFlag -> (a -> a -> b) -> a -> a -> b
unSwap SwapFlag
swapped Type -> Type -> TypeEqn
forall a. a -> a -> Pair a
Pair (TyVar -> Type
mkTyVarTy TyVar
tv) Type
ty
tyvar_tyvar :: TyVar -> TyVar -> TcS (Either TypeEqn Type)
tyvar_tyvar TyVar
tv1 TyVar
tv2
| TyVar
tv1 TyVar -> TyVar -> Bool
forall a. Eq a => a -> a -> Bool
== TyVar
tv2 = Either TypeEqn Type -> TcS (Either TypeEqn Type)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (Type -> Either TypeEqn Type
forall a b. b -> Either a b
Right (TyVar -> Type
mkTyVarTy TyVar
tv1))
| Bool
otherwise = do { (Type
ty1', Bool
progress1) <- TyVar -> TcS (Type, Bool)
quick_zonk TyVar
tv1
; (Type
ty2', Bool
progress2) <- TyVar -> TcS (Type, Bool)
quick_zonk TyVar
tv2
; if Bool
progress1 Bool -> Bool -> Bool
|| Bool
progress2
then Type -> Type -> TcS (Either TypeEqn Type)
go Type
ty1' Type
ty2'
else Either TypeEqn Type -> TcS (Either TypeEqn Type)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either TypeEqn Type -> TcS (Either TypeEqn Type))
-> Either TypeEqn Type -> TcS (Either TypeEqn Type)
forall a b. (a -> b) -> a -> b
$ TypeEqn -> Either TypeEqn Type
forall a b. a -> Either a b
Left (Type -> Type -> TypeEqn
forall a. a -> a -> Pair a
Pair (TyVar -> Type
TyVarTy TyVar
tv1) (TyVar -> Type
TyVarTy TyVar
tv2)) }
trace_indirect :: a -> a -> TcS ()
trace_indirect a
tv a
ty
= String -> SDoc -> TcS ()
traceTcS String
"Following filled tyvar (zonk_eq_types)"
(a -> SDoc
forall a. Outputable a => a -> SDoc
ppr a
tv SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
forall doc. IsLine doc => doc
equals SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> a -> SDoc
forall a. Outputable a => a -> SDoc
ppr a
ty)
quick_zonk :: TyVar -> TcS (Type, Bool)
quick_zonk TyVar
tv = case TyVar -> TcTyVarDetails
tcTyVarDetails TyVar
tv of
MetaTv { mtv_ref :: TcTyVarDetails -> IORef MetaDetails
mtv_ref = IORef MetaDetails
ref }
-> do { MetaDetails
cts <- IORef MetaDetails -> TcS MetaDetails
forall a. TcRef a -> TcS a
readTcRef IORef MetaDetails
ref
; case MetaDetails
cts of
MetaDetails
Flexi -> (Type, Bool) -> TcS (Type, Bool)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (TyVar -> Type
TyVarTy TyVar
tv, Bool
False)
Indirect Type
ty' -> do { TyVar -> Type -> TcS ()
forall {a} {a}. (Outputable a, Outputable a) => a -> a -> TcS ()
trace_indirect TyVar
tv Type
ty'
; (Type, Bool) -> TcS (Type, Bool)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (Type
ty', Bool
True) } }
TcTyVarDetails
_ -> (Type, Bool) -> TcS (Type, Bool)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (TyVar -> Type
TyVarTy TyVar
tv, Bool
False)
tycon :: TyCon -> [TcType] -> [TcType]
-> TcS (Either (Pair TcType) TcType)
tycon :: TyCon -> [Type] -> [Type] -> TcS (Either TypeEqn Type)
tycon TyCon
tc [Type]
tys1 [Type]
tys2
= do { [Either TypeEqn Type]
results <- (Type -> Type -> TcS (Either TypeEqn Type))
-> [Type] -> [Type] -> TcS [Either TypeEqn Type]
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM Type -> Type -> TcS (Either TypeEqn Type)
go [Type]
tys1 [Type]
tys2
; Either TypeEqn Type -> TcS (Either TypeEqn Type)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either TypeEqn Type -> TcS (Either TypeEqn Type))
-> Either TypeEqn Type -> TcS (Either TypeEqn Type)
forall a b. (a -> b) -> a -> b
$ case [Either TypeEqn Type] -> Either (Pair [Type]) [Type]
combine_results [Either TypeEqn Type]
results of
Left Pair [Type]
tys -> TypeEqn -> Either TypeEqn Type
forall a b. a -> Either a b
Left (TyCon -> [Type] -> Type
mkTyConApp TyCon
tc ([Type] -> Type) -> Pair [Type] -> TypeEqn
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Pair [Type]
tys)
Right [Type]
tys -> Type -> Either TypeEqn Type
forall a b. b -> Either a b
Right (TyCon -> [Type] -> Type
mkTyConApp TyCon
tc [Type]
tys) }
combine_results :: [Either (Pair TcType) TcType]
-> Either (Pair [TcType]) [TcType]
combine_results :: [Either TypeEqn Type] -> Either (Pair [Type]) [Type]
combine_results = (Pair [Type] -> Pair [Type])
-> ([Type] -> [Type])
-> Either (Pair [Type]) [Type]
-> Either (Pair [Type]) [Type]
forall a b c d. (a -> b) -> (c -> d) -> Either a c -> Either b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap (([Type] -> [Type]) -> Pair [Type] -> Pair [Type]
forall a b. (a -> b) -> Pair a -> Pair b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Type] -> [Type]
forall a. [a] -> [a]
reverse) [Type] -> [Type]
forall a. [a] -> [a]
reverse (Either (Pair [Type]) [Type] -> Either (Pair [Type]) [Type])
-> ([Either TypeEqn Type] -> Either (Pair [Type]) [Type])
-> [Either TypeEqn Type]
-> Either (Pair [Type]) [Type]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(Either (Pair [Type]) [Type]
-> Either TypeEqn Type -> Either (Pair [Type]) [Type])
-> Either (Pair [Type]) [Type]
-> [Either TypeEqn Type]
-> Either (Pair [Type]) [Type]
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' ((Type -> [Type] -> [Type])
-> Either (Pair [Type]) [Type]
-> Either TypeEqn Type
-> Either (Pair [Type]) [Type]
forall a b c.
(a -> b -> c)
-> Either (Pair b) b -> Either (Pair a) a -> Either (Pair c) c
combine_rev (:)) ([Type] -> Either (Pair [Type]) [Type]
forall a b. b -> Either a b
Right [])
combine_rev :: (a -> b -> c)
-> Either (Pair b) b
-> Either (Pair a) a
-> Either (Pair c) c
combine_rev :: forall a b c.
(a -> b -> c)
-> Either (Pair b) b -> Either (Pair a) a -> Either (Pair c) c
combine_rev a -> b -> c
f (Left Pair b
list) (Left Pair a
elt) = Pair c -> Either (Pair c) c
forall a b. a -> Either a b
Left (a -> b -> c
f (a -> b -> c) -> Pair a -> Pair (b -> c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Pair a
elt Pair (b -> c) -> Pair b -> Pair c
forall a b. Pair (a -> b) -> Pair a -> Pair b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Pair b
list)
combine_rev a -> b -> c
f (Left Pair b
list) (Right a
ty) = Pair c -> Either (Pair c) c
forall a b. a -> Either a b
Left (a -> b -> c
f (a -> b -> c) -> Pair a -> Pair (b -> c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Pair a
forall a. a -> Pair a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
ty Pair (b -> c) -> Pair b -> Pair c
forall a b. Pair (a -> b) -> Pair a -> Pair b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Pair b
list)
combine_rev a -> b -> c
f (Right b
tys) (Left Pair a
elt) = Pair c -> Either (Pair c) c
forall a b. a -> Either a b
Left (a -> b -> c
f (a -> b -> c) -> Pair a -> Pair (b -> c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Pair a
elt Pair (b -> c) -> Pair b -> Pair c
forall a b. Pair (a -> b) -> Pair a -> Pair b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> b -> Pair b
forall a. a -> Pair a
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
tys)
combine_rev a -> b -> c
f (Right b
tys) (Right a
ty) = c -> Either (Pair c) c
forall a b. b -> Either a b
Right (a -> b -> c
f a
ty b
tys)
canonicaliseEquality
:: CtEvidence -> EqRel
-> Type -> Type
-> SolverStage (Either IrredCt EqCt)
canonicaliseEquality :: CtEvidence
-> EqRel -> Type -> Type -> SolverStage (Either IrredCt EqCt)
canonicaliseEquality CtEvidence
ev EqRel
eq_rel Type
ty1 Type
ty2
= TcS (StopOrContinue (Either IrredCt EqCt))
-> SolverStage (Either IrredCt EqCt)
forall a. TcS (StopOrContinue a) -> SolverStage a
Stage (TcS (StopOrContinue (Either IrredCt EqCt))
-> SolverStage (Either IrredCt EqCt))
-> TcS (StopOrContinue (Either IrredCt EqCt))
-> SolverStage (Either IrredCt EqCt)
forall a b. (a -> b) -> a -> b
$ do { String -> SDoc -> TcS ()
traceTcS String
"canonicaliseEquality" (SDoc -> TcS ()) -> SDoc -> TcS ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ CtEvidence -> SDoc
forall a. Outputable a => a -> SDoc
ppr CtEvidence
ev, EqRel -> SDoc
forall a. Outputable a => a -> SDoc
ppr EqRel
eq_rel, Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty1, Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty2 ]
; GlobalRdrEnv
rdr_env <- TcS GlobalRdrEnv
getGlobalRdrEnvTcS
; (FamInstEnv, FamInstEnv)
fam_insts <- TcS (FamInstEnv, FamInstEnv)
getFamInstEnvs
; Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> Type
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc Bool
False GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
fam_insts CtEvidence
ev EqRel
eq_rel Type
ty1 Type
ty1 Type
ty2 Type
ty2 }
can_eq_nc
:: Bool
-> GlobalRdrEnv
-> FamInstEnvs
-> CtEvidence
-> EqRel
-> Type -> Type
-> Type -> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc :: Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> Type
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc Bool
_flat GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel ty1 :: Type
ty1@(TyConApp TyCon
tc1 []) Type
_ps_ty1 (TyConApp TyCon
tc2 []) Type
_ps_ty2
| TyCon
tc1 TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
tc2
= CtEvidence
-> EqRel -> Type -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. CtEvidence -> EqRel -> Type -> TcS (StopOrContinue a)
canEqReflexive CtEvidence
ev EqRel
eq_rel Type
ty1
can_eq_nc Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel Type
ty1 Type
ps_ty1 Type
ty2 Type
ps_ty2
| Just Type
ty1' <- Type -> Maybe Type
coreView Type
ty1 = Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> Type
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel Type
ty1' Type
ps_ty1 Type
ty2 Type
ps_ty2
| Just Type
ty2' <- Type -> Maybe Type
coreView Type
ty2 = Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> Type
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel Type
ty1 Type
ps_ty1 Type
ty2' Type
ps_ty2
can_eq_nc Bool
True GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
ReprEq Type
ty1 Type
_ Type
ty2 Type
_
| Type
ty1 HasDebugCallStack => Type -> Type -> Bool
Type -> Type -> Bool
`tcEqType` Type
ty2
= CtEvidence
-> EqRel -> Type -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. CtEvidence -> EqRel -> Type -> TcS (StopOrContinue a)
canEqReflexive CtEvidence
ev EqRel
ReprEq Type
ty1
can_eq_nc Bool
_rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel Type
ty1 Type
ps_ty1 Type
ty2 Type
ps_ty2
| EqRel
ReprEq <- EqRel
eq_rel
, Just ((Bag GlobalRdrElt, TcCoercion), Type)
stuff1 <- (FamInstEnv, FamInstEnv)
-> GlobalRdrEnv
-> Type
-> Maybe ((Bag GlobalRdrElt, TcCoercion), Type)
tcTopNormaliseNewTypeTF_maybe (FamInstEnv, FamInstEnv)
envs GlobalRdrEnv
rdr_env Type
ty1
= GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> SwapFlag
-> Type
-> ((Bag GlobalRdrElt, TcCoercion), Type)
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_newtype_nc GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev SwapFlag
NotSwapped Type
ty1 ((Bag GlobalRdrElt, TcCoercion), Type)
stuff1 Type
ty2 Type
ps_ty2
| EqRel
ReprEq <- EqRel
eq_rel
, Just ((Bag GlobalRdrElt, TcCoercion), Type)
stuff2 <- (FamInstEnv, FamInstEnv)
-> GlobalRdrEnv
-> Type
-> Maybe ((Bag GlobalRdrElt, TcCoercion), Type)
tcTopNormaliseNewTypeTF_maybe (FamInstEnv, FamInstEnv)
envs GlobalRdrEnv
rdr_env Type
ty2
= GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> SwapFlag
-> Type
-> ((Bag GlobalRdrElt, TcCoercion), Type)
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_newtype_nc GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev SwapFlag
IsSwapped Type
ty2 ((Bag GlobalRdrElt, TcCoercion), Type)
stuff2 Type
ty1 Type
ps_ty1
can_eq_nc Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel (CastTy Type
ty1 TcCoercion
co1) Type
_ Type
ty2 Type
ps_ty2
| Maybe CanEqLHS -> Bool
forall a. Maybe a -> Bool
isNothing (Type -> Maybe CanEqLHS
canEqLHS_maybe Type
ty2)
= Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> SwapFlag
-> Type
-> TcCoercion
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCast Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel SwapFlag
NotSwapped Type
ty1 TcCoercion
co1 Type
ty2 Type
ps_ty2
can_eq_nc Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel Type
ty1 Type
ps_ty1 (CastTy Type
ty2 TcCoercion
co2) Type
_
| Maybe CanEqLHS -> Bool
forall a. Maybe a -> Bool
isNothing (Type -> Maybe CanEqLHS
canEqLHS_maybe Type
ty1)
= Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> SwapFlag
-> Type
-> TcCoercion
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCast Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel SwapFlag
IsSwapped Type
ty2 TcCoercion
co2 Type
ty1 Type
ps_ty1
can_eq_nc Bool
_rewritten GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel ty1 :: Type
ty1@(LitTy TyLit
l1) Type
_ (LitTy TyLit
l2) Type
_
| TyLit
l1 TyLit -> TyLit -> Bool
forall a. Eq a => a -> a -> Bool
== TyLit
l2
= do { CtEvidence -> Bool -> EvTerm -> TcS ()
setEvBindIfWanted CtEvidence
ev Bool
True (TcCoercion -> EvTerm
evCoercion (TcCoercion -> EvTerm) -> TcCoercion -> EvTerm
forall a b. (a -> b) -> a -> b
$ Role -> Type -> TcCoercion
mkReflCo (EqRel -> Role
eqRelRole EqRel
eq_rel) Type
ty1)
; CtEvidence -> String -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. CtEvidence -> String -> TcS (StopOrContinue a)
stopWith CtEvidence
ev String
"Equal LitTy" }
can_eq_nc Bool
_rewritten GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel
(FunTy { ft_mult :: Type -> Type
ft_mult = Type
am1, ft_af :: Type -> FunTyFlag
ft_af = FunTyFlag
af1, ft_arg :: Type -> Type
ft_arg = Type
ty1a, ft_res :: Type -> Type
ft_res = Type
ty1b }) Type
_ps_ty1
(FunTy { ft_mult :: Type -> Type
ft_mult = Type
am2, ft_af :: Type -> FunTyFlag
ft_af = FunTyFlag
af2, ft_arg :: Type -> Type
ft_arg = Type
ty2a, ft_res :: Type -> Type
ft_res = Type
ty2b }) Type
_ps_ty2
| FunTyFlag
af1 FunTyFlag -> FunTyFlag -> Bool
forall a. Eq a => a -> a -> Bool
== FunTyFlag
af2
= CtEvidence
-> EqRel
-> FunTyFlag
-> (Type, Type, Type)
-> (Type, Type, Type)
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtEvidence
-> EqRel
-> FunTyFlag
-> (Type, Type, Type)
-> (Type, Type, Type)
-> TcS (StopOrContinue a)
canDecomposableFunTy CtEvidence
ev EqRel
eq_rel FunTyFlag
af1 (Type
am1,Type
ty1a,Type
ty1b) (Type
am2,Type
ty2a,Type
ty2b)
can_eq_nc Bool
rewritten GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel Type
ty1 Type
_ Type
ty2 Type
_
| Just (TyCon
tc1, [Type]
tys1) <- HasCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
tcSplitTyConApp_maybe Type
ty1
, Just (TyCon
tc2, [Type]
tys2) <- HasCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
tcSplitTyConApp_maybe Type
ty2
, Bool -> Bool
not (TyCon -> Bool
isTypeFamilyTyCon TyCon
tc1 Bool -> Bool -> Bool
|| TyCon -> Bool
isTypeFamilyTyCon TyCon
tc2)
, let role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
both_generative :: Bool
both_generative = TyCon -> Role -> Bool
isGenerativeTyCon TyCon
tc1 Role
role Bool -> Bool -> Bool
&& TyCon -> Role -> Bool
isGenerativeTyCon TyCon
tc2 Role
role
, Bool
rewritten Bool -> Bool -> Bool
|| Bool
both_generative
= CtEvidence
-> EqRel
-> Bool
-> TyCon
-> [Type]
-> TyCon
-> [Type]
-> TcS (StopOrContinue (Either IrredCt EqCt))
canTyConApp CtEvidence
ev EqRel
eq_rel Bool
both_generative TyCon
tc1 [Type]
tys1 TyCon
tc2 [Type]
tys2
can_eq_nc Bool
_rewritten GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel
s1 :: Type
s1@ForAllTy{} Type
_
s2 :: Type
s2@ForAllTy{} Type
_
= CtEvidence
-> EqRel
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc_forall CtEvidence
ev EqRel
eq_rel Type
s1 Type
s2
can_eq_nc Bool
True GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
NomEq Type
ty1 Type
_ Type
ty2 Type
_
| Just (Type
t1, Type
s1) <- Type -> Maybe (Type, Type)
tcSplitAppTy_maybe Type
ty1
, Just (Type
t2, Type
s2) <- Type -> Maybe (Type, Type)
tcSplitAppTy_maybe Type
ty2
= CtEvidence
-> Type
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_app CtEvidence
ev Type
t1 Type
s1 Type
t2 Type
s2
can_eq_nc Bool
False GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel Type
_ Type
ps_ty1 Type
_ Type
ps_ty2
=
do { (redn1 :: Reduction
redn1@(Reduction TcCoercion
_ Type
xi1), RewriterSet
rewriters1) <- CtEvidence -> Type -> TcS (Reduction, RewriterSet)
rewrite CtEvidence
ev Type
ps_ty1
; (redn2 :: Reduction
redn2@(Reduction TcCoercion
_ Type
xi2), RewriterSet
rewriters2) <- CtEvidence -> Type -> TcS (Reduction, RewriterSet)
rewrite CtEvidence
ev Type
ps_ty2
; CtEvidence
new_ev <- RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence (RewriterSet
rewriters1 RewriterSet -> RewriterSet -> RewriterSet
forall a. Semigroup a => a -> a -> a
S.<> RewriterSet
rewriters2) CtEvidence
ev SwapFlag
NotSwapped Reduction
redn1 Reduction
redn2
; String -> SDoc -> TcS ()
traceTcS String
"can_eq_nc: go round again" (CtEvidence -> SDoc
forall a. Outputable a => a -> SDoc
ppr CtEvidence
new_ev SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
xi1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
xi2)
; Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> Type
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc Bool
True GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
new_ev EqRel
eq_rel Type
xi1 Type
xi1 Type
xi2 Type
xi2 }
can_eq_nc Bool
True GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel Type
ty1 Type
ps_ty1 Type
ty2 Type
ps_ty2
| Just CanEqLHS
can_eq_lhs1 <- Type -> Maybe CanEqLHS
canEqLHS_maybe Type
ty1
= do { String -> SDoc -> TcS ()
traceTcS String
"can_eq1" (Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty2)
; CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS CtEvidence
ev EqRel
eq_rel SwapFlag
NotSwapped CanEqLHS
can_eq_lhs1 Type
ps_ty1 Type
ty2 Type
ps_ty2 }
| Just CanEqLHS
can_eq_lhs2 <- Type -> Maybe CanEqLHS
canEqLHS_maybe Type
ty2
= do { String -> SDoc -> TcS ()
traceTcS String
"can_eq2" (Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty2)
; CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS CtEvidence
ev EqRel
eq_rel SwapFlag
IsSwapped CanEqLHS
can_eq_lhs2 Type
ps_ty2 Type
ty1 Type
ps_ty1 }
can_eq_nc Bool
True GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel Type
_ Type
ps_ty1 Type
_ Type
ps_ty2
= do { String -> SDoc -> TcS ()
traceTcS String
"can_eq_nc catch-all case" (Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ps_ty1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ps_ty2)
; case EqRel
eq_rel of
EqRel
ReprEq -> CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt a))
finishCanWithIrred CtIrredReason
ReprEqReason CtEvidence
ev
EqRel
NomEq -> CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt a))
finishCanWithIrred CtIrredReason
ShapeMismatchReason CtEvidence
ev }
can_eq_nc_forall :: CtEvidence -> EqRel
-> Type -> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc_forall :: CtEvidence
-> EqRel
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc_forall CtEvidence
ev EqRel
eq_rel Type
s1 Type
s2
| CtWanted { ctev_loc :: CtEvidence -> CtLoc
ctev_loc = CtLoc
loc, ctev_dest :: CtEvidence -> TcEvDest
ctev_dest = TcEvDest
orig_dest, ctev_rewriters :: CtEvidence -> RewriterSet
ctev_rewriters = RewriterSet
rewriters } <- CtEvidence
ev
= do { let free_tvs :: TyCoVarSet
free_tvs = [Type] -> TyCoVarSet
tyCoVarsOfTypes [Type
s1,Type
s2]
([TyVarBinder]
bndrs1, Type
phi1) = Type -> ([TyVarBinder], Type)
tcSplitForAllTyVarBinders Type
s1
([TyVarBinder]
bndrs2, Type
phi2) = Type -> ([TyVarBinder], Type)
tcSplitForAllTyVarBinders Type
s2
flags1 :: [ForAllTyFlag]
flags1 = [TyVarBinder] -> [ForAllTyFlag]
forall tv argf. [VarBndr tv argf] -> [argf]
binderFlags [TyVarBinder]
bndrs1
flags2 :: [ForAllTyFlag]
flags2 = [TyVarBinder] -> [ForAllTyFlag]
forall tv argf. [VarBndr tv argf] -> [argf]
binderFlags [TyVarBinder]
bndrs2
; if Bool -> Bool
not ((ForAllTyFlag -> ForAllTyFlag -> Bool)
-> [ForAllTyFlag] -> [ForAllTyFlag] -> Bool
forall a b. (a -> b -> Bool) -> [a] -> [b] -> Bool
all2 ForAllTyFlag -> ForAllTyFlag -> Bool
eqForAllVis [ForAllTyFlag]
flags1 [ForAllTyFlag]
flags2)
then do { String -> SDoc -> TcS ()
traceTcS String
"Forall failure" (SDoc -> TcS ()) -> SDoc -> TcS ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
s1, Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
s2, [TyVarBinder] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [TyVarBinder]
bndrs1, [TyVarBinder] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [TyVarBinder]
bndrs2
, [ForAllTyFlag] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [ForAllTyFlag]
flags1, [ForAllTyFlag] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [ForAllTyFlag]
flags2 ]
; CtEvidence
-> Type -> Type -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtEvidence
-> Type -> Type -> TcS (StopOrContinue (Either IrredCt a))
canEqHardFailure CtEvidence
ev Type
s1 Type
s2 }
else
do { String -> SDoc -> TcS ()
traceTcS String
"Creating implication for polytype equality" (SDoc -> TcS ()) -> SDoc -> TcS ()
forall a b. (a -> b) -> a -> b
$ CtEvidence -> SDoc
forall a. Outputable a => a -> SDoc
ppr CtEvidence
ev
; let empty_subst1 :: Subst
empty_subst1 = InScopeSet -> Subst
mkEmptySubst (InScopeSet -> Subst) -> InScopeSet -> Subst
forall a b. (a -> b) -> a -> b
$ TyCoVarSet -> InScopeSet
mkInScopeSet TyCoVarSet
free_tvs
; SkolemInfo
skol_info <- SkolemInfoAnon -> TcS SkolemInfo
forall (m :: * -> *). MonadIO m => SkolemInfoAnon -> m SkolemInfo
mkSkolemInfo (Type -> SkolemInfoAnon
UnifyForAllSkol Type
phi1)
; (Subst
subst1, [TyVar]
skol_tvs) <- SkolemInfo -> Subst -> [TyVar] -> TcS (Subst, [TyVar])
tcInstSkolTyVarsX SkolemInfo
skol_info Subst
empty_subst1 ([TyVar] -> TcS (Subst, [TyVar]))
-> [TyVar] -> TcS (Subst, [TyVar])
forall a b. (a -> b) -> a -> b
$
[TyVarBinder] -> [TyVar]
forall tv argf. [VarBndr tv argf] -> [tv]
binderVars [TyVarBinder]
bndrs1
; let phi1' :: Type
phi1' = HasDebugCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst1 Type
phi1
go :: [TcTyVar] -> Subst -> [TyVarBinder]
-> TcS (TcCoercion, Cts)
go :: [TyVar] -> Subst -> [TyVarBinder] -> TcS (TcCoercion, Cts)
go (TyVar
skol_tv:[TyVar]
skol_tvs) Subst
subst (TyVarBinder
bndr2:[TyVarBinder]
bndrs2)
= do { let tv2 :: TyVar
tv2 = TyVarBinder -> TyVar
forall tv argf. VarBndr tv argf -> tv
binderVar TyVarBinder
bndr2
; (TcCoercion
kind_co, Cts
wanteds1) <- CtLoc
-> RewriterSet -> Role -> Type -> Type -> TcS (TcCoercion, Cts)
unify CtLoc
loc RewriterSet
rewriters Role
Nominal (TyVar -> Type
tyVarKind TyVar
skol_tv)
(HasDebugCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst (TyVar -> Type
tyVarKind TyVar
tv2))
; let subst' :: Subst
subst' = Subst -> TyVar -> Type -> Subst
extendTvSubstAndInScope Subst
subst TyVar
tv2
(Type -> TcCoercion -> Type
mkCastTy (TyVar -> Type
mkTyVarTy TyVar
skol_tv) TcCoercion
kind_co)
; (TcCoercion
co, Cts
wanteds2) <- [TyVar] -> Subst -> [TyVarBinder] -> TcS (TcCoercion, Cts)
go [TyVar]
skol_tvs Subst
subst' [TyVarBinder]
bndrs2
; (TcCoercion, Cts) -> TcS (TcCoercion, Cts)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return ( TyVar -> TcCoercion -> TcCoercion -> TcCoercion
mkForAllCo TyVar
skol_tv TcCoercion
kind_co TcCoercion
co
, Cts
wanteds1 Cts -> Cts -> Cts
forall a. Bag a -> Bag a -> Bag a
`unionBags` Cts
wanteds2 ) }
go [] Subst
subst [TyVarBinder]
bndrs2
= Bool -> TcS (TcCoercion, Cts) -> TcS (TcCoercion, Cts)
forall a. HasCallStack => Bool -> a -> a
assert ([TyVarBinder] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TyVarBinder]
bndrs2) (TcS (TcCoercion, Cts) -> TcS (TcCoercion, Cts))
-> TcS (TcCoercion, Cts) -> TcS (TcCoercion, Cts)
forall a b. (a -> b) -> a -> b
$
CtLoc
-> RewriterSet -> Role -> Type -> Type -> TcS (TcCoercion, Cts)
unify CtLoc
loc RewriterSet
rewriters (EqRel -> Role
eqRelRole EqRel
eq_rel) Type
phi1' (Subst -> Type -> Type
substTyUnchecked Subst
subst Type
phi2)
go [TyVar]
_ Subst
_ [TyVarBinder]
_ = String -> TcS (TcCoercion, Cts)
forall a. HasCallStack => String -> a
panic String
"cna_eq_nc_forall"
empty_subst2 :: Subst
empty_subst2 = InScopeSet -> Subst
mkEmptySubst (Subst -> InScopeSet
getSubstInScope Subst
subst1)
; (TcLevel
lvl, (TcCoercion
all_co, Cts
wanteds)) <- SDoc -> TcS (TcCoercion, Cts) -> TcS (TcLevel, (TcCoercion, Cts))
forall a. SDoc -> TcS a -> TcS (TcLevel, a)
pushLevelNoWorkList (SkolemInfo -> SDoc
forall a. Outputable a => a -> SDoc
ppr SkolemInfo
skol_info) (TcS (TcCoercion, Cts) -> TcS (TcLevel, (TcCoercion, Cts)))
-> TcS (TcCoercion, Cts) -> TcS (TcLevel, (TcCoercion, Cts))
forall a b. (a -> b) -> a -> b
$
[TyVar] -> Subst -> [TyVarBinder] -> TcS (TcCoercion, Cts)
go [TyVar]
skol_tvs Subst
empty_subst2 [TyVarBinder]
bndrs2
; TcLevel -> SkolemInfoAnon -> [TyVar] -> Cts -> TcS ()
emitTvImplicationTcS TcLevel
lvl (SkolemInfo -> SkolemInfoAnon
getSkolemInfo SkolemInfo
skol_info) [TyVar]
skol_tvs Cts
wanteds
; HasDebugCallStack => TcEvDest -> TcCoercion -> TcS ()
TcEvDest -> TcCoercion -> TcS ()
setWantedEq TcEvDest
orig_dest TcCoercion
all_co
; CtEvidence -> String -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. CtEvidence -> String -> TcS (StopOrContinue a)
stopWith CtEvidence
ev String
"Deferred polytype equality" } }
| Bool
otherwise
= do { String -> SDoc -> TcS ()
traceTcS String
"Omitting decomposition of given polytype equality" (SDoc -> TcS ()) -> SDoc -> TcS ()
forall a b. (a -> b) -> a -> b
$
Type -> Type -> SDoc
pprEq Type
s1 Type
s2
; CtEvidence -> String -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. CtEvidence -> String -> TcS (StopOrContinue a)
stopWith CtEvidence
ev String
"Discard given polytype equality" }
where
unify :: CtLoc -> RewriterSet -> Role -> TcType -> TcType -> TcS (TcCoercion, Cts)
unify :: CtLoc
-> RewriterSet -> Role -> Type -> Type -> TcS (TcCoercion, Cts)
unify CtLoc
loc RewriterSet
rewriters Role
role Type
ty1 Type
ty2
| Type
ty1 HasDebugCallStack => Type -> Type -> Bool
Type -> Type -> Bool
`tcEqType` Type
ty2
= (TcCoercion, Cts) -> TcS (TcCoercion, Cts)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (Role -> Type -> TcCoercion
mkReflCo Role
role Type
ty1, Cts
forall a. Bag a
emptyBag)
| Bool
otherwise
= do { (CtEvidence
wanted, TcCoercion
co) <- CtLoc
-> RewriterSet
-> Role
-> Type
-> Type
-> TcS (CtEvidence, TcCoercion)
newWantedEq CtLoc
loc RewriterSet
rewriters Role
role Type
ty1 Type
ty2
; (TcCoercion, Cts) -> TcS (TcCoercion, Cts)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (TcCoercion
co, Ct -> Cts
forall a. a -> Bag a
unitBag (CtEvidence -> Ct
mkNonCanonical CtEvidence
wanted)) }
can_eq_newtype_nc :: GlobalRdrEnv -> FamInstEnvs
-> CtEvidence
-> SwapFlag
-> TcType
-> ((Bag GlobalRdrElt, TcCoercion), TcType)
-> TcType
-> TcType
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_newtype_nc :: GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> SwapFlag
-> Type
-> ((Bag GlobalRdrElt, TcCoercion), Type)
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_newtype_nc GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev SwapFlag
swapped Type
ty1 ((Bag GlobalRdrElt
gres, TcCoercion
co1), Type
ty1') Type
ty2 Type
ps_ty2
= do { String -> SDoc -> TcS ()
traceTcS String
"can_eq_newtype_nc" (SDoc -> TcS ()) -> SDoc -> TcS ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ CtEvidence -> SDoc
forall a. Outputable a => a -> SDoc
ppr CtEvidence
ev, SwapFlag -> SDoc
forall a. Outputable a => a -> SDoc
ppr SwapFlag
swapped, TcCoercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr TcCoercion
co1, Bag GlobalRdrElt -> SDoc
forall a. Outputable a => a -> SDoc
ppr Bag GlobalRdrElt
gres, Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty1', Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty2 ]
; let loc :: CtLoc
loc = CtEvidence -> CtLoc
ctEvLoc CtEvidence
ev
ev' :: CtEvidence
ev' = CtEvidence
ev CtEvidence -> CtLoc -> CtEvidence
`setCtEvLoc` CtLoc -> CtLoc
bumpCtLocDepth CtLoc
loc
; CtLoc -> Type -> TcS ()
checkReductionDepth CtLoc
loc Type
ty1
; Bag GlobalRdrElt -> TcS ()
recordUsedGREs Bag GlobalRdrElt
gres
; let redn1 :: Reduction
redn1 = TcCoercion -> Type -> Reduction
mkReduction TcCoercion
co1 Type
ty1'
; CtEvidence
new_ev <- RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence RewriterSet
emptyRewriterSet CtEvidence
ev' SwapFlag
swapped
Reduction
redn1 (Role -> Type -> Reduction
mkReflRedn Role
Representational Type
ps_ty2)
; Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> Type
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc Bool
False GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
new_ev EqRel
ReprEq Type
ty1' Type
ty1' Type
ty2 Type
ps_ty2 }
can_eq_app :: CtEvidence
-> Xi -> Xi
-> Xi -> Xi
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_app :: CtEvidence
-> Type
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_app CtEvidence
ev Type
s1 Type
t1 Type
s2 Type
t2
| CtWanted { ctev_dest :: CtEvidence -> TcEvDest
ctev_dest = TcEvDest
dest } <- CtEvidence
ev
= do { String -> SDoc -> TcS ()
traceTcS String
"can_eq_app" ([SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"s1:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
s1, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"t1:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
t1
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"s2:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
s2, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"t2:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
t2
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"vis:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Bool -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Type -> Bool
isNextArgVisible Type
s1) ])
; (TcCoercion
co,Cts
_,[TyVar]
_) <- CtEvidence
-> Role
-> (UnifyEnv -> TcM TcCoercion)
-> TcS (TcCoercion, Cts, [TyVar])
forall a.
CtEvidence -> Role -> (UnifyEnv -> TcM a) -> TcS (a, Cts, [TyVar])
wrapUnifierTcS CtEvidence
ev Role
Nominal ((UnifyEnv -> TcM TcCoercion) -> TcS (TcCoercion, Cts, [TyVar]))
-> (UnifyEnv -> TcM TcCoercion) -> TcS (TcCoercion, Cts, [TyVar])
forall a b. (a -> b) -> a -> b
$ \UnifyEnv
uenv ->
do { let arg_env :: UnifyEnv
arg_env = UnifyEnv -> (CtLoc -> CtLoc) -> UnifyEnv
updUEnvLoc UnifyEnv
uenv (Bool -> Bool -> CtLoc -> CtLoc
adjustCtLoc (Type -> Bool
isNextArgVisible Type
s1) Bool
False)
; TcCoercion
co_t <- UnifyEnv -> Type -> Type -> TcM TcCoercion
uType UnifyEnv
arg_env Type
t1 Type
t2
; TcCoercion
co_s <- UnifyEnv -> Type -> Type -> TcM TcCoercion
uType UnifyEnv
uenv Type
s1 Type
s2
; TcCoercion -> TcM TcCoercion
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (TcCoercion -> TcCoercion -> TcCoercion
mkAppCo TcCoercion
co_s TcCoercion
co_t) }
; HasDebugCallStack => TcEvDest -> TcCoercion -> TcS ()
TcEvDest -> TcCoercion -> TcS ()
setWantedEq TcEvDest
dest TcCoercion
co
; CtEvidence -> String -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. CtEvidence -> String -> TcS (StopOrContinue a)
stopWith CtEvidence
ev String
"Decomposed [W] AppTy" }
| Type
s1k Type -> Type -> Bool
`mismatches` Type
s2k
= CtEvidence
-> Type -> Type -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtEvidence
-> Type -> Type -> TcS (StopOrContinue (Either IrredCt a))
canEqHardFailure CtEvidence
ev (Type
s1 Type -> Type -> Type
`mkAppTy` Type
t1) (Type
s2 Type -> Type -> Type
`mkAppTy` Type
t2)
| CtGiven { ctev_evar :: CtEvidence -> TyVar
ctev_evar = TyVar
evar } <- CtEvidence
ev
= do { let co :: TcCoercion
co = TyVar -> TcCoercion
mkCoVarCo TyVar
evar
co_s :: TcCoercion
co_s = LeftOrRight -> TcCoercion -> TcCoercion
mkLRCo LeftOrRight
CLeft TcCoercion
co
co_t :: TcCoercion
co_t = LeftOrRight -> TcCoercion -> TcCoercion
mkLRCo LeftOrRight
CRight TcCoercion
co
; CtEvidence
evar_s <- CtLoc -> (Type, EvTerm) -> TcS CtEvidence
newGivenEvVar CtLoc
loc ( CtEvidence -> Type -> Type -> Type
mkTcEqPredLikeEv CtEvidence
ev Type
s1 Type
s2
, TcCoercion -> EvTerm
evCoercion TcCoercion
co_s )
; CtEvidence
evar_t <- CtLoc -> (Type, EvTerm) -> TcS CtEvidence
newGivenEvVar CtLoc
loc ( CtEvidence -> Type -> Type -> Type
mkTcEqPredLikeEv CtEvidence
ev Type
t1 Type
t2
, TcCoercion -> EvTerm
evCoercion TcCoercion
co_t )
; [CtEvidence] -> TcS ()
emitWorkNC [CtEvidence
evar_t]
; Ct -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. Ct -> TcS (StopOrContinue a)
startAgainWith (CtEvidence -> Ct
mkNonCanonical CtEvidence
evar_s) }
where
loc :: CtLoc
loc = CtEvidence -> CtLoc
ctEvLoc CtEvidence
ev
s1k :: Type
s1k = HasDebugCallStack => Type -> Type
Type -> Type
typeKind Type
s1
s2k :: Type
s2k = HasDebugCallStack => Type -> Type
Type -> Type
typeKind Type
s2
Type
k1 mismatches :: Type -> Type -> Bool
`mismatches` Type
k2
= Type -> Bool
isForAllTy Type
k1 Bool -> Bool -> Bool
&& Bool -> Bool
not (Type -> Bool
isForAllTy Type
k2)
Bool -> Bool -> Bool
|| Bool -> Bool
not (Type -> Bool
isForAllTy Type
k1) Bool -> Bool -> Bool
&& Type -> Bool
isForAllTy Type
k2
canEqCast :: Bool
-> GlobalRdrEnv -> FamInstEnvs
-> CtEvidence
-> EqRel
-> SwapFlag
-> TcType -> Coercion
-> TcType -> TcType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCast :: Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> SwapFlag
-> Type
-> TcCoercion
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCast Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel SwapFlag
swapped Type
ty1 TcCoercion
co1 Type
ty2 Type
ps_ty2
= do { String -> SDoc -> TcS ()
traceTcS String
"Decomposing cast" ([SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ CtEvidence -> SDoc
forall a. Outputable a => a -> SDoc
ppr CtEvidence
ev
, Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty1 SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"|>" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> TcCoercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr TcCoercion
co1
, Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ps_ty2 ])
; CtEvidence
new_ev <- RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence RewriterSet
emptyRewriterSet CtEvidence
ev SwapFlag
swapped
(Role -> Type -> TcCoercion -> Reduction
mkGReflLeftRedn Role
role Type
ty1 TcCoercion
co1)
(Role -> Type -> Reduction
mkReflRedn Role
role Type
ps_ty2)
; Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> Type
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
new_ev EqRel
eq_rel Type
ty1 Type
ty1 Type
ty2 Type
ps_ty2 }
where
role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
canTyConApp :: CtEvidence -> EqRel
-> Bool
-> TyCon -> [TcType]
-> TyCon -> [TcType]
-> TcS (StopOrContinue (Either IrredCt EqCt))
canTyConApp :: CtEvidence
-> EqRel
-> Bool
-> TyCon
-> [Type]
-> TyCon
-> [Type]
-> TcS (StopOrContinue (Either IrredCt EqCt))
canTyConApp CtEvidence
ev EqRel
eq_rel Bool
both_generative TyCon
tc1 [Type]
tys1 TyCon
tc2 [Type]
tys2
| TyCon
tc1 TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
tc2
, [Type]
tys1 [Type] -> [Type] -> Bool
forall a b. [a] -> [b] -> Bool
`equalLength` [Type]
tys2
= do { InertSet
inerts <- TcS InertSet
getInertSet
; if InertSet -> Bool
can_decompose InertSet
inerts
then CtEvidence
-> EqRel
-> TyCon
-> [Type]
-> [Type]
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtEvidence
-> EqRel -> TyCon -> [Type] -> [Type] -> TcS (StopOrContinue a)
canDecomposableTyConAppOK CtEvidence
ev EqRel
eq_rel TyCon
tc1 [Type]
tys1 [Type]
tys2
else CtEvidence
-> EqRel
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtEvidence
-> EqRel -> Type -> Type -> TcS (StopOrContinue (Either IrredCt a))
canEqSoftFailure CtEvidence
ev EqRel
eq_rel Type
ty1 Type
ty2 }
| TyCon -> Bool
tyConSkolem TyCon
tc1 Bool -> Bool -> Bool
|| TyCon -> Bool
tyConSkolem TyCon
tc2
= do { String -> SDoc -> TcS ()
traceTcS String
"canTyConApp: skolem abstract" (TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
tc1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
tc2)
; CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt a))
finishCanWithIrred CtIrredReason
AbstractTyConReason CtEvidence
ev }
| Bool
otherwise
= if Bool
both_generative
then CtEvidence
-> Type -> Type -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtEvidence
-> Type -> Type -> TcS (StopOrContinue (Either IrredCt a))
canEqHardFailure CtEvidence
ev Type
ty1 Type
ty2
else CtEvidence
-> EqRel
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtEvidence
-> EqRel -> Type -> Type -> TcS (StopOrContinue (Either IrredCt a))
canEqSoftFailure CtEvidence
ev EqRel
eq_rel Type
ty1 Type
ty2
where
ty1 :: Type
ty1 = TyCon -> [Type] -> Type
mkTyConApp TyCon
tc1 [Type]
tys1
ty2 :: Type
ty2 = TyCon -> [Type] -> Type
mkTyConApp TyCon
tc2 [Type]
tys2
can_decompose :: InertSet -> Bool
can_decompose InertSet
inerts
= TyCon -> Role -> Bool
isInjectiveTyCon TyCon
tc1 (EqRel -> Role
eqRelRole EqRel
eq_rel)
Bool -> Bool -> Bool
|| (Bool -> Bool -> Bool
forall a. HasCallStack => Bool -> a -> a
assert (EqRel
eq_rel EqRel -> EqRel -> Bool
forall a. Eq a => a -> a -> Bool
== EqRel
ReprEq) (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$
CtEvidence -> CtFlavour
ctEvFlavour CtEvidence
ev CtFlavour -> CtFlavour -> Bool
forall a. Eq a => a -> a -> Bool
== CtFlavour
Wanted Bool -> Bool -> Bool
&& TyCon -> InertSet -> Bool
noGivenNewtypeReprEqs TyCon
tc1 InertSet
inerts)
canDecomposableTyConAppOK :: CtEvidence -> EqRel
-> TyCon -> [TcType] -> [TcType]
-> TcS (StopOrContinue a)
canDecomposableTyConAppOK :: forall a.
CtEvidence
-> EqRel -> TyCon -> [Type] -> [Type] -> TcS (StopOrContinue a)
canDecomposableTyConAppOK CtEvidence
ev EqRel
eq_rel TyCon
tc [Type]
tys1 [Type]
tys2
= Bool -> TcS (StopOrContinue a) -> TcS (StopOrContinue a)
forall a. HasCallStack => Bool -> a -> a
assert ([Type]
tys1 [Type] -> [Type] -> Bool
forall a b. [a] -> [b] -> Bool
`equalLength` [Type]
tys2) (TcS (StopOrContinue a) -> TcS (StopOrContinue a))
-> TcS (StopOrContinue a) -> TcS (StopOrContinue a)
forall a b. (a -> b) -> a -> b
$
do { String -> SDoc -> TcS ()
traceTcS String
"canDecomposableTyConAppOK"
(CtEvidence -> SDoc
forall a. Outputable a => a -> SDoc
ppr CtEvidence
ev SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ EqRel -> SDoc
forall a. Outputable a => a -> SDoc
ppr EqRel
eq_rel SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
tc SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ [Type] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Type]
tys1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ [Type] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Type]
tys2)
; case CtEvidence
ev of
CtWanted { ctev_dest :: CtEvidence -> TcEvDest
ctev_dest = TcEvDest
dest }
-> do { (TcCoercion
co, Cts
_, [TyVar]
_) <- CtEvidence
-> Role
-> (UnifyEnv -> TcM TcCoercion)
-> TcS (TcCoercion, Cts, [TyVar])
forall a.
CtEvidence -> Role -> (UnifyEnv -> TcM a) -> TcS (a, Cts, [TyVar])
wrapUnifierTcS CtEvidence
ev Role
role ((UnifyEnv -> TcM TcCoercion) -> TcS (TcCoercion, Cts, [TyVar]))
-> (UnifyEnv -> TcM TcCoercion) -> TcS (TcCoercion, Cts, [TyVar])
forall a b. (a -> b) -> a -> b
$ \UnifyEnv
uenv ->
do { [TcCoercion]
cos <- (CtLoc -> Role -> Type -> Type -> TcM TcCoercion)
-> [CtLoc]
-> [Role]
-> [Type]
-> [Type]
-> IOEnv (Env TcGblEnv TcLclEnv) [TcCoercion]
forall (m :: * -> *) a b c d e.
Monad m =>
(a -> b -> c -> d -> m e) -> [a] -> [b] -> [c] -> [d] -> m [e]
zipWith4M (UnifyEnv -> CtLoc -> Role -> Type -> Type -> TcM TcCoercion
u_arg UnifyEnv
uenv) [CtLoc]
new_locs [Role]
tc_roles [Type]
tys1 [Type]
tys2
; TcCoercion -> TcM TcCoercion
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (HasDebugCallStack => Role -> TyCon -> [TcCoercion] -> TcCoercion
Role -> TyCon -> [TcCoercion] -> TcCoercion
mkTyConAppCo Role
role TyCon
tc [TcCoercion]
cos) }
; HasDebugCallStack => TcEvDest -> TcCoercion -> TcS ()
TcEvDest -> TcCoercion -> TcS ()
setWantedEq TcEvDest
dest TcCoercion
co }
CtGiven { ctev_evar :: CtEvidence -> TyVar
ctev_evar = TyVar
evar }
| let ev_co :: TcCoercion
ev_co = TyVar -> TcCoercion
mkCoVarCo TyVar
evar
-> CtLoc -> [(Role, Type, Type, TcCoercion)] -> TcS ()
emitNewGivens CtLoc
loc
[ (Role
r, Type
ty1, Type
ty2, HasDebugCallStack => CoSel -> TcCoercion -> TcCoercion
CoSel -> TcCoercion -> TcCoercion
mkSelCo (Int -> Role -> CoSel
SelTyCon Int
i Role
r) TcCoercion
ev_co)
| (Role
r, Type
ty1, Type
ty2, Int
i) <- [Role] -> [Type] -> [Type] -> [Int] -> [(Role, Type, Type, Int)]
forall a b c d. [a] -> [b] -> [c] -> [d] -> [(a, b, c, d)]
zip4 [Role]
tc_roles [Type]
tys1 [Type]
tys2 [Int
0..]
, Role
r Role -> Role -> Bool
forall a. Eq a => a -> a -> Bool
/= Role
Phantom
, Bool -> Bool
not (Type -> Bool
isCoercionTy Type
ty1) Bool -> Bool -> Bool
&& Bool -> Bool
not (Type -> Bool
isCoercionTy Type
ty2) ]
; CtEvidence -> String -> TcS (StopOrContinue a)
forall a. CtEvidence -> String -> TcS (StopOrContinue a)
stopWith CtEvidence
ev String
"Decomposed TyConApp" }
where
loc :: CtLoc
loc = CtEvidence -> CtLoc
ctEvLoc CtEvidence
ev
role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
u_arg :: UnifyEnv -> CtLoc -> Role -> Type -> Type -> TcM TcCoercion
u_arg UnifyEnv
uenv CtLoc
arg_loc Role
arg_role = UnifyEnv -> Type -> Type -> TcM TcCoercion
uType UnifyEnv
arg_env
where
arg_env :: UnifyEnv
arg_env = UnifyEnv
uenv UnifyEnv -> Role -> UnifyEnv
`setUEnvRole` Role
arg_role
UnifyEnv -> (CtLoc -> CtLoc) -> UnifyEnv
`updUEnvLoc` CtLoc -> CtLoc -> CtLoc
forall a b. a -> b -> a
const CtLoc
arg_loc
tc_roles :: [Role]
tc_roles = Role -> TyCon -> [Role]
tyConRoleListX Role
role TyCon
tc
new_locs :: [CtLoc]
new_locs = [ TyConBinder -> CtLoc -> CtLoc
adjustCtLocTyConBinder TyConBinder
bndr CtLoc
loc
| TyConBinder
bndr <- TyCon -> [TyConBinder]
tyConBinders TyCon
tc ]
[CtLoc] -> [CtLoc] -> [CtLoc]
forall a. [a] -> [a] -> [a]
++ CtLoc -> [CtLoc]
forall a. a -> [a]
repeat CtLoc
loc
canDecomposableFunTy :: CtEvidence -> EqRel -> FunTyFlag
-> (Type,Type,Type)
-> (Type,Type,Type)
-> TcS (StopOrContinue a)
canDecomposableFunTy :: forall a.
CtEvidence
-> EqRel
-> FunTyFlag
-> (Type, Type, Type)
-> (Type, Type, Type)
-> TcS (StopOrContinue a)
canDecomposableFunTy CtEvidence
ev EqRel
eq_rel FunTyFlag
af f1 :: (Type, Type, Type)
f1@(Type
m1,Type
a1,Type
r1) f2 :: (Type, Type, Type)
f2@(Type
m2,Type
a2,Type
r2)
= do { String -> SDoc -> TcS ()
traceTcS String
"canDecomposableFunTy"
(CtEvidence -> SDoc
forall a. Outputable a => a -> SDoc
ppr CtEvidence
ev SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ EqRel -> SDoc
forall a. Outputable a => a -> SDoc
ppr EqRel
eq_rel SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ (Type, Type, Type) -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Type, Type, Type)
f1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ (Type, Type, Type) -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Type, Type, Type)
f2)
; case CtEvidence
ev of
CtWanted { ctev_dest :: CtEvidence -> TcEvDest
ctev_dest = TcEvDest
dest }
-> do { (TcCoercion
co, Cts
_, [TyVar]
_) <- CtEvidence
-> Role
-> (UnifyEnv -> TcM TcCoercion)
-> TcS (TcCoercion, Cts, [TyVar])
forall a.
CtEvidence -> Role -> (UnifyEnv -> TcM a) -> TcS (a, Cts, [TyVar])
wrapUnifierTcS CtEvidence
ev Role
Nominal ((UnifyEnv -> TcM TcCoercion) -> TcS (TcCoercion, Cts, [TyVar]))
-> (UnifyEnv -> TcM TcCoercion) -> TcS (TcCoercion, Cts, [TyVar])
forall a b. (a -> b) -> a -> b
$ \ UnifyEnv
uenv ->
do { let mult_env :: UnifyEnv
mult_env = UnifyEnv
uenv UnifyEnv -> (CtLoc -> CtLoc) -> UnifyEnv
`updUEnvLoc` CtLoc -> CtLoc
toInvisibleLoc
UnifyEnv -> Role -> UnifyEnv
`setUEnvRole` Role -> FunSel -> Role
funRole Role
role FunSel
SelMult
; TcCoercion
mult <- UnifyEnv -> Type -> Type -> TcM TcCoercion
uType UnifyEnv
mult_env Type
m1 Type
m2
; TcCoercion
arg <- UnifyEnv -> Type -> Type -> TcM TcCoercion
uType (UnifyEnv
uenv UnifyEnv -> Role -> UnifyEnv
`setUEnvRole` Role -> FunSel -> Role
funRole Role
role FunSel
SelArg) Type
a1 Type
a2
; TcCoercion
res <- UnifyEnv -> Type -> Type -> TcM TcCoercion
uType (UnifyEnv
uenv UnifyEnv -> Role -> UnifyEnv
`setUEnvRole` Role -> FunSel -> Role
funRole Role
role FunSel
SelRes) Type
r1 Type
r2
; TcCoercion -> TcM TcCoercion
forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Role
-> FunTyFlag
-> TcCoercion
-> TcCoercion
-> TcCoercion
-> TcCoercion
mkNakedFunCo Role
role FunTyFlag
af TcCoercion
mult TcCoercion
arg TcCoercion
res) }
; HasDebugCallStack => TcEvDest -> TcCoercion -> TcS ()
TcEvDest -> TcCoercion -> TcS ()
setWantedEq TcEvDest
dest TcCoercion
co }
CtGiven { ctev_evar :: CtEvidence -> TyVar
ctev_evar = TyVar
evar }
| let ev_co :: TcCoercion
ev_co = TyVar -> TcCoercion
mkCoVarCo TyVar
evar
-> CtLoc -> [(Role, Type, Type, TcCoercion)] -> TcS ()
emitNewGivens CtLoc
loc
[ (Role -> FunSel -> Role
funRole Role
role FunSel
fs, Type
ty1, Type
ty2, HasDebugCallStack => CoSel -> TcCoercion -> TcCoercion
CoSel -> TcCoercion -> TcCoercion
mkSelCo (FunSel -> CoSel
SelFun FunSel
fs) TcCoercion
ev_co)
| (FunSel
fs, Type
ty1, Type
ty2) <- [ (FunSel
SelMult, Type
m1, Type
m2)
, (FunSel
SelArg, Type
a1, Type
a2)
, (FunSel
SelRes, Type
r1, Type
r2)] ]
; CtEvidence -> String -> TcS (StopOrContinue a)
forall a. CtEvidence -> String -> TcS (StopOrContinue a)
stopWith CtEvidence
ev String
"Decomposed TyConApp" }
where
loc :: CtLoc
loc = CtEvidence -> CtLoc
ctEvLoc CtEvidence
ev
role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
canEqSoftFailure :: CtEvidence -> EqRel -> TcType -> TcType
-> TcS (StopOrContinue (Either IrredCt a))
canEqSoftFailure :: forall a.
CtEvidence
-> EqRel -> Type -> Type -> TcS (StopOrContinue (Either IrredCt a))
canEqSoftFailure CtEvidence
ev EqRel
NomEq Type
ty1 Type
ty2
= CtEvidence
-> Type -> Type -> TcS (StopOrContinue (Either IrredCt a))
forall a.
CtEvidence
-> Type -> Type -> TcS (StopOrContinue (Either IrredCt a))
canEqHardFailure CtEvidence
ev Type
ty1 Type
ty2
canEqSoftFailure CtEvidence
ev EqRel
ReprEq Type
ty1 Type
ty2
= do { (Reduction
redn1, RewriterSet
rewriters1) <- CtEvidence -> Type -> TcS (Reduction, RewriterSet)
rewrite CtEvidence
ev Type
ty1
; (Reduction
redn2, RewriterSet
rewriters2) <- CtEvidence -> Type -> TcS (Reduction, RewriterSet)
rewrite CtEvidence
ev Type
ty2
; String -> SDoc -> TcS ()
traceTcS String
"canEqSoftFailure with ReprEq" (SDoc -> TcS ()) -> SDoc -> TcS ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ CtEvidence -> SDoc
forall a. Outputable a => a -> SDoc
ppr CtEvidence
ev, Reduction -> SDoc
forall a. Outputable a => a -> SDoc
ppr Reduction
redn1, Reduction -> SDoc
forall a. Outputable a => a -> SDoc
ppr Reduction
redn2 ]
; CtEvidence
new_ev <- RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence (RewriterSet
rewriters1 RewriterSet -> RewriterSet -> RewriterSet
forall a. Semigroup a => a -> a -> a
S.<> RewriterSet
rewriters2) CtEvidence
ev SwapFlag
NotSwapped Reduction
redn1 Reduction
redn2
; CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt a))
forall a.
CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt a))
finishCanWithIrred CtIrredReason
ReprEqReason CtEvidence
new_ev }
canEqHardFailure :: CtEvidence -> TcType -> TcType
-> TcS (StopOrContinue (Either IrredCt a))
canEqHardFailure :: forall a.
CtEvidence
-> Type -> Type -> TcS (StopOrContinue (Either IrredCt a))
canEqHardFailure CtEvidence
ev Type
ty1 Type
ty2
= do { String -> SDoc -> TcS ()
traceTcS String
"canEqHardFailure" (Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty2)
; (Reduction
redn1, RewriterSet
rewriters1) <- CtEvidence -> Type -> TcS (Reduction, RewriterSet)
rewriteForErrors CtEvidence
ev Type
ty1
; (Reduction
redn2, RewriterSet
rewriters2) <- CtEvidence -> Type -> TcS (Reduction, RewriterSet)
rewriteForErrors CtEvidence
ev Type
ty2
; CtEvidence
new_ev <- RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence (RewriterSet
rewriters1 RewriterSet -> RewriterSet -> RewriterSet
forall a. Semigroup a => a -> a -> a
S.<> RewriterSet
rewriters2) CtEvidence
ev SwapFlag
NotSwapped Reduction
redn1 Reduction
redn2
; CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt a))
forall a.
CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt a))
finishCanWithIrred CtIrredReason
ShapeMismatchReason CtEvidence
new_ev }
canEqCanLHS :: CtEvidence
-> EqRel -> SwapFlag
-> CanEqLHS
-> TcType
-> TcType -> TcType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS :: CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 Type
ps_xi1 Type
xi2 Type
ps_xi2
| Type
k1 HasDebugCallStack => Type -> Type -> Bool
Type -> Type -> Bool
`tcEqType` Type
k2
= CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHomo CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 Type
ps_xi1 Type
xi2 Type
ps_xi2
| Bool
otherwise
= CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> Type
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHetero CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 Type
ps_xi1 Type
k1 Type
xi2 Type
ps_xi2 Type
k2
where
k1 :: Type
k1 = CanEqLHS -> Type
canEqLHSKind CanEqLHS
lhs1
k2 :: Type
k2 = HasDebugCallStack => Type -> Type
Type -> Type
typeKind Type
xi2
canEqCanLHSHetero :: CtEvidence
-> EqRel -> SwapFlag
-> CanEqLHS -> TcType
-> TcKind
-> TcType -> TcType
-> TcKind
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHetero :: CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> Type
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHetero CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 Type
ps_xi1 Type
ki1 Type
xi2 Type
ps_xi2 Type
ki2
= do { (TcCoercion
kind_co, RewriterSet
rewriters, Bool
unifs_happened) <- TcS (TcCoercion, RewriterSet, Bool)
mk_kind_eq
; if Bool
unifs_happened
then Ct -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. Ct -> TcS (StopOrContinue a)
startAgainWith (CtEvidence -> Ct
mkNonCanonical CtEvidence
ev)
else
do { let lhs_redn :: Reduction
lhs_redn = Role -> Type -> Reduction
mkReflRedn Role
role Type
ps_xi1
rhs_redn :: Reduction
rhs_redn = Role -> Type -> TcCoercion -> Reduction
mkGReflRightRedn Role
role Type
xi2 TcCoercion
mb_sym_kind_co
mb_sym_kind_co :: TcCoercion
mb_sym_kind_co = case SwapFlag
swapped of
SwapFlag
NotSwapped -> TcCoercion -> TcCoercion
mkSymCo TcCoercion
kind_co
SwapFlag
IsSwapped -> TcCoercion
kind_co
; String -> SDoc -> TcS ()
traceTcS String
"Hetero equality gives rise to kind equality"
(SwapFlag -> SDoc
forall a. Outputable a => a -> SDoc
ppr SwapFlag
swapped SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$
TcCoercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr TcCoercion
kind_co SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> [SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
sep [ Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ki1, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"~#", Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ki2 ])
; CtEvidence
type_ev <- RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence RewriterSet
rewriters CtEvidence
ev SwapFlag
swapped Reduction
lhs_redn Reduction
rhs_redn
; let new_xi2 :: Type
new_xi2 = Type -> TcCoercion -> Type
mkCastTy Type
ps_xi2 TcCoercion
mb_sym_kind_co
; CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHomo CtEvidence
type_ev EqRel
eq_rel SwapFlag
NotSwapped CanEqLHS
lhs1 Type
ps_xi1 Type
new_xi2 Type
new_xi2 }}
where
mk_kind_eq :: TcS (CoercionN, RewriterSet, Bool)
mk_kind_eq :: TcS (TcCoercion, RewriterSet, Bool)
mk_kind_eq = case CtEvidence
ev of
CtGiven { ctev_evar :: CtEvidence -> TyVar
ctev_evar = TyVar
evar }
-> do { let kind_co :: TcCoercion
kind_co = TcCoercion -> TcCoercion
mkKindCo (TyVar -> TcCoercion
mkCoVarCo TyVar
evar)
pred_ty :: Type
pred_ty = SwapFlag -> (Type -> Type -> Type) -> Type -> Type -> Type
forall a b. SwapFlag -> (a -> a -> b) -> a -> a -> b
unSwap SwapFlag
swapped (Type -> Type -> Type -> Type
mkNomPrimEqPred Type
liftedTypeKind) Type
ki1 Type
ki2
kind_loc :: CtLoc
kind_loc = Type -> Type -> CtLoc -> CtLoc
mkKindEqLoc Type
xi1 Type
xi2 (CtEvidence -> CtLoc
ctev_loc CtEvidence
ev)
; CtEvidence
kind_ev <- CtLoc -> (Type, EvTerm) -> TcS CtEvidence
newGivenEvVar CtLoc
kind_loc (Type
pred_ty, TcCoercion -> EvTerm
evCoercion TcCoercion
kind_co)
; [CtEvidence] -> TcS ()
emitWorkNC [CtEvidence
kind_ev]
; (TcCoercion, RewriterSet, Bool)
-> TcS (TcCoercion, RewriterSet, Bool)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (HasDebugCallStack => CtEvidence -> TcCoercion
CtEvidence -> TcCoercion
ctEvCoercion CtEvidence
kind_ev, RewriterSet
emptyRewriterSet, Bool
False) }
CtWanted {}
-> do { (TcCoercion
kind_co, Cts
cts, [TyVar]
unifs) <- CtEvidence
-> Role
-> (UnifyEnv -> TcM TcCoercion)
-> TcS (TcCoercion, Cts, [TyVar])
forall a.
CtEvidence -> Role -> (UnifyEnv -> TcM a) -> TcS (a, Cts, [TyVar])
wrapUnifierTcS CtEvidence
ev Role
Nominal ((UnifyEnv -> TcM TcCoercion) -> TcS (TcCoercion, Cts, [TyVar]))
-> (UnifyEnv -> TcM TcCoercion) -> TcS (TcCoercion, Cts, [TyVar])
forall a b. (a -> b) -> a -> b
$ \UnifyEnv
uenv ->
let uenv' :: UnifyEnv
uenv' = UnifyEnv -> (CtLoc -> CtLoc) -> UnifyEnv
updUEnvLoc UnifyEnv
uenv (Type -> Type -> CtLoc -> CtLoc
mkKindEqLoc Type
xi1 Type
xi2)
in SwapFlag
-> (Type -> Type -> TcM TcCoercion)
-> Type
-> Type
-> TcM TcCoercion
forall a b. SwapFlag -> (a -> a -> b) -> a -> a -> b
unSwap SwapFlag
swapped (UnifyEnv -> Type -> Type -> TcM TcCoercion
uType UnifyEnv
uenv') Type
ki1 Type
ki2
; (TcCoercion, RewriterSet, Bool)
-> TcS (TcCoercion, RewriterSet, Bool)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (TcCoercion
kind_co, Cts -> RewriterSet
rewriterSetFromCts Cts
cts, Bool -> Bool
not ([TyVar] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TyVar]
unifs)) }
xi1 :: Type
xi1 = CanEqLHS -> Type
canEqLHSType CanEqLHS
lhs1
role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
canEqCanLHSHomo :: CtEvidence
-> EqRel -> SwapFlag
-> CanEqLHS -> TcType
-> TcType -> TcType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHomo :: CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> Type
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHomo CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 Type
ps_xi1 Type
xi2 Type
ps_xi2
| (Type
xi2', MCoercion
mco) <- Type -> (Type, MCoercion)
split_cast_ty Type
xi2
, Just CanEqLHS
lhs2 <- Type -> Maybe CanEqLHS
canEqLHS_maybe Type
xi2'
= CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> CanEqLHS
-> Type
-> MCoercion
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS2 CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 Type
ps_xi1 CanEqLHS
lhs2 (Type
ps_xi2 Type -> MCoercion -> Type
`mkCastTyMCo` MCoercion -> MCoercion
mkSymMCo MCoercion
mco) MCoercion
mco
| Bool
otherwise
= CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 Type
ps_xi2
where
split_cast_ty :: Type -> (Type, MCoercion)
split_cast_ty (CastTy Type
ty TcCoercion
co) = (Type
ty, TcCoercion -> MCoercion
MCo TcCoercion
co)
split_cast_ty Type
other = (Type
other, MCoercion
MRefl)
canEqCanLHS2 :: CtEvidence
-> EqRel -> SwapFlag
-> CanEqLHS
-> TcType
-> CanEqLHS
-> TcType
-> MCoercion
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS2 :: CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> CanEqLHS
-> Type
-> MCoercion
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS2 CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 Type
ps_xi1 CanEqLHS
lhs2 Type
ps_xi2 MCoercion
mco
| CanEqLHS
lhs1 CanEqLHS -> CanEqLHS -> Bool
`eqCanEqLHS` CanEqLHS
lhs2
= CtEvidence
-> EqRel -> Type -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. CtEvidence -> EqRel -> Type -> TcS (StopOrContinue a)
canEqReflexive CtEvidence
ev EqRel
eq_rel Type
lhs1_ty
| TyVarLHS TyVar
tv1 <- CanEqLHS
lhs1
, TyVarLHS TyVar
tv2 <- CanEqLHS
lhs2
=
do { String -> SDoc -> TcS ()
traceTcS String
"canEqLHS2 swapOver" (TyVar -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyVar
tv1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ TyVar -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyVar
tv2 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ SwapFlag -> SDoc
forall a. Outputable a => a -> SDoc
ppr SwapFlag
swapped)
; if Bool -> TyVar -> TyVar -> Bool
swapOverTyVars (CtEvidence -> Bool
isGiven CtEvidence
ev) TyVar
tv1 TyVar
tv2
then TcS (StopOrContinue (Either IrredCt EqCt))
finish_with_swapping
else TcS (StopOrContinue (Either IrredCt EqCt))
finish_without_swapping }
| TyVarLHS {} <- CanEqLHS
lhs1
, TyFamLHS {} <- CanEqLHS
lhs2
= if Bool
put_tyvar_on_lhs
then TcS (StopOrContinue (Either IrredCt EqCt))
finish_without_swapping
else TcS (StopOrContinue (Either IrredCt EqCt))
finish_with_swapping
| TyFamLHS {} <- CanEqLHS
lhs1
, TyVarLHS {} <- CanEqLHS
lhs2
= if Bool
put_tyvar_on_lhs
then TcS (StopOrContinue (Either IrredCt EqCt))
finish_with_swapping
else TcS (StopOrContinue (Either IrredCt EqCt))
finish_without_swapping
| TyFamLHS TyCon
fun_tc1 [Type]
fun_args1 <- CanEqLHS
lhs1
, TyFamLHS TyCon
fun_tc2 [Type]
fun_args2 <- CanEqLHS
lhs2
= do { String -> SDoc -> TcS ()
traceTcS String
"canEqCanLHS2 two type families" (CanEqLHS -> SDoc
forall a. Outputable a => a -> SDoc
ppr CanEqLHS
lhs1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ CanEqLHS -> SDoc
forall a. Outputable a => a -> SDoc
ppr CanEqLHS
lhs2)
; Bool
unifications_done <- CtEvidence
-> EqRel
-> TyCon
-> [Type]
-> TyCon
-> [Type]
-> MCoercion
-> TcS Bool
tryFamFamInjectivity CtEvidence
ev EqRel
eq_rel
TyCon
fun_tc1 [Type]
fun_args1 TyCon
fun_tc2 [Type]
fun_args2 MCoercion
mco
; if Bool
unifications_done
then
Ct -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. Ct -> TcS (StopOrContinue a)
startAgainWith (CtEvidence -> Ct
mkNonCanonical CtEvidence
ev)
else
do { TcLevel
tclvl <- TcS TcLevel
getTcLevel
; let tvs1 :: TyCoVarSet
tvs1 = [Type] -> TyCoVarSet
tyCoVarsOfTypes [Type]
fun_args1
tvs2 :: TyCoVarSet
tvs2 = [Type] -> TyCoVarSet
tyCoVarsOfTypes [Type]
fun_args2
swap_for_size :: Bool
swap_for_size = [Type] -> Int
typesSize [Type]
fun_args2 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> [Type] -> Int
typesSize [Type]
fun_args1
swap_for_rewriting :: Bool
swap_for_rewriting = (TyVar -> Bool) -> TyCoVarSet -> Bool
anyVarSet (TcLevel -> TyVar -> Bool
isTouchableMetaTyVar TcLevel
tclvl) TyCoVarSet
tvs2 Bool -> Bool -> Bool
&&
Bool -> Bool
not ((TyVar -> Bool) -> TyCoVarSet -> Bool
anyVarSet (TcLevel -> TyVar -> Bool
isTouchableMetaTyVar TcLevel
tclvl) TyCoVarSet
tvs1)
; if Bool
swap_for_rewriting Bool -> Bool -> Bool
|| Bool
swap_for_size
then TcS (StopOrContinue (Either IrredCt EqCt))
finish_with_swapping
else TcS (StopOrContinue (Either IrredCt EqCt))
finish_without_swapping } }
where
sym_mco :: MCoercion
sym_mco = MCoercion -> MCoercion
mkSymMCo MCoercion
mco
role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
lhs1_ty :: Type
lhs1_ty = CanEqLHS -> Type
canEqLHSType CanEqLHS
lhs1
lhs2_ty :: Type
lhs2_ty = CanEqLHS -> Type
canEqLHSType CanEqLHS
lhs2
finish_without_swapping :: TcS (StopOrContinue (Either IrredCt EqCt))
finish_without_swapping
= CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 (Type
ps_xi2 Type -> MCoercion -> Type
`mkCastTyMCo` MCoercion
mco)
finish_with_swapping :: TcS (StopOrContinue (Either IrredCt EqCt))
finish_with_swapping
= do { let lhs1_redn :: Reduction
lhs1_redn = Role -> Type -> MCoercion -> Reduction
mkGReflRightMRedn Role
role Type
lhs1_ty MCoercion
sym_mco
lhs2_redn :: Reduction
lhs2_redn = Role -> Type -> MCoercion -> Reduction
mkGReflLeftMRedn Role
role Type
lhs2_ty MCoercion
mco
; CtEvidence
new_ev <-RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence RewriterSet
emptyRewriterSet CtEvidence
ev SwapFlag
swapped Reduction
lhs1_redn Reduction
lhs2_redn
; CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish CtEvidence
new_ev EqRel
eq_rel SwapFlag
IsSwapped CanEqLHS
lhs2 (Type
ps_xi1 Type -> MCoercion -> Type
`mkCastTyMCo` MCoercion
sym_mco) }
put_tyvar_on_lhs :: Bool
put_tyvar_on_lhs = CtEvidence -> Bool
isWanted CtEvidence
ev Bool -> Bool -> Bool
&& EqRel
eq_rel EqRel -> EqRel -> Bool
forall a. Eq a => a -> a -> Bool
== EqRel
NomEq
canEqCanLHSFinish, canEqCanLHSFinish_try_unification,
canEqCanLHSFinish_no_unification
:: CtEvidence
-> EqRel -> SwapFlag
-> CanEqLHS
-> TcType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish :: CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs Type
rhs
= do { String -> SDoc -> TcS ()
traceTcS String
"canEqCanLHSFinish" (SDoc -> TcS ()) -> SDoc -> TcS ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"ev:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> CtEvidence -> SDoc
forall a. Outputable a => a -> SDoc
ppr CtEvidence
ev
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"swapped:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SwapFlag -> SDoc
forall a. Outputable a => a -> SDoc
ppr SwapFlag
swapped
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"lhs:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> CanEqLHS -> SDoc
forall a. Outputable a => a -> SDoc
ppr CanEqLHS
lhs
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"rhs:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
rhs ]
; Bool -> TcS ()
forall (m :: * -> *). (HasCallStack, Applicative m) => Bool -> m ()
massert (CanEqLHS -> Type
canEqLHSKind CanEqLHS
lhs Type -> Type -> Bool
`eqType` HasDebugCallStack => Type -> Type
Type -> Type
typeKind Type
rhs)
; TcS Bool -> SDoc -> TcS ()
forall (m :: * -> *).
(HasCallStack, Monad m) =>
m Bool -> SDoc -> m ()
assertPprM TcS Bool
ty_eq_N_OK (SDoc -> TcS ()) -> SDoc -> TcS ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"CanEqCanLHSFinish: (TyEq:N) not satisfied"
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"rhs:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
rhs ]
; CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish_try_unification CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs Type
rhs }
where
ty_eq_N_OK :: TcS Bool
ty_eq_N_OK :: TcS Bool
ty_eq_N_OK
| EqRel
ReprEq <- EqRel
eq_rel
, Just (TyCon
tc, [Type]
tc_args) <- HasDebugCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
splitTyConApp_maybe Type
rhs
, Just DataCon
con <- TyCon -> Maybe DataCon
newTyConDataCon_maybe TyCon
tc
, [Type]
tc_args [Type] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthAtLeast` TyCon -> Int
tyConArity TyCon
tc
= do { GlobalRdrEnv
rdr_env <- TcS GlobalRdrEnv
getGlobalRdrEnvTcS
; let con_in_scope :: Bool
con_in_scope = Maybe GlobalRdrElt -> Bool
forall a. Maybe a -> Bool
isJust (Maybe GlobalRdrElt -> Bool) -> Maybe GlobalRdrElt -> Bool
forall a b. (a -> b) -> a -> b
$ GlobalRdrEnv -> Name -> Maybe GlobalRdrElt
forall info.
Outputable info =>
GlobalRdrEnvX info -> Name -> Maybe (GlobalRdrEltX info)
lookupGRE_Name GlobalRdrEnv
rdr_env (DataCon -> Name
dataConName DataCon
con)
; Bool -> TcS Bool
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> TcS Bool) -> Bool -> TcS Bool
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not Bool
con_in_scope }
| Bool
otherwise
= Bool -> TcS Bool
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
canEqCanLHSFinish_try_unification :: CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish_try_unification CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs Type
rhs
| CtEvidence -> Bool
isWanted CtEvidence
ev
, EqRel
NomEq <- EqRel
eq_rel
, TyVarLHS TyVar
tv <- CanEqLHS
lhs
= do { TcLevel
given_eq_lvl <- TcS TcLevel
getInnermostGivenEqLevel
; if Bool -> Bool
not (TcLevel -> TyVar -> Type -> Bool
touchabilityAndShapeTest TcLevel
given_eq_lvl TyVar
tv Type
rhs)
then if | Just CanEqLHS
can_rhs <- Type -> Maybe CanEqLHS
canTyFamEqLHS_maybe Type
rhs
-> CtEvidence
-> EqRel
-> SwapFlag
-> Type
-> CanEqLHS
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall unused.
CtEvidence
-> EqRel
-> SwapFlag
-> Type
-> CanEqLHS
-> TcS (StopOrContinue (Either unused EqCt))
swapAndFinish CtEvidence
ev EqRel
eq_rel SwapFlag
swapped (TyVar -> Type
mkTyVarTy TyVar
tv) CanEqLHS
can_rhs
| Bool
otherwise
-> CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish_no_unification CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs Type
rhs
else
do { PuResult () Reduction
check_result <- CtEvidence -> TyVar -> Type -> TcS (PuResult () Reduction)
checkTouchableTyVarEq CtEvidence
ev TyVar
tv Type
rhs
; case PuResult () Reduction
check_result of {
PuFail CheckTyEqResult
reason
| Just CanEqLHS
can_rhs <- Type -> Maybe CanEqLHS
canTyFamEqLHS_maybe Type
rhs
-> CtEvidence
-> EqRel
-> SwapFlag
-> Type
-> CanEqLHS
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall unused.
CtEvidence
-> EqRel
-> SwapFlag
-> Type
-> CanEqLHS
-> TcS (StopOrContinue (Either unused EqCt))
swapAndFinish CtEvidence
ev EqRel
eq_rel SwapFlag
swapped (TyVar -> Type
mkTyVarTy TyVar
tv) CanEqLHS
can_rhs
| CheckTyEqResult
reason CheckTyEqResult -> CheckTyEqResult -> Bool
`cterHasOnlyProblems` CheckTyEqResult
do_not_prevent_rewriting
-> CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish_no_unification CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs Type
rhs
| Bool
otherwise
-> CheckTyEqResult
-> CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall unused.
CheckTyEqResult
-> CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt unused))
tryIrredInstead CheckTyEqResult
reason CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs Type
rhs ;
PuOK Bag ()
_ Reduction
rhs_redn ->
do {
CtEvidence
new_ev <- if TcCoercion -> Bool
isReflCo (Reduction -> TcCoercion
reductionCoercion Reduction
rhs_redn)
then CtEvidence -> TcS CtEvidence
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return CtEvidence
ev
else RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence RewriterSet
emptyRewriterSet CtEvidence
ev SwapFlag
swapped
(Role -> Type -> Reduction
mkReflRedn Role
Nominal (TyVar -> Type
mkTyVarTy TyVar
tv)) Reduction
rhs_redn
; let tv_ty :: Type
tv_ty = TyVar -> Type
mkTyVarTy TyVar
tv
final_rhs :: Type
final_rhs = Reduction -> Type
reductionReducedType Reduction
rhs_redn
; String -> SDoc -> TcS ()
traceTcS String
"Sneaky unification:" (SDoc -> TcS ()) -> SDoc -> TcS ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Unifies:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> TyVar -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyVar
tv SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
":=" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
final_rhs,
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Coercion:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> Type -> SDoc
pprEq Type
tv_ty Type
final_rhs,
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Left Kind is:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr (HasDebugCallStack => Type -> Type
Type -> Type
typeKind Type
tv_ty),
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Right Kind is:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr (HasDebugCallStack => Type -> Type
Type -> Type
typeKind Type
final_rhs) ]
; TyVar -> Type -> TcS ()
unifyTyVar TyVar
tv Type
final_rhs
; CtEvidence -> Bool -> EvTerm -> TcS ()
setEvBindIfWanted CtEvidence
new_ev Bool
True (EvTerm -> TcS ()) -> EvTerm -> TcS ()
forall a b. (a -> b) -> a -> b
$
TcCoercion -> EvTerm
evCoercion (Type -> TcCoercion
mkNomReflCo Type
final_rhs)
; [TyVar] -> TcS ()
kickOutAfterUnification [TyVar
tv]
; StopOrContinue (Either IrredCt EqCt)
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (CtEvidence -> SDoc -> StopOrContinue (Either IrredCt EqCt)
forall a. CtEvidence -> SDoc -> StopOrContinue a
Stop CtEvidence
new_ev (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Solved by unification")) }}}}
| Bool
otherwise
= CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish_no_unification CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs Type
rhs
where
do_not_prevent_rewriting :: CheckTyEqResult
do_not_prevent_rewriting :: CheckTyEqResult
do_not_prevent_rewriting = CheckTyEqProblem -> CheckTyEqResult
cteProblem CheckTyEqProblem
cteSkolemEscape CheckTyEqResult -> CheckTyEqResult -> CheckTyEqResult
forall a. Semigroup a => a -> a -> a
S.<>
CheckTyEqProblem -> CheckTyEqResult
cteProblem CheckTyEqProblem
cteConcrete
canEqCanLHSFinish_no_unification :: CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish_no_unification CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs Type
rhs
= do {
; PuResult () Reduction
check_result <- CtEvidence
-> EqRel -> CanEqLHS -> Type -> TcS (PuResult () Reduction)
checkTypeEq CtEvidence
ev EqRel
eq_rel CanEqLHS
lhs Type
rhs
; let lhs_ty :: Type
lhs_ty = CanEqLHS -> Type
canEqLHSType CanEqLHS
lhs
; case PuResult () Reduction
check_result of
PuFail CheckTyEqResult
reason
-> CheckTyEqResult
-> CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall unused.
CheckTyEqResult
-> CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt unused))
tryIrredInstead CheckTyEqResult
reason CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs Type
rhs
PuOK Bag ()
_ Reduction
rhs_redn
-> do { CtEvidence
new_ev <- RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence RewriterSet
emptyRewriterSet CtEvidence
ev SwapFlag
swapped
(Role -> Type -> Reduction
mkReflRedn (EqRel -> Role
eqRelRole EqRel
eq_rel) Type
lhs_ty)
Reduction
rhs_redn
; Either IrredCt EqCt -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. a -> TcS (StopOrContinue a)
continueWith (Either IrredCt EqCt -> TcS (StopOrContinue (Either IrredCt EqCt)))
-> Either IrredCt EqCt
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall a b. (a -> b) -> a -> b
$ EqCt -> Either IrredCt EqCt
forall a b. b -> Either a b
Right (EqCt -> Either IrredCt EqCt) -> EqCt -> Either IrredCt EqCt
forall a b. (a -> b) -> a -> b
$
EqCt { eq_ev :: CtEvidence
eq_ev = CtEvidence
new_ev, eq_eq_rel :: EqRel
eq_eq_rel = EqRel
eq_rel
, eq_lhs :: CanEqLHS
eq_lhs = CanEqLHS
lhs
, eq_rhs :: Type
eq_rhs = Reduction -> Type
reductionReducedType Reduction
rhs_redn } } }
swapAndFinish :: CtEvidence -> EqRel -> SwapFlag
-> TcType -> CanEqLHS
-> TcS (StopOrContinue (Either unused EqCt))
swapAndFinish :: forall unused.
CtEvidence
-> EqRel
-> SwapFlag
-> Type
-> CanEqLHS
-> TcS (StopOrContinue (Either unused EqCt))
swapAndFinish CtEvidence
ev EqRel
eq_rel SwapFlag
swapped Type
lhs_ty CanEqLHS
can_rhs
= do { let role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
; CtEvidence
new_ev <- RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence RewriterSet
emptyRewriterSet CtEvidence
ev (SwapFlag -> SwapFlag
flipSwap SwapFlag
swapped)
(Role -> Type -> Reduction
mkReflRedn Role
role (CanEqLHS -> Type
canEqLHSType CanEqLHS
can_rhs))
(Role -> Type -> Reduction
mkReflRedn Role
role Type
lhs_ty)
; Either unused EqCt -> TcS (StopOrContinue (Either unused EqCt))
forall a. a -> TcS (StopOrContinue a)
continueWith (Either unused EqCt -> TcS (StopOrContinue (Either unused EqCt)))
-> Either unused EqCt -> TcS (StopOrContinue (Either unused EqCt))
forall a b. (a -> b) -> a -> b
$ EqCt -> Either unused EqCt
forall a b. b -> Either a b
Right (EqCt -> Either unused EqCt) -> EqCt -> Either unused EqCt
forall a b. (a -> b) -> a -> b
$
EqCt { eq_ev :: CtEvidence
eq_ev = CtEvidence
new_ev, eq_eq_rel :: EqRel
eq_eq_rel = EqRel
eq_rel
, eq_lhs :: CanEqLHS
eq_lhs = CanEqLHS
can_rhs, eq_rhs :: Type
eq_rhs = Type
lhs_ty } }
tryIrredInstead :: CheckTyEqResult -> CtEvidence
-> EqRel -> SwapFlag -> CanEqLHS -> TcType
-> TcS (StopOrContinue (Either IrredCt unused))
tryIrredInstead :: forall unused.
CheckTyEqResult
-> CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> Type
-> TcS (StopOrContinue (Either IrredCt unused))
tryIrredInstead CheckTyEqResult
reason CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs Type
rhs
= do { String -> SDoc -> TcS ()
traceTcS String
"cantMakeCanonical" (CheckTyEqResult -> SDoc
forall a. Outputable a => a -> SDoc
ppr CheckTyEqResult
reason SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ CanEqLHS -> SDoc
forall a. Outputable a => a -> SDoc
ppr CanEqLHS
lhs SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
rhs)
; let role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
; CtEvidence
new_ev <- RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence RewriterSet
emptyRewriterSet CtEvidence
ev SwapFlag
swapped
(Role -> Type -> Reduction
mkReflRedn Role
role (CanEqLHS -> Type
canEqLHSType CanEqLHS
lhs))
(Role -> Type -> Reduction
mkReflRedn Role
role Type
rhs)
; CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt unused))
forall a.
CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt a))
finishCanWithIrred (CheckTyEqResult -> CtIrredReason
NonCanonicalReason CheckTyEqResult
reason) CtEvidence
new_ev }
finishCanWithIrred :: CtIrredReason -> CtEvidence
-> TcS (StopOrContinue (Either IrredCt a))
finishCanWithIrred :: forall a.
CtIrredReason
-> CtEvidence -> TcS (StopOrContinue (Either IrredCt a))
finishCanWithIrred CtIrredReason
reason CtEvidence
ev
= do {
Bool -> TcS () -> TcS ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CtIrredReason -> Bool
isInsolubleReason CtIrredReason
reason) TcS ()
tryEarlyAbortTcS
; Either IrredCt a -> TcS (StopOrContinue (Either IrredCt a))
forall a. a -> TcS (StopOrContinue a)
continueWith (Either IrredCt a -> TcS (StopOrContinue (Either IrredCt a)))
-> Either IrredCt a -> TcS (StopOrContinue (Either IrredCt a))
forall a b. (a -> b) -> a -> b
$ IrredCt -> Either IrredCt a
forall a b. a -> Either a b
Left (IrredCt -> Either IrredCt a) -> IrredCt -> Either IrredCt a
forall a b. (a -> b) -> a -> b
$ IrredCt { ir_ev :: CtEvidence
ir_ev = CtEvidence
ev, ir_reason :: CtIrredReason
ir_reason = CtIrredReason
reason } }
canEqReflexive :: CtEvidence
-> EqRel
-> TcType
-> TcS (StopOrContinue a)
canEqReflexive :: forall a. CtEvidence -> EqRel -> Type -> TcS (StopOrContinue a)
canEqReflexive CtEvidence
ev EqRel
eq_rel Type
ty
= do { CtEvidence -> Bool -> EvTerm -> TcS ()
setEvBindIfWanted CtEvidence
ev Bool
True (EvTerm -> TcS ()) -> EvTerm -> TcS ()
forall a b. (a -> b) -> a -> b
$
TcCoercion -> EvTerm
evCoercion (Role -> Type -> TcCoercion
mkReflCo (EqRel -> Role
eqRelRole EqRel
eq_rel) Type
ty)
; CtEvidence -> String -> TcS (StopOrContinue a)
forall a. CtEvidence -> String -> TcS (StopOrContinue a)
stopWith CtEvidence
ev String
"Solved by reflexivity" }
rewriteEqEvidence :: RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence :: RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence RewriterSet
new_rewriters CtEvidence
old_ev SwapFlag
swapped (Reduction TcCoercion
lhs_co Type
nlhs) (Reduction TcCoercion
rhs_co Type
nrhs)
| SwapFlag
NotSwapped <- SwapFlag
swapped
, TcCoercion -> Bool
isReflCo TcCoercion
lhs_co
, TcCoercion -> Bool
isReflCo TcCoercion
rhs_co
= CtEvidence -> TcS CtEvidence
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (HasDebugCallStack => CtEvidence -> Type -> CtEvidence
CtEvidence -> Type -> CtEvidence
setCtEvPredType CtEvidence
old_ev Type
new_pred)
| CtGiven { ctev_evar :: CtEvidence -> TyVar
ctev_evar = TyVar
old_evar } <- CtEvidence
old_ev
= do { let new_tm :: EvTerm
new_tm = TcCoercion -> EvTerm
evCoercion ( TcCoercion -> TcCoercion
mkSymCo TcCoercion
lhs_co
TcCoercion -> TcCoercion -> TcCoercion
`mkTransCo` SwapFlag -> TcCoercion -> TcCoercion
maybeSymCo SwapFlag
swapped (TyVar -> TcCoercion
mkCoVarCo TyVar
old_evar)
TcCoercion -> TcCoercion -> TcCoercion
`mkTransCo` TcCoercion
rhs_co)
; CtLoc -> (Type, EvTerm) -> TcS CtEvidence
newGivenEvVar CtLoc
loc (Type
new_pred, EvTerm
new_tm) }
| CtWanted { ctev_dest :: CtEvidence -> TcEvDest
ctev_dest = TcEvDest
dest
, ctev_rewriters :: CtEvidence -> RewriterSet
ctev_rewriters = RewriterSet
rewriters } <- CtEvidence
old_ev
, let rewriters' :: RewriterSet
rewriters' = RewriterSet
rewriters RewriterSet -> RewriterSet -> RewriterSet
forall a. Semigroup a => a -> a -> a
S.<> RewriterSet
new_rewriters
= do { (CtEvidence
new_ev, TcCoercion
hole_co) <- CtLoc
-> RewriterSet
-> Role
-> Type
-> Type
-> TcS (CtEvidence, TcCoercion)
newWantedEq CtLoc
loc RewriterSet
rewriters' (CtEvidence -> Role
ctEvRole CtEvidence
old_ev) Type
nlhs Type
nrhs
; let co :: TcCoercion
co = SwapFlag -> TcCoercion -> TcCoercion
maybeSymCo SwapFlag
swapped (TcCoercion -> TcCoercion) -> TcCoercion -> TcCoercion
forall a b. (a -> b) -> a -> b
$
TcCoercion
lhs_co TcCoercion -> TcCoercion -> TcCoercion
`mkTransCo` TcCoercion
hole_co TcCoercion -> TcCoercion -> TcCoercion
`mkTransCo` TcCoercion -> TcCoercion
mkSymCo TcCoercion
rhs_co
; HasDebugCallStack => TcEvDest -> TcCoercion -> TcS ()
TcEvDest -> TcCoercion -> TcS ()
setWantedEq TcEvDest
dest TcCoercion
co
; String -> SDoc -> TcS ()
traceTcS String
"rewriteEqEvidence" ([SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ CtEvidence -> SDoc
forall a. Outputable a => a -> SDoc
ppr CtEvidence
old_ev
, Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
nlhs
, Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
nrhs
, TcCoercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr TcCoercion
co
, RewriterSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr RewriterSet
new_rewriters ])
; CtEvidence -> TcS CtEvidence
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return CtEvidence
new_ev }
#if __GLASGOW_HASKELL__ <= 810
| otherwise
= panic "rewriteEvidence"
#endif
where
new_pred :: Type
new_pred = CtEvidence -> Type -> Type -> Type
mkTcEqPredLikeEv CtEvidence
old_ev Type
nlhs Type
nrhs
loc :: CtLoc
loc = CtEvidence -> CtLoc
ctEvLoc CtEvidence
old_ev
tryInertEqs :: EqCt -> SolverStage ()
tryInertEqs :: EqCt -> SolverStage ()
tryInertEqs work_item :: EqCt
work_item@(EqCt { eq_ev :: EqCt -> CtEvidence
eq_ev = CtEvidence
ev, eq_eq_rel :: EqCt -> EqRel
eq_eq_rel = EqRel
eq_rel })
= TcS (StopOrContinue ()) -> SolverStage ()
forall a. TcS (StopOrContinue a) -> SolverStage a
Stage (TcS (StopOrContinue ()) -> SolverStage ())
-> TcS (StopOrContinue ()) -> SolverStage ()
forall a b. (a -> b) -> a -> b
$
do { InertCans
inerts <- TcS InertCans
getInertCans
; if | Just (CtEvidence
ev_i, SwapFlag
swapped) <- InertCans -> EqCt -> Maybe (CtEvidence, SwapFlag)
inertsCanDischarge InertCans
inerts EqCt
work_item
-> do { CtEvidence -> Bool -> EvTerm -> TcS ()
setEvBindIfWanted CtEvidence
ev Bool
True (EvTerm -> TcS ()) -> EvTerm -> TcS ()
forall a b. (a -> b) -> a -> b
$
TcCoercion -> EvTerm
evCoercion (SwapFlag -> TcCoercion -> TcCoercion
maybeSymCo SwapFlag
swapped (TcCoercion -> TcCoercion) -> TcCoercion -> TcCoercion
forall a b. (a -> b) -> a -> b
$
Role -> Role -> TcCoercion -> TcCoercion
downgradeRole (EqRel -> Role
eqRelRole EqRel
eq_rel)
(CtEvidence -> Role
ctEvRole CtEvidence
ev_i)
(HasDebugCallStack => CtEvidence -> TcCoercion
CtEvidence -> TcCoercion
ctEvCoercion CtEvidence
ev_i))
; CtEvidence -> String -> TcS (StopOrContinue ())
forall a. CtEvidence -> String -> TcS (StopOrContinue a)
stopWith CtEvidence
ev String
"Solved from inert" }
| Bool
otherwise
-> () -> TcS (StopOrContinue ())
forall a. a -> TcS (StopOrContinue a)
continueWith () }
inertsCanDischarge :: InertCans -> EqCt
-> Maybe ( CtEvidence
, SwapFlag )
inertsCanDischarge :: InertCans -> EqCt -> Maybe (CtEvidence, SwapFlag)
inertsCanDischarge InertCans
inerts (EqCt { eq_lhs :: EqCt -> CanEqLHS
eq_lhs = CanEqLHS
lhs_w, eq_rhs :: EqCt -> Type
eq_rhs = Type
rhs_w
, eq_ev :: EqCt -> CtEvidence
eq_ev = CtEvidence
ev_w, eq_eq_rel :: EqCt -> EqRel
eq_eq_rel = EqRel
eq_rel })
| (CtEvidence
ev_i : [CtEvidence]
_) <- [ CtEvidence
ev_i | EqCt { eq_ev :: EqCt -> CtEvidence
eq_ev = CtEvidence
ev_i, eq_rhs :: EqCt -> Type
eq_rhs = Type
rhs_i
, eq_eq_rel :: EqCt -> EqRel
eq_eq_rel = EqRel
eq_rel }
<- InertCans -> CanEqLHS -> [EqCt]
findEq InertCans
inerts CanEqLHS
lhs_w
, Type
rhs_i HasDebugCallStack => Type -> Type -> Bool
Type -> Type -> Bool
`tcEqType` Type
rhs_w
, CtEvidence -> EqRel -> Bool
inert_beats_wanted CtEvidence
ev_i EqRel
eq_rel ]
=
(CtEvidence, SwapFlag) -> Maybe (CtEvidence, SwapFlag)
forall a. a -> Maybe a
Just (CtEvidence
ev_i, SwapFlag
NotSwapped)
| Just CanEqLHS
rhs_lhs <- Type -> Maybe CanEqLHS
canEqLHS_maybe Type
rhs_w
, (CtEvidence
ev_i : [CtEvidence]
_) <- [ CtEvidence
ev_i | EqCt { eq_ev :: EqCt -> CtEvidence
eq_ev = CtEvidence
ev_i, eq_rhs :: EqCt -> Type
eq_rhs = Type
rhs_i
, eq_eq_rel :: EqCt -> EqRel
eq_eq_rel = EqRel
eq_rel }
<- InertCans -> CanEqLHS -> [EqCt]
findEq InertCans
inerts CanEqLHS
rhs_lhs
, Type
rhs_i HasDebugCallStack => Type -> Type -> Bool
Type -> Type -> Bool
`tcEqType` CanEqLHS -> Type
canEqLHSType CanEqLHS
lhs_w
, CtEvidence -> EqRel -> Bool
inert_beats_wanted CtEvidence
ev_i EqRel
eq_rel ]
=
(CtEvidence, SwapFlag) -> Maybe (CtEvidence, SwapFlag)
forall a. a -> Maybe a
Just (CtEvidence
ev_i, SwapFlag
IsSwapped)
where
loc_w :: CtLoc
loc_w = CtEvidence -> CtLoc
ctEvLoc CtEvidence
ev_w
flav_w :: CtFlavour
flav_w = CtEvidence -> CtFlavour
ctEvFlavour CtEvidence
ev_w
fr_w :: CtFlavourRole
fr_w = (CtFlavour
flav_w, EqRel
eq_rel)
inert_beats_wanted :: CtEvidence -> EqRel -> Bool
inert_beats_wanted CtEvidence
ev_i EqRel
eq_rel
=
CtFlavourRole
fr_i CtFlavourRole -> CtFlavourRole -> Bool
`eqCanRewriteFR` CtFlavourRole
fr_w
Bool -> Bool -> Bool
&& Bool -> Bool
not ((CtLoc
loc_w CtLoc -> CtLoc -> Bool
`strictly_more_visible` CtEvidence -> CtLoc
ctEvLoc CtEvidence
ev_i)
Bool -> Bool -> Bool
&& (CtFlavourRole
fr_w CtFlavourRole -> CtFlavourRole -> Bool
`eqCanRewriteFR` CtFlavourRole
fr_i))
where
fr_i :: CtFlavourRole
fr_i = (CtEvidence -> CtFlavour
ctEvFlavour CtEvidence
ev_i, EqRel
eq_rel)
strictly_more_visible :: CtLoc -> CtLoc -> Bool
strictly_more_visible CtLoc
loc1 CtLoc
loc2
= Bool -> Bool
not (CtOrigin -> Bool
isVisibleOrigin (CtLoc -> CtOrigin
ctLocOrigin CtLoc
loc2)) Bool -> Bool -> Bool
&&
CtOrigin -> Bool
isVisibleOrigin (CtLoc -> CtOrigin
ctLocOrigin CtLoc
loc1)
inertsCanDischarge InertCans
_ EqCt
_ = Maybe (CtEvidence, SwapFlag)
forall a. Maybe a
Nothing
tryQCsIrredEqCt :: IrredCt -> SolverStage ()
tryQCsIrredEqCt :: IrredCt -> SolverStage ()
tryQCsIrredEqCt irred :: IrredCt
irred@(IrredCt { ir_ev :: IrredCt -> CtEvidence
ir_ev = CtEvidence
ev })
| EqPred EqRel
eq_rel Type
t1 Type
t2 <- Type -> Pred
classifyPredType (CtEvidence -> Type
ctEvPred CtEvidence
ev)
= Ct -> EqRel -> Type -> Type -> SolverStage ()
lookup_eq_in_qcis (IrredCt -> Ct
CIrredCan IrredCt
irred) EqRel
eq_rel Type
t1 Type
t2
| Bool
otherwise
= String -> SDoc -> SolverStage ()
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"solveIrredEquality" (CtEvidence -> SDoc
forall a. Outputable a => a -> SDoc
ppr CtEvidence
ev)
tryQCsEqCt :: EqCt -> SolverStage ()
tryQCsEqCt :: EqCt -> SolverStage ()
tryQCsEqCt work_item :: EqCt
work_item@(EqCt { eq_lhs :: EqCt -> CanEqLHS
eq_lhs = CanEqLHS
lhs, eq_rhs :: EqCt -> Type
eq_rhs = Type
rhs, eq_eq_rel :: EqCt -> EqRel
eq_eq_rel = EqRel
eq_rel })
= Ct -> EqRel -> Type -> Type -> SolverStage ()
lookup_eq_in_qcis (EqCt -> Ct
CEqCan EqCt
work_item) EqRel
eq_rel (CanEqLHS -> Type
canEqLHSType CanEqLHS
lhs) Type
rhs
lookup_eq_in_qcis :: Ct -> EqRel -> TcType -> TcType -> SolverStage ()
lookup_eq_in_qcis :: Ct -> EqRel -> Type -> Type -> SolverStage ()
lookup_eq_in_qcis Ct
work_ct EqRel
eq_rel Type
lhs Type
rhs
= TcS (StopOrContinue ()) -> SolverStage ()
forall a. TcS (StopOrContinue a) -> SolverStage a
Stage (TcS (StopOrContinue ()) -> SolverStage ())
-> TcS (StopOrContinue ()) -> SolverStage ()
forall a b. (a -> b) -> a -> b
$
do { EvBindsVar
ev_binds_var <- TcS EvBindsVar
getTcEvBindsVar
; InertCans
ics <- TcS InertCans
getInertCans
; if CtEvidence -> Bool
isWanted CtEvidence
ev
Bool -> Bool -> Bool
&& Bool -> Bool
not ([QCInst] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (InertCans -> [QCInst]
inert_insts InertCans
ics))
Bool -> Bool -> Bool
&& Bool -> Bool
not (EvBindsVar -> Bool
isCoEvBindsVar EvBindsVar
ev_binds_var)
then TcS (StopOrContinue ())
try_for_qci
else () -> TcS (StopOrContinue ())
forall a. a -> TcS (StopOrContinue a)
continueWith () }
where
ev :: CtEvidence
ev = Ct -> CtEvidence
ctEvidence Ct
work_ct
loc :: CtLoc
loc = CtEvidence -> CtLoc
ctEvLoc CtEvidence
ev
role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
try_for_qci :: TcS (StopOrContinue ())
try_for_qci
| Just (Class
cls, [Type]
tys) <- EqRel -> Type -> Type -> Maybe (Class, [Type])
boxEqPred EqRel
eq_rel Type
lhs Type
rhs
= do { ClsInstResult
res <- Type -> CtLoc -> TcS ClsInstResult
matchLocalInst (Class -> [Type] -> Type
mkClassPred Class
cls [Type]
tys) CtLoc
loc
; String -> SDoc -> TcS ()
traceTcS String
"lookup_irred_in_qcis:1" (Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Class -> [Type] -> Type
mkClassPred Class
cls [Type]
tys))
; case ClsInstResult
res of
OneInst { cir_mk_ev :: ClsInstResult -> [EvExpr] -> EvTerm
cir_mk_ev = [EvExpr] -> EvTerm
mk_ev }
-> CtEvidence -> ClsInstResult -> TcS (StopOrContinue ())
forall a. CtEvidence -> ClsInstResult -> TcS (StopOrContinue a)
chooseInstance CtEvidence
ev (ClsInstResult
res { cir_mk_ev = mk_eq_ev cls tys mk_ev })
ClsInstResult
_ -> TcS (StopOrContinue ())
try_swapping }
| Bool
otherwise
= () -> TcS (StopOrContinue ())
forall a. a -> TcS (StopOrContinue a)
continueWith ()
try_swapping :: TcS (StopOrContinue ())
try_swapping
| Just (Class
cls, [Type]
tys) <- EqRel -> Type -> Type -> Maybe (Class, [Type])
boxEqPred EqRel
eq_rel Type
rhs Type
lhs
= do { ClsInstResult
res <- Type -> CtLoc -> TcS ClsInstResult
matchLocalInst (Class -> [Type] -> Type
mkClassPred Class
cls [Type]
tys) CtLoc
loc
; String -> SDoc -> TcS ()
traceTcS String
"lookup_irred_in_qcis:2" (Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Class -> [Type] -> Type
mkClassPred Class
cls [Type]
tys))
; case ClsInstResult
res of
OneInst { cir_mk_ev :: ClsInstResult -> [EvExpr] -> EvTerm
cir_mk_ev = [EvExpr] -> EvTerm
mk_ev }
-> do { CtEvidence
ev' <- RewriterSet
-> CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> TcS CtEvidence
rewriteEqEvidence RewriterSet
emptyRewriterSet CtEvidence
ev SwapFlag
IsSwapped
(Role -> Type -> Reduction
mkReflRedn Role
role Type
rhs) (Role -> Type -> Reduction
mkReflRedn Role
role Type
lhs)
; CtEvidence -> ClsInstResult -> TcS (StopOrContinue ())
forall a. CtEvidence -> ClsInstResult -> TcS (StopOrContinue a)
chooseInstance CtEvidence
ev' (ClsInstResult
res { cir_mk_ev = mk_eq_ev cls tys mk_ev }) }
ClsInstResult
_ -> do { String -> SDoc -> TcS ()
traceTcS String
"lookup_irred_in_qcis:3" (Ct -> SDoc
forall a. Outputable a => a -> SDoc
ppr Ct
work_ct)
; () -> TcS (StopOrContinue ())
forall a. a -> TcS (StopOrContinue a)
continueWith () }}
| Bool
otherwise
= () -> TcS (StopOrContinue ())
forall a. a -> TcS (StopOrContinue a)
continueWith ()
mk_eq_ev :: Class -> [Type] -> ([EvExpr] -> EvTerm) -> [EvExpr] -> EvTerm
mk_eq_ev Class
cls [Type]
tys [EvExpr] -> EvTerm
mk_ev [EvExpr]
evs
| TyVar
sc_id : [TyVar]
rest <- Class -> [TyVar]
classSCSelIds Class
cls
= Bool -> EvTerm -> EvTerm
forall a. HasCallStack => Bool -> a -> a
assert ([TyVar] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TyVar]
rest) (EvTerm -> EvTerm) -> EvTerm -> EvTerm
forall a b. (a -> b) -> a -> b
$ case ([EvExpr] -> EvTerm
mk_ev [EvExpr]
evs) of
EvExpr EvExpr
e -> EvExpr -> EvTerm
EvExpr (TyVar -> EvExpr
forall b. TyVar -> Expr b
Var TyVar
sc_id EvExpr -> [Type] -> EvExpr
forall b. Expr b -> [Type] -> Expr b
`mkTyApps` [Type]
tys EvExpr -> EvExpr -> EvExpr
forall b. Expr b -> Expr b -> Expr b
`App` EvExpr
e)
EvTerm
ev -> String -> SDoc -> EvTerm
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"mk_eq_ev" (EvTerm -> SDoc
forall a. Outputable a => a -> SDoc
ppr EvTerm
ev)
| Bool
otherwise = String -> SDoc -> EvTerm
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"finishEqCt" (Ct -> SDoc
forall a. Outputable a => a -> SDoc
ppr Ct
work_ct)
tryFamFamInjectivity :: CtEvidence -> EqRel
-> TyCon -> [TcType] -> TyCon -> [TcType] -> MCoercion
-> TcS Bool
tryFamFamInjectivity :: CtEvidence
-> EqRel
-> TyCon
-> [Type]
-> TyCon
-> [Type]
-> MCoercion
-> TcS Bool
tryFamFamInjectivity CtEvidence
ev EqRel
eq_rel TyCon
fun_tc1 [Type]
fun_args1 TyCon
fun_tc2 [Type]
fun_args2 MCoercion
mco
| EqRel
ReprEq <- EqRel
eq_rel
= Bool -> TcS Bool
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
| TyCon
fun_tc1 TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
/= TyCon
fun_tc2
= Bool -> TcS Bool
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
| CtEvidence -> Bool
isGiven CtEvidence
ev
= Bool -> TcS Bool
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
| Injective [Bool]
inj <- TyCon -> Injectivity
tyConInjectivityInfo TyCon
fun_tc1
= CtEvidence -> Role -> (UnifyEnv -> TcM ()) -> TcS Bool
unifyFunDeps CtEvidence
ev Role
Nominal ((UnifyEnv -> TcM ()) -> TcS Bool)
-> (UnifyEnv -> TcM ()) -> TcS Bool
forall a b. (a -> b) -> a -> b
$ \UnifyEnv
uenv ->
UnifyEnv -> [TypeEqn] -> TcM ()
uPairsTcM UnifyEnv
uenv [ Type -> Type -> TypeEqn
forall a. a -> a -> Pair a
Pair Type
ty1 Type
ty2
| (Type
ty1,Type
ty2,Bool
True) <- [Type] -> [Type] -> [Bool] -> [(Type, Type, Bool)]
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 [Type]
fun_args1 [Type]
fun_args2 [Bool]
inj ]
| Just BuiltInSynFamily
ops <- TyCon -> Maybe BuiltInSynFamily
isBuiltInSynFamTyCon_maybe TyCon
fun_tc1
= let tc_kind :: Type
tc_kind = TyCon -> Type
tyConKind TyCon
fun_tc1
ki1 :: Type
ki1 = HasDebugCallStack => Type -> [Type] -> Type
Type -> [Type] -> Type
piResultTys Type
tc_kind [Type]
fun_args1
ki2 :: Type
ki2 | MCoercion
MRefl <- MCoercion
mco
= Type
ki1
| Bool
otherwise
= HasDebugCallStack => Type -> [Type] -> Type
Type -> [Type] -> Type
piResultTys Type
tc_kind [Type]
fun_args2
fake_rhs1 :: Type
fake_rhs1 = Type -> Type
anyTypeOfKind Type
ki1
fake_rhs2 :: Type
fake_rhs2 = Type -> Type
anyTypeOfKind Type
ki2
eqs :: [TypeEqn]
eqs :: [TypeEqn]
eqs = BuiltInSynFamily -> [Type] -> Type -> [Type] -> Type -> [TypeEqn]
sfInteractInert BuiltInSynFamily
ops [Type]
fun_args1 Type
fake_rhs1 [Type]
fun_args2 Type
fake_rhs2
in
CtEvidence -> Role -> (UnifyEnv -> TcM ()) -> TcS Bool
unifyFunDeps CtEvidence
ev Role
Nominal ((UnifyEnv -> TcM ()) -> TcS Bool)
-> (UnifyEnv -> TcM ()) -> TcS Bool
forall a b. (a -> b) -> a -> b
$ \UnifyEnv
uenv ->
UnifyEnv -> [TypeEqn] -> TcM ()
uPairsTcM UnifyEnv
uenv [TypeEqn]
eqs
| Bool
otherwise
= Bool -> TcS Bool
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
tryFunDeps :: EqCt -> SolverStage ()
tryFunDeps :: EqCt -> SolverStage ()
tryFunDeps work_item :: EqCt
work_item@(EqCt { eq_lhs :: EqCt -> CanEqLHS
eq_lhs = CanEqLHS
lhs, eq_ev :: EqCt -> CtEvidence
eq_ev = CtEvidence
ev })
= TcS (StopOrContinue ()) -> SolverStage ()
forall a. TcS (StopOrContinue a) -> SolverStage a
Stage (TcS (StopOrContinue ()) -> SolverStage ())
-> TcS (StopOrContinue ()) -> SolverStage ()
forall a b. (a -> b) -> a -> b
$
case CanEqLHS
lhs of
TyFamLHS TyCon
tc [Type]
args -> do { InertCans
inerts <- TcS InertCans
getInertCans
; Bool
imp1 <- InertCans -> TyCon -> [Type] -> EqCt -> TcS Bool
improveLocalFunEqs InertCans
inerts TyCon
tc [Type]
args EqCt
work_item
; Bool
imp2 <- TyCon -> [Type] -> EqCt -> TcS Bool
improveTopFunEqs TyCon
tc [Type]
args EqCt
work_item
; if (Bool
imp1 Bool -> Bool -> Bool
|| Bool
imp2)
then Ct -> TcS (StopOrContinue ())
forall a. Ct -> TcS (StopOrContinue a)
startAgainWith (CtEvidence -> Ct
mkNonCanonical CtEvidence
ev)
else () -> TcS (StopOrContinue ())
forall a. a -> TcS (StopOrContinue a)
continueWith () }
TyVarLHS {} -> () -> TcS (StopOrContinue ())
forall a. a -> TcS (StopOrContinue a)
continueWith ()
improveTopFunEqs :: TyCon -> [TcType] -> EqCt -> TcS Bool
improveTopFunEqs :: TyCon -> [Type] -> EqCt -> TcS Bool
improveTopFunEqs TyCon
fam_tc [Type]
args (EqCt { eq_ev :: EqCt -> CtEvidence
eq_ev = CtEvidence
ev, eq_rhs :: EqCt -> Type
eq_rhs = Type
rhs })
| CtEvidence -> Bool
isGiven CtEvidence
ev
= Bool -> TcS Bool
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
| Bool
otherwise
= do { (FamInstEnv, FamInstEnv)
fam_envs <- TcS (FamInstEnv, FamInstEnv)
getFamInstEnvs
; [TypeEqn]
eqns <- (FamInstEnv, FamInstEnv)
-> TyCon -> [Type] -> Type -> TcS [TypeEqn]
improve_top_fun_eqs (FamInstEnv, FamInstEnv)
fam_envs TyCon
fam_tc [Type]
args Type
rhs
; String -> SDoc -> TcS ()
traceTcS String
"improveTopFunEqs" ([SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
fam_tc SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> [Type] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Type]
args SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
rhs
, [TypeEqn] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [TypeEqn]
eqns ])
; CtEvidence -> Role -> (UnifyEnv -> TcM ()) -> TcS Bool
unifyFunDeps CtEvidence
ev Role
Nominal ((UnifyEnv -> TcM ()) -> TcS Bool)
-> (UnifyEnv -> TcM ()) -> TcS Bool
forall a b. (a -> b) -> a -> b
$ \UnifyEnv
uenv ->
UnifyEnv -> [TypeEqn] -> TcM ()
uPairsTcM (UnifyEnv -> UnifyEnv
bump_depth UnifyEnv
uenv) ([TypeEqn] -> [TypeEqn]
forall a. [a] -> [a]
reverse [TypeEqn]
eqns) }
where
bump_depth :: UnifyEnv -> UnifyEnv
bump_depth UnifyEnv
env = UnifyEnv
env { u_loc = bumpCtLocDepth (u_loc env) }
improve_top_fun_eqs :: FamInstEnvs
-> TyCon -> [TcType] -> TcType
-> TcS [TypeEqn]
improve_top_fun_eqs :: (FamInstEnv, FamInstEnv)
-> TyCon -> [Type] -> Type -> TcS [TypeEqn]
improve_top_fun_eqs (FamInstEnv, FamInstEnv)
fam_envs TyCon
fam_tc [Type]
args Type
rhs_ty
| Just BuiltInSynFamily
ops <- TyCon -> Maybe BuiltInSynFamily
isBuiltInSynFamTyCon_maybe TyCon
fam_tc
= [TypeEqn] -> TcS [TypeEqn]
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (BuiltInSynFamily -> [Type] -> Type -> [TypeEqn]
sfInteractTop BuiltInSynFamily
ops [Type]
args Type
rhs_ty)
| TyCon -> Bool
isOpenTypeFamilyTyCon TyCon
fam_tc
, Injective [Bool]
injective_args <- TyCon -> Injectivity
tyConInjectivityInfo TyCon
fam_tc
, let fam_insts :: [FamInst]
fam_insts = (FamInstEnv, FamInstEnv) -> TyCon -> [FamInst]
lookupFamInstEnvByTyCon (FamInstEnv, FamInstEnv)
fam_envs TyCon
fam_tc
=
do { let improvs :: [([Type], Subst, [TyVar], Maybe CoAxBranch)]
improvs = [FamInst]
-> (FamInst -> [TyVar])
-> (FamInst -> [Type])
-> (FamInst -> Type)
-> (FamInst -> Maybe CoAxBranch)
-> [([Type], Subst, [TyVar], Maybe CoAxBranch)]
forall a.
[a]
-> (a -> [TyVar])
-> (a -> [Type])
-> (a -> Type)
-> (a -> Maybe CoAxBranch)
-> [([Type], Subst, [TyVar], Maybe CoAxBranch)]
buildImprovementData [FamInst]
fam_insts
FamInst -> [TyVar]
fi_tvs FamInst -> [Type]
fi_tys FamInst -> Type
fi_rhs (Maybe CoAxBranch -> FamInst -> Maybe CoAxBranch
forall a b. a -> b -> a
const Maybe CoAxBranch
forall a. Maybe a
Nothing)
; String -> SDoc -> TcS ()
traceTcS String
"improve_top_fun_eqs2" ([([Type], Subst, [TyVar], Maybe CoAxBranch)] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [([Type], Subst, [TyVar], Maybe CoAxBranch)]
improvs)
; (([Type], Subst, [TyVar], Maybe CoAxBranch) -> TcS [TypeEqn])
-> [([Type], Subst, [TyVar], Maybe CoAxBranch)] -> TcS [TypeEqn]
forall (m :: * -> *) (f :: * -> *) a b.
(Monad m, Traversable f) =>
(a -> m [b]) -> f a -> m [b]
concatMapM ([Bool]
-> ([Type], Subst, [TyVar], Maybe CoAxBranch) -> TcS [TypeEqn]
injImproveEqns [Bool]
injective_args) ([([Type], Subst, [TyVar], Maybe CoAxBranch)] -> TcS [TypeEqn])
-> [([Type], Subst, [TyVar], Maybe CoAxBranch)] -> TcS [TypeEqn]
forall a b. (a -> b) -> a -> b
$
Int
-> [([Type], Subst, [TyVar], Maybe CoAxBranch)]
-> [([Type], Subst, [TyVar], Maybe CoAxBranch)]
forall a. Int -> [a] -> [a]
take Int
1 [([Type], Subst, [TyVar], Maybe CoAxBranch)]
improvs }
| Just CoAxiom Branched
ax <- TyCon -> Maybe (CoAxiom Branched)
isClosedSynFamilyTyConWithAxiom_maybe TyCon
fam_tc
, Injective [Bool]
injective_args <- TyCon -> Injectivity
tyConInjectivityInfo TyCon
fam_tc
= (([Type], Subst, [TyVar], Maybe CoAxBranch) -> TcS [TypeEqn])
-> [([Type], Subst, [TyVar], Maybe CoAxBranch)] -> TcS [TypeEqn]
forall (m :: * -> *) (f :: * -> *) a b.
(Monad m, Traversable f) =>
(a -> m [b]) -> f a -> m [b]
concatMapM ([Bool]
-> ([Type], Subst, [TyVar], Maybe CoAxBranch) -> TcS [TypeEqn]
injImproveEqns [Bool]
injective_args) ([([Type], Subst, [TyVar], Maybe CoAxBranch)] -> TcS [TypeEqn])
-> [([Type], Subst, [TyVar], Maybe CoAxBranch)] -> TcS [TypeEqn]
forall a b. (a -> b) -> a -> b
$
[CoAxBranch]
-> (CoAxBranch -> [TyVar])
-> (CoAxBranch -> [Type])
-> (CoAxBranch -> Type)
-> (CoAxBranch -> Maybe CoAxBranch)
-> [([Type], Subst, [TyVar], Maybe CoAxBranch)]
forall a.
[a]
-> (a -> [TyVar])
-> (a -> [Type])
-> (a -> Type)
-> (a -> Maybe CoAxBranch)
-> [([Type], Subst, [TyVar], Maybe CoAxBranch)]
buildImprovementData (Branches Branched -> [CoAxBranch]
forall (br :: BranchFlag). Branches br -> [CoAxBranch]
fromBranches (CoAxiom Branched -> Branches Branched
forall (br :: BranchFlag). CoAxiom br -> Branches br
co_ax_branches CoAxiom Branched
ax))
CoAxBranch -> [TyVar]
cab_tvs CoAxBranch -> [Type]
cab_lhs CoAxBranch -> Type
cab_rhs CoAxBranch -> Maybe CoAxBranch
forall a. a -> Maybe a
Just
| Bool
otherwise
= [TypeEqn] -> TcS [TypeEqn]
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return []
where
in_scope :: InScopeSet
in_scope = TyCoVarSet -> InScopeSet
mkInScopeSet (Type -> TyCoVarSet
tyCoVarsOfType Type
rhs_ty)
buildImprovementData
:: [a]
-> (a -> [TyVar])
-> (a -> [Type])
-> (a -> Type)
-> (a -> Maybe CoAxBranch)
-> [( [Type], Subst, [TyVar], Maybe CoAxBranch )]
buildImprovementData :: forall a.
[a]
-> (a -> [TyVar])
-> (a -> [Type])
-> (a -> Type)
-> (a -> Maybe CoAxBranch)
-> [([Type], Subst, [TyVar], Maybe CoAxBranch)]
buildImprovementData [a]
axioms a -> [TyVar]
axiomTVs a -> [Type]
axiomLHS a -> Type
axiomRHS a -> Maybe CoAxBranch
wrap =
[ ([Type]
ax_args, Subst
subst, [TyVar]
unsubstTvs, a -> Maybe CoAxBranch
wrap a
axiom)
| a
axiom <- [a]
axioms
, let ax_args :: [Type]
ax_args = a -> [Type]
axiomLHS a
axiom
ax_rhs :: Type
ax_rhs = a -> Type
axiomRHS a
axiom
ax_tvs :: [TyVar]
ax_tvs = a -> [TyVar]
axiomTVs a
axiom
in_scope1 :: InScopeSet
in_scope1 = InScopeSet
in_scope InScopeSet -> [TyVar] -> InScopeSet
`extendInScopeSetList` [TyVar]
ax_tvs
, Just Subst
subst <- [Bool -> InScopeSet -> Type -> Type -> Maybe Subst
tcUnifyTyWithTFs Bool
False InScopeSet
in_scope1 Type
ax_rhs Type
rhs_ty]
, let notInSubst :: TyVar -> Bool
notInSubst TyVar
tv = Bool -> Bool
not (TyVar
tv TyVar -> VarEnv Type -> Bool
forall a. TyVar -> VarEnv a -> Bool
`elemVarEnv` Subst -> VarEnv Type
getTvSubstEnv Subst
subst)
unsubstTvs :: [TyVar]
unsubstTvs = (TyVar -> Bool) -> [TyVar] -> [TyVar]
forall a. (a -> Bool) -> [a] -> [a]
filter (TyVar -> Bool
notInSubst (TyVar -> Bool) -> (TyVar -> Bool) -> TyVar -> Bool
forall (f :: * -> *). Applicative f => f Bool -> f Bool -> f Bool
<&&> TyVar -> Bool
isTyVar) [TyVar]
ax_tvs ]
injImproveEqns :: [Bool]
-> ([Type], Subst, [TyCoVar], Maybe CoAxBranch)
-> TcS [TypeEqn]
injImproveEqns :: [Bool]
-> ([Type], Subst, [TyVar], Maybe CoAxBranch) -> TcS [TypeEqn]
injImproveEqns [Bool]
inj_args ([Type]
ax_args, Subst
subst, [TyVar]
unsubstTvs, Maybe CoAxBranch
cabr)
= do { Subst
subst <- Subst -> [TyVar] -> TcS Subst
instFlexiX Subst
subst [TyVar]
unsubstTvs
; [TypeEqn] -> TcS [TypeEqn]
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return [ Type -> Type -> TypeEqn
forall a. a -> a -> Pair a
Pair (HasDebugCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst Type
ax_arg) Type
arg
| case Maybe CoAxBranch
cabr of
Just CoAxBranch
cabr' -> [Type] -> CoAxBranch -> Bool
apartnessCheck (HasDebugCallStack => Subst -> [Type] -> [Type]
Subst -> [Type] -> [Type]
substTys Subst
subst [Type]
ax_args) CoAxBranch
cabr'
Maybe CoAxBranch
_ -> Bool
True
, (Type
ax_arg, Type
arg, Bool
True) <- [Type] -> [Type] -> [Bool] -> [(Type, Type, Bool)]
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 [Type]
ax_args [Type]
args [Bool]
inj_args ] }
improveLocalFunEqs :: InertCans -> TyCon -> [TcType] -> EqCt -> TcS Bool
improveLocalFunEqs :: InertCans -> TyCon -> [Type] -> EqCt -> TcS Bool
improveLocalFunEqs InertCans
inerts TyCon
fam_tc [Type]
args (EqCt { eq_ev :: EqCt -> CtEvidence
eq_ev = CtEvidence
work_ev, eq_rhs :: EqCt -> Type
eq_rhs = Type
rhs })
| [FunDepEqn (CtLoc, RewriterSet)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [FunDepEqn (CtLoc, RewriterSet)]
improvement_eqns
= Bool -> TcS Bool
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
| Bool
otherwise
= do { String -> SDoc -> TcS ()
traceTcS String
"interactFunEq improvements: " (SDoc -> TcS ()) -> SDoc -> TcS ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Eqns:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> [FunDepEqn (CtLoc, RewriterSet)] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [FunDepEqn (CtLoc, RewriterSet)]
improvement_eqns
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Candidates:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> [EqCt] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [EqCt]
funeqs_for_tc
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Inert eqs:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> InertEqs -> SDoc
forall a. Outputable a => a -> SDoc
ppr (InertCans -> InertEqs
inert_eqs InertCans
inerts) ]
; CtEvidence -> [FunDepEqn (CtLoc, RewriterSet)] -> TcS Bool
emitFunDepWanteds CtEvidence
work_ev [FunDepEqn (CtLoc, RewriterSet)]
improvement_eqns }
where
funeqs :: InertFunEqs
funeqs = InertCans -> InertFunEqs
inert_funeqs InertCans
inerts
funeqs_for_tc :: [EqCt]
funeqs_for_tc :: [EqCt]
funeqs_for_tc = [ EqCt
funeq_ct | [EqCt]
equal_ct_list <- InertFunEqs -> TyCon -> [[EqCt]]
forall a. FunEqMap a -> TyCon -> [a]
findFunEqsByTyCon InertFunEqs
funeqs TyCon
fam_tc
, EqCt
funeq_ct <- [EqCt]
equal_ct_list
, EqRel
NomEq EqRel -> EqRel -> Bool
forall a. Eq a => a -> a -> Bool
== EqCt -> EqRel
eq_eq_rel EqCt
funeq_ct ]
work_loc :: CtLoc
work_loc = CtEvidence -> CtLoc
ctEvLoc CtEvidence
work_ev
work_pred :: Type
work_pred = CtEvidence -> Type
ctEvPred CtEvidence
work_ev
fam_inj_info :: Injectivity
fam_inj_info = TyCon -> Injectivity
tyConInjectivityInfo TyCon
fam_tc
improvement_eqns :: [FunDepEqn (CtLoc, RewriterSet)]
improvement_eqns :: [FunDepEqn (CtLoc, RewriterSet)]
improvement_eqns
| Just BuiltInSynFamily
ops <- TyCon -> Maybe BuiltInSynFamily
isBuiltInSynFamTyCon_maybe TyCon
fam_tc
=
(EqCt -> [FunDepEqn (CtLoc, RewriterSet)])
-> [EqCt] -> [FunDepEqn (CtLoc, RewriterSet)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (BuiltInSynFamily
-> Type -> EqCt -> [FunDepEqn (CtLoc, RewriterSet)]
do_one_built_in BuiltInSynFamily
ops Type
rhs) [EqCt]
funeqs_for_tc
| Injective [Bool]
injective_args <- Injectivity
fam_inj_info
=
(EqCt -> [FunDepEqn (CtLoc, RewriterSet)])
-> [EqCt] -> [FunDepEqn (CtLoc, RewriterSet)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Bool] -> Type -> EqCt -> [FunDepEqn (CtLoc, RewriterSet)]
do_one_injective [Bool]
injective_args Type
rhs) [EqCt]
funeqs_for_tc
| Bool
otherwise
= []
do_one_built_in :: BuiltInSynFamily
-> Type -> EqCt -> [FunDepEqn (CtLoc, RewriterSet)]
do_one_built_in BuiltInSynFamily
ops Type
rhs (EqCt { eq_lhs :: EqCt -> CanEqLHS
eq_lhs = TyFamLHS TyCon
_ [Type]
iargs, eq_rhs :: EqCt -> Type
eq_rhs = Type
irhs, eq_ev :: EqCt -> CtEvidence
eq_ev = CtEvidence
inert_ev })
| Bool -> Bool
not (CtEvidence -> Bool
isGiven CtEvidence
inert_ev Bool -> Bool -> Bool
&& CtEvidence -> Bool
isGiven CtEvidence
work_ev)
= CtEvidence -> [TypeEqn] -> [FunDepEqn (CtLoc, RewriterSet)]
mk_fd_eqns CtEvidence
inert_ev (BuiltInSynFamily -> [Type] -> Type -> [Type] -> Type -> [TypeEqn]
sfInteractInert BuiltInSynFamily
ops [Type]
args Type
rhs [Type]
iargs Type
irhs)
| Bool
otherwise
= []
do_one_built_in BuiltInSynFamily
_ Type
_ EqCt
_ = String -> SDoc -> [FunDepEqn (CtLoc, RewriterSet)]
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"interactFunEq 1" (TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
fam_tc)
do_one_injective :: [Bool] -> Type -> EqCt -> [FunDepEqn (CtLoc, RewriterSet)]
do_one_injective [Bool]
inj_args Type
rhs (EqCt { eq_lhs :: EqCt -> CanEqLHS
eq_lhs = TyFamLHS TyCon
_ [Type]
inert_args
, eq_rhs :: EqCt -> Type
eq_rhs = Type
irhs, eq_ev :: EqCt -> CtEvidence
eq_ev = CtEvidence
inert_ev })
| Bool -> Bool
not (CtEvidence -> Bool
isGiven CtEvidence
inert_ev Bool -> Bool -> Bool
&& CtEvidence -> Bool
isGiven CtEvidence
work_ev)
, Type
rhs HasDebugCallStack => Type -> Type -> Bool
Type -> Type -> Bool
`tcEqType` Type
irhs
= CtEvidence -> [TypeEqn] -> [FunDepEqn (CtLoc, RewriterSet)]
mk_fd_eqns CtEvidence
inert_ev ([TypeEqn] -> [FunDepEqn (CtLoc, RewriterSet)])
-> [TypeEqn] -> [FunDepEqn (CtLoc, RewriterSet)]
forall a b. (a -> b) -> a -> b
$ [ Type -> Type -> TypeEqn
forall a. a -> a -> Pair a
Pair Type
arg Type
iarg
| (Type
arg, Type
iarg, Bool
True) <- [Type] -> [Type] -> [Bool] -> [(Type, Type, Bool)]
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 [Type]
args [Type]
inert_args [Bool]
inj_args ]
| Bool
otherwise
= []
do_one_injective [Bool]
_ Type
_ EqCt
_ = String -> SDoc -> [FunDepEqn (CtLoc, RewriterSet)]
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"interactFunEq 2" (TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
fam_tc)
mk_fd_eqns :: CtEvidence -> [TypeEqn] -> [FunDepEqn (CtLoc, RewriterSet)]
mk_fd_eqns :: CtEvidence -> [TypeEqn] -> [FunDepEqn (CtLoc, RewriterSet)]
mk_fd_eqns CtEvidence
inert_ev [TypeEqn]
eqns
| [TypeEqn] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TypeEqn]
eqns = []
| Bool
otherwise = [ FDEqn { fd_qtvs :: [TyVar]
fd_qtvs = [], fd_eqs :: [TypeEqn]
fd_eqs = [TypeEqn]
eqns
, fd_pred1 :: Type
fd_pred1 = Type
work_pred
, fd_pred2 :: Type
fd_pred2 = Type
inert_pred
, fd_loc :: (CtLoc, RewriterSet)
fd_loc = (CtLoc
loc, RewriterSet
inert_rewriters) } ]
where
initial_loc :: CtLoc
initial_loc
| CtEvidence -> Bool
isGiven CtEvidence
work_ev = CtLoc
inert_loc
| Bool
otherwise = CtLoc
work_loc
eqn_orig :: CtOrigin
eqn_orig = Type
-> CtOrigin
-> RealSrcSpan
-> Type
-> CtOrigin
-> RealSrcSpan
-> CtOrigin
InjTFOrigin1 Type
work_pred (CtLoc -> CtOrigin
ctLocOrigin CtLoc
work_loc) (CtLoc -> RealSrcSpan
ctLocSpan CtLoc
work_loc)
Type
inert_pred (CtLoc -> CtOrigin
ctLocOrigin CtLoc
inert_loc) (CtLoc -> RealSrcSpan
ctLocSpan CtLoc
inert_loc)
eqn_loc :: CtLoc
eqn_loc = CtLoc -> CtOrigin -> CtLoc
setCtLocOrigin CtLoc
initial_loc CtOrigin
eqn_orig
inert_pred :: Type
inert_pred = CtEvidence -> Type
ctEvPred CtEvidence
inert_ev
inert_loc :: CtLoc
inert_loc = CtEvidence -> CtLoc
ctEvLoc CtEvidence
inert_ev
inert_rewriters :: RewriterSet
inert_rewriters = CtEvidence -> RewriterSet
ctEvRewriters CtEvidence
inert_ev
loc :: CtLoc
loc = CtLoc
eqn_loc { ctl_depth = ctl_depth inert_loc `maxSubGoalDepth`
ctl_depth work_loc }