{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveFunctor #-}
{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}
module GHC.Tc.Solver.Rewrite(
rewrite, rewriteKind, rewriteArgsNom,
rewriteType
) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Core.TyCo.Ppr ( pprTyVar )
import GHC.Tc.Types.Constraint
import GHC.Core.Predicate
import GHC.Tc.Utils.TcType
import GHC.Core.Type
import GHC.Tc.Types.Evidence
import GHC.Core.TyCon
import GHC.Core.TyCo.Rep
import GHC.Core.Coercion
import GHC.Types.Var
import GHC.Types.Var.Set
import GHC.Types.Var.Env
import GHC.Driver.Session
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Tc.Solver.Monad as TcS
import GHC.Utils.Misc
import GHC.Data.Maybe
import GHC.Exts (oneShot)
import Data.Bifunctor
import Control.Monad
import GHC.Utils.Monad ( zipWith3M )
import Data.List.NonEmpty ( NonEmpty(..) )
import Control.Applicative (liftA3)
import GHC.Builtin.Types.Prim (tYPETyCon)
data RewriteEnv
= FE { RewriteEnv -> CtLoc
fe_loc :: !CtLoc
, RewriteEnv -> CtFlavour
fe_flavour :: !CtFlavour
, RewriteEnv -> EqRel
fe_eq_rel :: !EqRel
}
newtype RewriteM a
= RewriteM { forall a. RewriteM a -> RewriteEnv -> TcS a
runRewriteM :: RewriteEnv -> TcS a }
deriving (forall a b. a -> RewriteM b -> RewriteM a
forall a b. (a -> b) -> RewriteM a -> RewriteM b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> RewriteM b -> RewriteM a
$c<$ :: forall a b. a -> RewriteM b -> RewriteM a
fmap :: forall a b. (a -> b) -> RewriteM a -> RewriteM b
$cfmap :: forall a b. (a -> b) -> RewriteM a -> RewriteM b
Functor)
mkRewriteM :: (RewriteEnv -> TcS a) -> RewriteM a
mkRewriteM :: forall a. (RewriteEnv -> TcS a) -> RewriteM a
mkRewriteM RewriteEnv -> TcS a
f = forall a. (RewriteEnv -> TcS a) -> RewriteM a
RewriteM (oneShot :: forall a b. (a -> b) -> a -> b
oneShot RewriteEnv -> TcS a
f)
{-# INLINE mkRewriteM #-}
instance Monad RewriteM where
RewriteM a
m >>= :: forall a b. RewriteM a -> (a -> RewriteM b) -> RewriteM b
>>= a -> RewriteM b
k = forall a. (RewriteEnv -> TcS a) -> RewriteM a
mkRewriteM forall a b. (a -> b) -> a -> b
$ \RewriteEnv
env ->
do { a
a <- forall a. RewriteM a -> RewriteEnv -> TcS a
runRewriteM RewriteM a
m RewriteEnv
env
; forall a. RewriteM a -> RewriteEnv -> TcS a
runRewriteM (a -> RewriteM b
k a
a) RewriteEnv
env }
instance Applicative RewriteM where
pure :: forall a. a -> RewriteM a
pure a
x = forall a. (RewriteEnv -> TcS a) -> RewriteM a
mkRewriteM forall a b. (a -> b) -> a -> b
$ \RewriteEnv
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x
<*> :: forall a b. RewriteM (a -> b) -> RewriteM a -> RewriteM b
(<*>) = forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance HasDynFlags RewriteM where
getDynFlags :: RewriteM DynFlags
getDynFlags = forall a. TcS a -> RewriteM a
liftTcS forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
liftTcS :: TcS a -> RewriteM a
liftTcS :: forall a. TcS a -> RewriteM a
liftTcS TcS a
thing_inside
= forall a. (RewriteEnv -> TcS a) -> RewriteM a
mkRewriteM forall a b. (a -> b) -> a -> b
$ \RewriteEnv
_ -> TcS a
thing_inside
runRewriteCtEv :: CtEvidence -> RewriteM a -> TcS a
runRewriteCtEv :: forall a. CtEvidence -> RewriteM a -> TcS a
runRewriteCtEv CtEvidence
ev
= forall a. CtLoc -> CtFlavour -> EqRel -> RewriteM a -> TcS a
runRewrite (CtEvidence -> CtLoc
ctEvLoc CtEvidence
ev) (CtEvidence -> CtFlavour
ctEvFlavour CtEvidence
ev) (CtEvidence -> EqRel
ctEvEqRel CtEvidence
ev)
runRewrite :: CtLoc -> CtFlavour -> EqRel -> RewriteM a -> TcS a
runRewrite :: forall a. CtLoc -> CtFlavour -> EqRel -> RewriteM a -> TcS a
runRewrite CtLoc
loc CtFlavour
flav EqRel
eq_rel RewriteM a
thing_inside
= forall a. RewriteM a -> RewriteEnv -> TcS a
runRewriteM RewriteM a
thing_inside RewriteEnv
fmode
where
fmode :: RewriteEnv
fmode = FE { fe_loc :: CtLoc
fe_loc = CtLoc
loc
, fe_flavour :: CtFlavour
fe_flavour = CtFlavour
flav
, fe_eq_rel :: EqRel
fe_eq_rel = EqRel
eq_rel }
traceRewriteM :: String -> SDoc -> RewriteM ()
traceRewriteM :: String -> SDoc -> RewriteM ()
traceRewriteM String
herald SDoc
doc = forall a. TcS a -> RewriteM a
liftTcS forall a b. (a -> b) -> a -> b
$ String -> SDoc -> TcS ()
traceTcS String
herald SDoc
doc
{-# INLINE traceRewriteM #-}
getRewriteEnvField :: (RewriteEnv -> a) -> RewriteM a
getRewriteEnvField :: forall a. (RewriteEnv -> a) -> RewriteM a
getRewriteEnvField RewriteEnv -> a
accessor
= forall a. (RewriteEnv -> TcS a) -> RewriteM a
mkRewriteM forall a b. (a -> b) -> a -> b
$ \RewriteEnv
env -> forall (m :: * -> *) a. Monad m => a -> m a
return (RewriteEnv -> a
accessor RewriteEnv
env)
getEqRel :: RewriteM EqRel
getEqRel :: RewriteM EqRel
getEqRel = forall a. (RewriteEnv -> a) -> RewriteM a
getRewriteEnvField RewriteEnv -> EqRel
fe_eq_rel
getRole :: RewriteM Role
getRole :: RewriteM Role
getRole = EqRel -> Role
eqRelRole forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RewriteM EqRel
getEqRel
getFlavour :: RewriteM CtFlavour
getFlavour :: RewriteM CtFlavour
getFlavour = forall a. (RewriteEnv -> a) -> RewriteM a
getRewriteEnvField RewriteEnv -> CtFlavour
fe_flavour
getFlavourRole :: RewriteM CtFlavourRole
getFlavourRole :: RewriteM CtFlavourRole
getFlavourRole
= do { CtFlavour
flavour <- RewriteM CtFlavour
getFlavour
; EqRel
eq_rel <- RewriteM EqRel
getEqRel
; forall (m :: * -> *) a. Monad m => a -> m a
return (CtFlavour
flavour, EqRel
eq_rel) }
getLoc :: RewriteM CtLoc
getLoc :: RewriteM CtLoc
getLoc = forall a. (RewriteEnv -> a) -> RewriteM a
getRewriteEnvField RewriteEnv -> CtLoc
fe_loc
checkStackDepth :: Type -> RewriteM ()
checkStackDepth :: Xi -> RewriteM ()
checkStackDepth Xi
ty
= do { CtLoc
loc <- RewriteM CtLoc
getLoc
; forall a. TcS a -> RewriteM a
liftTcS forall a b. (a -> b) -> a -> b
$ CtLoc -> Xi -> TcS ()
checkReductionDepth CtLoc
loc Xi
ty }
setEqRel :: EqRel -> RewriteM a -> RewriteM a
setEqRel :: forall a. EqRel -> RewriteM a -> RewriteM a
setEqRel EqRel
new_eq_rel RewriteM a
thing_inside
= forall a. (RewriteEnv -> TcS a) -> RewriteM a
mkRewriteM forall a b. (a -> b) -> a -> b
$ \RewriteEnv
env ->
if EqRel
new_eq_rel forall a. Eq a => a -> a -> Bool
== RewriteEnv -> EqRel
fe_eq_rel RewriteEnv
env
then forall a. RewriteM a -> RewriteEnv -> TcS a
runRewriteM RewriteM a
thing_inside RewriteEnv
env
else forall a. RewriteM a -> RewriteEnv -> TcS a
runRewriteM RewriteM a
thing_inside (RewriteEnv
env { fe_eq_rel :: EqRel
fe_eq_rel = EqRel
new_eq_rel })
{-# INLINE setEqRel #-}
noBogusCoercions :: RewriteM a -> RewriteM a
noBogusCoercions :: forall a. RewriteM a -> RewriteM a
noBogusCoercions RewriteM a
thing_inside
= forall a. (RewriteEnv -> TcS a) -> RewriteM a
mkRewriteM forall a b. (a -> b) -> a -> b
$ \RewriteEnv
env ->
let !env' :: RewriteEnv
env' = case RewriteEnv -> CtFlavour
fe_flavour RewriteEnv
env of
CtFlavour
Derived -> RewriteEnv
env { fe_flavour :: CtFlavour
fe_flavour = ShadowInfo -> CtFlavour
Wanted ShadowInfo
WDeriv }
CtFlavour
_ -> RewriteEnv
env
in
forall a. RewriteM a -> RewriteEnv -> TcS a
runRewriteM RewriteM a
thing_inside RewriteEnv
env'
bumpDepth :: RewriteM a -> RewriteM a
bumpDepth :: forall a. RewriteM a -> RewriteM a
bumpDepth (RewriteM RewriteEnv -> TcS a
thing_inside)
= forall a. (RewriteEnv -> TcS a) -> RewriteM a
mkRewriteM forall a b. (a -> b) -> a -> b
$ \RewriteEnv
env -> do
{ let !env' :: RewriteEnv
env' = RewriteEnv
env { fe_loc :: CtLoc
fe_loc = CtLoc -> CtLoc
bumpCtLocDepth (RewriteEnv -> CtLoc
fe_loc RewriteEnv
env) }
; RewriteEnv -> TcS a
thing_inside RewriteEnv
env' }
rewrite :: CtEvidence -> TcType
-> TcS (Xi, TcCoercion)
rewrite :: CtEvidence -> Xi -> TcS (Xi, TcCoercionN)
rewrite CtEvidence
ev Xi
ty
= do { String -> SDoc -> TcS ()
traceTcS String
"rewrite {" (forall a. Outputable a => a -> SDoc
ppr Xi
ty)
; (Xi
ty', TcCoercionN
co) <- forall a. CtEvidence -> RewriteM a -> TcS a
runRewriteCtEv CtEvidence
ev (Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
ty)
; String -> SDoc -> TcS ()
traceTcS String
"rewrite }" (forall a. Outputable a => a -> SDoc
ppr Xi
ty')
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi
ty', TcCoercionN
co) }
rewriteKind :: CtLoc -> CtFlavour -> TcType -> TcS (Xi, TcCoercionN)
rewriteKind :: CtLoc -> CtFlavour -> Xi -> TcS (Xi, TcCoercionN)
rewriteKind CtLoc
loc CtFlavour
flav Xi
ty
= do { String -> SDoc -> TcS ()
traceTcS String
"rewriteKind {" (forall a. Outputable a => a -> SDoc
ppr CtFlavour
flav SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Xi
ty)
; let flav' :: CtFlavour
flav' = case CtFlavour
flav of
CtFlavour
Derived -> ShadowInfo -> CtFlavour
Wanted ShadowInfo
WDeriv
CtFlavour
_ -> CtFlavour
flav
; (Xi
ty', TcCoercionN
co) <- forall a. CtLoc -> CtFlavour -> EqRel -> RewriteM a -> TcS a
runRewrite CtLoc
loc CtFlavour
flav' EqRel
NomEq (Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
ty)
; String -> SDoc -> TcS ()
traceTcS String
"rewriteKind }" (forall a. Outputable a => a -> SDoc
ppr Xi
ty' SDoc -> SDoc -> SDoc
$$ forall a. Outputable a => a -> SDoc
ppr TcCoercionN
co)
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi
ty', TcCoercionN
co) }
rewriteArgsNom :: CtEvidence -> TyCon -> [TcType] -> TcS ([Xi], [TcCoercion])
rewriteArgsNom :: CtEvidence -> TyCon -> [Xi] -> TcS ([Xi], [TcCoercionN])
rewriteArgsNom CtEvidence
ev TyCon
tc [Xi]
tys
= do { String -> SDoc -> TcS ()
traceTcS String
"rewrite_args {" ([SDoc] -> SDoc
vcat (forall a b. (a -> b) -> [a] -> [b]
map forall a. Outputable a => a -> SDoc
ppr [Xi]
tys))
; ([Xi]
tys', [TcCoercionN]
cos, MCoercionN
kind_co)
<- forall a. CtEvidence -> RewriteM a -> TcS a
runRewriteCtEv CtEvidence
ev (TyCon
-> Maybe [Role]
-> [Xi]
-> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args_tc TyCon
tc forall a. Maybe a
Nothing [Xi]
tys)
; MASSERT( isReflMCo kind_co )
; String -> SDoc -> TcS ()
traceTcS String
"rewrite }" ([SDoc] -> SDoc
vcat (forall a b. (a -> b) -> [a] -> [b]
map forall a. Outputable a => a -> SDoc
ppr [Xi]
tys'))
; forall (m :: * -> *) a. Monad m => a -> m a
return ([Xi]
tys', [TcCoercionN]
cos) }
rewriteType :: CtLoc -> TcType -> TcS TcType
rewriteType :: CtLoc -> Xi -> TcS Xi
rewriteType CtLoc
loc Xi
ty
= do { (Xi
xi, TcCoercionN
_) <- forall a. CtLoc -> CtFlavour -> EqRel -> RewriteM a -> TcS a
runRewrite CtLoc
loc CtFlavour
Given EqRel
NomEq forall a b. (a -> b) -> a -> b
$
Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
ty
; forall (m :: * -> *) a. Monad m => a -> m a
return Xi
xi }
{-# INLINE rewrite_args_tc #-}
rewrite_args_tc
:: TyCon
-> Maybe [Role]
-> [Type]
-> RewriteM ( [Xi]
, [Coercion]
, MCoercionN)
rewrite_args_tc :: TyCon
-> Maybe [Role]
-> [Xi]
-> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args_tc TyCon
tc = [TyCoBinder]
-> Bool
-> Xi
-> TcTyCoVarSet
-> Maybe [Role]
-> [Xi]
-> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args [TyCoBinder]
all_bndrs Bool
any_named_bndrs Xi
inner_ki TcTyCoVarSet
emptyVarSet
where
([TyCoBinder]
bndrs, Bool
named)
= [TyConBinder] -> ([TyCoBinder], Bool)
ty_con_binders_ty_binders' (TyCon -> [TyConBinder]
tyConBinders TyCon
tc)
([TyCoBinder]
inner_bndrs, Xi
inner_ki, Bool
inner_named) = Xi -> ([TyCoBinder], Xi, Bool)
split_pi_tys' (TyCon -> Xi
tyConResKind TyCon
tc)
!all_bndrs :: [TyCoBinder]
all_bndrs = [TyCoBinder]
bndrs forall a. [a] -> [a] -> [a]
`chkAppend` [TyCoBinder]
inner_bndrs
!any_named_bndrs :: Bool
any_named_bndrs = Bool
named Bool -> Bool -> Bool
|| Bool
inner_named
{-# INLINE rewrite_args #-}
rewrite_args :: [TyCoBinder] -> Bool
-> Kind -> TcTyCoVarSet
-> Maybe [Role] -> [Type]
-> RewriteM ([Xi], [Coercion], MCoercionN)
rewrite_args :: [TyCoBinder]
-> Bool
-> Xi
-> TcTyCoVarSet
-> Maybe [Role]
-> [Xi]
-> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args [TyCoBinder]
orig_binders
Bool
any_named_bndrs
Xi
orig_inner_ki
TcTyCoVarSet
orig_fvs
Maybe [Role]
orig_m_roles
[Xi]
orig_tys
= case (Maybe [Role]
orig_m_roles, Bool
any_named_bndrs) of
(Maybe [Role]
Nothing, Bool
False) -> [Xi] -> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args_fast [Xi]
orig_tys
(Maybe [Role], Bool)
_ -> [TyCoBinder]
-> Xi
-> TcTyCoVarSet
-> [Role]
-> [Xi]
-> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args_slow [TyCoBinder]
orig_binders Xi
orig_inner_ki TcTyCoVarSet
orig_fvs [Role]
orig_roles [Xi]
orig_tys
where orig_roles :: [Role]
orig_roles = forall a. a -> Maybe a -> a
fromMaybe (forall a. a -> [a]
repeat Role
Nominal) Maybe [Role]
orig_m_roles
{-# INLINE rewrite_args_fast #-}
rewrite_args_fast :: [Type]
-> RewriteM ([Xi], [Coercion], MCoercionN)
rewrite_args_fast :: [Xi] -> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args_fast [Xi]
orig_tys
= forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Xi], [TcCoercionN]) -> ([Xi], [TcCoercionN], MCoercionN)
finish ([Xi] -> RewriteM ([Xi], [TcCoercionN])
iterate [Xi]
orig_tys)
where
iterate :: [Type]
-> RewriteM ([Xi], [Coercion])
iterate :: [Xi] -> RewriteM ([Xi], [TcCoercionN])
iterate (Xi
ty:[Xi]
tys) = do
(Xi
xi, TcCoercionN
co) <- Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
ty
([Xi]
xis, [TcCoercionN]
cos) <- [Xi] -> RewriteM ([Xi], [TcCoercionN])
iterate [Xi]
tys
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Xi
xi forall a. a -> [a] -> [a]
: [Xi]
xis, TcCoercionN
co forall a. a -> [a] -> [a]
: [TcCoercionN]
cos)
iterate [] = forall (f :: * -> *) a. Applicative f => a -> f a
pure ([], [])
{-# INLINE finish #-}
finish :: ([Xi], [Coercion]) -> ([Xi], [Coercion], MCoercionN)
finish :: ([Xi], [TcCoercionN]) -> ([Xi], [TcCoercionN], MCoercionN)
finish ([Xi]
xis, [TcCoercionN]
cos) = ([Xi]
xis, [TcCoercionN]
cos, MCoercionN
MRefl)
{-# INLINE rewrite_args_slow #-}
rewrite_args_slow :: [TyCoBinder] -> Kind -> TcTyCoVarSet
-> [Role] -> [Type]
-> RewriteM ([Xi], [Coercion], MCoercionN)
rewrite_args_slow :: [TyCoBinder]
-> Xi
-> TcTyCoVarSet
-> [Role]
-> [Xi]
-> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args_slow [TyCoBinder]
binders Xi
inner_ki TcTyCoVarSet
fvs [Role]
roles [Xi]
tys
= do { [(Xi, TcCoercionN)]
rewritten_args <- forall (m :: * -> *) a b c d.
Monad m =>
(a -> b -> c -> m d) -> [a] -> [b] -> [c] -> m [d]
zipWith3M Bool -> Role -> Xi -> RewriteM (Xi, TcCoercionN)
rw (forall a b. (a -> b) -> [a] -> [b]
map TyCoBinder -> Bool
isNamedBinder [TyCoBinder]
binders forall a. [a] -> [a] -> [a]
++ forall a. a -> [a]
repeat Bool
True)
[Role]
roles [Xi]
tys
; forall (m :: * -> *) a. Monad m => a -> m a
return ([TyCoBinder]
-> Xi
-> TcTyCoVarSet
-> [Role]
-> [(Xi, TcCoercionN)]
-> ([Xi], [TcCoercionN], MCoercionN)
simplifyArgsWorker [TyCoBinder]
binders Xi
inner_ki TcTyCoVarSet
fvs [Role]
roles [(Xi, TcCoercionN)]
rewritten_args) }
where
{-# INLINE rw #-}
rw :: Bool
-> Role -> Type -> RewriteM (Xi, Coercion)
rw :: Bool -> Role -> Xi -> RewriteM (Xi, TcCoercionN)
rw Bool
True Role
r Xi
ty = forall a. RewriteM a -> RewriteM a
noBogusCoercions forall a b. (a -> b) -> a -> b
$ Role -> Xi -> RewriteM (Xi, TcCoercionN)
rw1 Role
r Xi
ty
rw Bool
False Role
r Xi
ty = Role -> Xi -> RewriteM (Xi, TcCoercionN)
rw1 Role
r Xi
ty
{-# INLINE rw1 #-}
rw1 :: Role -> Type -> RewriteM (Xi, Coercion)
rw1 :: Role -> Xi -> RewriteM (Xi, TcCoercionN)
rw1 Role
Nominal Xi
ty
= forall a. EqRel -> RewriteM a -> RewriteM a
setEqRel EqRel
NomEq forall a b. (a -> b) -> a -> b
$
Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
ty
rw1 Role
Representational Xi
ty
= forall a. EqRel -> RewriteM a -> RewriteM a
setEqRel EqRel
ReprEq forall a b. (a -> b) -> a -> b
$
Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
ty
rw1 Role
Phantom Xi
ty
= do { Xi
ty <- forall a. TcS a -> RewriteM a
liftTcS forall a b. (a -> b) -> a -> b
$ Xi -> TcS Xi
zonkTcType Xi
ty
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi
ty, Role -> Xi -> TcCoercionN
mkReflCo Role
Phantom Xi
ty) }
rewrite_one :: TcType -> RewriteM (Xi, Coercion)
rewrite_one :: Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
ty
| Just Xi
ty' <- Xi -> Maybe Xi
rewriterView Xi
ty
= Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
ty'
rewrite_one xi :: Xi
xi@(LitTy {})
= do { Role
role <- RewriteM Role
getRole
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi
xi, Role -> Xi -> TcCoercionN
mkReflCo Role
role Xi
xi) }
rewrite_one (TyVarTy TcTyVar
tv)
= TcTyVar -> RewriteM (Xi, TcCoercionN)
rewriteTyVar TcTyVar
tv
rewrite_one (AppTy Xi
ty1 Xi
ty2)
= Xi -> [Xi] -> RewriteM (Xi, TcCoercionN)
rewrite_app_tys Xi
ty1 [Xi
ty2]
rewrite_one (TyConApp TyCon
tc [Xi]
tys)
| TyCon -> Bool
isTypeFamilyTyCon TyCon
tc
= TyCon -> [Xi] -> RewriteM (Xi, TcCoercionN)
rewrite_fam_app TyCon
tc [Xi]
tys
| Bool
otherwise
= TyCon -> [Xi] -> RewriteM (Xi, TcCoercionN)
rewrite_ty_con_app TyCon
tc [Xi]
tys
rewrite_one (FunTy { ft_af :: Xi -> AnonArgFlag
ft_af = AnonArgFlag
vis, ft_mult :: Xi -> Xi
ft_mult = Xi
mult, ft_arg :: Xi -> Xi
ft_arg = Xi
ty1, ft_res :: Xi -> Xi
ft_res = Xi
ty2 })
= do { (Xi
arg_xi,TcCoercionN
arg_co) <- Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
ty1
; (Xi
res_xi,TcCoercionN
res_co) <- Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
ty2
; let arg_rep :: Xi
arg_rep = HasDebugCallStack => Xi -> Xi
getRuntimeRep Xi
arg_xi
res_rep :: Xi
res_rep = HasDebugCallStack => Xi -> Xi
getRuntimeRep Xi
res_xi
; ((Xi, TcCoercionN)
w_redn, (Xi, TcCoercionN)
arg_rep_redn, (Xi, TcCoercionN)
res_rep_redn) <- forall a. EqRel -> RewriteM a -> RewriteM a
setEqRel EqRel
NomEq forall a b. (a -> b) -> a -> b
$
forall (f :: * -> *) a b c d.
Applicative f =>
(a -> b -> c -> d) -> f a -> f b -> f c -> f d
liftA3 (,,) (Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
mult)
(Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
arg_rep)
(Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
res_rep)
; Role
role <- RewriteM Role
getRole
; let arg_rep_co :: TcCoercionN
arg_rep_co = TcCoercionN -> TcCoercionN
mkSymCo (forall a b. (a, b) -> b
snd (Xi, TcCoercionN)
arg_rep_redn)
arg_ki_co :: TcCoercionN
arg_ki_co = HasDebugCallStack => Role -> TyCon -> [TcCoercionN] -> TcCoercionN
mkTyConAppCo Role
Nominal TyCon
tYPETyCon [TcCoercionN
arg_rep_co]
casted_arg_redn :: (Xi, TcCoercionN)
casted_arg_redn =
( Xi -> TcCoercionN -> Xi
mkCastTy Xi
arg_xi TcCoercionN
arg_ki_co
, Role -> Xi -> TcCoercionN -> TcCoercionN -> TcCoercionN
mkCoherenceLeftCo Role
role Xi
arg_xi TcCoercionN
arg_ki_co TcCoercionN
arg_co
)
res_ki_co :: TcCoercionN
res_ki_co = HasDebugCallStack => Role -> TyCon -> [TcCoercionN] -> TcCoercionN
mkTyConAppCo Role
Nominal TyCon
tYPETyCon [TcCoercionN -> TcCoercionN
mkSymCo forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> b
snd (Xi, TcCoercionN)
res_rep_redn]
casted_res_redn :: (Xi, TcCoercionN)
casted_res_redn =
( Xi -> TcCoercionN -> Xi
mkCastTy Xi
res_xi TcCoercionN
res_ki_co
, Role -> Xi -> TcCoercionN -> TcCoercionN -> TcCoercionN
mkCoherenceLeftCo Role
role Xi
res_xi TcCoercionN
res_ki_co TcCoercionN
res_co
)
; forall (m :: * -> *) a. Monad m => a -> m a
return
( AnonArgFlag -> Xi -> Xi -> Xi -> Xi
mkFunTy AnonArgFlag
vis (forall a b. (a, b) -> a
fst (Xi, TcCoercionN)
w_redn) (forall a b. (a, b) -> a
fst (Xi, TcCoercionN)
casted_arg_redn) (forall a b. (a, b) -> a
fst (Xi, TcCoercionN)
casted_res_redn)
, Role -> TcCoercionN -> TcCoercionN -> TcCoercionN -> TcCoercionN
mkFunCo Role
role (forall a b. (a, b) -> b
snd (Xi, TcCoercionN)
w_redn) (forall a b. (a, b) -> b
snd (Xi, TcCoercionN)
casted_arg_redn) (forall a b. (a, b) -> b
snd (Xi, TcCoercionN)
casted_res_redn)
)
}
rewrite_one ty :: Xi
ty@(ForAllTy {})
= do { let ([TyVarBinder]
bndrs, Xi
rho) = Xi -> ([TyVarBinder], Xi)
tcSplitForAllTyVarBinders Xi
ty
tvs :: [TcTyVar]
tvs = forall tv argf. [VarBndr tv argf] -> [tv]
binderVars [TyVarBinder]
bndrs
; (Xi
rho', TcCoercionN
co) <- Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
rho
; forall (m :: * -> *) a. Monad m => a -> m a
return ([TyVarBinder] -> Xi -> Xi
mkForAllTys [TyVarBinder]
bndrs Xi
rho', [TcTyVar] -> TcCoercionN -> TcCoercionN
mkHomoForAllCos [TcTyVar]
tvs TcCoercionN
co) }
rewrite_one (CastTy Xi
ty TcCoercionN
g)
= do { (Xi
xi, TcCoercionN
co) <- Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
ty
; (TcCoercionN
g', TcCoercionN
_) <- TcCoercionN -> RewriteM (TcCoercionN, TcCoercionN)
rewrite_co TcCoercionN
g
; Role
role <- RewriteM Role
getRole
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi -> TcCoercionN -> Xi
mkCastTy Xi
xi TcCoercionN
g', TcCoercionN -> Role -> Xi -> Xi -> TcCoercionN -> TcCoercionN
castCoercionKind1 TcCoercionN
co Role
role Xi
xi Xi
ty TcCoercionN
g') }
rewrite_one (CoercionTy TcCoercionN
co) = forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first TcCoercionN -> Xi
mkCoercionTy forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TcCoercionN -> RewriteM (TcCoercionN, TcCoercionN)
rewrite_co TcCoercionN
co
rewrite_co :: Coercion -> RewriteM (Coercion, Coercion)
rewrite_co :: TcCoercionN -> RewriteM (TcCoercionN, TcCoercionN)
rewrite_co TcCoercionN
co
= do { TcCoercionN
co <- forall a. TcS a -> RewriteM a
liftTcS forall a b. (a -> b) -> a -> b
$ TcCoercionN -> TcS TcCoercionN
zonkCo TcCoercionN
co
; Role
env_role <- RewriteM Role
getRole
; let co' :: TcCoercionN
co' = Role -> Xi -> TcCoercionN
mkTcReflCo Role
env_role (TcCoercionN -> Xi
mkCoercionTy TcCoercionN
co)
; forall (m :: * -> *) a. Monad m => a -> m a
return (TcCoercionN
co, TcCoercionN
co') }
rewrite_app_tys :: Type -> [Type] -> RewriteM (Xi, Coercion)
rewrite_app_tys :: Xi -> [Xi] -> RewriteM (Xi, TcCoercionN)
rewrite_app_tys (AppTy Xi
ty1 Xi
ty2) [Xi]
tys = Xi -> [Xi] -> RewriteM (Xi, TcCoercionN)
rewrite_app_tys Xi
ty1 (Xi
ty2forall a. a -> [a] -> [a]
:[Xi]
tys)
rewrite_app_tys Xi
fun_ty [Xi]
arg_tys
= do { (Xi
fun_xi, TcCoercionN
fun_co) <- Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
fun_ty
; Xi -> TcCoercionN -> [Xi] -> RewriteM (Xi, TcCoercionN)
rewrite_app_ty_args Xi
fun_xi TcCoercionN
fun_co [Xi]
arg_tys }
rewrite_app_ty_args :: Xi -> Coercion -> [Type] -> RewriteM (Xi, Coercion)
rewrite_app_ty_args :: Xi -> TcCoercionN -> [Xi] -> RewriteM (Xi, TcCoercionN)
rewrite_app_ty_args Xi
fun_xi TcCoercionN
fun_co []
= forall (m :: * -> *) a. Monad m => a -> m a
return (Xi
fun_xi, TcCoercionN
fun_co)
rewrite_app_ty_args Xi
fun_xi TcCoercionN
fun_co [Xi]
arg_tys
= do { (Xi
xi, TcCoercionN
co, MCoercionN
kind_co) <- case HasCallStack => Xi -> Maybe (TyCon, [Xi])
tcSplitTyConApp_maybe Xi
fun_xi of
Just (TyCon
tc, [Xi]
xis) ->
do { let tc_roles :: [Role]
tc_roles = TyCon -> [Role]
tyConRolesRepresentational TyCon
tc
arg_roles :: [Role]
arg_roles = forall b a. [b] -> [a] -> [a]
dropList [Xi]
xis [Role]
tc_roles
; ([Xi]
arg_xis, [TcCoercionN]
arg_cos, MCoercionN
kind_co)
<- Xi -> [Role] -> [Xi] -> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_vector (HasDebugCallStack => Xi -> Xi
tcTypeKind Xi
fun_xi) [Role]
arg_roles [Xi]
arg_tys
; EqRel
eq_rel <- RewriteM EqRel
getEqRel
; let app_xi :: Xi
app_xi = TyCon -> [Xi] -> Xi
mkTyConApp TyCon
tc ([Xi]
xis forall a. [a] -> [a] -> [a]
++ [Xi]
arg_xis)
app_co :: TcCoercionN
app_co = case EqRel
eq_rel of
EqRel
NomEq -> TcCoercionN -> [TcCoercionN] -> TcCoercionN
mkAppCos TcCoercionN
fun_co [TcCoercionN]
arg_cos
EqRel
ReprEq -> Role -> TyCon -> [TcCoercionN] -> TcCoercionN
mkTcTyConAppCo Role
Representational TyCon
tc
(forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Role -> Xi -> TcCoercionN
mkReflCo [Role]
tc_roles [Xi]
xis forall a. [a] -> [a] -> [a]
++ [TcCoercionN]
arg_cos)
TcCoercionN -> TcCoercionN -> TcCoercionN
`mkTcTransCo`
TcCoercionN -> [TcCoercionN] -> TcCoercionN
mkAppCos TcCoercionN
fun_co (forall a b. (a -> b) -> [a] -> [b]
map Xi -> TcCoercionN
mkNomReflCo [Xi]
arg_tys)
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi
app_xi, TcCoercionN
app_co, MCoercionN
kind_co) }
Maybe (TyCon, [Xi])
Nothing ->
do { ([Xi]
arg_xis, [TcCoercionN]
arg_cos, MCoercionN
kind_co)
<- Xi -> [Role] -> [Xi] -> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_vector (HasDebugCallStack => Xi -> Xi
tcTypeKind Xi
fun_xi) (forall a. a -> [a]
repeat Role
Nominal) [Xi]
arg_tys
; let arg_xi :: Xi
arg_xi = Xi -> [Xi] -> Xi
mkAppTys Xi
fun_xi [Xi]
arg_xis
arg_co :: TcCoercionN
arg_co = TcCoercionN -> [TcCoercionN] -> TcCoercionN
mkAppCos TcCoercionN
fun_co [TcCoercionN]
arg_cos
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi
arg_xi, TcCoercionN
arg_co, MCoercionN
kind_co) }
; Role
role <- RewriteM Role
getRole
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi -> TcCoercionN -> Role -> MCoercionN -> (Xi, TcCoercionN)
homogenise_result Xi
xi TcCoercionN
co Role
role MCoercionN
kind_co) }
rewrite_ty_con_app :: TyCon -> [TcType] -> RewriteM (Xi, Coercion)
rewrite_ty_con_app :: TyCon -> [Xi] -> RewriteM (Xi, TcCoercionN)
rewrite_ty_con_app TyCon
tc [Xi]
tys
= do { Role
role <- RewriteM Role
getRole
; let m_roles :: Maybe [Role]
m_roles | Role
Nominal <- Role
role = forall a. Maybe a
Nothing
| Bool
otherwise = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Role -> TyCon -> [Role]
tyConRolesX Role
role TyCon
tc
; ([Xi]
xis, [TcCoercionN]
cos, MCoercionN
kind_co) <- TyCon
-> Maybe [Role]
-> [Xi]
-> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args_tc TyCon
tc Maybe [Role]
m_roles [Xi]
tys
; let tyconapp_xi :: Xi
tyconapp_xi = TyCon -> [Xi] -> Xi
mkTyConApp TyCon
tc [Xi]
xis
tyconapp_co :: TcCoercionN
tyconapp_co = HasDebugCallStack => Role -> TyCon -> [TcCoercionN] -> TcCoercionN
mkTyConAppCo Role
role TyCon
tc [TcCoercionN]
cos
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi -> TcCoercionN -> Role -> MCoercionN -> (Xi, TcCoercionN)
homogenise_result Xi
tyconapp_xi TcCoercionN
tyconapp_co Role
role MCoercionN
kind_co) }
homogenise_result :: Xi
-> Coercion
-> Role
-> MCoercionN
-> (Xi, Coercion)
homogenise_result :: Xi -> TcCoercionN -> Role -> MCoercionN -> (Xi, TcCoercionN)
homogenise_result Xi
xi TcCoercionN
co Role
_ MCoercionN
MRefl = (Xi
xi, TcCoercionN
co)
homogenise_result Xi
xi TcCoercionN
co Role
r mco :: MCoercionN
mco@(MCo TcCoercionN
kind_co)
= (Xi
xi Xi -> TcCoercionN -> Xi
`mkCastTy` TcCoercionN
kind_co, (TcCoercionN -> TcCoercionN
mkSymCo forall a b. (a -> b) -> a -> b
$ Role -> Xi -> MCoercionN -> TcCoercionN
GRefl Role
r Xi
xi MCoercionN
mco) TcCoercionN -> TcCoercionN -> TcCoercionN
`mkTransCo` TcCoercionN
co)
{-# INLINE homogenise_result #-}
rewrite_vector :: Kind
-> [Role]
-> [Type]
-> RewriteM ([Xi], [Coercion], MCoercionN)
rewrite_vector :: Xi -> [Role] -> [Xi] -> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_vector Xi
ki [Role]
roles [Xi]
tys
= do { EqRel
eq_rel <- RewriteM EqRel
getEqRel
; case EqRel
eq_rel of
EqRel
NomEq -> [TyCoBinder]
-> Bool
-> Xi
-> TcTyCoVarSet
-> Maybe [Role]
-> [Xi]
-> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args [TyCoBinder]
bndrs
Bool
any_named_bndrs
Xi
inner_ki
TcTyCoVarSet
fvs
forall a. Maybe a
Nothing
[Xi]
tys
EqRel
ReprEq -> [TyCoBinder]
-> Bool
-> Xi
-> TcTyCoVarSet
-> Maybe [Role]
-> [Xi]
-> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args [TyCoBinder]
bndrs
Bool
any_named_bndrs
Xi
inner_ki
TcTyCoVarSet
fvs
(forall a. a -> Maybe a
Just [Role]
roles)
[Xi]
tys
}
where
([TyCoBinder]
bndrs, Xi
inner_ki, Bool
any_named_bndrs) = Xi -> ([TyCoBinder], Xi, Bool)
split_pi_tys' Xi
ki
fvs :: TcTyCoVarSet
fvs = Xi -> TcTyCoVarSet
tyCoVarsOfType Xi
ki
{-# INLINE rewrite_vector #-}
rewrite_fam_app :: TyCon -> [TcType] -> RewriteM (Xi, Coercion)
rewrite_fam_app :: TyCon -> [Xi] -> RewriteM (Xi, TcCoercionN)
rewrite_fam_app TyCon
tc [Xi]
tys
= ASSERT2( tys `lengthAtLeast` tyConArity tc
, ppr tc $$ ppr (tyConArity tc) $$ ppr tys)
do { let ([Xi]
tys1, [Xi]
tys_rest) = forall a. Arity -> [a] -> ([a], [a])
splitAt (TyCon -> Arity
tyConArity TyCon
tc) [Xi]
tys
; (Xi
xi1, TcCoercionN
co1) <- TyCon -> [Xi] -> RewriteM (Xi, TcCoercionN)
rewrite_exact_fam_app TyCon
tc [Xi]
tys1
; Xi -> TcCoercionN -> [Xi] -> RewriteM (Xi, TcCoercionN)
rewrite_app_ty_args Xi
xi1 TcCoercionN
co1 [Xi]
tys_rest }
rewrite_exact_fam_app :: TyCon -> [TcType] -> RewriteM (Xi, Coercion)
rewrite_exact_fam_app :: TyCon -> [Xi] -> RewriteM (Xi, TcCoercionN)
rewrite_exact_fam_app TyCon
tc [Xi]
tys
= do { Xi -> RewriteM ()
checkStackDepth (TyCon -> [Xi] -> Xi
mkTyConApp TyCon
tc [Xi]
tys)
; Maybe (TcCoercionN, Xi)
result1 <- TyCon -> [Xi] -> RewriteM (Maybe (TcCoercionN, Xi))
try_to_reduce TyCon
tc [Xi]
tys
; case Maybe (TcCoercionN, Xi)
result1 of
{ Just (TcCoercionN
co, Xi
xi) -> Bool -> (Xi, TcCoercionN) -> RewriteM (Xi, TcCoercionN)
finish Bool
False (Xi
xi, TcCoercionN
co)
; Maybe (TcCoercionN, Xi)
Nothing ->
do { EqRel
eq_rel <- RewriteM EqRel
getEqRel
; ([Xi]
xis, [TcCoercionN]
cos, MCoercionN
kind_co) <- if EqRel
eq_rel forall a. Eq a => a -> a -> Bool
== EqRel
NomEq
then TyCon
-> Maybe [Role]
-> [Xi]
-> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args_tc TyCon
tc forall a. Maybe a
Nothing [Xi]
tys
else forall a. EqRel -> RewriteM a -> RewriteM a
setEqRel EqRel
NomEq forall a b. (a -> b) -> a -> b
$
TyCon
-> Maybe [Role]
-> [Xi]
-> RewriteM ([Xi], [TcCoercionN], MCoercionN)
rewrite_args_tc TyCon
tc forall a. Maybe a
Nothing [Xi]
tys
; let role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
args_co :: TcCoercionN
args_co = HasDebugCallStack => Role -> TyCon -> [TcCoercionN] -> TcCoercionN
mkTyConAppCo Role
role TyCon
tc [TcCoercionN]
cos
homogenise :: TcType -> TcCoercion -> (TcType, TcCoercion)
homogenise :: Xi -> TcCoercionN -> (Xi, TcCoercionN)
homogenise Xi
xi TcCoercionN
co = Xi -> TcCoercionN -> Role -> MCoercionN -> (Xi, TcCoercionN)
homogenise_result Xi
xi (TcCoercionN
co TcCoercionN -> TcCoercionN -> TcCoercionN
`mkTcTransCo` TcCoercionN
args_co) Role
role MCoercionN
kind_co
; Maybe (TcCoercionN, Xi, CtFlavourRole)
result2 <- forall a. TcS a -> RewriteM a
liftTcS forall a b. (a -> b) -> a -> b
$ TyCon -> [Xi] -> TcS (Maybe (TcCoercionN, Xi, CtFlavourRole))
lookupFamAppInert TyCon
tc [Xi]
xis
; CtFlavour
flavour <- RewriteM CtFlavour
getFlavour
; case Maybe (TcCoercionN, Xi, CtFlavourRole)
result2 of
{ Just (TcCoercionN
co, Xi
xi, fr :: CtFlavourRole
fr@(CtFlavour
_, EqRel
inert_eq_rel))
| CtFlavourRole
fr CtFlavourRole -> CtFlavourRole -> Bool
`eqCanRewriteFR` (CtFlavour
flavour, EqRel
eq_rel) ->
do { String -> SDoc -> RewriteM ()
traceRewriteM String
"rewrite family application with inert"
(forall a. Outputable a => a -> SDoc
ppr TyCon
tc SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr [Xi]
xis SDoc -> SDoc -> SDoc
$$ forall a. Outputable a => a -> SDoc
ppr Xi
xi)
; Bool -> (Xi, TcCoercionN) -> RewriteM (Xi, TcCoercionN)
finish Bool
True (Xi -> TcCoercionN -> (Xi, TcCoercionN)
homogenise Xi
xi TcCoercionN
downgraded_co) }
where
inert_role :: Role
inert_role = EqRel -> Role
eqRelRole EqRel
inert_eq_rel
role :: Role
role = EqRel -> Role
eqRelRole EqRel
eq_rel
downgraded_co :: TcCoercionN
downgraded_co = Role -> Role -> TcCoercionN -> TcCoercionN
tcDowngradeRole Role
role Role
inert_role (TcCoercionN -> TcCoercionN
mkTcSymCo TcCoercionN
co)
; Maybe (TcCoercionN, Xi, CtFlavourRole)
_ ->
do { Maybe (TcCoercionN, Xi)
result3 <- TyCon -> [Xi] -> RewriteM (Maybe (TcCoercionN, Xi))
try_to_reduce TyCon
tc [Xi]
xis
; case Maybe (TcCoercionN, Xi)
result3 of
Just (TcCoercionN
co, Xi
xi) -> Bool -> (Xi, TcCoercionN) -> RewriteM (Xi, TcCoercionN)
finish Bool
True (Xi -> TcCoercionN -> (Xi, TcCoercionN)
homogenise Xi
xi TcCoercionN
co)
Maybe (TcCoercionN, Xi)
Nothing ->
forall (m :: * -> *) a. Monad m => a -> m a
return (Xi -> TcCoercionN -> (Xi, TcCoercionN)
homogenise Xi
reduced (Role -> Xi -> TcCoercionN
mkTcReflCo Role
role Xi
reduced))
where
reduced :: Xi
reduced = TyCon -> [Xi] -> Xi
mkTyConApp TyCon
tc [Xi]
xis }}}}}
where
finish :: Bool
-> (Xi, Coercion) -> RewriteM (Xi, Coercion)
finish :: Bool -> (Xi, TcCoercionN) -> RewriteM (Xi, TcCoercionN)
finish Bool
use_cache (Xi
xi, TcCoercionN
co)
= do {
(Xi
fully, TcCoercionN
fully_co) <- forall a. RewriteM a -> RewriteM a
bumpDepth forall a b. (a -> b) -> a -> b
$ Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
xi
; let final_co :: TcCoercionN
final_co = TcCoercionN
fully_co TcCoercionN -> TcCoercionN -> TcCoercionN
`mkTcTransCo` TcCoercionN
co
; EqRel
eq_rel <- RewriteM EqRel
getEqRel
; CtFlavour
flavour <- RewriteM CtFlavour
getFlavour
; forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
use_cache Bool -> Bool -> Bool
&& EqRel
eq_rel forall a. Eq a => a -> a -> Bool
== EqRel
NomEq Bool -> Bool -> Bool
&& CtFlavour
flavour forall a. Eq a => a -> a -> Bool
/= CtFlavour
Derived) forall a b. (a -> b) -> a -> b
$
forall a. TcS a -> RewriteM a
liftTcS forall a b. (a -> b) -> a -> b
$ TyCon -> [Xi] -> (TcCoercionN, Xi) -> TcS ()
extendFamAppCache TyCon
tc [Xi]
tys (TcCoercionN
final_co, Xi
fully)
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi
fully, TcCoercionN
final_co) }
{-# INLINE finish #-}
try_to_reduce :: TyCon -> [TcType] -> RewriteM (Maybe (TcCoercion, TcType))
try_to_reduce :: TyCon -> [Xi] -> RewriteM (Maybe (TcCoercionN, Xi))
try_to_reduce TyCon
tc [Xi]
tys
= do { Maybe (TcCoercionN, Xi)
result <- forall a. TcS a -> RewriteM a
liftTcS forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) (f :: * -> *) a.
(Monad m, Foldable f) =>
f (m (Maybe a)) -> m (Maybe a)
firstJustsM [ TyCon -> [Xi] -> TcS (Maybe (TcCoercionN, Xi))
lookupFamAppCache TyCon
tc [Xi]
tys
, TyCon -> [Xi] -> TcS (Maybe (TcCoercionN, Xi))
matchFam TyCon
tc [Xi]
tys ]
; Maybe (TcCoercionN, Xi) -> RewriteM (Maybe (TcCoercionN, Xi))
downgrade Maybe (TcCoercionN, Xi)
result }
where
downgrade :: Maybe (TcCoercionN, TcType) -> RewriteM (Maybe (TcCoercion, TcType))
downgrade :: Maybe (TcCoercionN, Xi) -> RewriteM (Maybe (TcCoercionN, Xi))
downgrade Maybe (TcCoercionN, Xi)
Nothing = forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
downgrade result :: Maybe (TcCoercionN, Xi)
result@(Just (TcCoercionN
co, Xi
xi))
= do { String -> SDoc -> RewriteM ()
traceRewriteM String
"Eager T.F. reduction success" forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
vcat [ forall a. Outputable a => a -> SDoc
ppr TyCon
tc, forall a. Outputable a => a -> SDoc
ppr [Xi]
tys, forall a. Outputable a => a -> SDoc
ppr Xi
xi
, forall a. Outputable a => a -> SDoc
ppr TcCoercionN
co SDoc -> SDoc -> SDoc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr (TcCoercionN -> Pair Xi
coercionKind TcCoercionN
co)
]
; EqRel
eq_rel <- RewriteM EqRel
getEqRel
; case EqRel
eq_rel of
EqRel
NomEq -> forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (TcCoercionN, Xi)
result
EqRel
ReprEq -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just (HasDebugCallStack => TcCoercionN -> TcCoercionN
mkSubCo TcCoercionN
co, Xi
xi)) }
data RewriteTvResult
= RTRNotFollowed
| RTRFollowed TcType Coercion
rewriteTyVar :: TyVar -> RewriteM (Xi, Coercion)
rewriteTyVar :: TcTyVar -> RewriteM (Xi, TcCoercionN)
rewriteTyVar TcTyVar
tv
= do { RewriteTvResult
mb_yes <- TcTyVar -> RewriteM RewriteTvResult
rewrite_tyvar1 TcTyVar
tv
; case RewriteTvResult
mb_yes of
RTRFollowed Xi
ty1 TcCoercionN
co1
-> do { (Xi
ty2, TcCoercionN
co2) <- Xi -> RewriteM (Xi, TcCoercionN)
rewrite_one Xi
ty1
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi
ty2, TcCoercionN
co2 TcCoercionN -> TcCoercionN -> TcCoercionN
`mkTransCo` TcCoercionN
co1) }
RewriteTvResult
RTRNotFollowed
-> do { TcTyVar
tv' <- forall a. TcS a -> RewriteM a
liftTcS forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *).
Monad m =>
(Xi -> m Xi) -> TcTyVar -> m TcTyVar
updateTyVarKindM Xi -> TcS Xi
zonkTcType TcTyVar
tv
; Role
role <- RewriteM Role
getRole
; let ty' :: Xi
ty' = TcTyVar -> Xi
mkTyVarTy TcTyVar
tv'
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi
ty', Role -> Xi -> TcCoercionN
mkTcReflCo Role
role Xi
ty') } }
rewrite_tyvar1 :: TcTyVar -> RewriteM RewriteTvResult
rewrite_tyvar1 :: TcTyVar -> RewriteM RewriteTvResult
rewrite_tyvar1 TcTyVar
tv
= do { Maybe Xi
mb_ty <- forall a. TcS a -> RewriteM a
liftTcS forall a b. (a -> b) -> a -> b
$ TcTyVar -> TcS (Maybe Xi)
isFilledMetaTyVar_maybe TcTyVar
tv
; case Maybe Xi
mb_ty of
Just Xi
ty -> do { String -> SDoc -> RewriteM ()
traceRewriteM String
"Following filled tyvar"
(forall a. Outputable a => a -> SDoc
ppr TcTyVar
tv SDoc -> SDoc -> SDoc
<+> SDoc
equals SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Xi
ty)
; Role
role <- RewriteM Role
getRole
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi -> TcCoercionN -> RewriteTvResult
RTRFollowed Xi
ty (Role -> Xi -> TcCoercionN
mkReflCo Role
role Xi
ty)) } ;
Maybe Xi
Nothing -> do { String -> SDoc -> RewriteM ()
traceRewriteM String
"Unfilled tyvar" (TcTyVar -> SDoc
pprTyVar TcTyVar
tv)
; CtFlavourRole
fr <- RewriteM CtFlavourRole
getFlavourRole
; TcTyVar -> CtFlavourRole -> RewriteM RewriteTvResult
rewrite_tyvar2 TcTyVar
tv CtFlavourRole
fr } }
rewrite_tyvar2 :: TcTyVar -> CtFlavourRole -> RewriteM RewriteTvResult
rewrite_tyvar2 :: TcTyVar -> CtFlavourRole -> RewriteM RewriteTvResult
rewrite_tyvar2 TcTyVar
tv fr :: CtFlavourRole
fr@(CtFlavour
_, EqRel
eq_rel)
= do { DTyVarEnv EqualCtList
ieqs <- forall a. TcS a -> RewriteM a
liftTcS forall a b. (a -> b) -> a -> b
$ TcS (DTyVarEnv EqualCtList)
getInertEqs
; case forall a. DVarEnv a -> TcTyVar -> Maybe a
lookupDVarEnv DTyVarEnv EqualCtList
ieqs TcTyVar
tv of
Just (EqualCtList (Ct
ct :| [Ct]
_))
| CEqCan { cc_ev :: Ct -> CtEvidence
cc_ev = CtEvidence
ctev, cc_lhs :: Ct -> CanEqLHS
cc_lhs = TyVarLHS TcTyVar
tv
, cc_rhs :: Ct -> Xi
cc_rhs = Xi
rhs_ty, cc_eq_rel :: Ct -> EqRel
cc_eq_rel = EqRel
ct_eq_rel } <- Ct
ct
, let ct_fr :: CtFlavourRole
ct_fr = (CtEvidence -> CtFlavour
ctEvFlavour CtEvidence
ctev, EqRel
ct_eq_rel)
, CtFlavourRole
ct_fr CtFlavourRole -> CtFlavourRole -> Bool
`eqCanRewriteFR` CtFlavourRole
fr
-> do { String -> SDoc -> RewriteM ()
traceRewriteM String
"Following inert tyvar"
(forall a. Outputable a => a -> SDoc
ppr TcTyVar
tv SDoc -> SDoc -> SDoc
<+>
SDoc
equals SDoc -> SDoc -> SDoc
<+>
forall a. Outputable a => a -> SDoc
ppr Xi
rhs_ty SDoc -> SDoc -> SDoc
$$ forall a. Outputable a => a -> SDoc
ppr CtEvidence
ctev)
; let rewrite_co1 :: TcCoercionN
rewrite_co1 = TcCoercionN -> TcCoercionN
mkSymCo (HasDebugCallStack => CtEvidence -> TcCoercionN
ctEvCoercion CtEvidence
ctev)
rewrite_co :: TcCoercionN
rewrite_co = case (EqRel
ct_eq_rel, EqRel
eq_rel) of
(EqRel
ReprEq, EqRel
_rel) -> ASSERT( _rel == ReprEq )
TcCoercionN
rewrite_co1
(EqRel
NomEq, EqRel
NomEq) -> TcCoercionN
rewrite_co1
(EqRel
NomEq, EqRel
ReprEq) -> HasDebugCallStack => TcCoercionN -> TcCoercionN
mkSubCo TcCoercionN
rewrite_co1
; forall (m :: * -> *) a. Monad m => a -> m a
return (Xi -> TcCoercionN -> RewriteTvResult
RTRFollowed Xi
rhs_ty TcCoercionN
rewrite_co) }
Maybe EqualCtList
_other -> forall (m :: * -> *) a. Monad m => a -> m a
return RewriteTvResult
RTRNotFollowed }
split_pi_tys' :: Type -> ([TyCoBinder], Type, Bool)
split_pi_tys' :: Xi -> ([TyCoBinder], Xi, Bool)
split_pi_tys' Xi
ty = Xi -> Xi -> ([TyCoBinder], Xi, Bool)
split Xi
ty Xi
ty
where
split :: Xi -> Xi -> ([TyCoBinder], Xi, Bool)
split Xi
_ (ForAllTy TyVarBinder
b Xi
res) = let
!([TyCoBinder]
bs, Xi
ty, Bool
_) = Xi -> Xi -> ([TyCoBinder], Xi, Bool)
split Xi
res Xi
res
in (TyVarBinder -> TyCoBinder
Named TyVarBinder
b forall a. a -> [a] -> [a]
: [TyCoBinder]
bs, Xi
ty, Bool
True)
split Xi
_ (FunTy { ft_af :: Xi -> AnonArgFlag
ft_af = AnonArgFlag
af, ft_mult :: Xi -> Xi
ft_mult = Xi
w, ft_arg :: Xi -> Xi
ft_arg = Xi
arg, ft_res :: Xi -> Xi
ft_res = Xi
res })
= let
!([TyCoBinder]
bs, Xi
ty, Bool
named) = Xi -> Xi -> ([TyCoBinder], Xi, Bool)
split Xi
res Xi
res
in (AnonArgFlag -> Scaled Xi -> TyCoBinder
Anon AnonArgFlag
af (forall a. Xi -> a -> Scaled a
mkScaled Xi
w Xi
arg) forall a. a -> [a] -> [a]
: [TyCoBinder]
bs, Xi
ty, Bool
named)
split Xi
orig_ty Xi
ty | Just Xi
ty' <- Xi -> Maybe Xi
coreView Xi
ty = Xi -> Xi -> ([TyCoBinder], Xi, Bool)
split Xi
orig_ty Xi
ty'
split Xi
orig_ty Xi
_ = ([], Xi
orig_ty, Bool
False)
{-# INLINE split_pi_tys' #-}
ty_con_binders_ty_binders' :: [TyConBinder] -> ([TyCoBinder], Bool)
ty_con_binders_ty_binders' :: [TyConBinder] -> ([TyCoBinder], Bool)
ty_con_binders_ty_binders' = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr TyConBinder -> ([TyCoBinder], Bool) -> ([TyCoBinder], Bool)
go ([], Bool
False)
where
go :: TyConBinder -> ([TyCoBinder], Bool) -> ([TyCoBinder], Bool)
go (Bndr TcTyVar
tv (NamedTCB ArgFlag
vis)) ([TyCoBinder]
bndrs, Bool
_)
= (TyVarBinder -> TyCoBinder
Named (forall var argf. var -> argf -> VarBndr var argf
Bndr TcTyVar
tv ArgFlag
vis) forall a. a -> [a] -> [a]
: [TyCoBinder]
bndrs, Bool
True)
go (Bndr TcTyVar
tv (AnonTCB AnonArgFlag
af)) ([TyCoBinder]
bndrs, Bool
n)
= (AnonArgFlag -> Scaled Xi -> TyCoBinder
Anon AnonArgFlag
af (forall a. a -> Scaled a
tymult (TcTyVar -> Xi
tyVarKind TcTyVar
tv)) forall a. a -> [a] -> [a]
: [TyCoBinder]
bndrs, Bool
n)
{-# INLINE go #-}
{-# INLINE ty_con_binders_ty_binders' #-}