Adam Gundry pushed to branch wip/amg/castz at Glasgow Haskell Compiler / GHC
Commits:
-
f459ecc1
by Adam Gundry at 2025-06-09T21:13:49+02:00
-
34eae6a1
by Adam Gundry at 2025-06-09T20:31:23+01:00
-
030a1d36
by Adam Gundry at 2025-06-09T20:31:37+01:00
-
967543c7
by Adam Gundry at 2025-06-09T20:34:10+01:00
-
3734e3b9
by Adam Gundry at 2025-06-09T20:51:34+01:00
-
64177f47
by Adam Gundry at 2025-06-09T20:51:42+01:00
-
8cf3d717
by Adam Gundry at 2025-06-09T20:56:50+01:00
-
3fb84e30
by Adam Gundry at 2025-06-09T21:16:39+01:00
-
32459579
by Adam Gundry at 2025-06-09T21:24:20+01:00
21 changed files:
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/FVs.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/DmdAnal.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/TyCo/FVs.hs
- compiler/GHC/Core/TyCo/Ppr.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/TyCo/Subst.hs
- compiler/GHC/Core/TyCo/Tidy.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Zonk/Type.hs
- docs/users_guide/debugging.rst
Changes:
... | ... | @@ -54,10 +54,7 @@ module GHC.Core.Coercion ( |
54 | 54 | |
55 | 55 | -- ** Cast coercions
|
56 | 56 | castCoToCo,
|
57 | - mkSymCastCo,
|
|
58 | 57 | mkTransCastCo, mkTransCastCoCo, mkTransCoCastCo,
|
59 | - mkPisCastCo,
|
|
60 | - zapCo, zapCos, zapCastCo,
|
|
61 | 58 | |
62 | 59 | -- ** Decomposition
|
63 | 60 | instNewTyCon_maybe,
|
... | ... | @@ -76,7 +73,7 @@ module GHC.Core.Coercion ( |
76 | 73 | pickLR,
|
77 | 74 | |
78 | 75 | isGReflCo, isReflCo, isReflCo_maybe, isGReflCo_maybe, isReflexiveCo, isReflexiveCo_maybe,
|
79 | - isReflCastCo, isReflexiveCastCo,
|
|
76 | + isReflexiveCastCo,
|
|
80 | 77 | isReflCoVar_maybe, isGReflMCo, mkGReflLeftMCo, mkGReflRightMCo,
|
81 | 78 | mkCoherenceRightMCo,
|
82 | 79 | |
... | ... | @@ -2421,7 +2418,7 @@ seqMCo (MCo co) = seqCo co |
2421 | 2418 | |
2422 | 2419 | seqCastCoercion :: CastCoercion -> ()
|
2423 | 2420 | seqCastCoercion (CCoercion co) = seqCo co
|
2424 | -seqCastCoercion (ZCoercion ty cos) = seqType ty `seq` seqCos cos
|
|
2421 | +seqCastCoercion (ZCoercion ty cos) = seqType ty `seq` seqVarSet cos
|
|
2425 | 2422 | |
2426 | 2423 | seqCo :: Coercion -> ()
|
2427 | 2424 | seqCo (Refl ty) = seqType ty
|
... | ... | @@ -2858,54 +2855,23 @@ eqCastCoercionX env = eqTypeX env `on` castCoercionRKind |
2858 | 2855 | -- have discarded the original 'Coercion'.
|
2859 | 2856 | castCoToCo :: Type -> CastCoercion -> CoercionR
|
2860 | 2857 | castCoToCo _ (CCoercion co) = co
|
2861 | -castCoToCo lhs_ty (ZCoercion rhs_ty cos) = mkUnivCo ZCoercionProv cos Representational lhs_ty rhs_ty
|
|
2862 | - |
|
2863 | -mkSymCastCo :: Type -> CastCoercion -> Coercion
|
|
2864 | -mkSymCastCo lhs_ty cco = mkSymCo (castCoToCo lhs_ty cco)
|
|
2858 | +castCoToCo lhs_ty (ZCoercion rhs_ty cos) = mkUnivCo ZCoercionProv (map CoVarCo (nonDetEltsUniqSet cos)) Representational lhs_ty rhs_ty
|
|
2865 | 2859 | |
2866 | 2860 | -- | Compose two 'CastCoercion's transitively, like 'mkTransCo'. If either is
|
2867 | 2861 | -- zapped the whole result will be zapped.
|
2868 | 2862 | mkTransCastCo :: HasDebugCallStack => CastCoercion -> CastCoercion -> CastCoercion
|
2869 | 2863 | mkTransCastCo cco (CCoercion co) = mkTransCastCoCo cco co
|
2870 | -mkTransCastCo cco (ZCoercion ty cos) = ZCoercion ty (zapCastCo cco ++ cos)
|
|
2864 | +mkTransCastCo cco (ZCoercion ty cos) = ZCoercion ty (shallowCoVarsOfCastCo cco `unionVarSet` cos)
|
|
2871 | 2865 | |
2872 | 2866 | -- | Transitively compose a 'CastCoercion' followed by a 'Coercion'.
|
2873 | 2867 | mkTransCastCoCo :: HasDebugCallStack => CastCoercion -> Coercion -> CastCoercion
|
2874 | 2868 | mkTransCastCoCo (CCoercion co1) co2 = CCoercion (mkTransCo co1 co2)
|
2875 | -mkTransCastCoCo (ZCoercion _ cos) co2 = ZCoercion (coercionRKind co2) (zapCo co2 ++ cos)
|
|
2869 | +mkTransCastCoCo (ZCoercion _ cos) co2 = ZCoercion (coercionRKind co2) (shallowCoVarsOfCo co2 `unionVarSet` cos)
|
|
2876 | 2870 | |
2877 | 2871 | -- | Transitively compose a 'Coercion' followed by a 'CastCoercion'.
|
2878 | 2872 | mkTransCoCastCo :: HasDebugCallStack => Coercion -> CastCoercion -> CastCoercion
|
2879 | 2873 | mkTransCoCastCo co1 (CCoercion co2) = CCoercion (mkTransCo co1 co2)
|
2880 | -mkTransCoCastCo co1 (ZCoercion ty cos) = ZCoercion ty (zapCo co1 ++ cos)
|
|
2881 | - |
|
2882 | --- TODO: Adapt this or rebuildLam to work for ZCoercion
|
|
2883 | -mkPisCastCo :: Role -> [Var] -> Type -> CastCoercion -> CastCoercion
|
|
2884 | -mkPisCastCo r vs expr_ty = CCoercion . mkPiCos r vs . castCoToCo expr_ty
|
|
2885 | - |
|
2886 | - |
|
2887 | -zapCo :: Coercion -> [Coercion]
|
|
2888 | -zapCo co = zapCos [co]
|
|
2889 | - |
|
2890 | --- | Throw away the structure of coercions, retaining only the set of variables
|
|
2891 | --- on which they depend.
|
|
2892 | ---
|
|
2893 | --- It is important we use only the *shallow* free CoVars here, because those are
|
|
2894 | --- the ones on which the original coercions necessarily depended and which may
|
|
2895 | --- be substituted away later. If we use the deep CoVars here, we can end up
|
|
2896 | --- retaining references to CoVars that are no longer in scope (see Note [Shallow
|
|
2897 | --- and deep free variables] in GHC.Core.TyCo.FVs).
|
|
2898 | -zapCos :: [Coercion] -> [Coercion]
|
|
2899 | -zapCos cos = map mkCoVarCo $ nonDetEltsUniqSet (shallowCoVarsOfCos cos) -- TODO nonDetEltsUniqSet justified?
|
|
2900 | - |
|
2901 | -zapCastCo :: CastCoercion -> [Coercion]
|
|
2902 | -zapCastCo (CCoercion co) = zapCo co
|
|
2903 | -zapCastCo (ZCoercion _ cos) = cos
|
|
2904 | - |
|
2905 | - |
|
2906 | -isReflCastCo :: CastCoercion -> Bool
|
|
2907 | -isReflCastCo (CCoercion co) = isReflCo co
|
|
2908 | -isReflCastCo (ZCoercion _ _) = False -- TODO: track this?
|
|
2874 | +mkTransCoCastCo co1 (ZCoercion ty cos) = ZCoercion ty (shallowCoVarsOfCo co1 `unionVarSet` cos)
|
|
2909 | 2875 | |
2910 | 2876 | -- | Slowly checks if the coercion is reflexive. Don't call this in a loop,
|
2911 | 2877 | -- as it walks over the entire coercion.
|
... | ... | @@ -279,7 +279,7 @@ expr_fvs (Let (Rec pairs) body) fv_cand in_scope acc |
279 | 279 | |
280 | 280 | cast_co_fvs :: CastCoercion -> FV
|
281 | 281 | cast_co_fvs (CCoercion co) fv_cand in_scope acc = (tyCoFVsOfCo co) fv_cand in_scope acc
|
282 | -cast_co_fvs (ZCoercion ty cos) fv_cand in_scope acc = (tyCoFVsOfType ty `unionFV` mapUnionFV tyCoFVsOfCo cos) fv_cand in_scope acc
|
|
282 | +cast_co_fvs (ZCoercion ty cos) fv_cand in_scope acc = (tyCoFVsOfType ty `unionFV` tyCoFVsOfCoVarSet cos) fv_cand in_scope acc
|
|
283 | 283 | |
284 | 284 | ---------
|
285 | 285 | rhs_fvs :: (Id, CoreExpr) -> FV
|
... | ... | @@ -2221,9 +2221,10 @@ etaInfoApp in_scope expr eis |
2221 | 2221 | go subst (Tick t e) eis
|
2222 | 2222 | = Tick (substTickish subst t) (go subst e eis)
|
2223 | 2223 | |
2224 | - go subst (Cast e (CCoercion co)) (EI bs mco) -- TODO: etaInfoApp ZCoercion
|
|
2224 | + go subst (Cast e cco) (EI bs mco)
|
|
2225 | 2225 | = go subst e (EI bs mco')
|
2226 | 2226 | where
|
2227 | + co = castCoToCo (exprType e) cco -- TODO: can we avoid this?
|
|
2227 | 2228 | mco' = checkReflexiveMCo (Core.substCo subst co `mkTransMCoR` mco)
|
2228 | 2229 | -- See Note [Check for reflexive casts in eta expansion]
|
2229 | 2230 | |
... | ... | @@ -2701,13 +2702,13 @@ same fix. |
2701 | 2702 | tryEtaReduce :: UnVarSet -> [Var] -> CoreExpr -> SubDemand -> Maybe CoreExpr
|
2702 | 2703 | -- Return an expression equal to (\bndrs. body)
|
2703 | 2704 | tryEtaReduce rec_ids bndrs body eval_sd
|
2704 | - = go (reverse bndrs) body (CCoercion (mkRepReflCo (exprType body)))
|
|
2705 | + = go (reverse bndrs) body (mkRepReflCo (exprType body))
|
|
2705 | 2706 | where
|
2706 | 2707 | incoming_arity = count isId bndrs -- See Note [Eta reduction makes sense], point (2)
|
2707 | 2708 | |
2708 | 2709 | go :: [Var] -- Binders, innermost first, types [a3,a2,a1]
|
2709 | 2710 | -> CoreExpr -- Of type tr
|
2710 | - -> CastCoercion -- Of type tr ~ ts
|
|
2711 | + -> Coercion -- Of type tr ~ ts
|
|
2711 | 2712 | -> Maybe CoreExpr -- Of type a1 -> a2 -> a3 -> ts
|
2712 | 2713 | -- See Note [Eta reduction with casted arguments]
|
2713 | 2714 | -- for why we have an accumulating coercion
|
... | ... | @@ -2717,7 +2718,7 @@ tryEtaReduce rec_ids bndrs body eval_sd |
2717 | 2718 | |
2718 | 2719 | -- See Note [Eta reduction with casted function]
|
2719 | 2720 | go bs (Cast e co1) co2
|
2720 | - = go bs e (co1 `mkTransCastCo` co2)
|
|
2721 | + = go bs e (castCoToCo (exprType e) co1 `mkTransCo` co2)
|
|
2721 | 2722 | |
2722 | 2723 | go bs (Tick t e) co
|
2723 | 2724 | | tickishFloatable t
|
... | ... | @@ -2740,7 +2741,7 @@ tryEtaReduce rec_ids bndrs body eval_sd |
2740 | 2741 | , remaining_bndrs `ltLength` bndrs
|
2741 | 2742 | -- Only reply Just if /something/ has happened
|
2742 | 2743 | , ok_fun fun
|
2743 | - , let used_vars = exprFreeVars fun `unionVarSet` tyCoVarsOfCastCo co
|
|
2744 | + , let used_vars = exprFreeVars fun `unionVarSet` tyCoVarsOfCo co
|
|
2744 | 2745 | reduced_bndrs = mkVarSet (dropList remaining_bndrs bndrs)
|
2745 | 2746 | -- reduced_bndrs are the ones we are eta-reducing away
|
2746 | 2747 | , used_vars `disjointVarSet` reduced_bndrs
|
... | ... | @@ -2749,7 +2750,7 @@ tryEtaReduce rec_ids bndrs body eval_sd |
2749 | 2750 | -- See Note [Eta reduction makes sense], intro and point (1)
|
2750 | 2751 | -- NB: don't compute used_vars from exprFreeVars (mkCast fun co)
|
2751 | 2752 | -- because the latter may be ill formed if the guard fails (#21801)
|
2752 | - = Just (mkLams (reverse remaining_bndrs) (mkCastCo fun co))
|
|
2753 | + = Just (mkLams (reverse remaining_bndrs) (mkCast fun co))
|
|
2753 | 2754 | |
2754 | 2755 | go _remaining_bndrs _fun _ = -- pprTrace "tER fail" (ppr _fun $$ ppr _remaining_bndrs) $
|
2755 | 2756 | Nothing
|
... | ... | @@ -2797,17 +2798,17 @@ tryEtaReduce rec_ids bndrs body eval_sd |
2797 | 2798 | ---------------
|
2798 | 2799 | ok_arg :: Var -- Of type bndr_t
|
2799 | 2800 | -> CoreExpr -- Of type arg_t
|
2800 | - -> CastCoercion -- Of kind (t1~t2)
|
|
2801 | + -> Coercion -- Of kind (t1~t2)
|
|
2801 | 2802 | -> Type -- Type (arg_t -> t1) of the function
|
2802 | 2803 | -- to which the argument is supplied
|
2803 | - -> Maybe (CastCoercion -- Of type (arg_t -> t1 ~ bndr_t -> t2)
|
|
2804 | - -- (and similarly for tyvars, coercion args)
|
|
2804 | + -> Maybe (Coercion -- Of type (arg_t -> t1 ~ bndr_t -> t2)
|
|
2805 | + -- (and similarly for tyvars, coercion args)
|
|
2805 | 2806 | , [CoreTickish])
|
2806 | 2807 | -- See Note [Eta reduction with casted arguments]
|
2807 | - ok_arg bndr (Type arg_ty) (CCoercion co) fun_ty
|
|
2808 | + ok_arg bndr (Type arg_ty) co fun_ty
|
|
2808 | 2809 | | Just tv <- getTyVar_maybe arg_ty
|
2809 | 2810 | , bndr == tv = case splitForAllForAllTyBinder_maybe fun_ty of
|
2810 | - Just (Bndr _ vis, _) -> Just (CCoercion fco, [])
|
|
2811 | + Just (Bndr _ vis, _) -> Just (fco, [])
|
|
2811 | 2812 | where !fco = mkForAllCo tv vis coreTyLamForAllTyFlag kco co
|
2812 | 2813 | -- The lambda we are eta-reducing always has visibility
|
2813 | 2814 | -- 'coreTyLamForAllTyFlag' which may or may not match
|
... | ... | @@ -2817,24 +2818,23 @@ tryEtaReduce rec_ids bndrs body eval_sd |
2817 | 2818 | (text "fun:" <+> ppr bndr
|
2818 | 2819 | $$ text "arg:" <+> ppr arg_ty
|
2819 | 2820 | $$ text "fun_ty:" <+> ppr fun_ty)
|
2820 | - ok_arg bndr (Var v) (CCoercion co) fun_ty
|
|
2821 | + ok_arg bndr (Var v) co fun_ty
|
|
2821 | 2822 | | bndr == v
|
2822 | 2823 | , let mult = idMult bndr
|
2823 | 2824 | , Just (_af, fun_mult, _, _) <- splitFunTy_maybe fun_ty
|
2824 | 2825 | , mult `eqType` fun_mult -- There is no change in multiplicity, otherwise we must abort
|
2825 | - = Just (CCoercion $ mkFunResCo Representational bndr co, [])
|
|
2826 | - ok_arg bndr (Cast e co_arg) (CCoercion co) fun_ty
|
|
2826 | + = Just (mkFunResCo Representational bndr co, [])
|
|
2827 | + ok_arg bndr (Cast e co_arg) co fun_ty
|
|
2827 | 2828 | | (ticks, Var v) <- stripTicksTop tickishFloatable e
|
2828 | 2829 | , Just (_, fun_mult, _, _) <- splitFunTy_maybe fun_ty
|
2829 | 2830 | , bndr == v
|
2830 | 2831 | , fun_mult `eqType` idMult bndr
|
2831 | - = Just (CCoercion $ mkFunCoNoFTF Representational (multToCo fun_mult) (mkSymCastCo (exprType e) co_arg) co, ticks)
|
|
2832 | + = Just (mkFunCoNoFTF Representational (multToCo fun_mult) (mkSymCo (castCoToCo (exprType e) co_arg)) co, ticks)
|
|
2832 | 2833 | -- The simplifier combines multiple casts into one,
|
2833 | 2834 | -- so we can have a simple-minded pattern match here
|
2834 | 2835 | ok_arg bndr (Tick t arg) co fun_ty
|
2835 | 2836 | | tickishFloatable t, Just (co', ticks) <- ok_arg bndr arg co fun_ty
|
2836 | 2837 | = Just (co', t:ticks)
|
2837 | - -- TODO ok_arg for ZCoercion?
|
|
2838 | 2838 | ok_arg _ _ _ _ = Nothing
|
2839 | 2839 | |
2840 | 2840 | -- | Can we eta-reduce the given function
|
... | ... | @@ -3107,13 +3107,13 @@ collectBindersPushingCo e |
3107 | 3107 | go :: [Var] -> CoreExpr -> ([Var], CoreExpr)
|
3108 | 3108 | -- The accumulator is in reverse order
|
3109 | 3109 | go bs (Lam b e) = go (b:bs) e
|
3110 | - go bs (Cast e (CCoercion co)) = go_c bs e co -- TODO: ought to have ZCoercion case or go_c generalised
|
|
3110 | + go bs (Cast e co) = go_c bs e (castCoToCo (exprType e) co) -- TODO: can we do better?
|
|
3111 | 3111 | go bs e = (reverse bs, e)
|
3112 | 3112 | |
3113 | 3113 | -- We are in a cast; peel off casts until we hit a lambda.
|
3114 | 3114 | go_c :: [Var] -> CoreExpr -> Coercion -> ([Var], CoreExpr)
|
3115 | 3115 | -- (go_c bs e c) is same as (go bs e (e |> c))
|
3116 | - go_c bs (Cast e (CCoercion co1)) co2 = go_c bs e (co1 `mkTransCo` co2) -- TODO ditto
|
|
3116 | + go_c bs (Cast e co1) co2 = go_c bs e (castCoToCo (exprType e) co1 `mkTransCo` co2) -- TODO: can we do better?
|
|
3117 | 3117 | go_c bs (Lam b e) co = go_lam bs b e co
|
3118 | 3118 | go_c bs e co = (reverse bs, mkCast e co)
|
3119 | 3119 |
... | ... | @@ -2405,13 +2405,17 @@ coercionDmdEnv co = coercionsDmdEnv [co] |
2405 | 2405 | |
2406 | 2406 | castCoercionDmdEnv :: CastCoercion -> DmdEnv
|
2407 | 2407 | castCoercionDmdEnv (CCoercion co) = coercionDmdEnv co
|
2408 | -castCoercionDmdEnv (ZCoercion _ cos) = coercionsDmdEnv cos
|
|
2408 | +castCoercionDmdEnv (ZCoercion _ cos) = coVarSetDmdEnv cos
|
|
2409 | 2409 | |
2410 | 2410 | coercionsDmdEnv :: [Coercion] -> DmdEnv
|
2411 | 2411 | coercionsDmdEnv cos
|
2412 | 2412 | = mkTermDmdEnv $ mapVarEnv (const topDmd) $ getUniqSet $ coVarsOfCos cos
|
2413 | 2413 | -- The VarSet from coVarsOfCos is really a VarEnv Var
|
2414 | 2414 | |
2415 | +coVarSetDmdEnv :: CoVarSet -> DmdEnv
|
|
2416 | +coVarSetDmdEnv cos
|
|
2417 | + = mkTermDmdEnv $ mapVarEnv (const topDmd) $ getUniqSet cos -- TODO shallow/deep confusion?
|
|
2418 | + |
|
2415 | 2419 | addVarDmd :: DmdType -> Var -> Demand -> DmdType
|
2416 | 2420 | addVarDmd (DmdType fv ds) var dmd
|
2417 | 2421 | = DmdType (addVarDmdEnv fv var dmd) ds
|
... | ... | @@ -3435,8 +3435,8 @@ scrutOkForBinderSwap :: OutExpr -> BinderSwapDecision |
3435 | 3435 | -- We use this same function in SpecConstr, and Simplify.Iteration,
|
3436 | 3436 | -- when something binder-swap-like is happening
|
3437 | 3437 | scrutOkForBinderSwap (Var v) = DoBinderSwap v MRefl
|
3438 | -scrutOkForBinderSwap (Cast (Var v) (CCoercion co)) -- TODO scrutOkForBinderSwap for ZCoercion
|
|
3439 | - | not (isDictId v) = DoBinderSwap v (MCo (mkSymCo co))
|
|
3438 | +scrutOkForBinderSwap (Cast (Var v) co)
|
|
3439 | + | not (isDictId v) = DoBinderSwap v (MCo (mkSymCo (castCoToCo (idType v) co))) -- TODO: can we do better?
|
|
3440 | 3440 | -- Cast: see Note [Case of cast]
|
3441 | 3441 | -- isDictId: see Note [Care with binder-swap on dictionaries]
|
3442 | 3442 | -- The isDictId rejects a Constraint/Constraint binder-swap, perhaps
|
... | ... | @@ -644,7 +644,7 @@ tryCastWorkerWrapper env bind_cxt old_bndr bndr (Cast rhs co) |
644 | 644 | mk_worker_unfolding top_lvl work_id work_rhs
|
645 | 645 | = case realUnfoldingInfo info of -- NB: the real one, even for loop-breakers
|
646 | 646 | unf@(CoreUnfolding { uf_tmpl = unf_rhs, uf_src = src })
|
647 | - | isStableSource src -> return (unf { uf_tmpl = mkCast unf_rhs (mkSymCastCo (exprType rhs) co) })
|
|
647 | + | isStableSource src -> return (unf { uf_tmpl = mkCast unf_rhs (mkSymCo (castCoToCo (exprType rhs) co)) })
|
|
648 | 648 | _ -> mkLetUnfolding env top_lvl VanillaSrc work_id False work_rhs
|
649 | 649 | |
650 | 650 | tryCastWorkerWrapper env _ _ bndr rhs -- All other bindings
|
... | ... | @@ -1836,7 +1836,7 @@ rebuildLam env bndrs@(bndr:_) body cont |
1836 | 1836 | | -- Note [Casts and lambdas]
|
1837 | 1837 | seCastSwizzle env
|
1838 | 1838 | , not (any bad bndrs)
|
1839 | - = mkCastCo (mk_lams bndrs body) (mkPisCastCo Representational bndrs (exprType body) co)
|
|
1839 | + = mkCast (mk_lams bndrs body) (mkPiCos Representational bndrs (castCoToCo (exprType body) co))
|
|
1840 | 1840 | where
|
1841 | 1841 | co_vars = tyCoVarsOfCastCo co
|
1842 | 1842 | bad bndr = isCoVar bndr && bndr `elemVarSet` co_vars
|
... | ... | @@ -35,6 +35,7 @@ import GHC.Types.Fixity (LexicalFixity(..)) |
35 | 35 | import GHC.Types.Literal( pprLiteral )
|
36 | 36 | import GHC.Types.Name( pprInfixName, pprPrefixName )
|
37 | 37 | import GHC.Types.Var
|
38 | +import GHC.Types.Var.Set
|
|
38 | 39 | import GHC.Types.Id
|
39 | 40 | import GHC.Types.Id.Info
|
40 | 41 | import GHC.Types.Demand
|
... | ... | @@ -171,10 +172,12 @@ noParens pp = pp |
171 | 172 | |
172 | 173 | pprOptCastCoercion :: CastCoercion -> SDoc
|
173 | 174 | pprOptCastCoercion (CCoercion co) = pprOptCo co
|
174 | -pprOptCastCoercion (ZCoercion ty cos) = -- TODO review ppr format
|
|
175 | - sdocOption sdocSuppressCoercions $ \case
|
|
176 | - True -> angleBrackets (text "ZapCo:" <> int (sum (map coercionSize cos))) <+> dcolon <+> co_type
|
|
177 | - False -> parens $ sep [text "Zap", ppr cos, dcolon <+> co_type]
|
|
175 | +pprOptCastCoercion (ZCoercion ty cos) = pprOptZappedCo ty cos
|
|
176 | + |
|
177 | +pprOptZappedCo :: Type -> CoVarSet -> SDoc
|
|
178 | +pprOptZappedCo ty cos = sdocOption sdocSuppressCoercions $ \case
|
|
179 | + True -> angleBrackets (text "ZapCo:" <> int (sizeVarSet cos)) <+> dcolon <+> co_type
|
|
180 | + False -> parens $ sep [text "ZapCo", ppr cos, dcolon <+> co_type]
|
|
178 | 181 | where
|
179 | 182 | co_type = sdocOption sdocSuppressCoercionTypes $ \case
|
180 | 183 | True -> int (typeSize ty) <+> text "..."
|
... | ... | @@ -1108,15 +1108,13 @@ match renv subst (Coercion co1) (Coercion co2) MRefl |
1108 | 1108 | -- Note [Casts in the target]
|
1109 | 1109 | -- Note [Cancel reflexive casts]
|
1110 | 1110 | |
1111 | -match renv subst e1 (Cast e2 (CCoercion co2)) mco
|
|
1112 | - = match renv subst e1 e2 (checkReflexiveMCo (mkTransMCoR co2 mco))
|
|
1111 | +match renv subst e1 (Cast e2 co2) mco
|
|
1112 | + = match renv subst e1 e2 (checkReflexiveMCo (mkTransMCoR (castCoToCo (exprType e2) co2) mco))
|
|
1113 | 1113 | -- checkReflexiveMCo: cancel casts if possible
|
1114 | 1114 | -- This is important: see Note [Cancel reflexive casts]
|
1115 | 1115 | |
1116 | -match renv subst (Cast e1 (CCoercion co1)) e2 mco
|
|
1117 | - = matchTemplateCast renv subst e1 co1 e2 mco
|
|
1118 | - |
|
1119 | --- TODO: rule matching for ZCoercion
|
|
1116 | +match renv subst (Cast e1 co1) e2 mco
|
|
1117 | + = matchTemplateCast renv subst e1 (castCoToCo (exprType e1) co1) e2 mco
|
|
1120 | 1118 | |
1121 | 1119 | ------------------------ Literals ---------------------
|
1122 | 1120 | match _ subst (Lit lit1) (Lit lit2) mco
|
... | ... | @@ -33,6 +33,7 @@ import GHC.Core.DataCon |
33 | 33 | import GHC.Core.Coercion.Opt ( optCoercion, OptCoercionOpts (..) )
|
34 | 34 | import GHC.Core.Type hiding ( substTy, extendTvSubst, extendCvSubst, extendTvSubstList
|
35 | 35 | , isInScope, substTyVarBndr, cloneTyVarBndr )
|
36 | +import GHC.Core.TyCo.Subst
|
|
36 | 37 | import GHC.Core.Predicate( isCoVarType )
|
37 | 38 | import GHC.Core.Coercion hiding ( substCo, substCoVarBndr )
|
38 | 39 | |
... | ... | @@ -324,7 +325,7 @@ simple_opt_expr env expr |
324 | 325 | |
325 | 326 | ----------------------
|
326 | 327 | go_cast_co (CCoercion co) = CCoercion (go_co co)
|
327 | - go_cast_co (ZCoercion ty cos) = ZCoercion (substTyUnchecked subst ty) (substCos subst cos)
|
|
328 | + go_cast_co (ZCoercion ty cos) = ZCoercion (substTyUnchecked subst ty) (substCoVarSet subst cos)
|
|
328 | 329 | |
329 | 330 | go_co co = optCoercion (so_co_opts (soe_opts env)) subst co
|
330 | 331 | |
... | ... | @@ -439,14 +440,13 @@ simple_app env e as |
439 | 440 | finish_app :: HasDebugCallStack
|
440 | 441 | => SimpleOptEnv -> OutExpr -> [SimpleClo] -> OutExpr
|
441 | 442 | -- See Note [Eliminate casts in function position]
|
442 | -finish_app env (Cast (Lam x e) (CCoercion co)) as@(_:_)
|
|
443 | +finish_app env (Cast (Lam x e) cco) as@(_:_)
|
|
443 | 444 | | not (isTyVar x) && not (isCoVar x)
|
445 | + , let co = castCoToCo (exprType (Lam x e)) cco
|
|
444 | 446 | , assert (not $ x `elemVarSet` tyCoVarsOfCo co) True
|
445 | 447 | , Just (x',e') <- pushCoercionIntoLambda (soeInScope env) x e co
|
446 | 448 | = simple_app (soeZapSubst env) (Lam x' e') as
|
447 | 449 | |
448 | --- TODO: ZCoercion version of the finish_app
|
|
449 | - |
|
450 | 450 | finish_app env fun args
|
451 | 451 | = foldl mk_app fun args
|
452 | 452 | where
|
... | ... | @@ -1297,13 +1297,11 @@ exprIsConApp_maybe ise@(ISE in_scope id_unf) expr |
1297 | 1297 | go subst floats (Tick t expr) cont
|
1298 | 1298 | | not (tickishIsCode t) = go subst floats expr cont
|
1299 | 1299 | |
1300 | - go subst floats (Cast expr (CCoercion co1)) (CC args m_co2)
|
|
1301 | - | Just (args', m_co1') <- pushCoArgs (subst_co subst co1) args
|
|
1300 | + go subst floats (Cast expr co1) (CC args m_co2)
|
|
1301 | + | Just (args', m_co1') <- pushCoArgs (subst_co subst (castCoToCo (exprType expr) co1)) args
|
|
1302 | 1302 | -- See Note [Push coercions in exprIsConApp_maybe]
|
1303 | 1303 | = go subst floats expr (CC args' (m_co1' `mkTransMCo` m_co2))
|
1304 | 1304 | |
1305 | - -- TODO: ZCoercion in exprIsConApp_maybe
|
|
1306 | - |
|
1307 | 1305 | go subst floats (App fun arg) (CC args mco)
|
1308 | 1306 | | let arg_type = exprType arg
|
1309 | 1307 | , not (isTypeArg arg) && needsCaseBinding arg_type arg
|
... | ... | @@ -1590,19 +1588,18 @@ exprIsLambda_maybe ise (Tick t e) |
1590 | 1588 | = Just (x, e, t:ts)
|
1591 | 1589 | |
1592 | 1590 | -- Also possible: A casted lambda. Push the coercion inside
|
1593 | -exprIsLambda_maybe ise@(ISE in_scope_set _) (Cast casted_e (CCoercion co))
|
|
1591 | +exprIsLambda_maybe ise@(ISE in_scope_set _) (Cast casted_e cco)
|
|
1594 | 1592 | | Just (x, e,ts) <- exprIsLambda_maybe ise casted_e
|
1595 | 1593 | -- Only do value lambdas.
|
1596 | 1594 | -- this implies that x is not in scope in gamma (makes this code simpler)
|
1597 | 1595 | , not (isTyVar x) && not (isCoVar x)
|
1596 | + , let co = castCoToCo (exprType casted_e) cco
|
|
1598 | 1597 | , assert (not $ x `elemVarSet` tyCoVarsOfCo co) True
|
1599 | 1598 | , Just (x',e') <- pushCoercionIntoLambda in_scope_set x e co
|
1600 | 1599 | , let res = Just (x',e',ts)
|
1601 | 1600 | = --pprTrace "exprIsLambda_maybe:Cast" (vcat [ppr casted_e,ppr co,ppr res)])
|
1602 | 1601 | res
|
1603 | 1602 | |
1604 | --- TODO: exprIsLambda_maybe for ZCoercion
|
|
1605 | - |
|
1606 | 1603 | -- Another attempt: See if we find a partial unfolding
|
1607 | 1604 | exprIsLambda_maybe ise@(ISE in_scope_set id_unf) e
|
1608 | 1605 | | (Var f, as, ts) <- collectArgsTicks tickishFloatable e
|
... | ... | @@ -18,10 +18,10 @@ module GHC.Core.TyCo.FVs |
18 | 18 | coVarsOfType, coVarsOfTypes,
|
19 | 19 | coVarsOfCo, coVarsOfCos,
|
20 | 20 | coVarsOfCastCo,
|
21 | - shallowCoVarsOfCos,
|
|
21 | + shallowCoVarsOfCo, shallowCoVarsOfCos, shallowCoVarsOfCastCo,
|
|
22 | 22 | tyCoVarsOfCastCoercionDSet,
|
23 | 23 | tyCoVarsOfCoDSet,
|
24 | - tyCoFVsOfCo, tyCoFVsOfCos,
|
|
24 | + tyCoFVsOfCo, tyCoFVsOfCos, tyCoFVsOfCoVarSet,
|
|
25 | 25 | tyCoVarsOfCoList,
|
26 | 26 | coVarsOfCoDSet, coVarsOfCosDSet,
|
27 | 27 | |
... | ... | @@ -303,7 +303,7 @@ runTyCoVars f = appEndo f emptyVarSet |
303 | 303 | |
304 | 304 | tyCoVarsOfCastCo :: CastCoercion -> TyCoVarSet
|
305 | 305 | tyCoVarsOfCastCo (CCoercion co) = coVarsOfCo co
|
306 | -tyCoVarsOfCastCo (ZCoercion ty cos) = tyCoVarsOfType ty `unionVarSet` tyCoVarsOfCos cos -- TODO: more efficient?
|
|
306 | +tyCoVarsOfCastCo (ZCoercion ty cos) = tyCoVarsOfType ty `unionVarSet` cos
|
|
307 | 307 | |
308 | 308 | tyCoVarsOfType :: Type -> TyCoVarSet
|
309 | 309 | -- The "deep" TyCoVars of the the type
|
... | ... | @@ -412,6 +412,16 @@ shallowTcvFolder = TyCoFolder { tcf_view = noView -- See Note [Free vars and sy |
412 | 412 | shallowCoVarsOfCos :: [Coercion] -> CoVarSet
|
413 | 413 | shallowCoVarsOfCos cos = filterVarSet isCoVar $ shallowTyCoVarsOfCos cos
|
414 | 414 | |
415 | +shallowCoVarsOfCo :: Coercion -> CoVarSet
|
|
416 | +shallowCoVarsOfCo co = filterVarSet isCoVar $ shallowTyCoVarsOfCo co
|
|
417 | + |
|
418 | +shallowCoVarsOfType :: Type -> CoVarSet
|
|
419 | +shallowCoVarsOfType ty = filterVarSet isCoVar $ shallowTyCoVarsOfType ty
|
|
420 | + |
|
421 | +shallowCoVarsOfCastCo :: CastCoercion -> CoVarSet
|
|
422 | +shallowCoVarsOfCastCo (CCoercion co) = shallowCoVarsOfCo co
|
|
423 | +shallowCoVarsOfCastCo (ZCoercion ty cos) = shallowCoVarsOfType ty `unionVarSet` cos
|
|
424 | + |
|
415 | 425 | |
416 | 426 | {- *********************************************************************
|
417 | 427 | * *
|
... | ... | @@ -432,7 +442,7 @@ See #14880. |
432 | 442 | |
433 | 443 | coVarsOfCastCo :: CastCoercion -> CoVarSet
|
434 | 444 | coVarsOfCastCo (CCoercion co) = coVarsOfCo co
|
435 | -coVarsOfCastCo (ZCoercion ty cos) = coVarsOfType ty `unionVarSet` coVarsOfCos cos -- TODO: more efficient?
|
|
445 | +coVarsOfCastCo (ZCoercion ty cos) = coVarsOfType ty `unionVarSet` cos -- TODO cos doesn't include deep, this isn't enough?
|
|
436 | 446 | |
437 | 447 | -- See Note [Finding free coercion variables]
|
438 | 448 | coVarsOfType :: Type -> CoVarSet
|
... | ... | @@ -666,7 +676,10 @@ tyCoFVsOfMCo (MCo co) = tyCoFVsOfCo co |
666 | 676 | |
667 | 677 | tyCoFVsOfCastCoercion :: CastCoercion -> FV
|
668 | 678 | tyCoFVsOfCastCoercion (CCoercion co) = tyCoFVsOfCo co
|
669 | -tyCoFVsOfCastCoercion (ZCoercion ty cos) = unionsFV (tyCoFVsOfType ty : map tyCoFVsOfCo cos)
|
|
679 | +tyCoFVsOfCastCoercion (ZCoercion ty cos) = tyCoFVsOfType ty `unionFV` tyCoFVsOfCoVarSet cos
|
|
680 | + |
|
681 | +tyCoFVsOfCoVarSet :: CoVarSet -> FV
|
|
682 | +tyCoFVsOfCoVarSet = nonDetStrictFoldVarSet (unionFV . tyCoFVsOfCoVar) emptyFV -- TODO better way? Nondeterminism?
|
|
670 | 683 | |
671 | 684 | tyCoFVsOfCo :: Coercion -> FV
|
672 | 685 | -- Extracts type and coercion variables from a coercion
|
... | ... | @@ -48,6 +48,7 @@ import GHC.Types.Var |
48 | 48 | |
49 | 49 | import GHC.Iface.Type
|
50 | 50 | |
51 | +import GHC.Types.Unique.Set
|
|
51 | 52 | import GHC.Types.Var.Set
|
52 | 53 | import GHC.Types.Var.Env
|
53 | 54 | |
... | ... | @@ -138,7 +139,7 @@ pprCastCo co = getPprStyle $ \ sty -> pprIfaceCastCoercion (tidyToIfaceCastCoSty |
138 | 139 | |
139 | 140 | tidyToIfaceCastCoSty :: CastCoercion -> PprStyle -> IfaceCastCoercion
|
140 | 141 | tidyToIfaceCastCoSty (CCoercion co) sty = IfaceCCoercion (tidyToIfaceCoSty co sty)
|
141 | -tidyToIfaceCastCoSty (ZCoercion ty cos) sty = IfaceZCoercion (tidyToIfaceType ty) (map (flip tidyToIfaceCoSty sty) cos) -- TODO
|
|
142 | +tidyToIfaceCastCoSty (ZCoercion ty cos) sty = IfaceZCoercion (tidyToIfaceType ty) (map (flip tidyToIfaceCoSty sty . CoVarCo) (nonDetEltsUniqSet cos)) -- TODO
|
|
142 | 143 | |
143 | 144 | tidyToIfaceCoSty :: Coercion -> PprStyle -> IfaceCoercion
|
144 | 145 | tidyToIfaceCoSty co sty
|
... | ... | @@ -77,7 +77,7 @@ import {-# SOURCE #-} GHC.Core.Type( chooseFunTyFlag, typeKind, typeTypeOrConstr |
77 | 77 | |
78 | 78 | -- friends:
|
79 | 79 | import GHC.Types.Var
|
80 | -import GHC.Types.Var.Set( elemVarSet )
|
|
80 | +import GHC.Types.Var.Set
|
|
81 | 81 | import GHC.Core.TyCon
|
82 | 82 | import GHC.Core.Coercion.Axiom
|
83 | 83 | |
... | ... | @@ -847,16 +847,17 @@ Note [Zapped casts] |
847 | 847 | ~~~~~~~~~~~~~~~~~~~
|
848 | 848 | A "zapped cast" is a Cast that does not store the full Coercion being used to
|
849 | 849 | cast, but instead stores the type resulting from the cast and a set of CoVars
|
850 | -used in the original coercion. This reduces the effectiveness of Core Lint,
|
|
851 | -because it cannot check the original coercion.
|
|
850 | +used in the original coercion. The CastCoercion type is used to represent
|
|
851 | +the coercion argument to a cast; it may be either a full coercion (CCoercion)
|
|
852 | +or zapped (ZCoercion).
|
|
852 | 853 | |
853 | 854 | Zapping casts is motivated by performance (see #8095 and related tickets).
|
854 | 855 | Sometimes the structure of the coercion can be very large, for example when
|
855 | 856 | using type families that take many reduction steps, and when Core Lint is
|
856 | 857 | not being used, the full structure of the coercion is not needed. We merely
|
857 | 858 | need the result type (to support exprType) and the set of coercion variables
|
858 | -(to avoid floating a coercion out of the scope in which it is valid).
|
|
859 | -TODO: reference another note about this.
|
|
859 | +(to avoid floating a coercion out of the scope in which it is valid, see
|
|
860 | +Note [The importance of tracking UnivCo dependencies]).
|
|
860 | 861 | |
861 | 862 | Zapped casts are introduced in exactly one place: finish_rewrite in
|
862 | 863 | GHC.Tc.Solver.Solve. This uses a heuristic (isSmallCo) to determine whether
|
... | ... | @@ -870,15 +871,32 @@ which is much smaller than: |
870 | 871 | |
871 | 872 | This arises in practice with the Rep type family from GHC Generics.
|
872 | 873 | |
874 | +We can convert a ZCoercion back into a normal Coercion using castCoToCo to
|
|
875 | +produce a UnivCo; such coercions can be identified for debugging with the
|
|
876 | +ZCoercionProv provenance. This is sometimes necessary in the optimizer, when a
|
|
877 | +Cast needs to be moved elsewhere. Since a UnivCo must store both the left and
|
|
878 | +right hand side types, it is less compact than a ZCoercion, so it is best to
|
|
879 | +avoid castCoToCo where possible.
|
|
880 | + |
|
873 | 881 | The `-fzap-casts` and `-fno-zap-casts` flags can be used to enable or disable
|
874 | 882 | cast zapping, for comparative performance testing or to ensure casts are not
|
875 | -zapped when debugging the compiler. In addition, using `-dcore-lint` will
|
|
876 | -automatically imply `-fno-zap-casts`.
|
|
883 | +zapped when debugging the compiler.
|
|
884 | + |
|
885 | +Zapping reduces the effectiveness of Core Lint, because it cannot check that
|
|
886 | +the original coercion was well-typed. Thus `-dcore-lint` will automatically
|
|
887 | +imply `-fno-zap-casts` for the same module. However, imported modules may still
|
|
888 | +include zapped casts.
|
|
877 | 889 | TODO: probably the boot libraries ought to be distributed with `-fno-zap-casts`,
|
878 | 890 | so users can get full checks from `-dcore-lint`.
|
879 | 891 | |
880 | -TODO: for simplicity ZCoercion currently stores a list of Coercions, but in
|
|
881 | -principle we need only the CoVars.
|
|
892 | +ZCoercion discards the structure of the coercion, retaining only the set of variables
|
|
893 | +on which it depends. It is important we store only the "shallow" free CoVars in the
|
|
894 | +set, because those are the ones on which the original coercions necessarily depended
|
|
895 | +and which may be substituted away later. If we use the deep CoVars, we can end up
|
|
896 | +retaining references to CoVars that are no longer in scope. See also
|
|
897 | +Note [Shallow and deep free variables] in GHC.Core.TyCo.FVs.
|
|
898 | + |
|
899 | +TODO: review determinism; are our uses of nonDetEltsUniqSet and similar safe?
|
|
882 | 900 | |
883 | 901 | -}
|
884 | 902 | |
... | ... | @@ -887,7 +905,7 @@ principle we need only the CoVars. |
887 | 905 | -- and free CoVars. See Note [Zapped casts].
|
888 | 906 | data CastCoercion
|
889 | 907 | = CCoercion CoercionR -- Not zapped; the Coercion has Representational role
|
890 | - | ZCoercion Type [Coercion] -- Zapped; the Coercions are just variables (TODO: use CoVarSet instead?)
|
|
908 | + | ZCoercion Type CoVarSet -- Zapped; stores only the RHS type and free CoVars
|
|
891 | 909 | deriving Data.Data
|
892 | 910 | |
893 | 911 | -- | A 'Coercion' is concrete evidence of the equality/convertibility
|
... | ... | @@ -2069,7 +2087,7 @@ typesSize tys = foldr ((+) . typeSize) 0 tys |
2069 | 2087 | |
2070 | 2088 | castCoercionSize :: CastCoercion -> Int
|
2071 | 2089 | castCoercionSize (CCoercion co) = coercionSize co
|
2072 | -castCoercionSize (ZCoercion ty cos) = typeSize ty + sum (map coercionSize cos)
|
|
2090 | +castCoercionSize (ZCoercion ty cos) = typeSize ty + sizeVarSet cos
|
|
2073 | 2091 | |
2074 | 2092 | coercionSize :: Coercion -> Int
|
2075 | 2093 | coercionSize (Refl ty) = typeSize ty
|
... | ... | @@ -34,7 +34,7 @@ module GHC.Core.TyCo.Subst |
34 | 34 | substTyUnchecked, substTysUnchecked, substScaledTysUnchecked, substThetaUnchecked,
|
35 | 35 | substTyWithUnchecked, substScaledTyUnchecked,
|
36 | 36 | substCoUnchecked, substCoWithUnchecked,
|
37 | - substCastCo, substCastCoUnchecked,
|
|
37 | + substCastCo, substCoVarSet,
|
|
38 | 38 | substTyWithInScope,
|
39 | 39 | substTys, substScaledTys, substTheta,
|
40 | 40 | lookupTyVar,
|
... | ... | @@ -846,12 +846,12 @@ lookupTyVar (Subst _ _ tenv _) tv |
846 | 846 | lookupVarEnv tenv tv
|
847 | 847 | |
848 | 848 | substCastCo :: HasDebugCallStack => Subst -> CastCoercion -> CastCoercion
|
849 | -substCastCo subst (CCoercion co) = CCoercion (substCo subst co)
|
|
850 | -substCastCo subst (ZCoercion ty cos) = ZCoercion (substTy subst ty) (map (substCo subst) cos) -- TODO: zap?
|
|
849 | +substCastCo subst (CCoercion co) = CCoercion (substCo subst co)
|
|
850 | +substCastCo subst (ZCoercion ty cos) = ZCoercion (substTy subst ty) (substCoVarSet subst cos)
|
|
851 | + |
|
852 | +substCoVarSet :: HasDebugCallStack => Subst -> CoVarSet -> CoVarSet
|
|
853 | +substCoVarSet subst = nonDetStrictFoldVarSet (unionVarSet . shallowCoVarsOfCo . substCoVar subst) emptyVarSet -- TODO better impl; determinism?
|
|
851 | 854 | |
852 | -substCastCoUnchecked :: Subst -> CastCoercion -> CastCoercion
|
|
853 | -substCastCoUnchecked subst (CCoercion co) = CCoercion (substCoUnchecked subst co)
|
|
854 | -substCastCoUnchecked subst (ZCoercion ty cos) = ZCoercion (substTyUnchecked subst ty) (map (substCoUnchecked subst) cos) -- TODO: zap?
|
|
855 | 855 | |
856 | 856 | -- | Substitute within a 'Coercion'
|
857 | 857 | -- The substitution has to satisfy the invariants described in
|
... | ... | @@ -26,6 +26,7 @@ import GHC.Core.TyCo.FVs |
26 | 26 | import GHC.Types.Name hiding (varName)
|
27 | 27 | import GHC.Types.Var
|
28 | 28 | import GHC.Types.Var.Env
|
29 | +import GHC.Types.Var.Set
|
|
29 | 30 | import GHC.Utils.Misc (strictMap)
|
30 | 31 | |
31 | 32 | import Data.List (mapAccumL)
|
... | ... | @@ -366,4 +367,4 @@ tidyCos env = strictMap (tidyCo env) |
366 | 367 | |
367 | 368 | tidyCastCo :: TidyEnv -> CastCoercion -> CastCoercion
|
368 | 369 | tidyCastCo env (CCoercion co) = CCoercion (tidyCo env co)
|
369 | -tidyCastCo env (ZCoercion ty cos) = ZCoercion (tidyType env ty) (tidyCos env cos) |
|
370 | +tidyCastCo env (ZCoercion ty cos) = ZCoercion (tidyType env ty) (mapVarSet (tidyTyCoVarOcc env) cos) |
... | ... | @@ -77,6 +77,7 @@ import GHC.Core.Type as Type |
77 | 77 | import GHC.Core.Predicate( isCoVarType )
|
78 | 78 | import GHC.Core.FamInstEnv
|
79 | 79 | import GHC.Core.TyCo.Compare( eqType, eqTypeX )
|
80 | +import GHC.Core.TyCo.FVs
|
|
80 | 81 | import GHC.Core.Coercion
|
81 | 82 | import GHC.Core.Reduction
|
82 | 83 | import GHC.Core.TyCon
|
... | ... | @@ -297,13 +298,13 @@ mkCast expr co |
297 | 298 | |
298 | 299 | -- | Wrap the given expression in a zapped cast (see Note [Zapped casts] in
|
299 | 300 | -- GHC.Core.TyCo.Rep).
|
300 | -mkCastZ :: HasDebugCallStack => CoreExpr -> Type -> [Coercion] -> CoreExpr
|
|
301 | +mkCastZ :: HasDebugCallStack => CoreExpr -> Type -> CoVarSet -> CoreExpr
|
|
301 | 302 | mkCastZ expr ty cos =
|
302 | 303 | case expr of
|
303 | - Cast expr co -> mkCastZ expr ty (zapCastCo co ++ cos)
|
|
304 | + Cast expr co -> mkCastZ expr ty (shallowCoVarsOfCastCo co `unionVarSet` cos)
|
|
304 | 305 | Tick t expr -> Tick t (mkCastZ expr ty cos)
|
305 | - -- TODO: do we need other cases from mkCast?
|
|
306 | - _ -> Cast expr (ZCoercion ty (zapCos cos))
|
|
306 | + Coercion e_co | isCoVarType ty -> Coercion (mkCoCastCo e_co (ZCoercion ty cos))
|
|
307 | + _ -> Cast expr (ZCoercion ty cos)
|
|
307 | 308 | |
308 | 309 | |
309 | 310 |
... | ... | @@ -85,6 +85,7 @@ import GHC.Types.Tickish |
85 | 85 | import GHC.Types.Demand ( isNopSig )
|
86 | 86 | import GHC.Types.Cpr ( topCprSig )
|
87 | 87 | import GHC.Types.SrcLoc (unLoc)
|
88 | +import GHC.Types.Unique.Set
|
|
88 | 89 | |
89 | 90 | import GHC.Utils.Outputable
|
90 | 91 | import GHC.Utils.Panic
|
... | ... | @@ -275,7 +276,7 @@ toIfaceTyLit (CharTyLit x) = IfaceCharTyLit x |
275 | 276 | ----------------
|
276 | 277 | toIfaceCastCoercion :: CastCoercion -> IfaceCastCoercion
|
277 | 278 | toIfaceCastCoercion (CCoercion co) = IfaceCCoercion (toIfaceCoercion co)
|
278 | -toIfaceCastCoercion (ZCoercion ty cos) = IfaceZCoercion (toIfaceType ty) (map toIfaceCoercion cos)
|
|
279 | +toIfaceCastCoercion (ZCoercion ty cos) = IfaceZCoercion (toIfaceType ty) (map (toIfaceCoercion . CoVarCo) (nonDetEltsUniqSet cos)) -- TODO determinism
|
|
279 | 280 | |
280 | 281 | toIfaceCoercion :: Coercion -> IfaceCoercion
|
281 | 282 | toIfaceCoercion = toIfaceCoercionX emptyVarSet
|
... | ... | @@ -63,6 +63,7 @@ import GHC.Core.Type |
63 | 63 | import GHC.Core.Coercion
|
64 | 64 | import GHC.Core.Coercion.Axiom
|
65 | 65 | import GHC.Core.FVs
|
66 | +import GHC.Core.TyCo.FVs
|
|
66 | 67 | import GHC.Core.TyCo.Rep -- needs to build types & coercions in a knot
|
67 | 68 | import GHC.Core.TyCo.Subst ( substTyCoVars )
|
68 | 69 | import GHC.Core.InstEnv
|
... | ... | @@ -1566,7 +1567,7 @@ tcIfaceTyLit (IfaceCharTyLit n) = return (CharTyLit n) |
1566 | 1567 | |
1567 | 1568 | tcIfaceCastCoercion :: IfaceCastCoercion -> IfL CastCoercion
|
1568 | 1569 | tcIfaceCastCoercion (IfaceCCoercion co) = CCoercion <$> tcIfaceCo co
|
1569 | -tcIfaceCastCoercion (IfaceZCoercion ty cos) = ZCoercion <$> tcIfaceType ty <*> mapM tcIfaceCo cos
|
|
1570 | +tcIfaceCastCoercion (IfaceZCoercion ty cos) = ZCoercion <$> tcIfaceType ty <*> (shallowCoVarsOfCos <$> mapM tcIfaceCo cos)
|
|
1570 | 1571 | |
1571 | 1572 | tcIfaceCo :: IfaceCoercion -> IfL Coercion
|
1572 | 1573 | tcIfaceCo = go
|
... | ... | @@ -36,6 +36,7 @@ import GHC.Core.Predicate |
36 | 36 | import GHC.Core.Reduction
|
37 | 37 | import GHC.Core.Coercion
|
38 | 38 | import GHC.Core.Class( classHasSCs )
|
39 | +import GHC.Core.TyCo.FVs
|
|
39 | 40 | import GHC.Core.TyCo.Rep (Coercion(..))
|
40 | 41 | |
41 | 42 | import GHC.Types.Id( idType )
|
... | ... | @@ -1494,7 +1495,7 @@ finish_rewrite |
1494 | 1495 | mkCastCoercion :: Bool -> Type -> Coercion -> CastCoercion
|
1495 | 1496 | mkCastCoercion zap_casts lhs_ty co
|
1496 | 1497 | | isSmallCo co || not zap_casts = CCoercion co
|
1497 | - | otherwise = ZCoercion lhs_ty (zapCo co)
|
|
1498 | + | otherwise = ZCoercion lhs_ty (shallowCoVarsOfCo co)
|
|
1498 | 1499 | |
1499 | 1500 | -- | Is this coercion probably smaller than its type? This is a rough heuristic,
|
1500 | 1501 | -- but crucially we treat axioms (perhaps wrapped in Sym/Sub/etc.) as small
|
... | ... | @@ -64,6 +64,7 @@ import GHC.Tc.Zonk.TcType |
64 | 64 | import GHC.Core.Type
|
65 | 65 | import GHC.Core.Coercion
|
66 | 66 | import GHC.Core.TyCon
|
67 | +import GHC.Core.TyCo.FVs
|
|
67 | 68 | |
68 | 69 | import GHC.Utils.Outputable
|
69 | 70 | import GHC.Utils.Misc
|
... | ... | @@ -78,11 +79,13 @@ import GHC.Types.Name |
78 | 79 | import GHC.Types.Name.Env
|
79 | 80 | import GHC.Types.Var
|
80 | 81 | import GHC.Types.Var.Env
|
82 | +import GHC.Types.Var.Set
|
|
81 | 83 | import GHC.Types.Id
|
82 | 84 | import GHC.Types.TypeEnv
|
83 | 85 | import GHC.Types.Basic
|
84 | 86 | import GHC.Types.SrcLoc
|
85 | 87 | import GHC.Types.Unique.FM
|
88 | +import GHC.Types.Unique.Set
|
|
86 | 89 | import GHC.Types.TyThing
|
87 | 90 | |
88 | 91 | import GHC.Tc.Types.BasicTypes
|
... | ... | @@ -532,15 +535,18 @@ zonkScaledTcTypeToTypeX (Scaled m ty) = Scaled <$> zonkTcTypeToTypeX m |
532 | 535 | zonkTcTypeToTypeX :: TcType -> ZonkTcM Type
|
533 | 536 | zonkTcTypesToTypesX :: [TcType] -> ZonkTcM [Type]
|
534 | 537 | zonkCoToCo :: Coercion -> ZonkTcM Coercion
|
535 | -zonkCosToCos :: [Coercion] -> ZonkTcM [Coercion]
|
|
536 | -(zonkTcTypeToTypeX, zonkTcTypesToTypesX, zonkCoToCo, zonkCosToCos)
|
|
538 | +_zonkCosToCos :: [Coercion] -> ZonkTcM [Coercion]
|
|
539 | +(zonkTcTypeToTypeX, zonkTcTypesToTypesX, zonkCoToCo, _zonkCosToCos)
|
|
537 | 540 | = case mapTyCoX zonk_tycomapper of
|
538 | 541 | (zty, ztys, zco, zcos) ->
|
539 | 542 | (ZonkT . flip zty, ZonkT . flip ztys, ZonkT . flip zco, ZonkT. flip zcos)
|
540 | 543 | |
541 | 544 | zonkCastCo :: CastCoercion -> ZonkTcM CastCoercion
|
542 | 545 | zonkCastCo (CCoercion co) = CCoercion <$> zonkCoToCo co
|
543 | -zonkCastCo (ZCoercion ty cos) = ZCoercion <$> zonkTcTypeToTypeX ty <*> zonkCosToCos cos
|
|
546 | +zonkCastCo (ZCoercion ty cos) = ZCoercion <$> zonkTcTypeToTypeX ty <*> zonkCoVarSet cos
|
|
547 | + |
|
548 | +zonkCoVarSet :: CoVarSet -> ZonkTcM CoVarSet
|
|
549 | +zonkCoVarSet = fmap shallowCoVarsOfCos . mapM zonkCoVarOcc . nonDetEltsUniqSet
|
|
544 | 550 | |
545 | 551 | zonkScaledTcTypesToTypesX :: [Scaled TcType] -> ZonkTcM [Scaled Type]
|
546 | 552 | zonkScaledTcTypesToTypesX scaled_tys =
|
... | ... | @@ -1223,14 +1223,16 @@ Other |
1223 | 1223 | :type: dynamic
|
1224 | 1224 | |
1225 | 1225 | :since: TODO
|
1226 | + :default: enabled
|
|
1226 | 1227 | |
1227 | 1228 | Reduce the size of Core terms by discarding coercion proofs that are needed
|
1228 | 1229 | only for debugging the compiler. This usually helps improve compile-time
|
1229 | 1230 | performance for some programs that make heavy use of type families.
|
1230 | 1231 | |
1231 | - When this flag is enabled, Core Lint will be less effective at verifying the
|
|
1232 | - correctness of Core programs involving casts. Hence this is automatically
|
|
1233 | - switched off by :ghc-flag:`-dcore-lint`.
|
|
1232 | + This is enabled by default. When it is enabled, Core Lint will be less
|
|
1233 | + effective at verifying the correctness of Core programs involving casts.
|
|
1234 | + Hence it is automatically switched off by :ghc-flag:`-dcore-lint`, or you
|
|
1235 | + can disable it using ``-fno-zap-casts``.
|
|
1234 | 1236 | |
1235 | 1237 | .. ghc-flag:: -dno-typeable-binds
|
1236 | 1238 | :shortdesc: Don't generate bindings for Typeable methods
|