Adam Gundry pushed to branch wip/amg/castz at Glasgow Haskell Compiler / GHC
Commits:
-
29d1d7b2
by Adam Gundry at 2026-06-12T15:36:55+01:00
9 changed files:
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/Coercion/Opt.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/TyCo/FVs.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Tc/Types/Evidence.hs
Changes:
| ... | ... | @@ -63,6 +63,10 @@ module GHC.Core.Coercion ( |
| 63 | 63 | applyForAllTy,
|
| 64 | 64 | decomposeFunCastCo,
|
| 65 | 65 | |
| 66 | + mkSymTypedCastCo,
|
|
| 67 | + mkTransTypedCastCo,
|
|
| 68 | + typedCastCoercionKind,
|
|
| 69 | + |
|
| 66 | 70 | -- ** Decomposition
|
| 67 | 71 | instNewTyCon_maybe,
|
| 68 | 72 | |
| ... | ... | @@ -97,7 +101,8 @@ module GHC.Core.Coercion ( |
| 97 | 101 | -- ** Free variables
|
| 98 | 102 | tyCoVarsOfCo, tyCoVarsOfCos, coVarsOfCo,
|
| 99 | 103 | tyCoVarsOfCastCo,
|
| 100 | - coercionSize, castCoercionSize, anyFreeVarsOfCo,
|
|
| 104 | + coercionSize, castCoercionSize,
|
|
| 105 | + anyFreeVarsOfCo, anyFreeVarsOfCastCo,
|
|
| 101 | 106 | |
| 102 | 107 | -- ** Substitution
|
| 103 | 108 | CvSubstEnv, emptyCvSubstEnv,
|
| ... | ... | @@ -123,7 +128,7 @@ module GHC.Core.Coercion ( |
| 123 | 128 | eqCoercion, eqCoercionX, eqCastCoercion, eqCastCoercionX,
|
| 124 | 129 | |
| 125 | 130 | -- ** Forcing evaluation of coercions
|
| 126 | - seqCo, seqCos, seqCastCoercion,
|
|
| 131 | + seqCo, seqCos, seqCastCoercion, seqTypedCastCoercion,
|
|
| 127 | 132 | |
| 128 | 133 | -- * Pretty-printing
|
| 129 | 134 | pprCo, pprParendCo,
|
| ... | ... | @@ -852,15 +857,16 @@ mkFunCoNoFTF r w arg_co res_co |
| 852 | 857 | Pair argl_ty argr_ty = coercionKind arg_co
|
| 853 | 858 | Pair resl_ty resr_ty = coercionKind res_co
|
| 854 | 859 | |
| 855 | --- AMG TODO: more cases here, or maybe better to have a FunCo constructor of CastCoercion?
|
|
| 856 | -mkFunCastCoNoFTF :: HasDebugCallStack => Role -> Mult -> Type -> CastCoercion -> Type -> CastCoercion -> CastCoercion
|
|
| 857 | -mkFunCastCoNoFTF _ mult _ (ZCoercion arg_ty arg_cos) _ (ZCoercion res_ty res_cos) = ZCoercion (mkFunctionType mult arg_ty res_ty) (arg_cos `unionDVarSet` res_cos)
|
|
| 858 | -mkFunCastCoNoFTF _ mult _ (ZCoercion arg_ty arg_cos) res_ty res_co = ZCoercion (mkFunctionType mult arg_ty (castCoercionRKind res_ty res_co)) (arg_cos `unionDVarSet` coVarsOfCastCoDSet res_co)
|
|
| 859 | -mkFunCastCoNoFTF _ mult arg_ty arg_co _ (ZCoercion res_ty res_cos) = ZCoercion (mkFunctionType mult (castCoercionRKind arg_ty arg_co) res_ty) (res_cos `unionDVarSet` coVarsOfCastCoDSet arg_co)
|
|
| 860 | -mkFunCastCoNoFTF r mult _ (CCoercion arg_co) _ (CCoercion res_co) = CCoercion (mkFunCoNoFTF r (multToCo mult) arg_co res_co)
|
|
| 861 | -mkFunCastCoNoFTF _ _ _ ReflCastCo _ ReflCastCo = ReflCastCo
|
|
| 862 | -mkFunCastCoNoFTF r mult _ (CCoercion arg_co) res_ty ReflCastCo = CCoercion (mkFunCoNoFTF r (multToCo mult) arg_co (mkReflCo r res_ty))
|
|
| 863 | -mkFunCastCoNoFTF r mult arg_ty ReflCastCo _ (CCoercion res_co) = CCoercion (mkFunCoNoFTF r (multToCo mult) (mkReflCo r arg_ty) res_co)
|
|
| 860 | +-- AMG TODO: maybe better to have a FunCo constructor of CastCoercion?
|
|
| 861 | +mkFunCastCoNoFTF :: HasDebugCallStack => Role -> Mult -> TypedCastCoercion -> TypedCastCoercion -> CastCoercion
|
|
| 862 | +mkFunCastCoNoFTF r mult (TCC arg_ty0 arg_co) (TCC res_ty0 res_co) =
|
|
| 863 | + case (arg_co, res_co) of
|
|
| 864 | + (ReflCastCo, ReflCastCo) -> ReflCastCo
|
|
| 865 | + (ZCoercion arg_ty1 arg_cos, _) -> ZCoercion (mkFunctionType mult arg_ty1 (castCoercionRKind res_ty0 res_co)) (arg_cos `unionDVarSet` coVarsOfCastCoDSet res_co)
|
|
| 866 | + (_, ZCoercion res_ty1 res_cos) -> ZCoercion (mkFunctionType mult (castCoercionRKind arg_ty0 arg_co) res_ty1) (res_cos `unionDVarSet` coVarsOfCastCoDSet arg_co)
|
|
| 867 | + (CCoercion arg_co, CCoercion res_co) -> CCoercion (mkFunCoNoFTF r (multToCo mult) arg_co res_co)
|
|
| 868 | + (CCoercion arg_co, ReflCastCo) -> CCoercion (mkFunCoNoFTF r (multToCo mult) arg_co (mkReflCo r res_ty0))
|
|
| 869 | + (ReflCastCo, CCoercion res_co) -> CCoercion (mkFunCoNoFTF r (multToCo mult) (mkReflCo r arg_ty0) res_co)
|
|
| 864 | 870 | |
| 865 | 871 | |
| 866 | 872 | -- | Build a function 'Coercion' from two other 'Coercion's. That is,
|
| ... | ... | @@ -990,8 +996,8 @@ mkForAllCo v visL visR kind_co co |
| 990 | 996 | = mk_forall_co v visL visR kind_co co
|
| 991 | 997 | |
| 992 | 998 | mkForAllCastCo :: HasDebugCallStack => Role -> TyCoVar -> ForAllTyFlag -> ForAllTyFlag
|
| 993 | - -> Type -> CastCoercion -> CastCoercion
|
|
| 994 | -mkForAllCastCo r v visL visR ty cco = case cco of
|
|
| 999 | + -> TypedCastCoercion -> CastCoercion
|
|
| 1000 | +mkForAllCastCo r v visL visR (TCC ty cco) = case cco of
|
|
| 995 | 1001 | CCoercion co -> CCoercion (mkForAllCo v visL visR MRefl co)
|
| 996 | 1002 | ZCoercion ty cos -> ZCoercion (mkTyCoForAllTy v visR ty) cos
|
| 997 | 1003 | ReflCastCo | visL `eqForAllVis` visR -> ReflCastCo
|
| ... | ... | @@ -1224,6 +1230,9 @@ mkSymCastCo _ (CCoercion co) = CCoercion (mkSymCo co) |
| 1224 | 1230 | mkSymCastCo ty (ZCoercion _ cos) = ZCoercion ty cos
|
| 1225 | 1231 | mkSymCastCo _ ReflCastCo = ReflCastCo
|
| 1226 | 1232 | |
| 1233 | +mkSymTypedCastCo :: TypedCastCoercion -> TypedCastCoercion
|
|
| 1234 | +mkSymTypedCastCo (TCC ty co) = TCC (castCoercionRKind ty co) (mkSymCastCo ty co)
|
|
| 1235 | + |
|
| 1227 | 1236 | -- | mkTransCo creates a new 'Coercion' by composing the two
|
| 1228 | 1237 | -- given 'Coercion's transitively: (co1 ; co2)
|
| 1229 | 1238 | mkTransCo :: HasDebugCallStack => Coercion -> Coercion -> Coercion
|
| ... | ... | @@ -2529,6 +2538,9 @@ seqCastCoercion (CCoercion co) = seqCo co |
| 2529 | 2538 | seqCastCoercion (ZCoercion ty cos) = seqType ty `seq` seqDVarSet cos
|
| 2530 | 2539 | seqCastCoercion ReflCastCo = ()
|
| 2531 | 2540 | |
| 2541 | +seqTypedCastCoercion :: TypedCastCoercion -> ()
|
|
| 2542 | +seqTypedCastCoercion (TCC ty co) = seqType ty `seq` seqCastCoercion co
|
|
| 2543 | + |
|
| 2532 | 2544 | seqCo :: Coercion -> ()
|
| 2533 | 2545 | seqCo (Refl ty) = seqType ty
|
| 2534 | 2546 | seqCo (GRefl r ty mco) = r `seq` seqType ty `seq` seqMCo mco
|
| ... | ... | @@ -3022,3 +3034,10 @@ coToCastCo :: Coercion -> CastCoercion |
| 3022 | 3034 | -- See #19815 for a bit of data and discussion on this point
|
| 3023 | 3035 | coToCastCo co | isReflCo co = ReflCastCo
|
| 3024 | 3036 | | otherwise = CCoercion co
|
| 3037 | + |
|
| 3038 | + |
|
| 3039 | +typedCastCoercionKind :: TypedCastCoercion -> Pair Type
|
|
| 3040 | +typedCastCoercionKind (TCC tyL co) = Pair (castCoercionLKind tyL co) (castCoercionRKind tyL co)
|
|
| 3041 | + |
|
| 3042 | +mkTransTypedCastCo :: TypedCastCoercion -> TypedCastCoercion -> TypedCastCoercion
|
|
| 3043 | +mkTransTypedCastCo (TCC ty1 co1) (TCC _ co2) = TCC ty1 (mkTransCastCo co1 co2) |
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | |
| 5 | 5 | module GHC.Core.Coercion.Opt
|
| 6 | 6 | ( optCoercion, optTransCo
|
| 7 | - , optCastCoercion
|
|
| 7 | + , optCastCoercion, optTransCastCo
|
|
| 8 | 8 | , OptCoercionOpts (..)
|
| 9 | 9 | )
|
| 10 | 10 | where
|
| ... | ... | @@ -178,6 +178,18 @@ optTransCo opts in_scope co1 co2 |
| 178 | 178 | | otherwise
|
| 179 | 179 | = co1 `mkTransCo` co2
|
| 180 | 180 | |
| 181 | +optTransCastCo :: HasDebugCallStack => OptCoercionOpts -> InScopeSet
|
|
| 182 | + -> TypedCastCoercion -> TypedCastCoercion -> TypedCastCoercion
|
|
| 183 | +optTransCastCo opts in_scope co1 co2
|
|
| 184 | + | optCoercionEnabled opts
|
|
| 185 | + = case (co1, co2) of
|
|
| 186 | + (TCC ty (CCoercion co1'), TCC _ (CCoercion co2')) -> TCC ty (CCoercion (opt_trans in_scope co1' co2'))
|
|
| 187 | + (co1, TCC _ ReflCastCo) -> co1
|
|
| 188 | + (TCC _ ReflCastCo, co2) -> co2
|
|
| 189 | + _ -> co1 `mkTransTypedCastCo` co2
|
|
| 190 | + | otherwise
|
|
| 191 | + = co1 `mkTransTypedCastCo` co2
|
|
| 192 | + |
|
| 181 | 193 | -- AMG TODO: not clear if coercionLKind or substTy is better choice here
|
| 182 | 194 | optCastCoercion :: OptCoercionOpts -> Subst -> TypedCastCoercion -> TypedCastCoercion
|
| 183 | 195 | optCastCoercion _ env (TCC tyL ReflCastCo) = TCC (substTy env tyL) ReflCastCo
|
| ... | ... | @@ -2702,7 +2702,6 @@ tryEtaReduce rec_ids bndrs body eval_sd |
| 2702 | 2702 | where
|
| 2703 | 2703 | incoming_arity = count isId bndrs -- See Note [Eta reduction makes sense], point (2)
|
| 2704 | 2704 | |
| 2705 | - -- AMG TOOD: make this pass TypedCastCoercion so we can call ok_arg more easily?
|
|
| 2706 | 2705 | go :: [Var] -- Binders, innermost first, types [a3,a2,a1]
|
| 2707 | 2706 | -> CoreExpr -- Of type tr
|
| 2708 | 2707 | -> CastCoercion -- Of type tr ~ ts
|
| ... | ... | @@ -2723,7 +2722,7 @@ tryEtaReduce rec_ids bndrs body eval_sd |
| 2723 | 2722 | -- Float app ticks: \x -> Tick t (e x) ==> Tick t e
|
| 2724 | 2723 | |
| 2725 | 2724 | go (b : bs) (App fun arg) co
|
| 2726 | - | Just (co', ticks) <- ok_arg b arg co (exprType fun) (exprType (App fun arg))
|
|
| 2725 | + | Just (co', ticks) <- ok_arg b arg (TCC (exprType (App fun arg)) co) (exprType fun)
|
|
| 2727 | 2726 | = fmap (flip (foldr mkTick) ticks) $ go bs fun co'
|
| 2728 | 2727 | -- Float arg ticks: \x -> e (Tick t x) ==> Tick t e
|
| 2729 | 2728 | |
| ... | ... | @@ -2795,19 +2794,18 @@ tryEtaReduce rec_ids bndrs body eval_sd |
| 2795 | 2794 | ---------------
|
| 2796 | 2795 | ok_arg :: Var -- Of type bndr_t
|
| 2797 | 2796 | -> CoreExpr -- Of type arg_t
|
| 2798 | - -> CastCoercion -- Of kind (t1~t2)
|
|
| 2797 | + -> TypedCastCoercion-- Of kind (t1~t2)
|
|
| 2799 | 2798 | -> Type -- Type (arg_t -> t1) of the function
|
| 2800 | 2799 | -- to which the argument is supplied
|
| 2801 | - -> Type -- Type t1 of the result (AMG TODO: use TypedCastCoercion or avoid needing to pass this?)
|
|
| 2802 | 2800 | -> Maybe (CastCoercion -- Of type (arg_t -> t1 ~ bndr_t -> t2)
|
| 2803 | 2801 | -- (and similarly for tyvars, coercion args)
|
| 2804 | 2802 | , [CoreTickish])
|
| 2805 | 2803 | -- See Note [Eta reduction with casted arguments]
|
| 2806 | - ok_arg bndr (Type arg_ty) co fun_ty res_ty
|
|
| 2804 | + ok_arg bndr (Type arg_ty) co fun_ty
|
|
| 2807 | 2805 | | Just tv <- getTyVar_maybe arg_ty
|
| 2808 | 2806 | , bndr == tv = case splitForAllForAllTyBinder_maybe fun_ty of
|
| 2809 | 2807 | Just (Bndr _ vis, _) -> Just (fco, [])
|
| 2810 | - where !fco = mkForAllCastCo Representational tv vis coreTyLamForAllTyFlag res_ty co
|
|
| 2808 | + where !fco = mkForAllCastCo Representational tv vis coreTyLamForAllTyFlag co
|
|
| 2811 | 2809 | -- The lambda we are eta-reducing always has visibility
|
| 2812 | 2810 | -- 'coreTyLamForAllTyFlag' which may or may not match
|
| 2813 | 2811 | -- the visibility on the inner function (#24014)
|
| ... | ... | @@ -2815,24 +2813,25 @@ tryEtaReduce rec_ids bndrs body eval_sd |
| 2815 | 2813 | (text "fun:" <+> ppr bndr
|
| 2816 | 2814 | $$ text "arg:" <+> ppr arg_ty
|
| 2817 | 2815 | $$ text "fun_ty:" <+> ppr fun_ty)
|
| 2818 | - ok_arg bndr (Var v) co fun_ty _
|
|
| 2816 | + ok_arg bndr (Var v) (TCC _ co) fun_ty
|
|
| 2819 | 2817 | | bndr == v
|
| 2820 | 2818 | , let mult = idMult bndr
|
| 2821 | 2819 | , Just (_af, fun_mult, _, _) <- splitFunTy_maybe fun_ty
|
| 2822 | 2820 | , mult `eqType` fun_mult -- There is no change in multiplicity, otherwise we must abort
|
| 2823 | 2821 | = Just (mkFunResCastCo Representational bndr co, [])
|
| 2824 | - ok_arg bndr (Cast e co_arg) co fun_ty _
|
|
| 2822 | + ok_arg bndr (Cast e co_arg) co fun_ty
|
|
| 2825 | 2823 | | (ticks, Var v) <- stripTicksTop tickishFloatable e
|
| 2826 | - , Just (_, fun_mult, _, res_ty) <- splitFunTy_maybe fun_ty
|
|
| 2824 | + , Just (_, fun_mult, _, _) <- splitFunTy_maybe fun_ty
|
|
| 2827 | 2825 | , bndr == v
|
| 2828 | 2826 | , fun_mult `eqType` idMult bndr
|
| 2829 | - = Just (mkFunCastCoNoFTF Representational fun_mult (castCoercionRKind (exprType e) co_arg) (mkSymCastCo (exprType e) co_arg) res_ty co, ticks)
|
|
| 2827 | + , let co_arg' = TCC (exprType e) co_arg
|
|
| 2828 | + = Just (mkFunCastCoNoFTF Representational fun_mult (mkSymTypedCastCo co_arg') co, ticks)
|
|
| 2830 | 2829 | -- The simplifier combines multiple casts into one,
|
| 2831 | 2830 | -- so we can have a simple-minded pattern match here
|
| 2832 | - ok_arg bndr (Tick t arg) co fun_ty res_ty
|
|
| 2833 | - | tickishFloatable t, Just (co', ticks) <- ok_arg bndr arg co fun_ty res_ty
|
|
| 2831 | + ok_arg bndr (Tick t arg) co fun_ty
|
|
| 2832 | + | tickishFloatable t, Just (co', ticks) <- ok_arg bndr arg co fun_ty
|
|
| 2834 | 2833 | = Just (co', t:ticks)
|
| 2835 | - ok_arg _ _ _ _ _ = Nothing
|
|
| 2834 | + ok_arg _ _ _ _ = Nothing
|
|
| 2836 | 2835 | |
| 2837 | 2836 | |
| 2838 | 2837 | {- *********************************************************************
|
| ... | ... | @@ -3003,18 +3002,17 @@ pushCoValArg co |
| 3003 | 3002 | old_arg_ty = funArgTy tyR
|
| 3004 | 3003 | |
| 3005 | 3004 | pushCoercionIntoLambda
|
| 3006 | - :: HasDebugCallStack => InScopeSet -> Var -> CoreExpr -> Type -> CastCoercion -> Maybe (Var, CoreExpr)
|
|
| 3005 | + :: HasDebugCallStack => InScopeSet -> Var -> CoreExpr -> TypedCastCoercion -> Maybe (Var, CoreExpr)
|
|
| 3007 | 3006 | -- This implements the Push rule from the paper on coercions
|
| 3008 | 3007 | -- (\x. e) |> co
|
| 3009 | 3008 | -- ===>
|
| 3010 | 3009 | -- (\x'. e |> co')
|
| 3011 | -pushCoercionIntoLambda in_scope x e ty co
|
|
| 3010 | +pushCoercionIntoLambda in_scope x e co
|
|
| 3012 | 3011 | | assert (not (isTyVar x) && not (isCoVar x)) True
|
| 3013 | - , let s1s2 = castCoercionLKind ty co
|
|
| 3014 | - , let t1t2 = castCoercionRKind ty co
|
|
| 3012 | + , Pair s1s2 t1t2 <- typedCastCoercionKind co
|
|
| 3015 | 3013 | , Just (_, _, s1, _) <- splitFunTy_maybe s1s2
|
| 3016 | 3014 | , Just (_, w1, t1,_t2) <- splitFunTy_maybe t1t2
|
| 3017 | - , (co1, co2) <- decomposeFunCastCo co
|
|
| 3015 | + , (co1, co2) <- decomposeFunCastCo (tccCastCoercion co)
|
|
| 3018 | 3016 | , typeHasFixedRuntimeRep t1
|
| 3019 | 3017 | -- We can't push the coercion into the lambda if it would create
|
| 3020 | 3018 | -- a representation-polymorphic binder.
|
| ... | ... | @@ -1412,6 +1412,19 @@ simplCoercion env co |
| 1412 | 1412 | opts = seOptCoercionOpts env
|
| 1413 | 1413 | subst_only = isEmptyTvSubst subst || reSimplifying env
|
| 1414 | 1414 | |
| 1415 | +simplCastCoercion :: SimplEnv -> InTypedCastCoercion -> SimplM OutTypedCastCoercion
|
|
| 1416 | +simplCastCoercion env co
|
|
| 1417 | + = seqTypedCastCoercion opt_co `seq` return opt_co
|
|
| 1418 | + where
|
|
| 1419 | + -- See Note [Optimising coercions]
|
|
| 1420 | + -- NB: substCo has a short-cut when both type and coercion substs are empty
|
|
| 1421 | + opt_co | subst_only = substTypedCastCo subst co
|
|
| 1422 | + | otherwise = optCastCoercion opts subst co
|
|
| 1423 | + |
|
| 1424 | + subst = getTCvSubst env
|
|
| 1425 | + opts = seOptCoercionOpts env
|
|
| 1426 | + subst_only = isEmptyTvSubst subst || reSimplifying env
|
|
| 1427 | + |
|
| 1415 | 1428 | {- Note [Optimising coercions]
|
| 1416 | 1429 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 1417 | 1430 | Some programs have very big coercions and we'd like to avoid repeatedly
|
| ... | ... | @@ -1440,19 +1453,6 @@ re-optimising them: |
| 1440 | 1453 | |
| 1441 | 1454 | -}
|
| 1442 | 1455 | |
| 1443 | -simplCastCoercion :: SimplEnv -> InTypedCastCoercion -> SimplM OutTypedCastCoercion
|
|
| 1444 | -simplCastCoercion env co
|
|
| 1445 | - = do { let opt_co | reSimplifying env = substTypedCastCo subst co
|
|
| 1446 | - | otherwise = optCastCoercion opts subst co
|
|
| 1447 | - -- If (reSimplifying env) is True we have already simplified
|
|
| 1448 | - -- this coercion once, and we don't want do so again; doing
|
|
| 1449 | - -- so repeatedly risks non-linear behaviour
|
|
| 1450 | - -- See Note [Inline depth] in GHC.Core.Opt.Simplify.Env
|
|
| 1451 | - ; seqCastCoercion (tccCastCoercion opt_co) `seq` return opt_co }
|
|
| 1452 | - where
|
|
| 1453 | - subst = getTCvSubst env
|
|
| 1454 | - opts = seOptCoercionOpts env
|
|
| 1455 | - |
|
| 1456 | 1456 | |
| 1457 | 1457 | -----------------------------------
|
| 1458 | 1458 | -- | Push a TickIt context outwards past applications and cases, as
|
| ... | ... | @@ -1861,7 +1861,7 @@ simplArg :: SimplEnvIS -- ^ Used only for its InScopeSet |
| 1861 | 1861 | -- continuation passed to 'simplExprC'
|
| 1862 | 1862 | -> OutType -- ^ Type of the function applied to this arg
|
| 1863 | 1863 | -> StaticEnv -> CoreExpr -- ^ Expression with its static envt
|
| 1864 | - -> OutCastCoercion -- Wrap this around the result
|
|
| 1864 | + -> OutCastCoercion -- ^ Wrap this around the result
|
|
| 1865 | 1865 | -> SimplM OutExpr
|
| 1866 | 1866 | simplArg _ _ _ (Simplified {}) arg co
|
| 1867 | 1867 | = return $ mkCastCo arg co -- See Note [Avoid repeated simplification]
|
| ... | ... | @@ -57,7 +57,6 @@ import GHC.Core.Unify as Unify ( ruleMatchTyKiX ) |
| 57 | 57 | import GHC.Core.Type as Type
|
| 58 | 58 | ( Type, extendTvSubst, extendCvSubst
|
| 59 | 59 | , substTy, getTyVar_maybe )
|
| 60 | -import GHC.Core.TyCo.FVs ( anyFreeVarsOfCastCo )
|
|
| 61 | 60 | import GHC.Core.TyCo.Ppr( pprParendType )
|
| 62 | 61 | import GHC.Core.Coercion as Coercion
|
| 63 | 62 | import GHC.Core.Tidy ( tidyRules )
|
| ... | ... | @@ -29,7 +29,7 @@ import GHC.Core.Unfold.Make |
| 29 | 29 | import GHC.Core.Make
|
| 30 | 30 | import GHC.Core.Opt.OccurAnal( occurAnalyseExpr, occurAnalysePgm, zapLambdaBndrs )
|
| 31 | 31 | import GHC.Core.DataCon
|
| 32 | -import GHC.Core.Coercion.Opt ( optCoercion, optCastCoercion, OptCoercionOpts (..) )
|
|
| 32 | +import GHC.Core.Coercion.Opt ( optCoercion, optCastCoercion, OptCoercionOpts (..), optTransCastCo )
|
|
| 33 | 33 | import GHC.Core.Type hiding ( substTy, extendTvSubst, extendCvSubst, extendTvSubstList
|
| 34 | 34 | , isInScope, substTyVarBndr, cloneTyVarBndr )
|
| 35 | 35 | import GHC.Core.Predicate( isCoVarType )
|
| ... | ... | @@ -303,11 +303,11 @@ simpleOptPgm opts this_mod binds rules = |
| 303 | 303 | ----------------------
|
| 304 | 304 | type SimpleClo = (SimpleOptEnv, InExpr)
|
| 305 | 305 | |
| 306 | -data SimpleContItem = ApplyToArg SimpleClo | CastIt OutType OutCastCoercion
|
|
| 306 | +data SimpleContItem = ApplyToArg SimpleClo | CastIt OutTypedCastCoercion
|
|
| 307 | 307 | |
| 308 | 308 | instance Outputable SimpleContItem where
|
| 309 | 309 | ppr (ApplyToArg (_, arg)) = text "ARG" <+> ppr arg
|
| 310 | - ppr (CastIt _ co) = text "CAST" <+> ppr co
|
|
| 310 | + ppr (CastIt co) = text "CAST" <+> ppr co
|
|
| 311 | 311 | |
| 312 | 312 | data SimpleOptEnv
|
| 313 | 313 | = SOE { soe_opts :: {-# UNPACK #-} !SimpleOpts
|
| ... | ... | @@ -473,7 +473,7 @@ simple_app env e0@(Lam {}) as0@(_:_) |
| 473 | 473 | where (env', b') = subst_opt_bndr env b
|
| 474 | 474 | |
| 475 | 475 | -- See Note [Eliminate casts in function position]
|
| 476 | - do_beta env e@(Lam b _) as@(CastIt ty out_co:rest)
|
|
| 476 | + do_beta env e@(Lam b _) as@(CastIt out_co:rest)
|
|
| 477 | 477 | | isNonCoVarId b
|
| 478 | 478 | -- Optimise the inner lambda to make it an 'OutExpr', which makes it
|
| 479 | 479 | -- possible to call 'pushCoercionIntoLambda' with the 'OutCoercion' 'co'.
|
| ... | ... | @@ -482,7 +482,7 @@ simple_app env e0@(Lam {}) as0@(_:_) |
| 482 | 482 | -- we need to do this to avoid mixing 'InExpr' and 'OutExpr', or two
|
| 483 | 483 | -- 'InExpr' with different environments (getting this wrong caused #26588 & #26589.)
|
| 484 | 484 | , Lam out_b out_body <- simple_app env e []
|
| 485 | - , Just (b', body') <- pushCoercionIntoLambda (soeInScope env) out_b out_body ty out_co
|
|
| 485 | + , Just (b', body') <- pushCoercionIntoLambda (soeInScope env) out_b out_body out_co
|
|
| 486 | 486 | = do_beta (soeZapSubst env) (Lam b' body') rest
|
| 487 | 487 | -- soeZapSubst: we've already optimised everything (the lambda and 'rest') by now.
|
| 488 | 488 | | otherwise
|
| ... | ... | @@ -542,19 +542,18 @@ simple_app env (Cast e co) as |
| 542 | 542 | simple_app env e as
|
| 543 | 543 | = rebuild_app env (simple_opt_expr env e) as
|
| 544 | 544 | |
| 545 | --- FIXME (cast-zapping rebase): HEAD added optTransCo to further optimise the
|
|
| 546 | --- combined coercion when stacking. There is no optTransCastCo yet, so for now
|
|
| 547 | --- we use mkTransCastCo and leave the deeper optimisation as a TODO.
|
|
| 548 | 545 | add_cast :: SimpleOptEnv -> InTypedCastCoercion -> [SimpleContItem] -> [SimpleContItem]
|
| 549 | -add_cast env (TCC tyL co1) as
|
|
| 550 | - | isReflCastCo co1'
|
|
| 546 | +add_cast env co1 as
|
|
| 547 | + | isReflCastCo (tccCastCoercion co1)
|
|
| 551 | 548 | = as
|
| 552 | 549 | | otherwise
|
| 553 | 550 | = case as of
|
| 554 | - CastIt _ co2:rest -> CastIt ty (co1' `mkTransCastCo` co2):rest
|
|
| 555 | - _ -> CastIt ty co1':as
|
|
| 551 | + CastIt co2:rest -> CastIt (optTransCastCo opts in_scope opt_co1 co2):rest
|
|
| 552 | + _ -> CastIt opt_co1:as
|
|
| 556 | 553 | where
|
| 557 | - TCC ty co1' = optCastCoercion (so_co_opts (soe_opts env)) (soe_subst env) (TCC tyL co1)
|
|
| 554 | + opts = so_co_opts (soe_opts env)
|
|
| 555 | + in_scope = soeInScope env
|
|
| 556 | + opt_co1 = optCastCoercion opts (soe_subst env) co1
|
|
| 558 | 557 | |
| 559 | 558 | rebuild_app :: HasDebugCallStack
|
| 560 | 559 | => SimpleOptEnv -> OutExpr -> [SimpleContItem] -> OutExpr
|
| ... | ... | @@ -563,19 +562,19 @@ rebuild_app env fun args = foldl mk_app fun args |
| 563 | 562 | in_scope = soeInScope env
|
| 564 | 563 | mk_app out_fun = \case
|
| 565 | 564 | ApplyToArg arg -> App out_fun (simple_opt_clo in_scope arg)
|
| 566 | - CastIt _ co -> mk_cast out_fun co
|
|
| 565 | + CastIt co -> mk_cast out_fun co
|
|
| 567 | 566 | |
| 568 | -mk_cast :: CoreExpr -> CastCoercion -> CoreExpr
|
|
| 567 | +mk_cast :: CoreExpr -> TypedCastCoercion -> CoreExpr
|
|
| 569 | 568 | -- Like GHC.Core.Utils.mkCast, but does a full reflexivity check.
|
| 570 | 569 | -- mkCast doesn't do that because the Simplifier does (in simplCast)
|
| 571 | 570 | -- But in SimpleOpt it's nice to kill those nested casts (#18112)
|
| 572 | -mk_cast (Cast e co1) co2 = mk_cast e (co1 `mkTransCastCo` co2)
|
|
| 573 | -mk_cast (Tick t e) co = Tick t (mk_cast e co)
|
|
| 571 | +mk_cast (Cast e co1) (TCC _ co2) = mk_cast e (TCC (exprType e) (co1 `mkTransCastCo` co2))
|
|
| 572 | +mk_cast (Tick t e) co = Tick t (mk_cast e co)
|
|
| 574 | 573 | mk_cast e co
|
| 575 | - | isReflexiveCastCo (TCC (exprType e) co)
|
|
| 574 | + | isReflexiveCastCo co
|
|
| 576 | 575 | = e
|
| 577 | 576 | | otherwise
|
| 578 | - = Cast e co
|
|
| 577 | + = Cast e (tccCastCoercion co)
|
|
| 579 | 578 | |
| 580 | 579 | {- Note [Desugaring unlifted newtypes]
|
| 581 | 580 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -1853,7 +1852,7 @@ exprIsLambda_maybe ise@(ISE in_scope_set _) (Cast casted_e co) |
| 1853 | 1852 | -- this implies that x is not in scope in gamma (makes this code simpler)
|
| 1854 | 1853 | , not (isTyVar x) && not (isCoVar x)
|
| 1855 | 1854 | , assert (not $ x `elemVarSet` tyCoVarsOfCastCo co) True
|
| 1856 | - , Just (x',e') <- pushCoercionIntoLambda in_scope_set x e (exprType casted_e) co
|
|
| 1855 | + , Just (x',e') <- pushCoercionIntoLambda in_scope_set x e (TCC (exprType casted_e) co)
|
|
| 1857 | 1856 | , let res = Just (x',e',ts)
|
| 1858 | 1857 | = --pprTrace "exprIsLambda_maybe:Cast" (vcat [ppr casted_e,ppr co,ppr res)])
|
| 1859 | 1858 | res
|
| ... | ... | @@ -205,11 +205,6 @@ in GHC.Tc.Solver. Yuk. This is not pretty. |
| 205 | 205 | * *
|
| 206 | 206 | ********************************************************************* -}
|
| 207 | 207 | |
| 208 | -tyCoVarsOfCastCo :: CastCoercion -> TyCoVarSet
|
|
| 209 | -tyCoVarsOfCastCo (CCoercion co) = coVarsOfCo co
|
|
| 210 | -tyCoVarsOfCastCo (ZCoercion ty cos) = tyCoVarsOfType ty `unionVarSet` dVarSetToVarSet cos
|
|
| 211 | -tyCoVarsOfCastCo ReflCastCo = emptyVarSet
|
|
| 212 | - |
|
| 213 | 208 | tyCoVarsOfType :: Type -> TyCoVarSet
|
| 214 | 209 | -- The "deep" TyCoVars of the the type
|
| 215 | 210 | tyCoVarsOfType ty = runTyCoVars (deepTypeFV ty)
|
| ... | ... | @@ -227,6 +222,9 @@ tyCoVarsOfCo :: Coercion -> TyCoVarSet |
| 227 | 222 | -- See Note [Computing deep free variables]
|
| 228 | 223 | tyCoVarsOfCo co = runTyCoVars (deepCoFV co)
|
| 229 | 224 | |
| 225 | +tyCoVarsOfCastCo :: CastCoercion -> TyCoVarSet
|
|
| 226 | +tyCoVarsOfCastCo co = runTyCoVars (deepCastCoFV co)
|
|
| 227 | + |
|
| 230 | 228 | tyCoVarsOfMCo :: MCoercion -> TyCoVarSet
|
| 231 | 229 | tyCoVarsOfMCo MRefl = emptyVarSet
|
| 232 | 230 | tyCoVarsOfMCo (MCo co) = tyCoVarsOfCo co
|
| ... | ... | @@ -264,7 +262,8 @@ deepTypeFV :: Type -> TyCoFV |
| 264 | 262 | deepTypesFV :: [Type] -> TyCoFV
|
| 265 | 263 | deepCoFV :: Coercion -> TyCoFV
|
| 266 | 264 | deepCosFV :: [Coercion] -> TyCoFV
|
| 267 | -(deepTypeFV, deepTypesFV, deepCoFV, deepCosFV, _) = foldTyCo deepTcvFolder
|
|
| 265 | +deepCastCoFV :: CastCoercion -> TyCoFV
|
|
| 266 | +(deepTypeFV, deepTypesFV, deepCoFV, deepCosFV, deepCastCoFV) = foldTyCo deepTcvFolder
|
|
| 268 | 267 | |
| 269 | 268 | deepTcvFolder :: TyCoFolder TyCoFV
|
| 270 | 269 | -- It's important that we use a one-shot EndoOS, to ensure that all
|
| ... | ... | @@ -908,10 +907,8 @@ anyFreeVarsOfCo check_fv co = DM.getAny (runFVTop (f co)) |
| 908 | 907 | where (_, _, f, _, _) = foldTyCo (afvFolder check_fv)
|
| 909 | 908 | |
| 910 | 909 | anyFreeVarsOfCastCo :: (TyCoVar -> Bool) -> CastCoercion -> Bool
|
| 911 | -anyFreeVarsOfCastCo check_fv (CCoercion co) = anyFreeVarsOfCo check_fv co
|
|
| 912 | -anyFreeVarsOfCastCo check_fv (ZCoercion ty cvs) =
|
|
| 913 | - anyFreeVarsOfType check_fv ty || anyDVarSet check_fv cvs
|
|
| 914 | -anyFreeVarsOfCastCo _ ReflCastCo = False
|
|
| 910 | +anyFreeVarsOfCastCo check_fv co = DM.getAny (runFVTop (f co))
|
|
| 911 | + where (_, _, _, _, f) = foldTyCo (afvFolder check_fv)
|
|
| 915 | 912 | |
| 916 | 913 | noFreeVarsOfType :: Type -> Bool
|
| 917 | 914 | noFreeVarsOfType ty = not $ DM.getAny (runFVTop (f ty))
|
| ... | ... | @@ -1058,6 +1058,9 @@ instance Outputable Coercion where |
| 1058 | 1058 | instance Outputable CastCoercion where
|
| 1059 | 1059 | ppr = pprCastCo
|
| 1060 | 1060 | |
| 1061 | +instance Outputable TypedCastCoercion where
|
|
| 1062 | + ppr (TCC ty co) = text "TCC" <> parens (ppr ty <> text "," <+> ppr co)
|
|
| 1063 | + |
|
| 1061 | 1064 | instance Outputable CoSel where
|
| 1062 | 1065 | ppr (SelTyCon n r) = text "Tc" <> parens (int n <> comma <> pprOneCharRole r)
|
| 1063 | 1066 | ppr SelForAll = text "All"
|
| ... | ... | @@ -636,7 +636,7 @@ optSubTypeHsWrapper wrap |
| 636 | 636 | not_in v (WpCompose w1 w2) = not_in v w1 && not_in v w2
|
| 637 | 637 | not_in v (WpEvApp (EvExpr e)) = not (v `elemVarSet` exprFreeVars e)
|
| 638 | 638 | not_in v (WpEvApp (EvCastExpr e co ty)) = not (v `elemVarSet` exprFreeVars e)
|
| 639 | - && not_in_cast_co v co
|
|
| 639 | + && not (anyFreeVarsOfCastCo (== v) co)
|
|
| 640 | 640 | && not (anyFreeVarsOfType (== v) ty)
|
| 641 | 641 | not_in _ (WpEvApp (EvTypeable {})) = False -- Giving up; conservative
|
| 642 | 642 | not_in _ (WpEvApp (EvFun {})) = False -- Giving up; conservative
|
| ... | ... | @@ -644,13 +644,6 @@ optSubTypeHsWrapper wrap |
| 644 | 644 | not_in _ (WpEvLam {}) = False -- Ditto
|
| 645 | 645 | not_in _ (WpLet {}) = False -- Ditto
|
| 646 | 646 | |
| 647 | - not_in_cast_co :: TyVar -> CastCoercion -> Bool
|
|
| 648 | - not_in_cast_co v = \case
|
|
| 649 | - CCoercion co -> not (anyFreeVarsOfCo (== v) co)
|
|
| 650 | - ZCoercion ty cvs -> not (anyFreeVarsOfType (== v) ty)
|
|
| 651 | - && not (v `elemDVarSet` cvs)
|
|
| 652 | - ReflCastCo -> True
|
|
| 653 | - |
|
| 654 | 647 | not_in_submult :: TyVar -> SubMultCo -> Bool
|
| 655 | 648 | not_in_submult v = \case
|
| 656 | 649 | EqMultCo co -> not (anyFreeVarsOfCo (== v) co)
|