{-# LANGUAGE CPP #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}
module GHC.Tc.Solver.Equality(
solveEquality
) where
import GHC.Prelude
import {-# SOURCE #-} GHC.Tc.Solver.Solve( solveSimpleWanteds )
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.FunDeps( tryEqFunDeps )
import GHC.Tc.Solver.InertSet
import GHC.Tc.Types.Evidence
import GHC.Tc.Types.Constraint
import GHC.Tc.Types.CtLoc
import GHC.Tc.Types.Origin
import GHC.Tc.Utils.Unify
import GHC.Tc.Utils.TcType
import GHC.Tc.Instance.Family ( tcTopNormaliseNewTypeTF_maybe )
import qualified GHC.Tc.Utils.Monad as TcM
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.Reduction
import GHC.Core.FamInstEnv ( FamInstEnvs )
import GHC.Core
import GHC.Types.Var
import GHC.Types.Var.Env
import GHC.Types.Var.Set
import GHC.Types.Name.Reader
import GHC.Types.Basic
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Utils.Misc
import GHC.Utils.Monad
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 -> PredType -> PredType -> SolverStage Void
solveEquality CtEvidence
ev EqRel
eq_rel PredType
ty1 PredType
ty2
= do { Pair ty1' ty2' <- CtEvidence
-> EqRel -> PredType -> PredType -> SolverStage (Pair PredType)
zonkEqTypes CtEvidence
ev EqRel
eq_rel PredType
ty1 PredType
ty2
; mb_canon <- canonicaliseEquality ev eq_rel ty1' ty2'
; case 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 ()
tryEqFunDeps 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)
; tc_lvl <- TcS TcLevel
getTcLevel
; updInertCans (addEqToCans tc_lvl eq_ct) }
zonkEqTypes :: CtEvidence -> EqRel -> TcType -> TcType -> SolverStage (Pair TcType)
zonkEqTypes :: CtEvidence
-> EqRel -> PredType -> PredType -> SolverStage (Pair PredType)
zonkEqTypes CtEvidence
ev EqRel
eq_rel PredType
ty1 PredType
ty2
= TcS (StopOrContinue (Pair PredType)) -> SolverStage (Pair PredType)
TcS (StopOrContinue (Pair PredType)) -> SolverStage (Pair PredType)
forall a. TcS (StopOrContinue a) -> SolverStage a
Stage (TcS (StopOrContinue (Pair PredType))
-> SolverStage (Pair PredType))
-> TcS (StopOrContinue (Pair PredType))
-> SolverStage (Pair PredType)
forall a b. (a -> b) -> a -> b
$ do { res <- PredType -> PredType -> TcS (Either (Pair PredType) PredType)
go PredType
ty1 PredType
ty2
; case res of
Left Pair PredType
pair -> Pair PredType -> TcS (StopOrContinue (Pair PredType))
forall a. a -> TcS (StopOrContinue a)
continueWith Pair PredType
pair
Right PredType
ty -> CtEvidence
-> EqRel -> PredType -> TcS (StopOrContinue (Pair PredType))
forall a. CtEvidence -> EqRel -> PredType -> TcS (StopOrContinue a)
canEqReflexive CtEvidence
ev EqRel
eq_rel PredType
ty }
where
go :: TcType -> TcType -> TcS (Either (Pair TcType) TcType)
go :: PredType -> PredType -> TcS (Either (Pair PredType) PredType)
go (TyVarTy TyVar
tv1) (TyVarTy TyVar
tv2) = TyVar -> TyVar -> TcS (Either (Pair PredType) PredType)
tyvar_tyvar TyVar
tv1 TyVar
tv2
go (TyVarTy TyVar
tv1) PredType
ty2 = SwapFlag
-> TyVar -> PredType -> TcS (Either (Pair PredType) PredType)
tyvar SwapFlag
NotSwapped TyVar
tv1 PredType
ty2
go PredType
ty1 (TyVarTy TyVar
tv2) = SwapFlag
-> TyVar -> PredType -> TcS (Either (Pair PredType) PredType)
tyvar SwapFlag
IsSwapped TyVar
tv2 PredType
ty1
go (FunTy FunTyFlag
af1 PredType
w1 PredType
arg1 PredType
res1) (FunTy FunTyFlag
af2 PredType
w2 PredType
arg2 PredType
res2)
| FunTyFlag
af1 FunTyFlag -> FunTyFlag -> Bool
forall a. Eq a => a -> a -> Bool
== FunTyFlag
af2
, HasCallStack => PredType -> PredType -> Bool
PredType -> PredType -> Bool
eqType PredType
w1 PredType
w2
= do { res_a <- PredType -> PredType -> TcS (Either (Pair PredType) PredType)
go PredType
arg1 PredType
arg2
; res_b <- go res1 res2
; return $ combine_rev (FunTy af1 w1) res_b res_a }
go ty1 :: PredType
ty1@(FunTy {}) PredType
ty2 = PredType -> PredType -> TcS (Either (Pair PredType) PredType)
forall {m :: * -> *} {a} {b}.
Monad m =>
a -> a -> m (Either (Pair a) b)
bale_out PredType
ty1 PredType
ty2
go PredType
ty1 ty2 :: PredType
ty2@(FunTy {}) = PredType -> PredType -> TcS (Either (Pair PredType) PredType)
forall {m :: * -> *} {a} {b}.
Monad m =>
a -> a -> m (Either (Pair a) b)
bale_out PredType
ty1 PredType
ty2
go PredType
ty1 PredType
ty2
| Just (TyCon
tc1, [PredType]
tys1) <- HasDebugCallStack => PredType -> Maybe (TyCon, [PredType])
PredType -> Maybe (TyCon, [PredType])
splitTyConAppNoView_maybe PredType
ty1
, Just (TyCon
tc2, [PredType]
tys2) <- HasDebugCallStack => PredType -> Maybe (TyCon, [PredType])
PredType -> Maybe (TyCon, [PredType])
splitTyConAppNoView_maybe PredType
ty2
= if TyCon
tc1 TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
tc2 Bool -> Bool -> Bool
&& [PredType]
tys1 [PredType] -> [PredType] -> Bool
forall a b. [a] -> [b] -> Bool
`equalLength` [PredType]
tys2
then TyCon
-> [PredType]
-> [PredType]
-> TcS (Either (Pair PredType) PredType)
tycon TyCon
tc1 [PredType]
tys1 [PredType]
tys2
else PredType -> PredType -> TcS (Either (Pair PredType) PredType)
forall {m :: * -> *} {a} {b}.
Monad m =>
a -> a -> m (Either (Pair a) b)
bale_out PredType
ty1 PredType
ty2
go ty1 :: PredType
ty1@(LitTy TyLit
lit1) (LitTy TyLit
lit2)
| TyLit
lit1 TyLit -> TyLit -> Bool
forall a. Eq a => a -> a -> Bool
== TyLit
lit2
= Either (Pair PredType) PredType
-> TcS (Either (Pair PredType) PredType)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (PredType -> Either (Pair PredType) PredType
forall a b. b -> Either a b
Right PredType
ty1)
go PredType
ty1 PredType
ty2 = PredType -> PredType -> TcS (Either (Pair PredType) PredType)
forall {m :: * -> *} {a} {b}.
Monad m =>
a -> a -> m (Either (Pair a) b)
bale_out PredType
ty1 PredType
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 -> PredType -> TcS (Either (Pair PredType) PredType)
tyvar SwapFlag
swapped TyVar
tv PredType
ty
= case TyVar -> TcTyVarDetails
tcTyVarDetails TyVar
tv of
MetaTv { mtv_ref :: TcTyVarDetails -> IORef MetaDetails
mtv_ref = IORef MetaDetails
ref }
-> do { cts <- IORef MetaDetails -> TcS MetaDetails
forall a. TcRef a -> TcS a
readTcRef IORef MetaDetails
ref
; case cts of
MetaDetails
Flexi -> TcS (Either (Pair PredType) PredType)
give_up
Indirect PredType
ty' -> do { TyVar -> PredType -> TcS ()
forall {a} {a}. (Outputable a, Outputable a) => a -> a -> TcS ()
trace_indirect TyVar
tv PredType
ty'
; SwapFlag
-> (PredType -> PredType -> TcS (Either (Pair PredType) PredType))
-> PredType
-> PredType
-> TcS (Either (Pair PredType) PredType)
forall a b. SwapFlag -> (a -> a -> b) -> a -> a -> b
unSwap SwapFlag
swapped PredType -> PredType -> TcS (Either (Pair PredType) PredType)
go PredType
ty' PredType
ty } }
TcTyVarDetails
_ -> TcS (Either (Pair PredType) PredType)
give_up
where
give_up :: TcS (Either (Pair PredType) PredType)
give_up = Either (Pair PredType) PredType
-> TcS (Either (Pair PredType) PredType)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either (Pair PredType) PredType
-> TcS (Either (Pair PredType) PredType))
-> Either (Pair PredType) PredType
-> TcS (Either (Pair PredType) PredType)
forall a b. (a -> b) -> a -> b
$ Pair PredType -> Either (Pair PredType) PredType
Pair PredType -> Either (Pair PredType) PredType
forall a b. a -> Either a b
Left (Pair PredType -> Either (Pair PredType) PredType)
-> Pair PredType -> Either (Pair PredType) PredType
forall a b. (a -> b) -> a -> b
$ SwapFlag
-> (PredType -> PredType -> Pair PredType)
-> PredType
-> PredType
-> Pair PredType
forall a b. SwapFlag -> (a -> a -> b) -> a -> a -> b
unSwap SwapFlag
swapped PredType -> PredType -> Pair PredType
PredType -> PredType -> Pair PredType
forall a. a -> a -> Pair a
Pair (TyVar -> PredType
mkTyVarTy TyVar
tv) PredType
ty
tyvar_tyvar :: TyVar -> TyVar -> TcS (Either (Pair PredType) PredType)
tyvar_tyvar TyVar
tv1 TyVar
tv2
| TyVar
tv1 TyVar -> TyVar -> Bool
forall a. Eq a => a -> a -> Bool
== TyVar
tv2 = Either (Pair PredType) PredType
-> TcS (Either (Pair PredType) PredType)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (PredType -> Either (Pair PredType) PredType
forall a b. b -> Either a b
Right (TyVar -> PredType
mkTyVarTy TyVar
tv1))
| Bool
otherwise = do { (ty1', progress1) <- TyVar -> TcS (PredType, Bool)
quick_zonk TyVar
tv1
; (ty2', progress2) <- quick_zonk tv2
; if progress1 || progress2
then go ty1' ty2'
else return $ Left (Pair (TyVarTy tv1) (TyVarTy 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 (PredType, Bool)
quick_zonk TyVar
tv = case TyVar -> TcTyVarDetails
tcTyVarDetails TyVar
tv of
MetaTv { mtv_ref :: TcTyVarDetails -> IORef MetaDetails
mtv_ref = IORef MetaDetails
ref }
-> do { cts <- IORef MetaDetails -> TcS MetaDetails
forall a. TcRef a -> TcS a
readTcRef IORef MetaDetails
ref
; case cts of
MetaDetails
Flexi -> (PredType, Bool) -> TcS (PredType, Bool)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (TyVar -> PredType
TyVarTy TyVar
tv, Bool
False)
Indirect PredType
ty' -> do { TyVar -> PredType -> TcS ()
forall {a} {a}. (Outputable a, Outputable a) => a -> a -> TcS ()
trace_indirect TyVar
tv PredType
ty'
; (PredType, Bool) -> TcS (PredType, Bool)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (PredType
ty', Bool
True) } }
TcTyVarDetails
_ -> (PredType, Bool) -> TcS (PredType, Bool)
forall a. a -> TcS a
forall (m :: * -> *) a. Monad m => a -> m a
return (TyVar -> PredType
TyVarTy TyVar
tv, Bool
False)
tycon :: TyCon -> [TcType] -> [TcType]
-> TcS (Either (Pair TcType) TcType)
tycon :: TyCon
-> [PredType]
-> [PredType]
-> TcS (Either (Pair PredType) PredType)
tycon TyCon
tc [PredType]
tys1 [PredType]
tys2
= do { results <- (PredType -> PredType -> TcS (Either (Pair PredType) PredType))
-> [PredType]
-> [PredType]
-> TcS [Either (Pair PredType) PredType]
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM PredType -> PredType -> TcS (Either (Pair PredType) PredType)
go [PredType]
tys1 [PredType]
tys2
; return $ case combine_results results of
Left Pair [PredType]
tys -> Pair PredType -> Either (Pair PredType) PredType
forall a b. a -> Either a b
Left (TyCon -> [PredType] -> PredType
mkTyConApp TyCon
tc ([PredType] -> PredType) -> Pair [PredType] -> Pair PredType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Pair [PredType]
tys)
Right [PredType]
tys -> PredType -> Either (Pair PredType) PredType
forall a b. b -> Either a b
Right (TyCon -> [PredType] -> PredType
mkTyConApp TyCon
tc [PredType]
tys) }
combine_results :: [Either (Pair TcType) TcType]
-> Either (Pair [TcType]) [TcType]
combine_results :: [Either (Pair PredType) PredType]
-> Either (Pair [PredType]) [PredType]
combine_results = (Pair [PredType] -> Pair [PredType])
-> ([PredType] -> [PredType])
-> Either (Pair [PredType]) [PredType]
-> Either (Pair [PredType]) [PredType]
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 (([PredType] -> [PredType]) -> Pair [PredType] -> Pair [PredType]
forall a b. (a -> b) -> Pair a -> Pair b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [PredType] -> [PredType]
forall a. [a] -> [a]
reverse) [PredType] -> [PredType]
forall a. [a] -> [a]
reverse (Either (Pair [PredType]) [PredType]
-> Either (Pair [PredType]) [PredType])
-> ([Either (Pair PredType) PredType]
-> Either (Pair [PredType]) [PredType])
-> [Either (Pair PredType) PredType]
-> Either (Pair [PredType]) [PredType]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(Either (Pair [PredType]) [PredType]
-> Either (Pair PredType) PredType
-> Either (Pair [PredType]) [PredType])
-> Either (Pair [PredType]) [PredType]
-> [Either (Pair PredType) PredType]
-> Either (Pair [PredType]) [PredType]
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' ((PredType -> [PredType] -> [PredType])
-> Either (Pair [PredType]) [PredType]
-> Either (Pair PredType) PredType
-> Either (Pair [PredType]) [PredType]
forall a b c.
(a -> b -> c)
-> Either (Pair b) b -> Either (Pair a) a -> Either (Pair c) c
combine_rev (:)) ([PredType] -> Either (Pair [PredType]) [PredType]
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
-> PredType
-> PredType
-> SolverStage (Either IrredCt EqCt)
canonicaliseEquality CtEvidence
ev EqRel
eq_rel PredType
ty1 PredType
ty2
= TcS (StopOrContinue (Either IrredCt EqCt))
-> SolverStage (Either IrredCt EqCt)
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, PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ty1, PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ty2 ]
; rdr_env <- TcS GlobalRdrEnv
getGlobalRdrEnvTcS
; fam_insts <- getFamInstEnvs
; can_eq_nc False rdr_env fam_insts ev eq_rel ty1 ty1 ty2 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
-> PredType
-> PredType
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc Bool
_flat GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel ty1 :: PredType
ty1@(TyConApp TyCon
tc1 []) PredType
_ps_ty1 (TyConApp TyCon
tc2 []) PredType
_ps_ty2
| TyCon
tc1 TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
tc2
= CtEvidence
-> EqRel -> PredType -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. CtEvidence -> EqRel -> PredType -> TcS (StopOrContinue a)
canEqReflexive CtEvidence
ev EqRel
eq_rel PredType
ty1
can_eq_nc Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel PredType
ty1 PredType
ps_ty1 PredType
ty2 PredType
ps_ty2
| Just PredType
ty1' <- PredType -> Maybe PredType
coreView PredType
ty1 = Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> PredType
-> PredType
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel PredType
ty1' PredType
ps_ty1 PredType
ty2 PredType
ps_ty2
| Just PredType
ty2' <- PredType -> Maybe PredType
coreView PredType
ty2 = Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> PredType
-> PredType
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel PredType
ty1 PredType
ps_ty1 PredType
ty2' PredType
ps_ty2
can_eq_nc Bool
True GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
ReprEq PredType
ty1 PredType
_ PredType
ty2 PredType
_
| PredType
ty1 HasDebugCallStack => PredType -> PredType -> Bool
PredType -> PredType -> Bool
`tcEqType` PredType
ty2
= CtEvidence
-> EqRel -> PredType -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. CtEvidence -> EqRel -> PredType -> TcS (StopOrContinue a)
canEqReflexive CtEvidence
ev EqRel
ReprEq PredType
ty1
can_eq_nc Bool
_rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel PredType
ty1 PredType
ps_ty1 PredType
ty2 PredType
ps_ty2
| EqRel
ReprEq <- EqRel
eq_rel
, Just ((Bag GlobalRdrElt, TcCoercion), PredType)
stuff1 <- (FamInstEnv, FamInstEnv)
-> GlobalRdrEnv
-> PredType
-> Maybe ((Bag GlobalRdrElt, TcCoercion), PredType)
tcTopNormaliseNewTypeTF_maybe (FamInstEnv, FamInstEnv)
envs GlobalRdrEnv
rdr_env PredType
ty1
= GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> SwapFlag
-> PredType
-> ((Bag GlobalRdrElt, TcCoercion), PredType)
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_newtype_nc GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev SwapFlag
NotSwapped PredType
ty1 ((Bag GlobalRdrElt, TcCoercion), PredType)
stuff1 PredType
ty2 PredType
ps_ty2
| EqRel
ReprEq <- EqRel
eq_rel
, Just ((Bag GlobalRdrElt, TcCoercion), PredType)
stuff2 <- (FamInstEnv, FamInstEnv)
-> GlobalRdrEnv
-> PredType
-> Maybe ((Bag GlobalRdrElt, TcCoercion), PredType)
tcTopNormaliseNewTypeTF_maybe (FamInstEnv, FamInstEnv)
envs GlobalRdrEnv
rdr_env PredType
ty2
= GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> SwapFlag
-> PredType
-> ((Bag GlobalRdrElt, TcCoercion), PredType)
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_newtype_nc GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev SwapFlag
IsSwapped PredType
ty2 ((Bag GlobalRdrElt, TcCoercion), PredType)
stuff2 PredType
ty1 PredType
ps_ty1
can_eq_nc Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel (CastTy PredType
ty1 TcCoercion
co1) PredType
_ PredType
ty2 PredType
ps_ty2
| Maybe CanEqLHS -> Bool
forall a. Maybe a -> Bool
isNothing (PredType -> Maybe CanEqLHS
canEqLHS_maybe PredType
ty2)
=
Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> SwapFlag
-> PredType
-> TcCoercion
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCast Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel SwapFlag
NotSwapped PredType
ty1 TcCoercion
co1 PredType
ty2 PredType
ps_ty2
can_eq_nc Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel PredType
ty1 PredType
ps_ty1 (CastTy PredType
ty2 TcCoercion
co2) PredType
_
| Maybe CanEqLHS -> Bool
forall a. Maybe a -> Bool
isNothing (PredType -> Maybe CanEqLHS
canEqLHS_maybe PredType
ty1)
=
Bool
-> GlobalRdrEnv
-> (FamInstEnv, FamInstEnv)
-> CtEvidence
-> EqRel
-> SwapFlag
-> PredType
-> TcCoercion
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCast Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel SwapFlag
IsSwapped PredType
ty2 TcCoercion
co2 PredType
ty1 PredType
ps_ty1
can_eq_nc Bool
_rewritten GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel ty1 :: PredType
ty1@(LitTy TyLit
l1) PredType
_ (LitTy TyLit
l2) PredType
_
| TyLit
l1 TyLit -> TyLit -> Bool
forall a. Eq a => a -> a -> Bool
== TyLit
l2
= do { CtEvidence -> CoercionPlusHoles -> TcS ()
setEqIfWanted CtEvidence
ev (EqRel -> PredType -> CoercionPlusHoles
mkReflCPH EqRel
eq_rel PredType
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
ty1 :: PredType
ty1@(FunTy { ft_mult :: PredType -> PredType
ft_mult = PredType
am1, ft_af :: PredType -> FunTyFlag
ft_af = FunTyFlag
af1, ft_arg :: PredType -> PredType
ft_arg = PredType
ty1a, ft_res :: PredType -> PredType
ft_res = PredType
ty1b }) PredType
_ps_ty1
ty2 :: PredType
ty2@(FunTy { ft_mult :: PredType -> PredType
ft_mult = PredType
am2, ft_af :: PredType -> FunTyFlag
ft_af = FunTyFlag
af2, ft_arg :: PredType -> PredType
ft_arg = PredType
ty2a, ft_res :: PredType -> PredType
ft_res = PredType
ty2b }) PredType
_ps_ty2
| FunTyFlag
af1 FunTyFlag -> FunTyFlag -> Bool
forall a. Eq a => a -> a -> Bool
== FunTyFlag
af2
= CtEvidence
-> EqRel
-> FunTyFlag
-> (PredType, PredType, PredType, PredType)
-> (PredType, PredType, PredType, PredType)
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtEvidence
-> EqRel
-> FunTyFlag
-> (PredType, PredType, PredType, PredType)
-> (PredType, PredType, PredType, PredType)
-> TcS (StopOrContinue a)
canDecomposableFunTy CtEvidence
ev EqRel
eq_rel FunTyFlag
af1 (PredType
ty1,PredType
am1,PredType
ty1a,PredType
ty1b) (PredType
ty2,PredType
am2,PredType
ty2a,PredType
ty2b)
can_eq_nc Bool
rewritten GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel PredType
ty1 PredType
_ PredType
ty2 PredType
_
| Just (TyCon
tc1, [PredType]
tys1) <- HasDebugCallStack => PredType -> Maybe (TyCon, [PredType])
PredType -> Maybe (TyCon, [PredType])
tcSplitTyConApp_maybe PredType
ty1
, Just (TyCon
tc2, [PredType]
tys2) <- HasDebugCallStack => PredType -> Maybe (TyCon, [PredType])
PredType -> Maybe (TyCon, [PredType])
tcSplitTyConApp_maybe PredType
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
-> (PredType, TyCon, [PredType])
-> (PredType, TyCon, [PredType])
-> TcS (StopOrContinue (Either IrredCt EqCt))
canTyConApp CtEvidence
ev EqRel
eq_rel Bool
both_generative (PredType
ty1,TyCon
tc1,[PredType]
tys1) (PredType
ty2,TyCon
tc2,[PredType]
tys2)
can_eq_nc Bool
_rewritten GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel
s1 :: PredType
s1@ForAllTy{} PredType
_
s2 :: PredType
s2@ForAllTy{} PredType
_
= CtEvidence
-> EqRel
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc_forall CtEvidence
ev EqRel
eq_rel PredType
s1 PredType
s2
can_eq_nc Bool
True GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
NomEq PredType
ty1 PredType
_ PredType
ty2 PredType
_
| Just (PredType
t1, PredType
s1) <- PredType -> Maybe (PredType, PredType)
tcSplitAppTy_maybe PredType
ty1
, Just (PredType
t2, PredType
s2) <- PredType -> Maybe (PredType, PredType)
tcSplitAppTy_maybe PredType
ty2
= CtEvidence
-> PredType
-> PredType
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_app CtEvidence
ev PredType
t1 PredType
s1 PredType
t2 PredType
s2
can_eq_nc Bool
False GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel PredType
_ PredType
ps_ty1 PredType
_ PredType
ps_ty2
=
do { (redn1@(Reduction _ xi1), rewriters1) <- CtEvidence -> PredType -> TcS (Reduction, CoHoleSet)
rewrite CtEvidence
ev PredType
ps_ty1
; (redn2@(Reduction _ xi2), rewriters2) <- rewrite ev ps_ty2
; new_ev <- rewriteEqEvidence ev NotSwapped redn1 redn2
(rewriters1 S.<> rewriters2)
; traceTcS "can_eq_nc: go round again" (ppr new_ev $$ ppr xi1 $$ ppr xi2)
; can_eq_nc True rdr_env envs new_ev eq_rel xi1 xi1 xi2 xi2 }
can_eq_nc Bool
True GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel PredType
ty1 PredType
ps_ty1 PredType
ty2 PredType
ps_ty2
| Just CanEqLHS
can_eq_lhs1 <- PredType -> Maybe CanEqLHS
canEqLHS_maybe PredType
ty1
= do { String -> SDoc -> TcS ()
traceTcS String
"can_eq1" (PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ty1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ty2)
; CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS CtEvidence
ev EqRel
eq_rel SwapFlag
NotSwapped CanEqLHS
can_eq_lhs1 PredType
ps_ty1 PredType
ty2 PredType
ps_ty2 }
| Just CanEqLHS
can_eq_lhs2 <- PredType -> Maybe CanEqLHS
canEqLHS_maybe PredType
ty2
= do { String -> SDoc -> TcS ()
traceTcS String
"can_eq2" (PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ty1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ty2)
; CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS CtEvidence
ev EqRel
eq_rel SwapFlag
IsSwapped CanEqLHS
can_eq_lhs2 PredType
ps_ty2 PredType
ty1 PredType
ps_ty1 }
can_eq_nc Bool
True GlobalRdrEnv
_rdr_env (FamInstEnv, FamInstEnv)
_envs CtEvidence
ev EqRel
eq_rel PredType
_ PredType
ps_ty1 PredType
_ PredType
ps_ty2
= do { String -> SDoc -> TcS ()
traceTcS String
"can_eq_nc catch-all case" (PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ps_ty1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
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
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_nc_forall CtEvidence
ev EqRel
eq_rel PredType
s1 PredType
s2
| CtWanted (WantedCt { ctev_dest :: WantedCtEvidence -> TcEvDest
ctev_dest = TcEvDest
orig_dest }) <- CtEvidence
ev
= do { let ([ForAllTyBinder]
bndrs1, PredType
phi1, [ForAllTyBinder]
bndrs2, PredType
phi2) = PredType
-> PredType
-> ([ForAllTyBinder], PredType, [ForAllTyBinder], PredType)
split_foralls PredType
s1 PredType
s2
flags1 :: [ForAllTyFlag]
flags1 = [ForAllTyBinder] -> [ForAllTyFlag]
forall tv argf. [VarBndr tv argf] -> [argf]
binderFlags [ForAllTyBinder]
bndrs1
flags2 :: [ForAllTyFlag]
flags2 = [ForAllTyBinder] -> [ForAllTyFlag]
forall tv argf. [VarBndr tv argf] -> [argf]
binderFlags [ForAllTyBinder]
bndrs2
; if EqRel
eq_rel EqRel -> EqRel -> Bool
forall a. Eq a => a -> a -> Bool
== EqRel
NomEq Bool -> Bool -> Bool
&& 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: visibility-mismatch" (SDoc -> TcS ()) -> SDoc -> TcS ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
s1, PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
s2, [ForAllTyBinder] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [ForAllTyBinder]
bndrs1, [ForAllTyBinder] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [ForAllTyBinder]
bndrs2
, [ForAllTyFlag] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [ForAllTyFlag]
flags1, [ForAllTyFlag] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [ForAllTyFlag]
flags2 ]
; CtEvidence
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtEvidence
-> PredType -> PredType -> TcS (StopOrContinue (Either IrredCt a))
canEqHardFailure CtEvidence
ev PredType
s1 PredType
s2 }
else
do { let free_tvs :: TcTyVarSet
free_tvs = [PredType] -> TcTyVarSet
tyCoVarsOfTypes [PredType
s1,PredType
s2]
empty_subst1 :: Subst
empty_subst1 = InScopeSet -> Subst
mkEmptySubst (InScopeSet -> Subst) -> InScopeSet -> Subst
forall a b. (a -> b) -> a -> b
$ TcTyVarSet -> InScopeSet
mkInScopeSet TcTyVarSet
free_tvs
skol_info_anon :: SkolemInfoAnon
skol_info_anon = PredType -> SkolemInfoAnon
UnifyForAllSkol PredType
phi1
; skol_info <- SkolemInfoAnon -> TcS SkolemInfo
forall (m :: * -> *). MonadIO m => SkolemInfoAnon -> m SkolemInfo
mkSkolemInfo SkolemInfoAnon
skol_info_anon
; (subst1, skol_tvs) <- tcInstSkolTyVarsX skol_info empty_subst1 $
binderVars bndrs1
; let phi1' = HasDebugCallStack => Subst -> PredType -> PredType
Subst -> PredType -> PredType
substTy Subst
subst1 PredType
phi1
go :: UnifyEnv -> [TcTyVar] -> Subst
-> [TyVarBinder] -> [TyVarBinder] -> TcM.TcM TcCoercion
go UnifyEnv
uenv (TyVar
skol_tv:[TyVar]
skol_tvs) Subst
subst2 (ForAllTyBinder
bndr1:[ForAllTyBinder]
bndrs1) (ForAllTyBinder
bndr2:[ForAllTyBinder]
bndrs2)
= do { let tv2 :: TyVar
tv2 = ForAllTyBinder -> TyVar
forall tv argf. VarBndr tv argf -> tv
binderVar ForAllTyBinder
bndr2
vis1 :: ForAllTyFlag
vis1 = ForAllTyBinder -> ForAllTyFlag
forall tv argf. VarBndr tv argf -> argf
binderFlag ForAllTyBinder
bndr1
vis2 :: ForAllTyFlag
vis2 = ForAllTyBinder -> ForAllTyFlag
forall tv argf. VarBndr tv argf -> argf
binderFlag ForAllTyBinder
bndr2
; kind_co <- UnifyEnv -> PredType -> PredType -> TcM TcCoercion
uType (UnifyEnv
uenv UnifyEnv -> Role -> UnifyEnv
`setUEnvRole` Role
Nominal)
(TyVar -> PredType
tyVarKind TyVar
skol_tv)
(HasDebugCallStack => Subst -> PredType -> PredType
Subst -> PredType -> PredType
substTy Subst
subst2 (TyVar -> PredType
tyVarKind TyVar
tv2))
; let subst2' = Subst -> TyVar -> PredType -> Subst
extendTvSubstAndInScope Subst
subst2 TyVar
tv2
(PredType -> TcCoercion -> PredType
mkCastTy (TyVar -> PredType
mkTyVarTy TyVar
skol_tv) TcCoercion
kind_co)
; co <- go uenv skol_tvs subst2' bndrs1 bndrs2
; return (mkNakedForAllCo skol_tv vis1 vis2 kind_co co)}
go UnifyEnv
uenv [] Subst
subst2 [ForAllTyBinder]
bndrs1 [ForAllTyBinder]
bndrs2
= Bool -> TcM TcCoercion -> TcM TcCoercion
forall a. HasCallStack => Bool -> a -> a
assert ([ForAllTyBinder] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ForAllTyBinder]
bndrs1 Bool -> Bool -> Bool
&& [ForAllTyBinder] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ForAllTyBinder]
bndrs2) (TcM TcCoercion -> TcM TcCoercion)
-> TcM TcCoercion -> TcM TcCoercion
forall a b. (a -> b) -> a -> b
$
UnifyEnv -> PredType -> PredType -> TcM TcCoercion
uType UnifyEnv
uenv PredType
phi1' (Subst -> PredType -> PredType
substTyUnchecked Subst
subst2 PredType
phi2)
go UnifyEnv
_ [TyVar]
_ Subst
_ [ForAllTyBinder]
_ [ForAllTyBinder]
_ = String -> TcM TcCoercion
forall a. HasCallStack => String -> a
panic String
"can_eq_nc_forall"
init_subst2 = InScopeSet -> Subst
mkEmptySubst (Subst -> InScopeSet
substInScopeSet Subst
subst1)
; traceTcS "Generating wanteds" (ppr s1 $$ ppr s2)
; nested_ev_binds_var <- newNoTcEvBinds
; (unifs, (all_co, solved))
<- reportFineGrainUnifications $
do {
(tclvl, (all_co, wanteds))
<- pushLevelNoWorkList (ppr skol_info) $
wrapUnifier ev (eqRelRole eq_rel) $ \UnifyEnv
uenv ->
UnifyEnv
-> [TyVar]
-> Subst
-> [ForAllTyBinder]
-> [ForAllTyBinder]
-> TcM TcCoercion
go UnifyEnv
uenv [TyVar]
skol_tvs Subst
init_subst2 [ForAllTyBinder]
bndrs1 [ForAllTyBinder]
bndrs2
; traceTcS "Trying to solve the implication" (ppr s1 $$ ppr s2 $$ ppr wanteds)
; residual_wanted <- nestImplicTcS skol_info_anon nested_ev_binds_var tclvl $
solveSimpleWanteds wanteds
; return (all_co, isSolvedWC residual_wanted) }
; kickOutAfterUnification unifs
; if solved
then do {
ev_binds_var <- getTcEvBindsVar
; updTcEvBinds ev_binds_var nested_ev_binds_var
; setWantedEq orig_dest (CPH { cph_co = all_co, cph_holes = emptyCoHoleSet })
; stopWith ev "Polytype equality: solved" }
else canEqSoftFailure IrredShapeReason ev s1 s2 } }
| 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
$
PredType -> PredType -> SDoc
pprEq PredType
s1 PredType
s2
; CtEvidence -> String -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. CtEvidence -> String -> TcS (StopOrContinue a)
stopWith CtEvidence
ev String
"Discard given polytype equality" }
where
split_foralls :: TcType -> TcType
-> ( [ForAllTyBinder], TcType
, [ForAllTyBinder], TcType)
split_foralls :: PredType
-> PredType
-> ([ForAllTyBinder], PredType, [ForAllTyBinder], PredType)
split_foralls PredType
s1 PredType
s2
| Just (ForAllTyBinder
bndr1, PredType
s1') <- PredType -> Maybe (ForAllTyBinder, PredType)
splitForAllForAllTyBinder_maybe PredType
s1
, Just (ForAllTyBinder
bndr2, PredType
s2') <- PredType -> Maybe (ForAllTyBinder, PredType)
splitForAllForAllTyBinder_maybe PredType
s2
= let !([ForAllTyBinder]
bndrs1, PredType
phi1, [ForAllTyBinder]
bndrs2, PredType
phi2) = PredType
-> PredType
-> ([ForAllTyBinder], PredType, [ForAllTyBinder], PredType)
split_foralls PredType
s1' PredType
s2'
in (ForAllTyBinder
bndr1ForAllTyBinder -> [ForAllTyBinder] -> [ForAllTyBinder]
forall a. a -> [a] -> [a]
:[ForAllTyBinder]
bndrs1, PredType
phi1, ForAllTyBinder
bndr2ForAllTyBinder -> [ForAllTyBinder] -> [ForAllTyBinder]
forall a. a -> [a] -> [a]
:[ForAllTyBinder]
bndrs2, PredType
phi2)
split_foralls PredType
s1 PredType
s2 = ([], PredType
s1, [], PredType
s2)
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
-> PredType
-> ((Bag GlobalRdrElt, TcCoercion), PredType)
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_newtype_nc GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev SwapFlag
swapped PredType
ty1 ((Bag GlobalRdrElt
gres, TcCoercion
co1), PredType
ty1') PredType
ty2 PredType
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, PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ty1', PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
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 -> PredType -> TcS ()
checkReductionDepth CtLoc
loc PredType
ty1
; Bag GlobalRdrElt -> TcS ()
recordUsedGREs Bag GlobalRdrElt
gres
; let redn1 :: Reduction
redn1 = TcCoercion -> PredType -> Reduction
mkReduction TcCoercion
co1 PredType
ty1'
redn2 :: Reduction
redn2 = Role -> PredType -> Reduction
mkReflRedn Role
Representational PredType
ps_ty2
; new_ev <- CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> CoHoleSet
-> TcS CtEvidence
rewriteEqEvidence CtEvidence
ev' SwapFlag
swapped Reduction
redn1 Reduction
redn2
CoHoleSet
emptyCoHoleSet
; can_eq_nc False rdr_env envs new_ev ReprEq ty1' ty1' ty2 ps_ty2 }
can_eq_app :: CtEvidence
-> Xi -> Xi
-> Xi -> Xi
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_app :: CtEvidence
-> PredType
-> PredType
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
can_eq_app CtEvidence
ev PredType
s1 PredType
t1 PredType
s2 PredType
t2
| CtWanted (WantedCt { ctev_dest :: WantedCtEvidence -> 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
<+> PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
s1, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"t1:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
t1
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"s2:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
s2, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"t2:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
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 (PredType -> Bool
isNextArgVisible PredType
s1) ])
; co_plus_holes <- CtEvidence
-> Role -> (UnifyEnv -> TcM TcCoercion) -> TcS CoercionPlusHoles
wrapUnifierAndEmit CtEvidence
ev Role
Nominal ((UnifyEnv -> TcM TcCoercion) -> TcS CoercionPlusHoles)
-> (UnifyEnv -> TcM TcCoercion) -> TcS CoercionPlusHoles
forall a b. (a -> b) -> a -> b
$ \UnifyEnv
uenv ->
do { let mb_invis :: Maybe InvisibleBit
mb_invis = if PredType -> Bool
isNextArgVisible PredType
s1
then Maybe InvisibleBit
forall a. Maybe a
Nothing
else InvisibleBit -> Maybe InvisibleBit
forall a. a -> Maybe a
Just InvisibleBit
InvisibleKind
arg_env :: UnifyEnv
arg_env = UnifyEnv -> (CtLoc -> CtLoc) -> UnifyEnv
updUEnvLoc UnifyEnv
uenv (Maybe InvisibleBit -> Bool -> CtLoc -> CtLoc
adjustCtLoc Maybe InvisibleBit
mb_invis Bool
False)
; co_t <- UnifyEnv -> PredType -> PredType -> TcM TcCoercion
uType UnifyEnv
arg_env PredType
t1 PredType
t2
; co_s <- uType uenv s1 s2
; return (mkAppCo co_s co_t) }
; setWantedEq dest co_plus_holes
; stopWith ev "Decomposed [W] AppTy" }
| PredType
s1k PredType -> PredType -> Bool
`mismatches` PredType
s2k
= CtEvidence
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtEvidence
-> PredType -> PredType -> TcS (StopOrContinue (Either IrredCt a))
canEqHardFailure CtEvidence
ev (PredType
s1 PredType -> PredType -> PredType
`mkAppTy` PredType
t1) (PredType
s2 PredType -> PredType -> PredType
`mkAppTy` PredType
t2)
| CtGiven (GivenCt { ctev_evar :: GivenCtEvidence -> TyVar
ctev_evar = TyVar
evar }) <- CtEvidence
ev
= do { let = 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
; ev_s <- CtLoc -> (PredType, EvTerm) -> TcS GivenCtEvidence
newGivenEv CtLoc
loc ( CtEvidence -> PredType -> PredType -> PredType
mkTcEqPredLikeEv CtEvidence
ev PredType
s1 PredType
s2
, TcCoercion -> EvTerm
evCoercion TcCoercion
co_s )
; ev_t <- newGivenEv loc ( mkTcEqPredLikeEv ev t1 t2
, evCoercion co_t )
; emitWorkNC [CtGiven ev_t]
; startAgainWith (mkNonCanonical $ CtGiven ev_s) }
where
loc :: CtLoc
loc = CtEvidence -> CtLoc
ctEvLoc CtEvidence
ev
s1k :: PredType
s1k = HasDebugCallStack => PredType -> PredType
PredType -> PredType
typeKind PredType
s1
s2k :: PredType
s2k = HasDebugCallStack => PredType -> PredType
PredType -> PredType
typeKind PredType
s2
PredType
k1 mismatches :: PredType -> PredType -> Bool
`mismatches` PredType
k2
= PredType -> Bool
isForAllTy PredType
k1 Bool -> Bool -> Bool
&& Bool -> Bool
not (PredType -> Bool
isForAllTy PredType
k2)
Bool -> Bool -> Bool
|| Bool -> Bool
not (PredType -> Bool
isForAllTy PredType
k1) Bool -> Bool -> Bool
&& PredType -> Bool
isForAllTy PredType
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
-> PredType
-> TcCoercion
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCast Bool
rewritten GlobalRdrEnv
rdr_env (FamInstEnv, FamInstEnv)
envs CtEvidence
ev EqRel
eq_rel PredType
ty1 TcCoercion
co1 PredType
ty2 PredType
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
, PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
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
, PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ps_ty2 ])
; new_ev <- CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> CoHoleSet
-> TcS CtEvidence
rewriteEqEvidence CtEvidence
ev SwapFlag
swapped
(Role -> PredType -> TcCoercion -> Reduction
mkGReflLeftRedn Role
role PredType
ty1 TcCoercion
co1)
(Role -> PredType -> Reduction
mkReflRedn Role
role PredType
ps_ty2)
CoHoleSet
emptyCoHoleSet
; can_eq_nc rewritten rdr_env envs new_ev eq_rel ty1 ty1 ty2 ps_ty2 }
where
role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
canTyConApp :: CtEvidence -> EqRel
-> Bool
-> (Type,TyCon,[TcType])
-> (Type,TyCon,[TcType])
-> TcS (StopOrContinue (Either IrredCt EqCt))
canTyConApp :: CtEvidence
-> EqRel
-> Bool
-> (PredType, TyCon, [PredType])
-> (PredType, TyCon, [PredType])
-> TcS (StopOrContinue (Either IrredCt EqCt))
canTyConApp CtEvidence
ev EqRel
eq_rel Bool
both_generative (PredType
ty1,TyCon
tc1,[PredType]
tys1) (PredType
ty2,TyCon
tc2,[PredType]
tys2)
| TyCon
tc1 TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
tc2
, [PredType]
tys1 [PredType] -> [PredType] -> Bool
forall a b. [a] -> [b] -> Bool
`equalLength` [PredType]
tys2
= do { inerts <- TcS InertSet
getInertSet
; if can_decompose inerts
then canDecomposableTyConAppOK ev eq_rel tc1 (ty1,tys1) (ty2,tys2)
else assert (eq_rel == ReprEq) $
canEqSoftFailure ReprEqReason ev ty1 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 }
| EqRel
NomEq <- EqRel
eq_rel
= CtEvidence
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtEvidence
-> PredType -> PredType -> TcS (StopOrContinue (Either IrredCt a))
canEqHardFailure CtEvidence
ev PredType
ty1 PredType
ty2
| Bool
both_generative
= CtEvidence
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtEvidence
-> PredType -> PredType -> TcS (StopOrContinue (Either IrredCt a))
canEqHardFailure CtEvidence
ev PredType
ty1 PredType
ty2
| Bool
otherwise
= CtIrredReason
-> CtEvidence
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall a.
CtIrredReason
-> CtEvidence
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt a))
canEqSoftFailure CtIrredReason
ReprEqReason CtEvidence
ev PredType
ty1 PredType
ty2
where
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
-> (Type,[TcType]) -> (Type,[TcType])
-> TcS (StopOrContinue a)
canDecomposableTyConAppOK :: forall a.
CtEvidence
-> EqRel
-> TyCon
-> (PredType, [PredType])
-> (PredType, [PredType])
-> TcS (StopOrContinue a)
canDecomposableTyConAppOK CtEvidence
ev EqRel
eq_rel TyCon
tc (PredType
ty1,[PredType]
tys1) (PredType
ty2,[PredType]
tys2)
= Bool -> TcS (StopOrContinue a) -> TcS (StopOrContinue a)
forall a. HasCallStack => Bool -> a -> a
assert ([PredType]
tys1 [PredType] -> [PredType] -> Bool
forall a b. [a] -> [b] -> Bool
`equalLength` [PredType]
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
$$ [PredType] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [PredType]
tys1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ [PredType] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [PredType]
tys2)
; case CtEvidence
ev of
CtWanted (WantedCt { ctev_dest :: WantedCtEvidence -> TcEvDest
ctev_dest = TcEvDest
dest })
-> do { co_plus_holes <- CtEvidence
-> Role -> (UnifyEnv -> TcM TcCoercion) -> TcS CoercionPlusHoles
wrapUnifierAndEmit CtEvidence
ev Role
role ((UnifyEnv -> TcM TcCoercion) -> TcS CoercionPlusHoles)
-> (UnifyEnv -> TcM TcCoercion) -> TcS CoercionPlusHoles
forall a b. (a -> b) -> a -> b
$ \UnifyEnv
uenv ->
do { cos <- (CtLoc -> Role -> PredType -> PredType -> TcM TcCoercion)
-> [CtLoc]
-> [Role]
-> [PredType]
-> [PredType]
-> 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 -> PredType -> PredType -> TcM TcCoercion
u_arg UnifyEnv
uenv) [CtLoc]
new_locs [Role]
tc_roles [PredType]
tys1 [PredType]
tys2
; return (mkTyConAppCo role tc cos) }
; setWantedEq dest co_plus_holes }
CtGiven (GivenCt { ctev_evar :: GivenCtEvidence -> TyVar
ctev_evar = TyVar
evar })
| let pred_ty :: PredType
pred_ty = EqRel -> PredType -> PredType -> PredType
mkEqPred EqRel
eq_rel PredType
ty1 PredType
ty2
ev_co :: TcCoercion
ev_co = TyVar -> TcCoercion
mkCoVarCo (TyVar -> PredType -> TyVar
setVarType TyVar
evar PredType
pred_ty)
-> CtLoc -> [(Role, TcCoercion)] -> TcS ()
emitNewGivens CtLoc
loc
[ (Role
r, HasDebugCallStack => CoSel -> TcCoercion -> TcCoercion
CoSel -> TcCoercion -> TcCoercion
mkSelCo (Int -> Role -> CoSel
SelTyCon Int
i Role
r) TcCoercion
ev_co)
| (Role
r, PredType
ty1, PredType
ty2, Int
i) <- [Role]
-> [PredType]
-> [PredType]
-> [Int]
-> [(Role, PredType, PredType, Int)]
forall a b c d. [a] -> [b] -> [c] -> [d] -> [(a, b, c, d)]
zip4 [Role]
tc_roles [PredType]
tys1 [PredType]
tys2 [Int
0..]
, Role
r Role -> Role -> Bool
forall a. Eq a => a -> a -> Bool
/= Role
Phantom
, Bool -> Bool
not (PredType -> Bool
isCoercionTy PredType
ty1) Bool -> Bool -> Bool
&& Bool -> Bool
not (PredType -> Bool
isCoercionTy PredType
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 -> PredType -> PredType -> TcM TcCoercion
u_arg UnifyEnv
uenv CtLoc
arg_loc Role
arg_role = UnifyEnv -> PredType -> PredType -> 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,Type,Type)
-> TcS (StopOrContinue a)
canDecomposableFunTy :: forall a.
CtEvidence
-> EqRel
-> FunTyFlag
-> (PredType, PredType, PredType, PredType)
-> (PredType, PredType, PredType, PredType)
-> TcS (StopOrContinue a)
canDecomposableFunTy CtEvidence
ev EqRel
eq_rel FunTyFlag
af f1 :: (PredType, PredType, PredType, PredType)
f1@(PredType
ty1,PredType
m1,PredType
a1,PredType
r1) f2 :: (PredType, PredType, PredType, PredType)
f2@(PredType
ty2,PredType
m2,PredType
a2,PredType
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
$$ (PredType, PredType, PredType, PredType) -> SDoc
forall a. Outputable a => a -> SDoc
ppr (PredType, PredType, PredType, PredType)
f1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ (PredType, PredType, PredType, PredType) -> SDoc
forall a. Outputable a => a -> SDoc
ppr (PredType, PredType, PredType, PredType)
f2)
; case CtEvidence
ev of
CtWanted (WantedCt { ctev_dest :: WantedCtEvidence -> TcEvDest
ctev_dest = TcEvDest
dest })
-> do { co_plus_holes <- CtEvidence
-> Role -> (UnifyEnv -> TcM TcCoercion) -> TcS CoercionPlusHoles
wrapUnifierAndEmit CtEvidence
ev Role
Nominal ((UnifyEnv -> TcM TcCoercion) -> TcS CoercionPlusHoles)
-> (UnifyEnv -> TcM TcCoercion) -> TcS CoercionPlusHoles
forall a b. (a -> b) -> a -> b
$ \ UnifyEnv
uenv ->
do { let mult_env :: UnifyEnv
mult_env = UnifyEnv
uenv UnifyEnv -> (CtLoc -> CtLoc) -> UnifyEnv
`updUEnvLoc` InvisibleBit -> CtLoc -> CtLoc
toInvisibleLoc InvisibleBit
InvisibleMultiplicity
UnifyEnv -> Role -> UnifyEnv
`setUEnvRole` Role -> FunSel -> Role
funRole Role
role FunSel
SelMult
; mult <- UnifyEnv -> PredType -> PredType -> TcM TcCoercion
uType UnifyEnv
mult_env PredType
m1 PredType
m2
; arg <- uType (uenv `setUEnvRole` funRole role SelArg) a1 a2
; res <- uType (uenv `setUEnvRole` funRole role SelRes) r1 r2
; return (mkNakedFunCo role af mult arg res) }
; setWantedEq dest co_plus_holes }
CtGiven (GivenCt { ctev_evar :: GivenCtEvidence -> TyVar
ctev_evar = TyVar
evar })
| let pred_ty :: PredType
pred_ty = EqRel -> PredType -> PredType -> PredType
mkEqPred EqRel
eq_rel PredType
ty1 PredType
ty2
ev_co :: TcCoercion
ev_co = TyVar -> TcCoercion
mkCoVarCo (TyVar -> PredType -> TyVar
setVarType TyVar
evar PredType
pred_ty)
-> CtLoc -> [(Role, TcCoercion)] -> TcS ()
emitNewGivens CtLoc
loc
[ (Role -> FunSel -> Role
funRole Role
role FunSel
fs, HasDebugCallStack => CoSel -> TcCoercion -> TcCoercion
CoSel -> TcCoercion -> TcCoercion
mkSelCo (FunSel -> CoSel
SelFun FunSel
fs) TcCoercion
ev_co)
| FunSel
fs <- [FunSel
SelMult, FunSel
SelArg, FunSel
SelRes] ]
; 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 :: CtIrredReason -> CtEvidence -> TcType -> TcType
-> TcS (StopOrContinue (Either IrredCt a))
canEqSoftFailure :: forall a.
CtIrredReason
-> CtEvidence
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt a))
canEqSoftFailure CtIrredReason
reason CtEvidence
ev PredType
ty1 PredType
ty2
= do { (redn1, rewriters1) <- CtEvidence -> PredType -> TcS (Reduction, CoHoleSet)
rewrite CtEvidence
ev PredType
ty1
; (redn2, rewriters2) <- rewrite ev ty2
; traceTcS "canEqSoftFailure" $
vcat [ ppr ev, ppr redn1, ppr redn2 ]
; new_ev <- rewriteEqEvidence ev NotSwapped redn1 redn2
(rewriters1 S.<> rewriters2)
; finishCanWithIrred reason new_ev }
canEqHardFailure :: CtEvidence -> TcType -> TcType
-> TcS (StopOrContinue (Either IrredCt a))
canEqHardFailure :: forall a.
CtEvidence
-> PredType -> PredType -> TcS (StopOrContinue (Either IrredCt a))
canEqHardFailure CtEvidence
ev PredType
ty1 PredType
ty2
= do { String -> SDoc -> TcS ()
traceTcS String
"canEqHardFailure" (PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ty1 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ty2)
; (redn1, rewriters1) <- CtEvidence -> PredType -> TcS (Reduction, CoHoleSet)
rewriteForErrors CtEvidence
ev PredType
ty1
; (redn2, rewriters2) <- rewriteForErrors ev ty2
; new_ev <- rewriteEqEvidence ev NotSwapped redn1 redn2
(rewriters1 S.<> rewriters2)
; finishCanWithIrred ShapeMismatchReason new_ev }
canEqCanLHS :: CtEvidence
-> EqRel -> SwapFlag
-> CanEqLHS
-> TcType
-> TcType -> TcType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS :: CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 PredType
ps_xi1 PredType
xi2 PredType
ps_xi2
| PredType
k1 HasDebugCallStack => PredType -> PredType -> Bool
PredType -> PredType -> Bool
`tcEqType` PredType
k2
= CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHomo CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 PredType
ps_xi1 PredType
xi2 PredType
ps_xi2
| Bool
otherwise
= CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> PredType
-> PredType
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHetero CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 PredType
ps_xi1 PredType
k1 PredType
xi2 PredType
ps_xi2 PredType
k2
where
k1 :: PredType
k1 = CanEqLHS -> PredType
canEqLHSKind CanEqLHS
lhs1
k2 :: PredType
k2 = HasDebugCallStack => PredType -> PredType
PredType -> PredType
typeKind PredType
xi2
canEqCanLHSHetero :: CtEvidence
-> EqRel -> SwapFlag
-> CanEqLHS -> TcType
-> TcKind
-> TcType -> TcType
-> TcKind
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHetero :: CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> PredType
-> PredType
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHetero CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 PredType
ps_xi1 PredType
ki1 PredType
xi2 PredType
ps_xi2 PredType
ki2
= case CtEvidence
ev of
CtGiven (GivenCt { ctev_evar :: GivenCtEvidence -> TyVar
ctev_evar = TyVar
evar, ctev_loc :: GivenCtEvidence -> CtLoc
ctev_loc = CtLoc
loc })
-> do { let kind_co :: TcCoercion
kind_co = SwapFlag -> TcCoercion -> TcCoercion
maybeSymCo (SwapFlag -> SwapFlag
flipSwap SwapFlag
swapped) (TcCoercion -> TcCoercion) -> TcCoercion -> TcCoercion
forall a b. (a -> b) -> a -> b
$
TcCoercion -> TcCoercion
mkKindCo (TyVar -> TcCoercion
mkCoVarCo TyVar
evar)
pred_ty :: PredType
pred_ty = PredType -> PredType -> PredType
mkNomEqPred PredType
ki2 PredType
ki1
kind_loc :: CtLoc
kind_loc = PredType -> PredType -> CtLoc -> CtLoc
mkKindEqLoc PredType
xi1 PredType
xi2 CtLoc
loc
; kind_ev <- CtLoc -> (PredType, EvTerm) -> TcS GivenCtEvidence
newGivenEv CtLoc
kind_loc (PredType
pred_ty, TcCoercion -> EvTerm
evCoercion TcCoercion
kind_co)
; emitWorkNC [CtGiven kind_ev]
; finish emptyCoHoleSet (givenCtEvCoercion kind_ev) }
CtWanted {}
-> do { (unifs, (kind_co, eqs)) <- TcS (TcCoercion, Bag Ct) -> TcS (TcTyVarSet, (TcCoercion, Bag Ct))
forall a. TcS a -> TcS (TcTyVarSet, a)
reportFineGrainUnifications (TcS (TcCoercion, Bag Ct)
-> TcS (TcTyVarSet, (TcCoercion, Bag Ct)))
-> TcS (TcCoercion, Bag Ct)
-> TcS (TcTyVarSet, (TcCoercion, Bag Ct))
forall a b. (a -> b) -> a -> b
$
CtEvidence
-> Role -> (UnifyEnv -> TcM TcCoercion) -> TcS (TcCoercion, Bag Ct)
forall a.
CtEvidence -> Role -> (UnifyEnv -> TcM a) -> TcS (a, Bag Ct)
wrapUnifier CtEvidence
ev Role
Nominal ((UnifyEnv -> TcM TcCoercion) -> TcS (TcCoercion, Bag Ct))
-> (UnifyEnv -> TcM TcCoercion) -> TcS (TcCoercion, Bag Ct)
forall a b. (a -> b) -> a -> b
$ \UnifyEnv
uenv ->
let uenv' :: UnifyEnv
uenv' = UnifyEnv -> (CtLoc -> CtLoc) -> UnifyEnv
updUEnvLoc UnifyEnv
uenv (PredType -> PredType -> CtLoc -> CtLoc
mkKindEqLoc PredType
xi1 PredType
xi2)
in UnifyEnv -> PredType -> PredType -> TcM TcCoercion
uType UnifyEnv
uenv' PredType
ki2 PredType
ki1
; kickOutAfterUnification unifs
; if not (isEmptyVarSet unifs)
then
startAgainWith (mkNonCanonical ev)
else
do { emitChildEqs ev eqs
; assertPpr (not (isEmptyCts eqs))
(vcat [ppr ev, ppr ki1, ppr ki2, ppr unifs, ppr eqs]) $
finish (rewriterSetFromCts eqs) kind_co }}
where
xi1 :: PredType
xi1 = CanEqLHS -> PredType
canEqLHSType CanEqLHS
lhs1
role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
finish :: CoHoleSet
-> TcCoercion -> TcS (StopOrContinue (Either IrredCt EqCt))
finish CoHoleSet
rewriters TcCoercion
kind_co
= do { 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 [ PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ki1, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"~#", PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
ki2 ])
; new_ev <- CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> CoHoleSet
-> TcS CtEvidence
rewriteEqEvidence CtEvidence
ev SwapFlag
swapped Reduction
lhs_redn Reduction
rhs_redn CoHoleSet
rewriters
; canEqCanLHSHomo new_ev eq_rel NotSwapped lhs1 ps_xi1 new_xi2 new_xi2 }
where
lhs_redn :: Reduction
lhs_redn = Role -> PredType -> Reduction
mkReflRedn Role
role PredType
ps_xi1
rhs_redn :: Reduction
rhs_redn = Role -> PredType -> TcCoercion -> Reduction
mkGReflRightRedn Role
role PredType
xi2 TcCoercion
kind_co
new_xi2 :: PredType
new_xi2 = PredType -> TcCoercion -> PredType
mkCastTy PredType
ps_xi2 TcCoercion
kind_co
canEqCanLHSHomo :: CtEvidence
-> EqRel -> SwapFlag
-> CanEqLHS -> TcType
-> TcType -> TcType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHomo :: CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> PredType
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSHomo CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 PredType
ps_xi1 PredType
xi2 PredType
ps_xi2
| (PredType
xi2', MCoercion
mco) <- PredType -> (PredType, MCoercion)
split_cast_ty PredType
xi2
, Just CanEqLHS
lhs2 <- PredType -> Maybe CanEqLHS
canEqLHS_maybe PredType
xi2'
= CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> CanEqLHS
-> PredType
-> MCoercion
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS2 CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 PredType
ps_xi1 CanEqLHS
lhs2 (PredType
ps_xi2 PredType -> MCoercion -> PredType
`mkCastTyMCo` MCoercion -> MCoercion
mkSymMCo MCoercion
mco) MCoercion
mco
| Bool
otherwise
= CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 PredType
ps_xi2
where
split_cast_ty :: PredType -> (PredType, MCoercion)
split_cast_ty (CastTy PredType
ty TcCoercion
co) = (PredType
ty, TcCoercion -> MCoercion
MCo TcCoercion
co)
split_cast_ty PredType
other = (PredType
other, MCoercion
MRefl)
canEqCanLHS2 :: CtEvidence
-> EqRel -> SwapFlag
-> CanEqLHS
-> TcType
-> CanEqLHS
-> TcType
-> MCoercion
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS2 :: CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> CanEqLHS
-> PredType
-> MCoercion
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHS2 CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 PredType
ps_xi1 CanEqLHS
lhs2 PredType
ps_xi2 MCoercion
mco
| CanEqLHS
lhs1 CanEqLHS -> CanEqLHS -> Bool
`eqCanEqLHS` CanEqLHS
lhs2
= CtEvidence
-> EqRel -> PredType -> TcS (StopOrContinue (Either IrredCt EqCt))
forall a. CtEvidence -> EqRel -> PredType -> TcS (StopOrContinue a)
canEqReflexive CtEvidence
ev EqRel
eq_rel PredType
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 [PredType]
fun_args1 <- CanEqLHS
lhs1
, TyFamLHS TyCon
_fun_tc2 [PredType]
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)
; tclvl <- TcS TcLevel
getTcLevel
; let tvs1 = [PredType] -> TcTyVarSet
tyCoVarsOfTypes [PredType]
fun_args1
tvs2 = [PredType] -> TcTyVarSet
tyCoVarsOfTypes [PredType]
fun_args2
swap_for_size = [PredType] -> Int
typesSize [PredType]
fun_args2 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> [PredType] -> Int
typesSize [PredType]
fun_args1
meta_tv_lhs = (TyVar -> Bool) -> TcTyVarSet -> Bool
anyVarSet (TcLevel -> TyVar -> Bool
isTouchableMetaTyVar TcLevel
tclvl) TcTyVarSet
tvs1
meta_tv_rhs = (TyVar -> Bool) -> TcTyVarSet -> Bool
anyVarSet (TcLevel -> TyVar -> Bool
isTouchableMetaTyVar TcLevel
tclvl) TcTyVarSet
tvs2
swap_for_rewriting = Bool
meta_tv_rhs Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
meta_tv_lhs
; if swap_for_rewriting || (meta_tv_lhs == meta_tv_rhs && swap_for_size)
then finish_with_swapping
else 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 :: PredType
lhs1_ty = CanEqLHS -> PredType
canEqLHSType CanEqLHS
lhs1
lhs2_ty :: PredType
lhs2_ty = CanEqLHS -> PredType
canEqLHSType CanEqLHS
lhs2
finish_without_swapping :: TcS (StopOrContinue (Either IrredCt EqCt))
finish_without_swapping
= CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs1 (PredType
ps_xi2 PredType -> MCoercion -> PredType
`mkCastTyMCo` MCoercion
mco)
finish_with_swapping :: TcS (StopOrContinue (Either IrredCt EqCt))
finish_with_swapping
= do { let lhs1_redn :: Reduction
lhs1_redn = Role -> PredType -> MCoercion -> Reduction
mkGReflRightMRedn Role
role PredType
lhs1_ty MCoercion
sym_mco
lhs2_redn :: Reduction
lhs2_redn = Role -> PredType -> MCoercion -> Reduction
mkGReflLeftMRedn Role
role PredType
lhs2_ty MCoercion
mco
; new_ev <-CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> CoHoleSet
-> TcS CtEvidence
rewriteEqEvidence CtEvidence
ev SwapFlag
swapped Reduction
lhs1_redn Reduction
lhs2_redn CoHoleSet
emptyCoHoleSet
; canEqCanLHSFinish new_ev eq_rel IsSwapped lhs2 (ps_xi1 `mkCastTyMCo` 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
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs PredType
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
<+> PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
rhs ]
; Bool -> TcS ()
forall (m :: * -> *). (HasCallStack, Applicative m) => Bool -> m ()
massert (CanEqLHS -> PredType
canEqLHSKind CanEqLHS
lhs HasCallStack => PredType -> PredType -> Bool
PredType -> PredType -> Bool
`eqType` HasDebugCallStack => PredType -> PredType
PredType -> PredType
typeKind PredType
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
<+> PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
rhs ]
; CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish_try_unification CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs PredType
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, [PredType]
tc_args) <- HasDebugCallStack => PredType -> Maybe (TyCon, [PredType])
PredType -> Maybe (TyCon, [PredType])
splitTyConApp_maybe PredType
rhs
, Just DataCon
con <- TyCon -> Maybe DataCon
newTyConDataCon_maybe TyCon
tc
, [PredType]
tc_args [PredType] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthAtLeast` TyCon -> Int
tyConArity TyCon
tc
= do { rdr_env <- TcS GlobalRdrEnv
getGlobalRdrEnvTcS
; let 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)
; return $ not 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
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish_try_unification CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs PredType
rhs
| CtWanted WantedCtEvidence
wev <- CtEvidence
ev
, EqRel
NomEq <- EqRel
eq_rel
, WantedCtEvidence -> Bool
wantedCtHasNoRewriters WantedCtEvidence
wev
, TyVarLHS TyVar
lhs_tv <- CanEqLHS
lhs
= do { given_eq_lvl <- TcS TcLevel
getInnermostGivenEqLevel
; case simpleUnifyCheck UC_Solver given_eq_lvl lhs_tv rhs of
SimpleUnifyResult
SUC_CanUnify ->
TyVar -> Reduction -> TcS (StopOrContinue (Either IrredCt EqCt))
unify TyVar
lhs_tv (Role -> PredType -> Reduction
mkReflRedn Role
Nominal PredType
rhs)
SimpleUnifyResult
SUC_CannotUnify
| Just CanEqLHS
can_rhs <- PredType -> Maybe CanEqLHS
canTyFamEqLHS_maybe PredType
rhs
-> TyVar -> CanEqLHS -> TcS (StopOrContinue (Either IrredCt EqCt))
swap_and_finish TyVar
lhs_tv CanEqLHS
can_rhs
| Bool
otherwise
-> TcS (StopOrContinue (Either IrredCt EqCt))
finish_no_unify
SimpleUnifyResult
SUC_NotSure ->
do { let flags :: TyEqFlags (IOEnv (Env TcGblEnv TcLclEnv)) Ct
flags = CtEvidence -> TyVar -> TyEqFlags (IOEnv (Env TcGblEnv TcLclEnv)) Ct
unifyingLHSMetaTyVar_TEFTask CtEvidence
ev TyVar
lhs_tv
; check_result <- TcM (PuResult Ct Reduction) -> TcS (PuResult Ct Reduction)
forall a. TcM a -> TcS a
wrapTcS (TyEqFlags (IOEnv (Env TcGblEnv TcLclEnv)) Ct
-> PredType -> TcM (PuResult Ct Reduction)
forall (m :: * -> *) a.
Monad m =>
TyEqFlags m a -> PredType -> m (PuResult a Reduction)
checkTyEqRhs TyEqFlags (IOEnv (Env TcGblEnv TcLclEnv)) Ct
flags PredType
rhs)
; case check_result of
PuOK Bag Ct
cts Reduction
rhs_redn ->
do { Bag Ct -> TcS ()
emitWork Bag Ct
cts
; TyVar -> Reduction -> TcS (StopOrContinue (Either IrredCt EqCt))
unify TyVar
lhs_tv Reduction
rhs_redn }
PuFail CheckTyEqResult
reason
| Just CanEqLHS
can_rhs <- PredType -> Maybe CanEqLHS
canTyFamEqLHS_maybe PredType
rhs
-> TyVar -> CanEqLHS -> TcS (StopOrContinue (Either IrredCt EqCt))
swap_and_finish TyVar
lhs_tv CanEqLHS
can_rhs
| CheckTyEqResult
reason CheckTyEqResult -> CheckTyEqResult -> Bool
`cterHasOnlyProblems` CheckTyEqResult
do_not_prevent_rewriting
->
do { new_ev <- CtEvidence
-> EqRel -> SwapFlag -> CanEqLHS -> PredType -> TcS CtEvidence
rewriteEqEvidenceSwapOnly CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs PredType
rhs
; continueWith $ Right $
EqCt { eq_ev = new_ev, eq_eq_rel = eq_rel
, eq_lhs = lhs , eq_rhs = rhs }
}
| Bool
otherwise
-> CheckTyEqResult -> TcS (StopOrContinue (Either IrredCt EqCt))
try_irred CheckTyEqResult
reason
}
}
| Bool
otherwise
= TcS (StopOrContinue (Either IrredCt EqCt))
finish_no_unify
where
finish_no_unify :: TcS (StopOrContinue (Either IrredCt EqCt))
finish_no_unify =
CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish_no_unification CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs PredType
rhs
try_irred :: CheckTyEqResult -> TcS (StopOrContinue (Either IrredCt EqCt))
try_irred CheckTyEqResult
reason =
CheckTyEqResult
-> CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall unused.
CheckTyEqResult
-> CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> TcS (StopOrContinue (Either IrredCt unused))
tryIrredInstead CheckTyEqResult
reason CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs PredType
rhs
swap_and_finish :: TyVar -> CanEqLHS -> TcS (StopOrContinue (Either IrredCt EqCt))
swap_and_finish TyVar
tv CanEqLHS
can_rhs =
CtEvidence
-> EqRel
-> SwapFlag
-> PredType
-> CanEqLHS
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall unused.
CtEvidence
-> EqRel
-> SwapFlag
-> PredType
-> CanEqLHS
-> TcS (StopOrContinue (Either unused EqCt))
swapAndFinish CtEvidence
ev EqRel
eq_rel SwapFlag
swapped (TyVar -> PredType
mkTyVarTy TyVar
tv) CanEqLHS
can_rhs
unify :: TyVar -> Reduction -> TcS (StopOrContinue (Either IrredCt EqCt))
unify TyVar
tv Reduction
rhs_redn =
do {
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 CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> CoHoleSet
-> TcS CtEvidence
rewriteEqEvidence CtEvidence
ev SwapFlag
swapped
(Role -> PredType -> Reduction
mkReflRedn Role
Nominal (TyVar -> PredType
mkTyVarTy TyVar
tv)) Reduction
rhs_redn
CoHoleSet
emptyCoHoleSet
; let tv_ty = TyVar -> PredType
mkTyVarTy TyVar
tv
final_rhs = Reduction -> PredType
reductionReducedType Reduction
rhs_redn
; traceTcS "Sneaky unification:" $
vcat [text "Unifies:" <+> ppr tv <+> text ":=" <+> ppr final_rhs,
text "Coercion:" <+> pprEq tv_ty final_rhs,
text "Left Kind is:" <+> ppr (typeKind tv_ty),
text "Right Kind is:" <+> ppr (typeKind final_rhs) ]
; unifyTyVar tv final_rhs
; setEqIfWanted new_ev (mkReflCPH NomEq final_rhs)
; kickOutAfterUnification (unitVarSet tv)
; return (Stop new_ev (text "Solved by unification")) }
canEqCanLHSFinish_no_unification :: CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
canEqCanLHSFinish_no_unification CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs PredType
rhs
= do {
; check_result <- CtEvidence
-> EqRel -> CanEqLHS -> PredType -> TcS (PuResult Ct Reduction)
checkTypeEq CtEvidence
ev EqRel
eq_rel CanEqLHS
lhs PredType
rhs
; let lhs_ty = CanEqLHS -> PredType
canEqLHSType CanEqLHS
lhs
; case check_result of
PuFail CheckTyEqResult
reason
| CheckTyEqResult
reason CheckTyEqResult -> CheckTyEqResult -> Bool
`cterHasOnlyProblems` CheckTyEqResult
do_not_prevent_rewriting
-> do { new_ev <- CtEvidence
-> EqRel -> SwapFlag -> CanEqLHS -> PredType -> TcS CtEvidence
rewriteEqEvidenceSwapOnly CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs PredType
rhs
; continueWith $ Right $
EqCt { eq_ev = new_ev, eq_eq_rel = eq_rel
, eq_lhs = lhs , eq_rhs = rhs }
}
| Bool
otherwise
-> CheckTyEqResult
-> CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> TcS (StopOrContinue (Either IrredCt EqCt))
forall unused.
CheckTyEqResult
-> CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> TcS (StopOrContinue (Either IrredCt unused))
tryIrredInstead CheckTyEqResult
reason CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs PredType
rhs
PuOK Bag Ct
new_eqs Reduction
rhs_redn
-> do { Bag Ct -> TcS ()
emitWork Bag Ct
new_eqs
; let new_holes :: CoHoleSet
new_holes = Bag Ct -> CoHoleSet
rewriterSetFromCts Bag Ct
new_eqs
lhs_redn :: Reduction
lhs_redn = Role -> PredType -> Reduction
mkReflRedn (EqRel -> Role
eqRelRole EqRel
eq_rel) PredType
lhs_ty
; new_ev <- CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> CoHoleSet
-> TcS CtEvidence
rewriteEqEvidence CtEvidence
ev SwapFlag
swapped Reduction
lhs_redn Reduction
rhs_redn CoHoleSet
new_holes
; continueWith $ Right $
EqCt { eq_ev = new_ev, eq_eq_rel = eq_rel
, eq_lhs = lhs
, eq_rhs = reductionReducedType rhs_redn } } }
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
swapAndFinish :: CtEvidence -> EqRel -> SwapFlag
-> TcType -> CanEqLHS
-> TcS (StopOrContinue (Either unused EqCt))
swapAndFinish :: forall unused.
CtEvidence
-> EqRel
-> SwapFlag
-> PredType
-> CanEqLHS
-> TcS (StopOrContinue (Either unused EqCt))
swapAndFinish CtEvidence
ev EqRel
eq_rel SwapFlag
swapped PredType
lhs_ty CanEqLHS
can_rhs
= do { new_ev <- CtEvidence
-> EqRel -> SwapFlag -> CanEqLHS -> PredType -> TcS CtEvidence
rewriteEqEvidenceSwapOnly CtEvidence
ev EqRel
eq_rel (SwapFlag -> SwapFlag
flipSwap SwapFlag
swapped) CanEqLHS
can_rhs PredType
lhs_ty
; continueWith $ Right $
EqCt { eq_ev = new_ev, eq_eq_rel = eq_rel
, eq_lhs = can_rhs, eq_rhs = lhs_ty } }
tryIrredInstead :: CheckTyEqResult -> CtEvidence
-> EqRel -> SwapFlag -> CanEqLHS -> TcType
-> TcS (StopOrContinue (Either IrredCt unused))
tryIrredInstead :: forall unused.
CheckTyEqResult
-> CtEvidence
-> EqRel
-> SwapFlag
-> CanEqLHS
-> PredType
-> TcS (StopOrContinue (Either IrredCt unused))
tryIrredInstead CheckTyEqResult
reason CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs PredType
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
$$ PredType -> SDoc
forall a. Outputable a => a -> SDoc
ppr PredType
rhs)
; new_ev <- CtEvidence
-> EqRel -> SwapFlag -> CanEqLHS -> PredType -> TcS CtEvidence
rewriteEqEvidenceSwapOnly CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs PredType
rhs
; finishCanWithIrred (NonCanonicalReason reason) 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
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 -> PredType -> TcS (StopOrContinue a)
canEqReflexive CtEvidence
ev EqRel
eq_rel PredType
ty
= do { CtEvidence -> CoercionPlusHoles -> TcS ()
setEqIfWanted CtEvidence
ev (EqRel -> PredType -> CoercionPlusHoles
mkReflCPH EqRel
eq_rel PredType
ty)
; CtEvidence -> String -> TcS (StopOrContinue a)
forall a. CtEvidence -> String -> TcS (StopOrContinue a)
stopWith CtEvidence
ev String
"Solved by reflexivity" }
rewriteEqEvidence :: CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> CoHoleSet
-> TcS CtEvidence
rewriteEqEvidence :: CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> CoHoleSet
-> TcS CtEvidence
rewriteEqEvidence CtEvidence
old_ev SwapFlag
swapped (Reduction TcCoercion
lhs_co PredType
nlhs) (Reduction TcCoercion
rhs_co PredType
nrhs) CoHoleSet
new_holes
| 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 -> PredType -> CtEvidence
CtEvidence -> PredType -> CtEvidence
setCtEvPredType CtEvidence
old_ev PredType
new_pred)
| CtGiven (GivenCt { ctev_evar :: GivenCtEvidence -> 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
HasDebugCallStack => TcCoercion -> TcCoercion -> TcCoercion
TcCoercion -> TcCoercion -> TcCoercion
`mkTransCo` SwapFlag -> TcCoercion -> TcCoercion
maybeSymCo SwapFlag
swapped (TyVar -> TcCoercion
mkCoVarCo TyVar
old_evar)
HasDebugCallStack => TcCoercion -> TcCoercion -> TcCoercion
TcCoercion -> TcCoercion -> TcCoercion
`mkTransCo` TcCoercion
rhs_co)
; GivenCtEvidence -> CtEvidence
GivenCtEvidence -> CtEvidence
CtGiven (GivenCtEvidence -> CtEvidence)
-> TcS GivenCtEvidence -> TcS CtEvidence
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CtLoc -> (PredType, EvTerm) -> TcS GivenCtEvidence
newGivenEv CtLoc
loc (PredType
new_pred, EvTerm
new_tm) }
| CtWanted (WantedCt { ctev_dest :: WantedCtEvidence -> TcEvDest
ctev_dest = TcEvDest
dest, ctev_rewriters :: WantedCtEvidence -> CoHoleSet
ctev_rewriters = CoHoleSet
rewriters }) <- CtEvidence
old_ev
= do { let rewriters' :: CoHoleSet
rewriters' = CoHoleSet
rewriters CoHoleSet -> CoHoleSet -> CoHoleSet
forall a. Semigroup a => a -> a -> a
S.<> CoHoleSet
new_holes
; (new_ev, hole) <- CtLoc
-> CoHoleSet
-> Role
-> PredType
-> PredType
-> TcS (WantedCtEvidence, CoercionHole)
newWantedEq CtLoc
loc CoHoleSet
rewriters' (HasDebugCallStack => CtEvidence -> Role
CtEvidence -> Role
ctEvRewriteRole CtEvidence
old_ev) PredType
nlhs PredType
nrhs
; let co = SwapFlag -> TcCoercion -> TcCoercion
maybeSymCo SwapFlag
swapped (TcCoercion -> TcCoercion) -> TcCoercion -> TcCoercion
forall a b. (a -> b) -> a -> b
$
TcCoercion
lhs_co HasDebugCallStack => TcCoercion -> TcCoercion -> TcCoercion
TcCoercion -> TcCoercion -> TcCoercion
`mkTransCo` CoercionHole -> TcCoercion
mkHoleCo CoercionHole
hole HasDebugCallStack => TcCoercion -> TcCoercion -> TcCoercion
TcCoercion -> TcCoercion -> TcCoercion
`mkTransCo` TcCoercion -> TcCoercion
mkSymCo TcCoercion
rhs_co
; setWantedEq dest (CPH { cph_co = co
, cph_holes = new_holes `mappend` unitCoHoleSet hole })
; traceTcS "rewriteEqEvidence" (vcat [ ppr old_ev
, ppr nlhs
, ppr nrhs
, ppr co
, ppr new_holes ])
; return $ CtWanted new_ev }
where
new_pred :: PredType
new_pred = CtEvidence -> PredType -> PredType -> PredType
mkTcEqPredLikeEv CtEvidence
old_ev PredType
nlhs PredType
nrhs
loc :: CtLoc
loc = CtEvidence -> CtLoc
ctEvLoc CtEvidence
old_ev
rewriteEqEvidenceSwapOnly :: CtEvidence -> EqRel -> SwapFlag -> CanEqLHS -> TcType
-> TcS CtEvidence
rewriteEqEvidenceSwapOnly :: CtEvidence
-> EqRel -> SwapFlag -> CanEqLHS -> PredType -> TcS CtEvidence
rewriteEqEvidenceSwapOnly CtEvidence
ev EqRel
eq_rel SwapFlag
swapped CanEqLHS
lhs PredType
rhs
= CtEvidence
-> SwapFlag
-> Reduction
-> Reduction
-> CoHoleSet
-> TcS CtEvidence
rewriteEqEvidence CtEvidence
ev SwapFlag
swapped
(Role -> PredType -> Reduction
mkReflRedn Role
role (CanEqLHS -> PredType
canEqLHSType CanEqLHS
lhs))
(Role -> PredType -> Reduction
mkReflRedn Role
role PredType
rhs)
CoHoleSet
emptyCoHoleSet
where
role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
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 ()
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 { inerts <- TcS InertCans
getInertCans
; if | Just (ev_i, swapped) <- inertsEqsCanDischarge inerts work_item
-> case ev of
CtGiven {} -> CtEvidence -> String -> TcS (StopOrContinue ())
forall a. CtEvidence -> String -> TcS (StopOrContinue a)
stopWith CtEvidence
ev String
"Given solved from inert"
CtWanted (WantedCt { ctev_dest :: WantedCtEvidence -> TcEvDest
ctev_dest = TcEvDest
dest })
-> do { let co :: TcCoercion
co = 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)
(HasDebugCallStack => CtEvidence -> Role
CtEvidence -> Role
ctEvRewriteRole CtEvidence
ev_i)
(HasDebugCallStack => CtEvidence -> TcCoercion
CtEvidence -> TcCoercion
ctEvCoercion CtEvidence
ev_i)
; HasDebugCallStack => TcEvDest -> CoercionPlusHoles -> TcS ()
TcEvDest -> CoercionPlusHoles -> TcS ()
setWantedEq TcEvDest
dest (CPH { cph_co :: TcCoercion
cph_co = TcCoercion
co
, cph_holes :: CoHoleSet
cph_holes = CtEvidence -> CoHoleSet
ctEvCoHoleSet CtEvidence
ev_i })
; CtEvidence -> String -> TcS (StopOrContinue ())
forall a. CtEvidence -> String -> TcS (StopOrContinue a)
stopWith CtEvidence
ev String
"Wanted solved from inert" }
| otherwise
-> continueWith () }
inertsEqsCanDischarge :: InertCans -> EqCt
-> Maybe ( CtEvidence
, SwapFlag )
inertsEqsCanDischarge :: InertCans -> EqCt -> Maybe (CtEvidence, SwapFlag)
inertsEqsCanDischarge InertCans
inerts (EqCt { eq_lhs :: EqCt -> CanEqLHS
eq_lhs = CanEqLHS
lhs_w, eq_rhs :: EqCt -> PredType
eq_rhs = PredType
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 -> PredType
eq_rhs = PredType
rhs_i
, eq_eq_rel :: EqCt -> EqRel
eq_eq_rel = EqRel
eq_rel }
<- InertCans -> CanEqLHS -> [EqCt]
findEq InertCans
inerts CanEqLHS
lhs_w
, PredType
rhs_i HasDebugCallStack => PredType -> PredType -> Bool
PredType -> PredType -> Bool
`tcEqType` PredType
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 <- PredType -> Maybe CanEqLHS
canEqLHS_maybe PredType
rhs_w
, (CtEvidence
ev_i : [CtEvidence]
_) <- [ CtEvidence
ev_i | EqCt { eq_ev :: EqCt -> CtEvidence
eq_ev = CtEvidence
ev_i, eq_rhs :: EqCt -> PredType
eq_rhs = PredType
rhs_i
, eq_eq_rel :: EqCt -> EqRel
eq_eq_rel = EqRel
eq_rel }
<- InertCans -> CanEqLHS -> [EqCt]
findEq InertCans
inerts CanEqLHS
rhs_lhs
, PredType
rhs_i HasDebugCallStack => PredType -> PredType -> Bool
PredType -> PredType -> Bool
`tcEqType` CanEqLHS -> PredType
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)
empty_rw_w :: Bool
empty_rw_w = CoHoleSet -> Bool
isEmptyCoHoleSet (CtEvidence -> CoHoleSet
ctEvRewriters CtEvidence
ev_w)
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 (CtEvidence -> Bool
prefer_wanted 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)
prefer_wanted :: CtEvidence -> Bool
prefer_wanted CtEvidence
ev_i
= (CtLoc
loc_w CtLoc -> CtLoc -> Bool
`strictly_more_visible` CtEvidence -> CtLoc
ctEvLoc CtEvidence
ev_i)
Bool -> Bool -> Bool
|| (Bool
empty_rw_w Bool -> Bool -> Bool
&& Bool -> Bool
not (CoHoleSet -> Bool
isEmptyCoHoleSet (CtEvidence -> CoHoleSet
ctEvRewriters CtEvidence
ev_i)))
inertsEqsCanDischarge InertCans
_ EqCt
_ = Maybe (CtEvidence, SwapFlag)
forall a. Maybe a
Nothing
tryQCsIrredEqCt :: IrredCt -> SolverStage ()
tryQCsIrredEqCt :: IrredCt -> SolverStage ()
tryQCsIrredEqCt (IrredCt { ir_ev :: IrredCt -> CtEvidence
ir_ev = CtEvidence
ev })
| EqPred EqRel
eq_rel PredType
t1 PredType
t2 <- HasDebugCallStack => PredType -> Pred
PredType -> Pred
classifyPredType (CtEvidence -> PredType
ctEvPred CtEvidence
ev)
= CtEvidence -> EqRel -> PredType -> PredType -> SolverStage ()
lookup_eq_in_qcis CtEvidence
ev EqRel
eq_rel PredType
t1 PredType
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 (EqCt { eq_ev :: EqCt -> CtEvidence
eq_ev = CtEvidence
ev, eq_lhs :: EqCt -> CanEqLHS
eq_lhs = CanEqLHS
lhs, eq_rhs :: EqCt -> PredType
eq_rhs = PredType
rhs, eq_eq_rel :: EqCt -> EqRel
eq_eq_rel = EqRel
eq_rel })
= CtEvidence -> EqRel -> PredType -> PredType -> SolverStage ()
lookup_eq_in_qcis CtEvidence
ev EqRel
eq_rel (CanEqLHS -> PredType
canEqLHSType CanEqLHS
lhs) PredType
rhs
lookup_eq_in_qcis :: CtEvidence -> EqRel -> TcType -> TcType -> SolverStage ()
lookup_eq_in_qcis :: CtEvidence -> EqRel -> PredType -> PredType -> SolverStage ()
lookup_eq_in_qcis (CtGiven {}) EqRel
_ PredType
_ PredType
_
= () -> SolverStage ()
forall a. a -> SolverStage a
nopStage ()
lookup_eq_in_qcis ev :: CtEvidence
ev@(CtWanted (WantedCt { ctev_dest :: WantedCtEvidence -> TcEvDest
ctev_dest = TcEvDest
dest, ctev_loc :: WantedCtEvidence -> CtLoc
ctev_loc = CtLoc
loc })) EqRel
eq_rel PredType
lhs PredType
rhs
= do { ev_binds_var <- TcS EvBindsVar -> SolverStage EvBindsVar
forall a. TcS a -> SolverStage a
simpleStage TcS EvBindsVar
getTcEvBindsVar
; ics <- simpleStage getInertCans
; if null (inert_qcis ics)
|| isCoEvBindsVar ev_binds_var
then nopStage ()
else
do { try NotSwapped; try IsSwapped } }
where
hole :: CoercionHole
hole = case TcEvDest
dest of
HoleDest CoercionHole
hole -> CoercionHole
hole
TcEvDest
_ -> String -> SDoc -> CoercionHole
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"lookup_eq_in_qcis" (TcEvDest -> SDoc
forall a. Outputable a => a -> SDoc
ppr TcEvDest
dest)
try :: SwapFlag -> SolverStage ()
try :: SwapFlag -> SolverStage ()
try SwapFlag
swap
| Just (Class
cls, [PredType]
tys) <- SwapFlag
-> (PredType -> PredType -> Maybe (Class, [PredType]))
-> PredType
-> PredType
-> Maybe (Class, [PredType])
forall a b. SwapFlag -> (a -> a -> b) -> a -> a -> b
unSwap SwapFlag
swap (EqRel -> PredType -> PredType -> Maybe (Class, [PredType])
boxEqPred EqRel
eq_rel) PredType
lhs PredType
rhs
= TcS (StopOrContinue ()) -> SolverStage ()
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 { let cls_pred :: PredType
cls_pred = Class -> [PredType] -> PredType
mkClassPred Class
cls [PredType]
tys
; res <- PredType -> CtLoc -> TcS ClsInstResult
matchLocalInst PredType
cls_pred CtLoc
loc
; traceTcS "lookup_eq_in_qcis:1" (ppr cls_pred)
; case res of
OneInst {}
-> do { dict_ev <- CtLoc -> CoHoleSet -> PredType -> TcS WantedCtEvidence
newWantedEvVarNC CtLoc
loc CoHoleSet
emptyCoHoleSet PredType
cls_pred
; chooseInstance dict_ev res
; co_var <- newEvVar (unSwap swap (mkEqPred eq_rel) lhs rhs)
; setEvBind (mkWantedEvBind co_var EvCanonical (mk_sc_sel cls tys dict_ev))
; fillCoercionHole hole (CPH { cph_co = maybeSymCo swap (mkCoVarCo co_var)
, cph_holes = emptyCoHoleSet })
; stopWith ev "lookup_eq_in_qcis" }
ClsInstResult
_ -> () -> TcS (StopOrContinue ())
forall a. a -> TcS (StopOrContinue a)
continueWith () }
| Bool
otherwise
= () -> SolverStage ()
forall a. a -> SolverStage a
nopStage ()
mk_sc_sel :: Class -> [PredType] -> WantedCtEvidence -> EvTerm
mk_sc_sel Class
cls [PredType]
tys WantedCtEvidence
dict_ev
| [TyVar
sc_id] <- Class -> [TyVar]
classSCSelIds Class
cls
= EvExpr -> EvTerm
EvExpr (TyVar -> EvExpr
forall b. TyVar -> Expr b
Var TyVar
sc_id EvExpr -> [PredType] -> EvExpr
forall b. Expr b -> [PredType] -> Expr b
`mkTyApps` [PredType]
tys EvExpr -> EvExpr -> EvExpr
forall b. Expr b -> Expr b -> Expr b
`App` TyVar -> EvExpr
forall b. TyVar -> Expr b
Var (WantedCtEvidence -> TyVar
wantedCtEvEvId WantedCtEvidence
dict_ev))
| Bool
otherwise
= String -> SDoc -> EvTerm
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"looup_eq_in_qcis" (WantedCtEvidence -> SDoc
forall a. Outputable a => a -> SDoc
ppr WantedCtEvidence
dict_ev)