Simon Peyton Jones pushed to branch wip/T23162-spj at Glasgow Haskell Compiler / GHC
Commits:
17e57012 by Simon Peyton Jones at 2025-10-14T22:22:20+01:00
Tidy up trySolveImplication
This completes some leftover mess from
commit 14123ee646f2b9738a917b7cec30f9d3941c13de
Author: Simon Peyton Jones
Date: Wed Aug 20 00:35:48 2025 +0100
Solve forall-constraints via an implication, again
- - - - -
addfb498 by Simon Peyton Jones at 2025-10-15T22:26:30+01:00
Big increment in rewriter tracking
Needs more documentation
- - - - -
11 changed files:
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/Irred.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Solver/Solve.hs-boot
- compiler/GHC/Tc/Types/Constraint.hs
- testsuite/tests/perf/compiler/T8095.hs
- testsuite/tests/perf/compiler/T9872a.hs
Changes:
=====================================
compiler/GHC/Core/TyCo/Rep.hs
=====================================
@@ -1690,6 +1690,8 @@ data CoercionHole
-- See Note [CoercionHoles and coercion free variables]
, ch_ref :: IORef (Maybe (Coercion, RewriterSet))
+ -- The RewriterSet is (possibly a superset of)
+ -- the free coercion holes of the coercion
}
coHoleCoVar :: CoercionHole -> CoVar
=====================================
compiler/GHC/Tc/Solver/Default.hs
=====================================
@@ -447,7 +447,7 @@ defaultExceptionContext ct
; empty_ec_id <- lookupId emptyExceptionContextName
; let ev = ctEvidence ct
ev_tm = EvExpr (evWrapIPE (ctEvPred ev) (Var empty_ec_id))
- ; setEvBindIfWanted ev EvCanonical ev_tm
+ ; setDictIfWanted ev EvCanonical ev_tm
-- EvCanonical: see Note [CallStack and ExceptionContext hack]
-- in GHC.Tc.Solver.Dict
; return True }
@@ -541,8 +541,7 @@ defaultEquality encl_eqs ct
= do { traceTcS "defaultEquality success:" (ppr rhs_ty)
; unifyTyVar lhs_tv rhs_ty -- NB: unifyTyVar adds to the
-- TcS unification counter
- ; setEvBindIfWanted (ctEvidence ct) EvCanonical $
- evCoercion (mkReflCo Nominal rhs_ty)
+ ; setEqIfWanted (ctEvidence ct) emptyRewriterSet (mkReflCo Nominal rhs_ty)
; return True
}
@@ -567,8 +566,7 @@ defaultEquality encl_eqs ct
-- See Note [Defaulting representational equalities].
; if null new_eqs
then do { traceTcS "defaultEquality ReprEq } (yes)" empty
- ; setEvBindIfWanted (ctEvidence ct) EvCanonical $
- evCoercion $ mkSubCo co
+ ; setEqIfWanted (ctEvidence ct) emptyRewriterSet (mkSubCo co)
; return True }
else do { traceTcS "defaultEquality ReprEq } (no)" empty
; return False } }
=====================================
compiler/GHC/Tc/Solver/Dict.hs
=====================================
@@ -178,7 +178,7 @@ solveCallStack ev ev_cs
-- `IP ip CallStack`. See Note [Overview of implicit CallStacks]
= do { inner_stk <- evCallStack pred ev_cs
; let ev_tm = EvExpr (evWrapIPE pred inner_stk)
- ; setEvBindIfWanted ev EvCanonical ev_tm }
+ ; setDictIfWanted ev EvCanonical ev_tm }
-- EvCanonical: see Note [CallStack and ExceptionContext hack]
where
pred = ctEvPred ev
@@ -394,9 +394,18 @@ There are two more similar "equality classes" like this. The full list is
* Coercible coercibleTyCon
(See Note [The equality types story] in GHC.Builtin.Types.Prim.)
-(EQC1) For Givens, when expanding the superclasses of a equality class,
- we can /replace/ the constraint with its superclasses (which, remember, are
- equally powerful) rather than /adding/ them. This can make a huge difference.
+(EQC1) For a Given (boxed) equality like (t1 ~ t2), we /replace/ the constraint
+ with its superclass (which, remember, is equally powerful) rather than /adding/
+ it. Thus, we turn [G] d : t1 ~ t2 into
+ [G] g : t1 ~# t2
+ g := sc_sel d -- Extend the evidence bindings
+
+ We achieve this by
+ (a) not expanding superclasses for equality classes at all;
+ see the `isEqualityClass` test in `mk_strict_superclasses`
+ (b) special logic to solve (t1 ~ t2) in the Given case of `solveEqualityDict`.
+
+ Using replacement rather than adding can make a huge difference.
Consider T17836, which has a constraint like
forall b,c. a ~ (b,c) =>
forall d,e. c ~ (d,e) =>
@@ -411,11 +420,6 @@ There are two more similar "equality classes" like this. The full list is
pattern matching. Its compile-time allocation decreased by 40% when
I added the "replace" rather than "add" semantics.)
- We achieve this by
- (a) not expanding superclasses for equality classes at all;
- see the `isEqualityClass` test in `mk_strict_superclasses`
- (b) special logic to solve (t1 ~ t2) in `solveEqualityDict`.
-
(EQC2) Faced with [W] t1 ~ t2, it's always OK to reduce it to [W] t1 ~# t2,
without worrying about Note [Instance and Given overlap]. Why? Because
if we had [G] s1 ~ s2, then we'd get the superclass [G] s1 ~# s2, and
@@ -468,26 +472,29 @@ solveEqualityDict :: CtEvidence -> Class -> [Type] -> SolverStage Void
-- See Note [Solving equality classes]
-- Precondition: (isEqualityClass cls) True, so cls is (~), (~~), or Coercible
solveEqualityDict ev cls tys
+ | CtGiven (GivenCt { ctev_evar = ev_id }) <- ev
+ , [sel_id] <- classSCSelIds cls -- Equality classes have just one superclass
+ = Stage $
+ do { let loc = ctEvLoc ev
+ sc_pred = classMethodInstTy sel_id tys
+ ev_expr = EvExpr $ Var sel_id `mkTyApps` tys `App` evId ev_id
+ -- See (EQC1) in Note [Solving equality classes]
+ -- This call to newGivenEv makes the evidence binding for the (unboxed) coercion
+ ; given_ev <- newGivenEv loc (sc_pred, ev_expr)
+ ; startAgainWith (mkNonCanonical $ CtGiven given_ev) }
+
| CtWanted (WantedCt { ctev_dest = dest }) <- ev
= Stage $
do { let (role, t1, t2) = matchEqualityInst cls tys
-- Unify t1~t2, putting anything that can't be solved
-- immediately into the work list
- ; co <- wrapUnifierAndEmit ev role $ \uenv ->
- uType uenv t1 t2
+ ; (co,_rws) <- wrapUnifierAndEmit ev role $ \uenv ->
+ uType uenv t1 t2
-- Set d :: (t1~t2) = Eq# co
; setWantedDict dest EvCanonical $
evDictApp cls tys [Coercion co]
; stopWith ev "Solved wanted lifted equality" }
- | CtGiven (GivenCt { ctev_evar = ev_id }) <- ev
- , [sel_id] <- classSCSelIds cls -- Equality classes have just one superclass
- = Stage $
- do { let loc = ctEvLoc ev
- sc_pred = classMethodInstTy sel_id tys
- ev_expr = EvExpr $ Var sel_id `mkTyApps` tys `App` evId ev_id
- ; given_ev <- newGivenEv loc (sc_pred, ev_expr)
- ; startAgainWith (mkNonCanonical $ CtGiven given_ev) }
| otherwise
= pprPanic "solveEqualityDict" (ppr cls)
@@ -730,10 +737,10 @@ try_inert_dicts inerts dict_w@(DictCt { di_ev = ev_w, di_cls = cls, di_tys = tys
| otherwise -- We can either solve the inert from the work-item or vice-versa.
-> case solveOneFromTheOther (CDictCan dict_i) (CDictCan dict_w) of
KeepInert -> do { traceTcS "lookupInertDict:KeepInert" (ppr dict_w)
- ; setEvBindIfWanted ev_w EvCanonical (ctEvTerm ev_i)
+ ; setDictIfWanted ev_w EvCanonical (ctEvTerm ev_i)
; return $ Stop ev_w (text "Dict equal" <+> ppr dict_w) }
KeepWork -> do { traceTcS "lookupInertDict:KeepWork" (ppr dict_w)
- ; setEvBindIfWanted ev_i EvCanonical (ctEvTerm ev_w)
+ ; setDictIfWanted ev_i EvCanonical (ctEvTerm ev_w)
; updInertCans (updDicts $ delDict dict_w)
; continueWith () } }
@@ -796,7 +803,7 @@ try_instances inerts work_item@(DictCt { di_ev = ev, di_cls = cls
-- See Note [No Given/Given fundeps]
| Just solved_ev <- lookupSolvedDict inerts cls xis -- Cached
- = do { setEvBindIfWanted ev EvCanonical (ctEvTerm solved_ev)
+ = do { setDictIfWanted ev EvCanonical (ctEvTerm solved_ev)
; stopWith ev "Dict/Top (cached)" }
| otherwise -- Wanted, but not cached
@@ -828,7 +835,7 @@ chooseInstance work_item
; assertPprM (getTcEvBindsVar >>= return . not . isCoEvBindsVar)
(ppr work_item)
; evc_vars <- mapM (newWanted deeper_loc (ctEvRewriters work_item)) theta
- ; setEvBindIfWanted work_item canonical (mk_ev (map getEvExpr evc_vars))
+ ; setDictIfWanted work_item canonical (mk_ev (map getEvExpr evc_vars))
; emitWorkNC (map CtWanted $ freshGoals evc_vars)
; stopWith work_item "Dict/Top (solved wanted)" }
where
=====================================
compiler/GHC/Tc/Solver/Equality.hs
=====================================
@@ -10,7 +10,7 @@ module GHC.Tc.Solver.Equality(
import GHC.Prelude
-import {-# SOURCE #-} GHC.Tc.Solver.Solve( trySolveImplication )
+import {-# SOURCE #-} GHC.Tc.Solver.Solve( solveSimpleWanteds )
import GHC.Tc.Solver.Irred( solveIrred )
import GHC.Tc.Solver.Dict( matchLocalInst, chooseInstance )
@@ -372,7 +372,7 @@ can_eq_nc rewritten rdr_env envs ev eq_rel ty1 ps_ty1 (CastTy ty2 co2) _
-- Literals
can_eq_nc _rewritten _rdr_env _envs ev eq_rel ty1@(LitTy l1) _ (LitTy l2) _
| l1 == l2
- = do { setEvBindIfWanted ev EvCanonical (evCoercion $ mkReflCo (eqRelRole eq_rel) ty1)
+ = do { setEqIfWanted ev emptyRewriterSet (mkReflCo (eqRelRole eq_rel) ty1)
; stopWith ev "Equal LitTy" }
-- Decompose FunTy: (s -> t) and (c => t)
@@ -485,7 +485,7 @@ can_eq_nc_forall :: CtEvidence -> EqRel
-- See Note [Solving forall equalities]
can_eq_nc_forall ev eq_rel s1 s2
- | CtWanted (WantedCt { ctev_dest = orig_dest, ctev_rewriters = rws, ctev_loc = loc }) <- ev
+ | CtWanted (WantedCt { ctev_dest = orig_dest }) <- ev
= do { let (bndrs1, phi1, bndrs2, phi2) = split_foralls s1 s2
flags1 = binderFlags bndrs1
flags2 = binderFlags bndrs2
@@ -541,36 +541,40 @@ can_eq_nc_forall ev eq_rel s1 s2
; traceTcS "Generating wanteds" (ppr s1 $$ ppr s2)
- -- Generate the constraints that live in the body of the implication
- -- See (SF5) in Note [Solving forall equalities]
- ; (unifs, (lvl, (all_co, wanteds)))
- <- reportFineGrainUnifications $
- pushLevelNoWorkList (ppr skol_info) $
- wrapUnifier ev (eqRelRole eq_rel) $ \uenv ->
- go uenv skol_tvs init_subst2 bndrs1 bndrs2
+ -- Generate and solve the constraints that live in the body of the implication
+ -- See (SF5) and (SF6) in Note [Solving forall equalities]
+ ; (unifs, (all_co, solved))
+ <- reportFineGrainUnifications $
+ do { -- Generate constraints
+ (tclvl, (all_co, wanteds))
+ <- pushLevelNoWorkList (ppr skol_info) $
+ wrapUnifier ev (eqRelRole eq_rel) $ \uenv ->
+ go uenv skol_tvs init_subst2 bndrs1 bndrs2
+
+ ; traceTcS "Trying to solve the implication" (ppr s1 $$ ppr s2 $$ ppr wanteds)
+
+ -- Solve the `wanteds` in a nested context
+ ; ev_binds_var <- newNoTcEvBinds
+ ; residual_wanted <- nestImplicTcS skol_info_anon ev_binds_var tclvl $
+ solveSimpleWanteds wanteds
+
+ ; return (all_co, isSolvedWC residual_wanted) }
+
-- Kick out any inerts constraints that mention unified type variables
; kickOutAfterUnification unifs
- -- Solve the implication right away, using `trySolveImplication`
- -- See (SF6) in Note [Solving forall equalities]
- ; traceTcS "Trying to solve the implication" (ppr s1 $$ ppr s2 $$ ppr wanteds)
- ; ev_binds_var <- newNoTcEvBinds
- ; solved <- trySolveImplication $
- (implicationPrototype (ctLocEnv loc))
- { ic_tclvl = lvl
- , ic_binds = ev_binds_var
- , ic_info = skol_info_anon
- , ic_warn_inaccessible = False
- , ic_skols = skol_tvs
- , ic_given = []
- , ic_wanted = emptyWC { wc_simple = wanteds } }
-
; if solved
- then do { -- all_co <- zonkCo all_co
- -- -- ToDo: explain this zonk
- setWantedEq orig_dest rws all_co
+ then do { all_co <- zonkCo all_co
+ -- setWantedEq will add `all_co` to the `ebv_tcvs`, to record
+ -- that `all_co` is used. But if `all_co` contains filled
+ -- CoercionHoles, from the nested solve, and we may miss the
+ -- use of CoVars. Test T7196 showed this up
+
+ ; setWantedEq orig_dest emptyRewriterSet all_co
+ -- emptyRewriterSet: fully solved, so all_co has no holes
; stopWith ev "Polytype equality: solved" }
+
else canEqSoftFailure IrredShapeReason ev s1 s2 } }
| otherwise
@@ -592,11 +596,12 @@ can_eq_nc_forall ev eq_rel s1 s2
in (bndr1:bndrs1, phi1, bndr2:bndrs2, phi2)
split_foralls s1 s2 = ([], s1, [], s2)
+
{- Note [Solving forall equalities]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To solve an equality between foralls
[W] (forall a. t1) ~ (forall b. t2)
-the basic plan is simple: use `trySolveImplication` to solve the
+the basic plan is simple: behave rather as if we were solving the
implication constraint
[W] forall a. { t1 ~ (t2[a/b]) }
@@ -643,19 +648,15 @@ There are lots of wrinkles of course:
because we want to /gather/ the equality constraint (to put in the implication)
rather than /emit/ them into the monad, as `wrapUnifierAndEmit` does.
-(SF6) We solve the implication on the spot, using `trySolveImplication`. In
- the past we instead generated an `Implication` to be solved later. Nice in
- some ways but it added complexity:
- - We needed a `wl_implics` field of `WorkList` to collect
- these emitted implications
- - The types of `solveSimpleWanteds` and friends were more complicated
- - Trickily, an `EvFun` had to contain an `EvBindsVar` ref-cell, which made
- `evVarsOfTerm` harder. Now an `EvFun` just contains the bindings.
- The disadvantage of solve-on-the-spot is that if we fail we are simply
- left with an unsolved (forall a. blah) ~ (forall b. blah), and it may
- not be clear /why/ we couldn't solve it. But on balance the error messages
- improve: it is easier to undertand that
- (forall a. a->a) ~ (forall b. b->Int)
+(SF6) We solve the nested constraints right away. In the past we instead generated
+ an `Implication` to be solved later, but we no longer have a convenient place
+ to accumulate such an implication for later solving. Instead we just try to solve
+ them on the spot, and abandon the attempt if we fail.
+
+ In the latter case we are left with an unsolved (forall a. blah) ~ (forall b. blah),
+ and it may not be clear /why/ we couldn't solve it. But on balance the error
+ messages improve: it is easier to understand that
+ (forall a. a->a) ~ (forall b. b->Int)
is insoluble than it is to understand a message about matching `a` with `Int`.
-}
@@ -809,11 +810,11 @@ can_eq_app :: CtEvidence -- :: s1 t1 ~N s2 t2
-- to an irreducible constraint; see typecheck/should_compile/T10494
-- See Note [Decomposing AppTy equalities]
can_eq_app ev s1 t1 s2 t2
- | CtWanted (WantedCt { ctev_dest = dest, ctev_rewriters = rws }) <- ev
+ | CtWanted (WantedCt { ctev_dest = dest }) <- ev
= do { traceTcS "can_eq_app" (vcat [ text "s1:" <+> ppr s1, text "t1:" <+> ppr t1
, text "s2:" <+> ppr s2, text "t2:" <+> ppr t2
, text "vis:" <+> ppr (isNextArgVisible s1) ])
- ; co <- wrapUnifierAndEmit ev Nominal $ \uenv ->
+ ; (co,rws) <- wrapUnifierAndEmit ev Nominal $ \uenv ->
-- Unify arguments t1/t2 before function s1/s2, because
-- the former have smaller kinds, and hence simpler error messages
-- c.f. GHC.Tc.Utils.Unify.uType (go_app)
@@ -1374,11 +1375,11 @@ canDecomposableTyConAppOK ev eq_rel tc (ty1,tys1) (ty2,tys2)
do { traceTcS "canDecomposableTyConAppOK"
(ppr ev $$ ppr eq_rel $$ ppr tc $$ ppr tys1 $$ ppr tys2)
; case ev of
- CtWanted (WantedCt { ctev_dest = dest, ctev_rewriters = rws })
+ CtWanted (WantedCt { ctev_dest = dest })
-- new_locs and tc_roles are both infinite, so we are
-- guaranteed that cos has the same length as tys1 and tys2
-- See Note [Fast path when decomposing TyConApps]
- -> do { co <- wrapUnifierAndEmit ev role $ \uenv ->
+ -> do { (co,rws) <- wrapUnifierAndEmit ev role $ \uenv ->
do { cos <- zipWith4M (u_arg uenv) new_locs tc_roles tys1 tys2
-- zipWith4M: see Note [Work-list ordering]
; return (mkTyConAppCo role tc cos) }
@@ -1432,8 +1433,8 @@ canDecomposableFunTy ev eq_rel af f1@(ty1,m1,a1,r1) f2@(ty2,m2,a2,r2)
= do { traceTcS "canDecomposableFunTy"
(ppr ev $$ ppr eq_rel $$ ppr f1 $$ ppr f2)
; case ev of
- CtWanted (WantedCt { ctev_dest = dest, ctev_rewriters = rws })
- -> do { co <- wrapUnifierAndEmit ev Nominal $ \ uenv ->
+ CtWanted (WantedCt { ctev_dest = dest })
+ -> do { (co,rws) <- wrapUnifierAndEmit ev Nominal $ \ uenv ->
do { let mult_env = uenv `updUEnvLoc` toInvisibleLoc InvisibleMultiplicity
`setUEnvRole` funRole role SelMult
; mult <- uType mult_env m1 m2
@@ -2011,6 +2012,7 @@ canEqCanLHSFinish_try_unification ev eq_rel swapped lhs rhs
then return ev
else rewriteEqEvidence emptyRewriterSet ev swapped
(mkReflRedn Nominal (mkTyVarTy tv)) rhs_redn
+ -- emptyRewriterSet: rhs_redn has no CoercionHoles
; let tv_ty = mkTyVarTy tv
final_rhs = reductionReducedType rhs_redn
@@ -2026,8 +2028,7 @@ canEqCanLHSFinish_try_unification ev eq_rel swapped lhs rhs
-- Provide Refl evidence for the constraint
-- Ignore 'swapped' because it's Refl!
- ; setEvBindIfWanted new_ev EvCanonical $
- evCoercion (mkNomReflCo final_rhs)
+ ; setEqIfWanted new_ev emptyRewriterSet (mkNomReflCo final_rhs)
-- Kick out any constraints that can now be rewritten
; kickOutAfterUnification (unitVarSet tv)
@@ -2147,8 +2148,7 @@ canEqReflexive :: CtEvidence -- ty ~ ty
-> TcType -- ty
-> TcS (StopOrContinue a) -- always Stop
canEqReflexive ev eq_rel ty
- = do { setEvBindIfWanted ev EvCanonical $
- evCoercion (mkReflCo (eqRelRole eq_rel) ty)
+ = do { setEqIfWanted ev emptyRewriterSet (mkReflCo (eqRelRole eq_rel) ty)
; stopWith ev "Solved by reflexivity" }
{- Note [Equalities with heterogeneous kinds]
@@ -2649,10 +2649,11 @@ rewriteEqEvidence new_rewriters old_ev swapped (Reduction lhs_co nlhs) (Reductio
| CtWanted (WantedCt { ctev_dest = dest, ctev_rewriters = rewriters }) <- old_ev
= do { let rewriters' = rewriters S.<> new_rewriters
- ; (new_ev, hole_co) <- newWantedEq loc rewriters' (ctEvRewriteRole old_ev) nlhs nrhs
+ ; (new_ev, hole) <- newWantedEq loc rewriters' (ctEvRewriteRole old_ev) nlhs nrhs
; let co = maybeSymCo swapped $
- lhs_co `mkTransCo` hole_co `mkTransCo` mkSymCo rhs_co
- ; setWantedEq dest rewriters' co
+ lhs_co `mkTransCo` mkHoleCo hole `mkTransCo` mkSymCo rhs_co
+ -- new_rewriters has all the holes from lhs_co and rhs_co
+ ; setWantedEq dest (new_rewriters `mappend` unitRewriterSet hole) co
; traceTcS "rewriteEqEvidence" (vcat [ ppr old_ev
, ppr nlhs
, ppr nrhs
@@ -2730,11 +2731,11 @@ tryInertEqs work_item@(EqCt { eq_ev = ev, eq_eq_rel = eq_rel })
= Stage $
do { inerts <- getInertCans
; if | Just (ev_i, swapped) <- inertsEqsCanDischarge inerts work_item
- -> do { setEvBindIfWanted ev EvCanonical $
- evCoercion (maybeSymCo swapped $
- downgradeRole (eqRelRole eq_rel)
- (ctEvRewriteRole ev_i)
- (ctEvCoercion ev_i))
+ -> do { setEqIfWanted ev (ctEvRewriterSet ev_i) $
+ maybeSymCo swapped $
+ downgradeRole (eqRelRole eq_rel)
+ (ctEvRewriteRole ev_i)
+ (ctEvCoercion ev_i)
; stopWith ev "Solved from inert" }
| otherwise
=====================================
compiler/GHC/Tc/Solver/Irred.hs
=====================================
@@ -14,11 +14,10 @@ import GHC.Tc.Solver.Dict( matchLocalInst, chooseInstance )
import GHC.Tc.Solver.Monad
import GHC.Tc.Types.Evidence
-import GHC.Core.Coercion
-
import GHC.Types.Basic( SwapFlag(..) )
import GHC.Utils.Outputable
+import GHC.Utils.Panic
import GHC.Data.Bag
@@ -69,9 +68,9 @@ try_inert_irreds inerts irred_w@(IrredCt { ir_ev = ev_w, ir_reason = reason })
vcat [ text "wanted:" <+> (ppr ct_w $$ ppr (ctOrigin ct_w))
, text "inert: " <+> (ppr ct_i $$ ppr (ctOrigin ct_i)) ]
; case solveOneFromTheOther ct_i ct_w of
- KeepInert -> do { setEvBindIfWanted ev_w EvCanonical (swap_me swap ev_i)
+ KeepInert -> do { setIrredIfWanted ev_w swap ev_i
; return (Stop ev_w (text "Irred equal:KeepInert" <+> ppr ct_w)) }
- KeepWork -> do { setEvBindIfWanted ev_i EvCanonical (swap_me swap ev_w)
+ KeepWork -> do { setIrredIfWanted ev_i swap ev_w
; updInertCans (updIrreds (\_ -> others))
; continueWith () } }
@@ -81,12 +80,19 @@ try_inert_irreds inerts irred_w@(IrredCt { ir_ev = ev_w, ir_reason = reason })
where
ct_w = CIrredCan irred_w
- swap_me :: SwapFlag -> CtEvidence -> EvTerm
- swap_me swap ev
- = case swap of
- NotSwapped -> ctEvTerm ev
- IsSwapped -> evCoercion (mkSymCo (evTermCoercion (ctEvTerm ev)))
-
+setIrredIfWanted :: CtEvidence -> SwapFlag -> CtEvidence -> TcS ()
+-- Irreds can be equalities or dictionaries
+setIrredIfWanted ev_dest swap ev_source
+ | CtWanted (WantedCt { ctev_dest = dest }) <- ev_dest
+ = case dest of
+ HoleDest {} -> setWantedEq dest (ctEvRewriterSet ev_source)
+ (maybeSymCo swap (ctEvCoercion ev_source))
+
+ EvVarDest {} -> assertPpr (swap==NotSwapped) (ppr ev_dest $$ ppr ev_source) $
+ -- findMatchingIrreds only returns IsSwapped for equalities
+ setWantedDict dest EvCanonical (ctEvTerm ev_source)
+ | otherwise
+ = return ()
{- Note [Multiple matching irreds]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=====================================
compiler/GHC/Tc/Solver/Monad.hs
=====================================
@@ -50,13 +50,12 @@ module GHC.Tc.Solver.Monad (
CanonicalEvidence(..),
newTcEvBinds, newNoTcEvBinds,
- newWantedEq, emitNewWantedEq,
+ newWantedEq,
newWanted,
newWantedNC, newWantedEvVarNC,
newBoundEvVarId,
unifyTyVar, reportFineGrainUnifications, reportCoarseGrainUnifications,
- setEvBind, setWantedEq, setWantedDict,
- setWantedEvTerm, setEvBindIfWanted,
+ setEvBind, setWantedEq, setWantedDict, setEqIfWanted, setDictIfWanted,
newEvVar, newGivenEv, emitNewGivens,
emitChildEqs, checkReductionDepth,
@@ -1209,12 +1208,28 @@ setTcLevelTcS :: TcLevel -> TcS a -> TcS a
setTcLevelTcS lvl (TcS thing_inside)
= TcS $ \ env -> TcM.setTcLevel lvl (thing_inside env)
+{- Note [nestImplicTcS]
+~~~~~~~~~~~~~~~~~~~~~~~
+`nestImplicTcS` is used to build a nested scope when we begin solving an implication.
+
+(NI1) One subtle point is that `nestImplicTcS` uses `resetInertCans` to
+ initialise the `InertSet` of the nested scope to the `inert_givens` (/not/
+ the `inert_cans`) of the current inert set. It is super-important not to
+ pollute the sub-solving problem with the unsolved Wanteds of the current
+ scope.
+
+ Whenever we do `solveSimpleGivens`, we snapshot the `inert_cans` into `inert_givens`.
+ (At that moment there should be no Wanteds.)
+-}
+
nestImplicTcS :: SkolemInfoAnon -> EvBindsVar
-> TcLevel -> TcS a
-> TcS a
+-- See Note [nestImplicTcS]
nestImplicTcS skol_info ev_binds_var inner_tclvl (TcS thing_inside)
= TcS $ \ env@(TcSEnv { tcs_inerts = old_inert_var }) ->
- do { nest_inert <- mk_nested_inert_set skol_info old_inert_var
+ do { old_inerts <- TcM.readTcRef old_inert_var
+ ; let nest_inert = mk_nested_inerts old_inerts
; new_inert_var <- TcM.newTcRef nest_inert
; new_wl_var <- TcM.newTcRef emptyWorkList
; let nest_env = env { tcs_ev_binds = ev_binds_var
@@ -1233,24 +1248,18 @@ nestImplicTcS skol_info ev_binds_var inner_tclvl (TcS thing_inside)
#endif
; return res }
where
- mk_nested_inert_set skol_info old_inert_var
+ mk_nested_inerts old_inerts
-- For an implication that comes from a static form (static e),
-- start with a completely empty inert set; in particular, no Givens
-- See (SF3) in Note [Grand plan for static forms]
-- in GHC.Iface.Tidy.StaticPtrTable
| StaticFormSkol <- skol_info
- = return (emptyInertSet inner_tclvl)
+ = emptyInertSet inner_tclvl
| otherwise
- = do { inerts <- TcM.readTcRef old_inert_var
-
- -- resetInertCans: initialise the inert_cans from the inert_givens of the
- -- parent so that the child is not polluted with the parent's inert Wanteds
- -- See Note [trySolveImplication] in GHC.Tc.Solver.Solve
- -- All other InertSet fields are inherited
- ; return (pushCycleBreakerVarStack $
- resetInertCans $
- inerts) }
+ = pushCycleBreakerVarStack $
+ resetInertCans $ -- See (NI1) in Note [nestImplicTcS]
+ old_inerts
nestFunDepsTcS :: TcS a -> TcS a
nestFunDepsTcS (TcS thing_inside)
@@ -1950,64 +1959,40 @@ addUsedCoercion co
= do { ev_binds_var <- getTcEvBindsVar
; wrapTcS (TcM.updTcRef (ebv_tcvs ev_binds_var) (co :)) }
+setEqIfWanted :: CtEvidence -> RewriterSet -> TcCoercion -> TcS ()
+setEqIfWanted ev rewriters co
+ = case ev of
+ CtWanted (WantedCt { ctev_dest = dest })
+ -> setWantedEq dest rewriters co
+ _ -> return ()
+
setWantedEq :: HasDebugCallStack => TcEvDest -> RewriterSet -> TcCoercion -> TcS ()
-- ^ Equalities only
-setWantedEq (HoleDest hole) rewriters co
- = do { addUsedCoercion co
- ; fillCoercionHole hole rewriters co }
-setWantedEq (EvVarDest ev) _ _ = pprPanic "setWantedEq: EvVarDest" (ppr ev)
+setWantedEq dest rewriters co
+ = case dest of
+ HoleDest hole -> fillCoercionHole hole rewriters co
+ EvVarDest ev -> pprPanic "setWantedEq: EvVarDest" (ppr ev)
+
+setDictIfWanted :: CtEvidence -> CanonicalEvidence -> EvTerm -> TcS ()
+setDictIfWanted ev canonical tm
+ = case ev of
+ CtWanted (WantedCt { ctev_dest = dest })
+ -> setWantedDict dest canonical tm
+ _ -> return ()
setWantedDict :: TcEvDest -> CanonicalEvidence -> EvTerm -> TcS ()
-- ^ Dictionaries only
-setWantedDict (EvVarDest ev_id) canonical tm
- = setEvBind (mkWantedEvBind ev_id canonical tm)
-setWantedDict (HoleDest h) _ _ = pprPanic "setWantedEq: HoleDest" (ppr h)
-
-setWantedEvTerm :: TcEvDest -> RewriterSet -> CanonicalEvidence -> EvTerm -> TcS ()
--- ^ Good for both equalities and non-equalities
-setWantedEvTerm (EvVarDest ev_id) _rewriters canonical tm
- = setEvBind (mkWantedEvBind ev_id canonical tm)
-setWantedEvTerm (HoleDest hole) rewriters _canonical tm
- | Just co <- evTermCoercion_maybe tm
- = do { addUsedCoercion co
- ; fillCoercionHole hole rewriters co }
- | otherwise
- = -- See Note [Yukky eq_sel for a HoleDest]
- do { let co_var = coHoleCoVar hole
- ; setEvBind (mkWantedEvBind co_var EvCanonical tm)
- ; fillCoercionHole hole rewriters (mkCoVarCo co_var) }
-
-{- Note [Yukky eq_sel for a HoleDest]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-How can it be that a Wanted with HoleDest gets evidence that isn't
-just a coercion? i.e. evTermCoercion_maybe returns Nothing.
-
-Consider [G] forall a. blah => a ~ T
- [W] S ~# T
-
-Then doTopReactEqPred carefully looks up the (boxed) constraint (S ~ T)
-in the quantified constraints, and wraps the (boxed) evidence it
-gets back in an eq_sel to extract the unboxed (S ~# T). We can't put
-that term into a coercion, so we add a value binding
- h = eq_sel (...)
-and the coercion variable h to fill the coercion hole.
-We even re-use the CoHole's Id for this binding!
-
-Yuk!
--}
+setWantedDict dest canonical tm
+ = case dest of
+ EvVarDest ev_id -> setEvBind (mkWantedEvBind ev_id canonical tm)
+ HoleDest h -> pprPanic "setWantedEq: HoleDest" (ppr h)
fillCoercionHole :: CoercionHole -> RewriterSet -> Coercion -> TcS ()
fillCoercionHole hole rewriters co
- = do { wrapTcS $ TcM.fillCoercionHole hole (co, rewriters)
+ = do { addUsedCoercion co
+ ; wrapTcS $ TcM.fillCoercionHole hole (co, rewriters)
; kickOutAfterFillingCoercionHole hole rewriters }
-setEvBindIfWanted :: CtEvidence -> CanonicalEvidence -> EvTerm -> TcS ()
-setEvBindIfWanted ev canonical tm
- = case ev of
- CtWanted (WantedCt { ctev_dest = dest, ctev_rewriters = rewriters })
- -> setWantedEvTerm dest rewriters canonical tm
- _ -> return ()
-
newTcEvBinds :: TcS EvBindsVar
newTcEvBinds = wrapTcS TcM.newTcEvBinds
@@ -2019,9 +2004,11 @@ newEvVar pred = wrapTcS (TcM.newEvVar pred)
newGivenEv :: CtLoc -> (TcPredType, EvTerm) -> TcS GivenCtEvidence
-- Make a new variable of the given PredType,
--- immediately bind it to the given term
--- and return its CtEvidence
+-- immediately bind it to the given term, and return its CtEvidence
-- See Note [Bind new Givens immediately] in GHC.Tc.Types.Constraint
+--
+-- The `pred` can be an /equality predicate/ t1 ~# t2;
+-- see (EQC1) in Note [Solving equality classes] in GHC.Tc.Solver.Dict
newGivenEv loc (pred, rhs)
= do { new_ev <- newBoundEvVarId pred rhs
; return $ GivenCt { ctev_pred = pred, ctev_evar = new_ev, ctev_loc = loc } }
@@ -2044,13 +2031,6 @@ emitNewGivens loc pts
, not (ty1 `tcEqType` ty2) ] -- Kill reflexive Givens at birth
; emitWorkNC (map CtGiven gs) }
-emitNewWantedEq :: CtLoc -> RewriterSet -> Role -> TcType -> TcType -> TcS Coercion
--- | Emit a new Wanted equality into the work-list
-emitNewWantedEq loc rewriters role ty1 ty2
- = do { (wtd, co) <- newWantedEq loc rewriters role ty1 ty2
- ; updWorkListTcS (extendWorkListEq rewriters (mkNonCanonical $ CtWanted wtd))
- ; return co }
-
emitChildEqs :: CtEvidence -> Cts -> TcS ()
-- Emit a bunch of equalities into the work list
-- See Note [Work-list ordering] in GHC.Tc.Solver.Equality
@@ -2067,14 +2047,14 @@ emitChildEqs ev eqs
-- | Create a new Wanted constraint holding a coercion hole
-- for an equality between the two types at the given 'Role'.
newWantedEq :: CtLoc -> RewriterSet -> Role -> TcType -> TcType
- -> TcS (WantedCtEvidence, Coercion)
+ -> TcS (WantedCtEvidence, CoercionHole)
newWantedEq loc rewriters role ty1 ty2
= do { hole <- wrapTcS $ TcM.newCoercionHole pty
; let wtd = WantedCt { ctev_pred = pty
, ctev_dest = HoleDest hole
, ctev_loc = loc
, ctev_rewriters = rewriters }
- ; return (wtd, mkHoleCo hole) }
+ ; return (wtd, hole) }
where
pty = mkEqPredRole role ty1 ty2
@@ -2214,10 +2194,11 @@ uPairsTcM uenv eqns = mapM_ (\(Pair ty1 ty2) -> uType uenv ty1 ty2) eqns
wrapUnifierAndEmit :: CtEvidence -> Role
-> (UnifyEnv -> TcM a) -- Some calls to uType
- -> TcS a
+ -> TcS (a, RewriterSet)
-- Like wrapUnifier, but
-- emits any unsolved equalities into the work-list
-- kicks out any inert constraints that mention unified variables
+-- returns a RewriterSet describing the new unsolved goals
wrapUnifierAndEmit ev role do_unifications
= do { (unifs, (res, eqs)) <- reportFineGrainUnifications $
wrapUnifier ev role do_unifications
@@ -2228,7 +2209,7 @@ wrapUnifierAndEmit ev role do_unifications
-- Kick out any inert constraints mentioning the unified variables
; kickOutAfterUnification unifs
- ; return res }
+ ; return (res, rewriterSetFromCts eqs) }
wrapUnifier :: CtEvidence -> Role
-> (UnifyEnv -> TcM a) -- Some calls to uType
=====================================
compiler/GHC/Tc/Solver/Solve.hs
=====================================
@@ -7,7 +7,6 @@ module GHC.Tc.Solver.Solve (
solveWanteds, -- Solves WantedConstraints
solveSimpleGivens, -- Solves [Ct]
solveSimpleWanteds, -- Solves Cts
- trySolveImplication,
setImplicationStatus
) where
@@ -369,35 +368,6 @@ solveNestedImplications implics
; return unsolved_implics }
-{- Note [trySolveImplication]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-`trySolveImplication` may be invoked while solving simple wanteds, notably from
-`solveWantedForAll`. It returns a Bool to say if solving succeeded or failed.
-
-It uses `nestImplicTcS` to build a nested scope. One subtle point is that
-`nestImplicTcS` uses the `inert_givens` (not the `inert_cans`) of the current
-inert set to initialse the `InertSet` of the nested scope. It is super-important not
-to pollute the sub-solving problem with the unsolved Wanteds of the current scope.
-
-Whenever we do `solveSimpleGivens`, we snapshot the `inert_cans` into `inert_givens`.
-(At that moment there should be no Wanteds.)
--}
-
-trySolveImplication :: Implication -> TcS Bool
--- See Note [trySolveImplication]
-trySolveImplication (Implic { ic_tclvl = tclvl
- , ic_binds = ev_binds_var
- , ic_given = given_ids
- , ic_wanted = wanteds
- , ic_env = ct_loc_env
- , ic_info = info })
- = nestImplicTcS info ev_binds_var tclvl $
- do { let loc = mkGivenLoc tclvl info ct_loc_env
- givens = mkGivens loc given_ids
- ; solveSimpleGivens givens
- ; residual_wanted <- solveWanteds wanteds
- ; return (isSolvedWC residual_wanted) }
-
solveImplication :: Implication -- Wanted
-> TcS Implication -- Simplified implication
-- Precondition: The TcS monad contains an empty worklist and given-only inerts
@@ -1091,7 +1061,7 @@ solveSimpleGivens givens
-- Capture the Givens in the inert_givens of the inert set
-- for use by subsequent calls of nestImplicTcS
- -- See Note [trySolveImplication]
+ -- See Note [nestImplicTcS] in GHc.Tc.Solver.Monad
; updInertSet (\is -> is { inert_givens = inert_cans is })
; cans <- getInertCans
@@ -1273,7 +1243,7 @@ solveCt (CEqCan (EqCt { eq_ev = ev, eq_eq_rel = eq_rel
= solveEquality ev eq_rel (canEqLHSType lhs) rhs
solveCt (CQuantCan qci@(QCI { qci_ev = ev }))
- = do { ev' <- rewriteEvidence ev
+ = do { ev' <- rewriteDictEvidence ev
-- It is (much) easier to rewrite and re-classify than to
-- rewrite the pieces and build a Reduction that will rewrite
-- the whole constraint
@@ -1284,7 +1254,7 @@ solveCt (CQuantCan qci@(QCI { qci_ev = ev }))
_ -> pprPanic "SolveCt" (ppr ev) }
solveCt (CDictCan (DictCt { di_ev = ev, di_pend_sc = pend_sc }))
- = do { ev <- rewriteEvidence ev
+ = do { ev <- rewriteDictEvidence ev
-- It is easier to rewrite and re-classify than to rewrite
-- the pieces and build a Reduction that will rewrite the
-- whole constraint
@@ -1309,7 +1279,7 @@ solveNC ev
_ ->
-- Do rewriting on the constraint, especially zonking
- do { ev <- rewriteEvidence ev
+ do { ev <- rewriteDictEvidence ev
-- And then re-classify
; case classifyPredType (ctEvPred ev) of
@@ -1582,7 +1552,7 @@ try_inert_qcs (QCI { qci_ev = ev_w }) inerts =
; continueWith () }
ev_i:_ ->
do { traceTcS "tryInertQCs:KeepInert" (ppr ev_i)
- ; setEvBindIfWanted ev_w EvCanonical (ctEvTerm ev_i)
+ ; setDictIfWanted ev_w EvCanonical (ctEvTerm ev_i)
; stopWith ev_w "Solved Wanted forall-constraint from inert" }
where
matching_inert (QCI { qci_ev = ev_i })
@@ -1689,10 +1659,12 @@ solveWantedQCI _ ct = return (Left ct)
************************************************************************
-}
-rewriteEvidence :: CtEvidence -> SolverStage CtEvidence
--- (rewriteEvidence old_ev new_pred co do_next)
+rewriteDictEvidence :: CtEvidence -> SolverStage CtEvidence
+-- (rewriteDictEvidence old_ev new_pred co do_next)
-- Main purpose: create new evidence for new_pred;
-- unless new_pred is cached already
+-- Precondition: new_pred is not an equality: the evidence is a term-level
+-- thing, hence "Dict".
-- * Calls do_next with (new_ev :: new_pred), with same wanted/given flag as old_ev
-- * If old_ev was wanted, create a binding for old_ev, in terms of new_ev
-- * If old_ev was given, AND not cached, create a binding for new_ev, in terms of old_ev
@@ -1723,8 +1695,8 @@ the rewriter set. We check this with an assertion.
-}
-rewriteEvidence ev
- = Stage $ do { traceTcS "rewriteEvidence" (ppr ev)
+rewriteDictEvidence ev
+ = Stage $ do { traceTcS "rewriteDictEvidence" (ppr ev)
; (redn, rewriters) <- rewrite ev (ctEvPred ev)
; finish_rewrite ev redn rewriters }
@@ -1761,8 +1733,8 @@ finish_rewrite
ev_rw_role = ctEvRewriteRole ev
; mb_new_ev <- newWanted loc rewriters' new_pred
; massert (coercionRole co == ev_rw_role)
- ; setWantedEvTerm dest rewriters' EvCanonical $
- evCast (getEvExpr mb_new_ev) $
+ ; setWantedDict dest EvCanonical $
+ evCast (getEvExpr mb_new_ev) $
downgradeRole Representational ev_rw_role (mkSymCo co)
; case mb_new_ev of
Fresh new_ev -> continueWith $ CtWanted new_ev
@@ -1826,17 +1798,22 @@ runTcPluginsWanted wanted
listToBag unsolved_wanted `andCts`
listToBag insols
- ; mapM_ setEv solved_wanted
+ ; mapM_ setPluginEv solved_wanted
; traceTcS "Finished plugins }" (ppr new_wanted)
; return ( notNull (pluginNewCts p), all_new_wanted ) } }
- where
- setEv :: (EvTerm,Ct) -> TcS ()
- setEv (ev,ct) = case ctEvidence ct of
- CtWanted (WantedCt { ctev_dest = dest, ctev_rewriters = rewriters })
- -> setWantedEvTerm dest rewriters EvCanonical ev
- -- TODO: plugins should be able to signal non-canonicity
- _ -> panic "runTcPluginsWanted.setEv: attempt to solve non-wanted!"
+
+setPluginEv :: (EvTerm,Ct) -> TcS ()
+setPluginEv (tm,ct)
+ = case ctEvidence ct of
+ CtWanted (WantedCt { ctev_dest = dest })
+ -> case dest of
+ EvVarDest {} -> setWantedDict dest EvCanonical tm
+ -- TODO: plugins should be able to signal non-canonicity
+ HoleDest {} -> setWantedEq dest emptyRewriterSet (evTermCoercion tm)
+ -- TODO: should we try to track rewriters?
+
+ CtGiven {} -> panic "runTcPluginsWanted.setEv: attempt to solve non-wanted!"
-- | A pair of (given, wanted) constraints to pass to plugins
type SplitCts = ([Ct], [Ct])
=====================================
compiler/GHC/Tc/Solver/Solve.hs-boot
=====================================
@@ -1,8 +1,6 @@
module GHC.Tc.Solver.Solve where
-import Prelude( Bool )
import GHC.Tc.Solver.Monad( TcS )
-import GHC.Tc.Types.Constraint( Cts, Implication, WantedConstraints )
+import GHC.Tc.Types.Constraint( Cts, WantedConstraints )
solveSimpleWanteds :: Cts -> TcS WantedConstraints
-trySolveImplication :: Implication -> TcS Bool
=====================================
compiler/GHC/Tc/Types/Constraint.hs
=====================================
@@ -80,7 +80,8 @@ module GHC.Tc.Types.Constraint (
ctEvExpr, ctEvTerm,
ctEvCoercion, givenCtEvCoercion,
ctEvEvId, wantedCtEvEvId,
- ctEvRewriters, setWantedCtEvRewriters, ctEvUnique, tcEvDestUnique,
+ ctEvRewriters, ctEvRewriterSet, setWantedCtEvRewriters,
+ ctEvUnique, tcEvDestUnique,
ctEvRewriteRole, ctEvRewriteEqRel, setCtEvPredType, setCtEvLoc,
tyCoVarsOfCtEvList, tyCoVarsOfCtEv, tyCoVarsOfCtEvsList,
@@ -2291,7 +2292,8 @@ For Givens we make new EvVars and bind them immediately. Two main reasons:
f :: C a b => ....
Then in f's Givens we have g:(C a b) and the superclass sc(g,0):a~b.
But that superclass selector can't (yet) appear in a coercion
- (see evTermCoercion), so the easy thing is to bind it to an Id.
+ (see evTermCoercion), so the easy thing is to bind it to a (coercion) Id.
+ This happens in GHC.Tc.Solver.Dict.solveEqualityDict.
So a Given has EvVar inside it rather than (as previously) an EvTerm.
@@ -2393,6 +2395,12 @@ wantedCtHasNoRewriters (WantedCt { ctev_rewriters = rws })
setWantedCtEvRewriters :: WantedCtEvidence -> RewriterSet -> WantedCtEvidence
setWantedCtEvRewriters ev rs = ev { ctev_rewriters = rs }
+ctEvRewriterSet :: CtEvidence -> RewriterSet
+-- Returns the set of holes (empty or singleton) for the evidence itself
+-- Note the difference from ctEvRewriters!
+ctEvRewriterSet (CtWanted (WantedCt { ctev_dest = HoleDest hole })) = unitRewriterSet hole
+ctEvRewriterSet _ = emptyRewriterSet
+
rewriterSetFromCts :: Bag Ct -> RewriterSet
-- Take a bag of Wanted equalities, and collect them as a RewriterSet
rewriterSetFromCts cts
@@ -2404,8 +2412,8 @@ rewriterSetFromCts cts
_ -> rw_set
ctEvExpr :: HasDebugCallStack => CtEvidence -> EvExpr
-ctEvExpr (CtWanted ev@(WantedCt { ctev_dest = HoleDest _ }))
- = Coercion $ ctEvCoercion (CtWanted ev)
+ctEvExpr (CtWanted (WantedCt { ctev_dest = HoleDest hole }))
+ = Coercion $ mkHoleCo hole
ctEvExpr ev = evId (ctEvEvId ev)
givenCtEvCoercion :: GivenCtEvidence -> TcCoercion
=====================================
testsuite/tests/perf/compiler/T8095.hs
=====================================
@@ -13,7 +13,9 @@ class Class a where
data Data (xs::a) = X | Y
deriving (Read,Show)
main = print test1
-instance (xs ~ Replicate1 ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Zero ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) ()) => Class (Data xs) where
+-- instance (xs ~ Replicate1 ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Zero ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) ()) => Class (Data xs) where
+instance (xs ~ Replicate1 ( Succ ( Succ ( Succ ( Succ ( Succ (Succ (Succ Zero ))))))) ()) => Class (Data xs) where
f X = Y
f Y = X
-test1 = f (X :: Data ( Replicate1 ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Zero ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) () ))
+test1 = f (X :: Data ( Replicate1 ( Succ ( Succ ( Succ ( Succ (Succ (Succ (Succ Zero))))))) () ))
+-- test1 = f (X :: Data ( Replicate1 ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Succ ( Zero ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) () ))
=====================================
testsuite/tests/perf/compiler/T9872a.hs
=====================================
@@ -140,7 +140,8 @@ type Cube2 = Cube W G B W R R
type Cube3 = Cube G W R B R R
type Cube4 = Cube B R G G W W
-type Cubes = Cons Cube1 (Cons Cube2 (Cons Cube3 (Cons Cube4 Nil)))
+-- type Cubes = Cons Cube1 (Cons Cube2 (Cons Cube3 (Cons Cube4 Nil)))
+type Cubes = Cons Cube1 Nil
type family Compatible c d :: *
type instance Compatible (Cube u1 f1 r1 b1 l1 d1) (Cube u2 f2 r2 b2 l2 d2) =
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5cf99a788eb64bf7289aa4fa0546a95...
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5cf99a788eb64bf7289aa4fa0546a95...
You're receiving this email because of your account on gitlab.haskell.org.