Conversation
Drop the [real_unit] op wrapper — the instance form accepts an inline lambda for [op unit]. unitout now uses [smt(invr0)] (the [inv 0%r = 0%r] rule), removing the previous reliance on the circular [instax_inst_real_idomain_unitout] axiom.
[opprK] and [mulrNz] are TC-polymorphic; in minimal-mode SMT we have to point them at [int] explicitly. Also drops the duplicate [opprK].
In TC-minimal mode, two issues blocked section-abstract lemmas from
applying to goals at the same abstract carrier:
- [placeholder_dict] emitted a fresh [missing_dict<N>] for every
TC-op call site, so the goal and the user-hinted lemma used
distinct dicts for the same [(*)]. Cached on
(carrier_w3_ty, tc_name) so calls at the same abstract carrier +
class share one constant.
- [trans_class] emitted chain-projection spec axioms describing
[parent_field(proj d) = child_field(d)]. Skipped in minimal mode:
we send class operators but not TC axioms.
Also:
- Track [pi.pr_wanted] in [tenv.te_wanted]. A TC-polymorphic lemma
explicitly requested via [smt(L)] without a [<:T>] instantiation
is now a hard error (not a silent skip).
- Arity-check [<:T1, …>] against the lemma's [ax_tparams] in
[process_dbhint]; mismatched counts raise [hierror] at scope
time instead of being dropped silently in [trans_axiom].
- TcNumber line 747: instantiate [mul0r<:t>] (the only TC-poly
lemma in that hint set; the rest are section-local).
In TC-minimal mode the dict-projection encoding was emitting one-step
projections at the witness's class (e.g. [tcrealdomain_times d]) while
operator bodies that internally project via chain projections produced
multi-hop forms (e.g. [monoid_mop (mulmonoid_to_monoid_0 (...)) x y]).
The two never matched without chain-projection spec axioms — and even
with them, the noise drowned Z3/CVC5.
This commit:
- [try_dict_proj] now canonicalizes class-op Fops in minimal mode:
walk the dict all the way to the OP's class via [lift] and project
using the op's local name there. Both lemma and operator-body refs
converge at the SAME (carrier, op_class, lift) key.
- Pre-emit one flat-constant logic-definition per
(carrier, reachable-ancestor-class, lift-of-edges) at init time.
The body is the explicit chain composition; references to the
constant unfold to the same chain expression when needed. Both
[try_dict_proj] and [compute_op_dicts] route through this cache —
every body term becomes a flat [<class>_<op> d_t_<class>_<lift> …]
rather than a 4-deep nested [proj1 (proj2 (...))] expression.
- [trans_class] in minimal mode skips emitting chain-proj spec axioms
(canonicalization makes them redundant) AND emits projection
lsymbols only for the natively-declared ops of each class
(inherited ops are reached via origin canonicalization, not via
leaf-class field clones).
- [lenv_of_tparams_for_hyp] strips the leading tick from EC tparam
tysymbol names ([ec_tv_a] instead of ['a]) and [trans_hyp] uses
[preid_lid] for lsymbol names so the dump's [.why] companion is
valid Why3 source. [str_p_raw] sanitises operator/punctuation
chars in path-derived names.
- [emit_one_dict] gains [?emit_axioms:bool]; minimal-mode dict
emission passes [~emit_axioms:false] (no [axhold] / no
[tcaxiom_] decls).
- Lemma instantiation in [trans_axiom] uses
[EcUnify.UniEnv.opentvi] to resolve witnesses for [smt(L<:T>)]
hints — the same path as proof-term elaboration. Handles
section-abstract carriers correctly, replacing the hand-rolled
[List.find_opt] lookup.
- [process_dbhint] now arity-checks [<:T1,…>] against
[ax_tparams] at scope time (mismatched count is a hard
[hierror], not a silent skip in [trans_axiom]).
Status: Alt-Ergo proves the TcBigalg:291 task in 0.02s. Z3 and CVC5
still struggle (Unknown / Timeout) despite identical SMT-symbol
matching across lemma / hypotheses / goal — investigation continues
(possibly per-call-site specialisation à la option C).
…e 1)
In TC-minimal mode, [try_dict_proj] now emits a CONCRETE-TYPED lsymbol
per (carrier, op_class, lift) instead of a dict-passing projection.
This mimics what clone-based theories produce: one fresh first-order
function symbol per (concrete instantiation, leg), with no polymorphism
or dict argument visible to the SMT prover.
- Cache keyed by (carrier_w3_ty, op_class_path, local_name) in
[te_carrier_ops]. Each entry is a fresh lsymbol whose
[ls_args]/[ls_value] come from substituting the op's self-tparam
with the carrier in the EC signature.
- Lemma side (after [opentvi]) and operator-body side at the same
(carrier, leg) hit the same cache entry — bytewise-identical SMT
terms across the task. Z3 and CVC5 pattern-match without needing
to instantiate polymorphic types or unfold dict projections.
- Partial / over-application paths now branch on whether we
resolved to [`Concrete ls] (minimal mode) or [`Field (d, w3cd, f)]
(dict-passing mode); HO wrappers for the concrete form reuse
[mk_highorder_func] from regular-op translation.
Sweep at this point (regular ops with TC tparams still polymorphic,
i.e. [bigM] keeps a dict argument — Phase 2 will specialize those
per call site too):
PASS: TcMonoid, TcRing, TcInt, TcReal, TcNumber, TcBigop, TcBigalg,
TcPolySmokeTest, TcZModPSmokeTest
FAIL: TcBinomial:14, TcPoly, TcZModP:294
…nches
- Remove the [tc_minimal_mode] env-var flag and all
[if (not) (tc_minimal_mode ()) then …] conditionals — keep the
minimal-mode body, drop the polymorphic-dict-passing branches.
- Drop chain-projection spec axiom emission from [trans_class]
(replaced by origin canonicalization in [try_dict_proj]).
- Drop the polymorphic-dict-passing axiom encoding in [trans_axiom]
plus its [_at_<carrier>_<class>] instance specialization
(replaced by [do_instantiated] via [smt(L<:T>)] hints).
- Drop the ancestor-class flattening in [trans_class] (only emit
fields for natively-declared ops of the current class).
- Drop the [Field] case of [try_dict_proj]'s [resolved] disjunction
— class-op references always resolve to the concrete-typed
[`Concrete] lsymbol now.
- [emit_one_dict] no longer takes an [?emit_axioms] parameter; the
axhold / tcaxiom emission paths are gone. It always emits
dict-const + flat-constant logic-defs for ancestors.
- [init] simplifies — no Phase B branch, just direct emission of
tparam + abstract-type dicts.
Sweep unchanged from previous commit: 9 PASS, 3 FAIL (TcBinomial:14,
TcPoly, TcZModP:294).
…rrier Three call sites of [smt(ge0_deg)] and two of [smt(oner_neq0)] in sections declaring [c :: comring] / [c :: idomain]. Both lemmas are TC-polymorphic; the minimal-mode encoding requires explicit [<:c>] instantiation.
- TcZModP:unitE — replace [smt(zmod_mulrC zmod_mul1r choicebP)]
with [apply: (unitr0<:zmod>)] (analogue of main's
[apply: ZModpRing.unitr0]).
- TcZModP:zmod_mulf_eq0 — port main's case-analysis proof
using [mul0r] / [mulr0] / [mulrI] / [unitE].
- TcBinomial:fact0 — replace [rewrite /fact /bigiM /bigM
range_geq /#] with [rewrite /fact big_geq // ler_naddl]
(main's proof).
- TcBinomial:size_bin1 — replace the [/#] tail with main's
[subz0 ler_maxr ?size_ge0] rewrite chain.
All four had been rewritten with [smt(...)] / [/#] tails that
relied on auto-relevance to pull in lemmas the minimal-mode
encoding doesn't surface. Backporting main's proofs verbatim
closes them.
…rier [pmulr_gt0] is TC-polymorphic; the minimal-mode SMT encoding requires explicit [<:t>] instantiation (section's [t :: tcrealdomain]). [prodr_ge0_seq] is section-local with 0 tparams — left bare.
Conflicts resolved in 6 files, all from origin/main's [ac42e2a subtype: generalize over section-declared free types at section close]. That commit's subtype-tracking change had already been applied to HEAD's [module Ty.add_subtype]/[Ty.add] independently (tyd_subtype field threaded through, carrier+pred stored on the tydecl), so the conflict resolutions all KEEP HEAD's structure: - [tydecl] keeps HEAD's [tyd_resolve] field on top of the [tyd_subtype] field both branches added. - Type-body constructors stay as polymorphic variants ([`Abstract], [`Concrete]) — TC needs the typeclass-list payload on [`Abstract tc] that main's plain constructor form doesn't carry. - Subtype-related tydecl construction sites all carry the [tyd_resolve = …] field. - [generalize_tydecl] in [ecSection] keeps the destructuring [fun (id, _) -> …] for HEAD's tparam-with-tcs tuple shape. - [ecScope.ml]'s conflict was a structural duplicate (origin/main's [module Ty] block was being pasted before HEAD's [module Search]; both branches already have [module Ty] independently) — dropped the duplicated insertion. Verified: [dune build] clean, tcalgebra sweep 12/12 PASS after merge.
Commit [0b2f706 TC: matcher recognizes ops with same canonical origin] left this line as a broken split [rewrite ... addrAC. rewrite !addzA. ler_subr_addl (...).] — apparent WIP that didn't get re-joined. Restoring main's single-line form [rewrite ... addrAC !addrA ler_subr_addl (IntID.addrC 1).].
Commit [5e04bf6 TC: drain pending TC-constraints before [try_delta]'s tc_reduce check] added [flush_tc_problems] + [norm f1] / [norm f2] at the entrance of [try_delta]. The flush is needed; the [norm] calls are not — they re-substitute ev/tu bindings that may have been pinned during earlier sibling-argument matches, which can change which heads appear after [destr_app] and silently steer the case dispatch away from the [Op.reducible] branch that would otherwise apply. Concrete regression: [theories/algebra/IntDiv.ec:1234]'s [rewrite -(big_mapT _ idfun)] failed with [nothing to rewrite] because the pattern's [idfun \o ?h] couldn't unfold past the norm- substituted form. Dropping the [norm] calls restores the match (IntDiv.ec passes again; tcalgebra 12/12 still PASS). [flush_tc_problems] alone is enough to make the queued [TcCtt] problems get resolved so [tc_reducible] can fire on the now-pinned witnesses.
…ding Reverts the identifier-mangling that was added solely so the Why3 task could be re-emitted as a parseable .why source. The mangling (lower/uppercasing first chars, mapping operator chars to alphabetic prefixes, stripping ticks from EC tparam names) produced lowercased prelude identifiers (top_*) that Z3 4.12 was sensitive to: Matrix.eca:145 returned unknown under the lowercased form but unsat under main's case-preserving identifiers. Removed: - dump_task_theory function and its caller in out_task - str_lid / str_uid / str_p_raw / str_p_ctor / preid_p_ctor / preid_lid (folded back into main's simple str_p / preid) - sanitize_op_name (HO-wrapper and carrier-op naming) — use raw names - strip_tick mangling in lenv_of_tparams_for_hyp — use preid id directly tcalgebra: 12/12 still pass. make stdlib: Matrix.eca:145 now passes again (was unsat-regressed); DynMatrix.eca:1666 unchanged (independent).
TC class axioms are lemmas. They must never be auto-emitted into the why3 task — neither as a side-effect of generating an instance dict, nor through auto-instantiation. The only paths to surface them are: - user-explicit hint: smt(L<:T>) — instantiates and emits. - relevance: blocked by ax_smt = false on TC class axioms. Code changes: - emit_instance_dict: drop the auto-emitted instax_* ancestor-class axioms. Dict const + axhold + bridges (user definitions, not class axioms) remain. - trans_axiom: replace the failwith on TC-poly explicit hints with a registered SmtHintError exception — clean EC-style error, no anomaly. - Delete the dead trans_tc_axioms helper. - Add te_hyps_lenv + te_hyps_tparams to tenv, populated in init from the goal's lenv/h_tvar. do_instantiated uses them so substituted axioms translate against the goal's why3 tysymbols/dicts AND so flush_tc_problems can infer TC witnesses for [Tvar 'a] carriers. - Thread active_tparams(scope) through do_prover_info → process_prover_option → process_dbhint, so <:'a> in smt(L<:'a>) resolves to the lemma's own tparam ident instead of minting a fresh one. Test changes: - Delete tests/tc-concretize-fold.ec (depended on the just-removed examples/tcstdlib/). - tests/tc/smt.ec, tests/tc/diamond.ec: add explicit <:'a> / <:t> on every TC-poly hint at abstract carriers. Verification: make unit passes; tcalgebra 12/12; make stdlib leaves only Logic.ec:525 + DynMatrix.eca:1666, both pre-existing in main.
The two TC docs accumulated drift faster than they were maintained: - typeclasses.md §9 documents the now-removed auto-axiom SMT inclusion; §10's "diamond" claim about deduplicated auto-axioms is also gone. - The "Examples" section points at examples/tcstdlib/ and examples/typeclasses/ (removed in 1d48ccd, 3d23703) and tests/tc-concretize-fold.ec (removed in 116589f). - The "Files of interest" table cites src/ecSmt.ml trans_tc_axioms which was deleted in 116589f. - typeclasses-inference.md describes a multi-phase strategy-framework redesign that was never implemented in that form; the live resolver in ecUnify.ml is what governs behavior. Also drop the dangling "See doc/typeclasses-inference.md ..." comment in ecUnify.ml.
The additive identity in [addmonoid] was named [zero], diverging from the conventional stdlib name [zeror] used in [Ring.ZModule.zeror], [ComRing.zeror], etc. This is a prerequisite to porting stdlib files (Matrix.eca next) whose proof bodies reference [zeror] verbatim and that we want to keep unchanged. Word-boundary rename across all examples/tcalgebra/*.ec: - TcMonoid.ec: the [addmonoid <: (monoid with idm = zero, ...)] rename clause and the [abbrev zero ['a <: addmonoid] = idm<:'a>] declaration. - All call sites (333 occurrences across 8 files). Comment text containing the word "zero" (e.g. "zero divisors") gets the rename too -- acceptable noise. tcalgebra sweep: 12/12 pass.
[reduce_user_gen] in ecReduction.ml backs the [hint simplify] machinery. It opens the rule's tparams as fresh univars, walks the goal subterm against the rule pattern via [unify_etyarg], then checks closedness. Three issues prevented TC-polymorphic lemmas from matching: 1. The unienv was created with [None] tparams, so when the matcher tried to unify a fresh univar (bounded by a TC) with a goal-side [Tvar 'r] (also TC-bounded), the unifier had no record of 'r's bounds and rejected the unification. Fix: seed [UniEnv.create] with the goal's [hyps.h_tvar]. 2. [Tvar.subst_etyarg] only substitutes the type slot of the pattern's etyargs, leaving witness slots referencing the rule's own tparam ids. Those don't match the goal's tparam ids, so the TcTw equation falls into the [tcw_equal] arm and fails. Fix: use [EcCoreSubst.etyarg_subst] with an [f_subst] populated from [tvi.subst] (both [tv] and [tw] maps), so the witnesses are also substituted to fresh TC-witness univars that can unify against the goal's abstract witnesses via TcTw [bind_uni]. 3. After unification, parked [TcCtt] problems (one per opened TC bound) remain in [tcenv.problems] without entries in [tcenv.resolution], so [closed] returns false. Fix: call [flush_tc_problems] after [doit] and before [closed], mirroring what [trans_axiom]'s [do_instantiated] already does in ecSmt.ml. With all three changes, hint simplify on TC-polymorphic lemmas fires both at top level and inside sections with [declare type r <: tc]. Verification: - All four probes (same-section, top-level, lemma-in-section-used-at-top, cross-section) — three pass; cross-section still fails (separate issue: hint registration doesn't propagate across section close). - tcalgebra 12/12 still pass. - make unit: all pass. - make stdlib: only pre-existing Logic.ec:525 and DynMatrix.eca:1666 fail; no new regressions.
When a user-rewrite rule fires on a TC-polymorphic lemma, [reduce_user_gen] opens the rule's tparams and unifies its pattern against the goal subterm. The closing substitution only carried the type-univar map [assubst ue]; the TC-witness univar map [tw_assubst ue] was dropped. Result: [TCIUni _] placeholders survived in the rewritten term and poisoned later matches (closedness check failed, cbv fell through to delta on the carrier op). Pass [tw_uni] through to [Tuni.subst] so witness univars resolve alongside type univars.
[generalize_ctheory] entered a sub-theory, accumulated substitutions / tparams / binds / clears for its items in a local [genenv], then returned only the compiled theory body. The outer [genenv] kept its original [tg_subst] — so use sites in *later* items of the same section that referenced an op renamed inside the sub-theory were never rewritten with the section's freshly-introduced tparams. The [Fop (sub.op, [])] left behind crashed at first reduction with [List.combine: list lengths differ] (n_tparams=1, n_tys=0). Triggered by [subtype X as Sub] inside a section: [Sub.insubd] gets generalised properly within [Sub], but downstream [op f = Sub.insubd ...] saw the un-substituted reference. Fix: pull [tg_params] / [tg_binds] / [tg_subst] / [tg_clear] from the inner genenv back to the outer one before reassembling [tg_env].
[examples/tcalgebra/TcMatrix.eca]: TC port of [theories/algebra/Matrix.eca]
over [r <: comring]. Vector and matrix are now subtype-based (not
axiomatic); the [clone import Ring.ZModule] for each becomes [instance
addgroup … reducible] with obligations discharged via [realize] after
the instance declaration.
Proofs are backported verbatim. Two forced TC adaptations:
- scalevE: [smt(offunvK tofunvK)] -> [smt(offunvK<:r> tofunvK<:r>)]
(smt hints require explicit TC instantiation).
- offunM: [/getm_outL|/getm_outR] -> [/getm_outL<:r>|/getm_outR<:r>]
(the lemma's premise [!(0 <= i < size)] doesn't mention 'r, so
the discriminator step can't pin 'r before the next [->] runs).
Matrix's [Matrix.offunB] is renamed to [offunmB] to avoid clashing
with [Vector.offunB] at top level (both lose their theory namespace
when moved outside their respective sections, where the addgroup
instance is registered).
[examples/tcalgebra/TcDynMatrix.eca]: TC port of [theories/algebra/DynMatrix.eca]. Dynamic-size vectors and matrices as quotient types via [Quotient.EquivQuotient], over [r <: comring]. No addgroup instance — dynamic-size carriers don't form a Z-module (no canonical zero across all sizes; [add0v v : zerov (size v) + v = v] depends on the size). Proofs are backported verbatim. Forced TC adaptations on a handful of SMT-hint sites where the lemma is type-class polymorphic and the smt pipeline requires explicit instantiation: - dotpDr: smt(... mul0r) -> smt(... mul0r<:r>) - dotp_scalarv: smt(mulrA mulrC) -> smt(mulrA<:r> mulrC<:r>) - mulmxA, catmrDr: smt(... mulr0 mul0r ...) -> ...<:r> - addm_catmr: smt(addrA addrC) -> smt(addrA<:r> addrC<:r>) - mul_colmxc: Big.BAdd.big_int1 -> big_int1 (TC name) Two unrelated stdlib-side proof breakages also fixed in-place during the backport: [catmr_subm] and [scalarNm] both fail to close with their existing hints (smt accepts [size_*] but cannot project the resulting pair equation into the [rows = ... /\ cols = ...] components it needs). Replacing [size_X] with [rows_X cols_X] in those smt calls gives the solver the int-shaped equations directly. The original DynMatrix.eca fails identically on deploy-tc/main — the fix is not TC-related.
The [hint simplify subrr.] declaration inside the addgroup section did not survive section close (per the project's standing observation that hint declarations are section-local). Re-register it at top level so the TC-polymorphic [subrr] rule fires on goals like [zeror<:t> - zeror<:t> = zeror<:t>] at use sites of [t <: addgroup] in other files (e.g. closing the trivial subgoal of [apply/idealP => //] for the [id0] ideal).
When a TC instance has multiple obligations with the same axiom name reached through different parent-class paths (e.g. [comring] reaches [mopA] both via [addgroup/addmonoid/monoid] and [mulmonoid/monoid]), [check_tci_axioms] disambiguates by encoding the effective name as [mopA<:addgroup/addmonoid/monoid>] in the pending-obligation path. The inline [proof X<:Lbl> by Y] form on the instance declaration matches via a sub-sequence containment on labels. The [realize] command, however, only accepted a bare qident and tried exact path equality, so [realize mopA<:addmonoid>] could not be used to discharge such obligations. Extend the [realize] grammar to optionally accept the same [<: l1 / l2 / ... >] label suffix as the inline form, and lookup the matching pending obligation via the same sub-sequence rule. prealize gains [pr_labels : psymbol list option]. Labelled form is restricted to unqualified obligation names (the parsetree's [pr_name] retains the prefix path for the cross-theory case; labelled lookup is only meaningful inside the active proof context).
[examples/tcalgebra/TcIdeal.eca]: TC port of [theories/algebra/Ideal.ec].
- [abstract theory TcIdealComRing] declares [type t <: comring]
directly (replacing stdlib's [clone import Ring.ComRing as
IComRing]). The ideal theory body (~250 lines: [(%|)], [(%=)],
[ideal], [idgen], [principal], [dvdr*], [eqp_*]) is backported
verbatim, TC-polymorphic in [t].
- [RingQuotientBase] inside keeps the stdlib abstract-theory
shape: declares the ideal predicate [p : t -> bool], its
[IdealAxioms], clones [Quotient.EquivQuotient], defines ring
ops on [qT], proves all ring axioms.
- [RingQuotientDflInv] / [RingQuotient] each emit
[instance comring with qT op ... .] (replacing stdlib's [clone
import ComRingDflInv]/[ComRing]). [RingQuotientDflInv] supplies
[qunit]/[qinvr] via [choiceb]; [RingQuotient] takes
[mulVr]/[unitP]/[unitout] as axioms.
- [TcIdeal] mirrors stdlib's [Ideal] (IDomain specialisation) via
[clone include TcIdealComRing with type t <- t].
Forced adaptations from verbatim:
- [ideal_sum] / [eqv_sum]: stdlib's [BAdd.big<:'a> P F s] becomes
[bigA P F s] (un-annotated). The TC [bigA] has two tparams
['a, 't <: addmonoid]; positional [<: t>] would bind the wrong
one. Explicit param types on [P/F] fix [t] via unification.
- [in_idgen_mem]: [pose cs := rcons (nseq n zeror) oner] cannot
pin [zeror]'s type from context. One annotation: [zeror<:t>].
- [addrN] for [qT]: stdlib's [addNr : left_inverse zeror [-] (+)]
is kept verbatim. The TC [addgroup] class's axiom is
[addrN : right_inverse zeror [-] (+)] (opposite side, different
name). Added a derived [addrN] lemma:
[by move=> x; rewrite addrC; apply: addNr.]
Backports [theories/algebra/Poly.ec:782+] (finite_for_poly_ledeg, dpoly, supp_dpoly, dpoly_ll, dpoly_fu, dpoly_uni) into the comring section of TcPoly. All proofs verbatim from stdlib. Needed by TcPolyReduce / TcPolyReduceZp's finiteness and uniform-sampling lemmas (finite_for_polyXnD1, dpolyX, dpolyXnD1).
[examples/tcalgebra/TcPolyReduce.eca]: TC port of
[theories/algebra/PolyReduce.ec]. Builds the ring k[x]/<X^n + 1>.
Structure:
- [abstract theory TcPolyReduce] declares [type coeff <: comring]
directly (replacing stdlib's [clone import ComRing as Coeff]).
- Uses [TcPoly]'s [coeff poly] directly. Drops stdlib's [clone
export PolyComRing as BasePoly] — TcPoly's instance comring
already gives us the polynomial ring on TC.
- [clone import TcIdealComRing as PIdeal with type t <- coeff poly]
specialises the TC-bound ideal machinery to the polynomial ring.
- [op n], [op I = idgen [exp X n + poly1]], then
[clone include RingQuotientDflInv with op p <- I
rename "qT" as "polyXnD1"]
creates the quotient type and auto-registers it as a comring
(via the [instance comring with qT] inside RingQuotientDflInv).
- Drops stdlib's [clone BigComRing as BigXnD1] — bigops on the
quotient resolve automatically because [polyXnD1 : comring]
via the instance.
- All ~400 lines of [pinject]/[prepr]/[iX]/[( ** )]/[reduce]/
[reduced]/[crepr] and friends backported verbatim.
- [abstract theory TcPolyReduceZp] clones [TcZModP.ZModRing] and
[TcPolyReduce at coeff = Zp.zmod], then defines [dpolyX],
[dpolyXnD1] and lossless/uniform/full/funi/[reduced_dpoly]
lemmas.
Forced TC adaptations:
- In [eqv_reduce] proof: stdlib's [(IntID.mulrC _ n)] becomes
[(TcRing.mulrC<:int> _ n)] — the local cloned [mulrC] on the
quotient ring shadows; qualifying with the [TcRing] prefix +
explicit instantiation picks the integer one.
- In [finite_for_polyXnD1]: stdlib's [pose P p := deg p <= n]
becomes [pose P (p : coeff poly) := deg p <= n] — without the
type ascription [pose] cannot infer [p]'s type from the
TC-polymorphic [deg]/[n].
When an instance for a typeclass [C] on carrier [T 'a] reuses
existing chain entries from a previously-registered instance of
[C']'s ancestor on the same carrier, those existing entries were
registered at a different tparam bound list (e.g. ['a <: C']) than
the user's new instance (['a <: C]). The reuse exposed body
witnesses encoded at the existing-instance's bound depth, so
[tc_core_reduce]'s post-substitution result had stripped lifts and
the obligation's proof script could not match.
Fix: compute a per-chain-entry "bridging" lift — the parent-index
path through context-changing chain steps from chain_decls[0]
(user's class) to that entry. A step is context-changing iff the
two entries' tparam bound lists differ (using TC-name equality);
the existing instance's bounds are read via [TcInstance.by_path] on
the reused path. Bake [bridging] into [self_etyargs]'s
[TCIAbstract] witnesses in [add_tydef]'s [self_witness]: each
witness's [lift] becomes the bridging path, so body's
[AbsV('c, off=k, lift_body)] substitutes to
[AbsV('c, off=k, bridging @ lift_body)] — the use-site walk that
reaches the reused entry's tparam depth before continuing with
the body's own lift.
[tc_core_reduce] also gains a parallel [bridging] tracker on the
walk and threads it to [finalise], which applies it to the etyargs
before building the substitution. This covers obligations whose
class-op witnesses point at fresh entries but transition through
reused ones during reduction.
Unblocks Phase 8 (`instance idomain with ['c <: idomain] ('c poly)`).
All 16 tcalgebra files pass.
Phase 8 instance registration: backport stdlib [Poly.ec:850-974]'s [abstract theory Poly] (the IDomain coefficient phase). Re-emits the comring obligations (resolved verbatim from the same [polyD_*]/[polyM_*] lemmas as the Phase 5 comring instance) plus [mulf_eq0] discharged via [polyM_mulf_eq0] (already in TcPoly's idomain section). Required the bridging-lift fix in [scope/env] (parent commit) to get past the tparam-context mismatch the obligation form would otherwise have when the idomain chain reuses the existing comring/addgroup/addmonoid/monoid chain entries on the same carrier.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.