Repository navigation
The FreeMonoid match lowering answers every arm, at any spine depth, or refuses - #12026
Conversation
…or refuses
A nested constructor pattern in a field position was dropped and every arm
after it discarded, so the emitted program ran and returned a well-typed wrong
value.
emit_native_freemonoid_match asked two questions -- which arm mentions Empty,
which arm mentions Cons -- kept the FIRST answer to each, and emitted
`if __fm.is_empty() { A } else { B }`. Its admission predicate
arms_are_freemonoid_coproduct established only that the arms resolve to
FreeMonoid; it never asked whether they FIT a two-way split. Three silent
consequences, not the two reported: a refutable field sub-pattern degraded to a
wildcard, because the binding reader returned "_" for anything that was not a
Bind, so `Cons { head: _, tail: Empty }` matched every non-empty list; every arm
after the first Cons arm was discarded, because nothing read past `first`; and
an arm GUARD was dropped on the same reasoning, since no branch body ever read
arm_guard.
Measured in the emitted binary rather than the interpreter (witty-cat-84,
Pkg12): v2.std.algebra list_init emitted as
`if __fm.is_empty() { vec![] } else { vec![] }`, so
qualified_name_init(["v2","acp_user","acp_row"]) returned [] instead of
["v2","acp_user"] and the native resolver's ancestor walk skipped every
intermediate ancestor. v2.lens.cost.copied_port_derivation is the same class
with a different consequence -- "exactly one" for a three-element list -- which
is what makes this a defect in the RULE rather than at either site.
THE CONSTRUCTION. A FreeMonoid pattern is a spine of Cons levels terminating in
either Empty (an exact length) or a binding/wildcard tail (a length floor), so
each arm carries a decidable length predicate and its head bindings are
decidable index reads at any depth. The arms become an ordered chain of those
predicates, which is what a match means. Exhaustiveness is decided on the same
facts, so the final `else` is proven total rather than assumed and no
unreachable! is fabricated. Shapes the analysis cannot express -- an arm guard,
a refutable head sub-pattern, a variant that is neither Empty nor Cons, a set
not provably exhaustive -- emit a located compile_error!. The failure arm
refuses; it does not widen.
The TCO twin carried the identical defect and now shares the analysis, refusal
and chain, with the body emitter the only variance.
SELF-HOSTING: this module is emitted by the seed it fixes, so the repair avoids
the shape it repairs -- the spine recursion tests the tail's count rather than
matching `tail: Empty`. Verified by inspecting the regenerated mirror: the old
emitter lowered fm_chain_from correctly, so one regen round reaches the fixed
point.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ating red
TWO FINDINGS, BOTH CORRECT, BOTH FIXED.
1. THE REFUSAL WAS AN IN-BAND SENTINEL. `FmArmPlan { supported: Bool, reason:
String }` answered "is this lowerable" with `""` meaning yes -- the same
protocol this change deleted one layer down, where `""` from the lowering meant
"fall through to the generic path", reintroduced one layer up. It made illegal
states representable: a supported plan carrying a reason, an unsupported plan
whose zeroed `len` was still readable by the coverage fold, and a bottom spelled
`1000000`.
Now a coproduct: FmArmAnalysis = FmSpine { exact, len, head_binds, tail_bind }
| FmUnsupportedArm { cause: FmLoweringRefusal }, with a seven-variant cause and
one fm_lowering_refusal_message rendering it -- the shape
std.operator_realization already uses for OperatorRealizationRefused, which this
module consumes. Its own cause type rather than reusing
OperatorRealizationRefusal, which is about operators: sharing that spelling
would be a meaning fork, not single authority. An unsupported arm now HAS NO
spine fields to misread, and fm_min_open_len returns Int? where absent means "no
arm accepts unbounded length" rather than a number pretending to be a length.
Both the ordinary lowering and the TCO twin consume it.
2. NO ENROLLED DISCRIMINATING EVIDENCE, AND THE ROW DECLARED THAT GAP
UNBRIDGEABLE WHEN IT WAS NOT. This was a SUBJECT CONFLATION and the row is
retracted rather than softened. "Every claim the floor runs is interpreted" is
true of the defect's CONSEQUENCE -- a miscompiled binary answering wrongly at
runtime -- and false of the repair's own SUBJECT: the lowering is a pure String
fold, so the arms it emits and the refusals it raises are decidable by an
interpreted claim over a fixture handed to the compiler. DESIGN section 4b says
exactly that, and the emitter_*_witness_test family already does it routinely.
The hard question was used to excuse not asking the easy one, which reported
"can climb now but unbuilt" as "cannot climb further".
Enrolled as test.claim.emitter_freemonoid_arm_chain_witness_test, four rows:
the discriminating red over the pre-repair shape (asserting both `__fm.len() ==
1` and the third arm's body, since a lowering that kept two arms and dropped
only the last would otherwise pass); a positive control that the ordinary
two-arm shape still lowers natively and does NOT refuse, without which the
refusal arm is satisfiable by refusing everything; and two refusal controls, a
refutable head sub-pattern and a guarded arm.
The row's next-rung trigger is rescoped to what is genuinely out of reach: these
rows assert emitted TEXT, and no enrolled claim executes emitted CODE, so the
behavioural half remains the differential oracle's subject.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Mirror-only, from the merged base. Fixed point proven by a second regen round with a binary verified to carry the rework: round two reports drift in std_measure.rs alone, so v1_compiler_emit_rust.rs is what the reworked emitter itself emits. std_measure.rs is excluded as before -- it is #11992's unmirrored grain-rounder, and #12027 is the PR that repairs it. EVIDENCE RE-ESTABLISHED AFTER THE REWORK, because the coproduct change touched emit_native_freemonoid_match and every earlier behavioural claim described a superseded revision: list_init identical three-arm chain, __fm.len() == 1 preserved refusals in closure 0, unchanged __fm.len() conditions 13 (2 exact, 11 floor), unchanged probe 5/5, exit 0 red control 3/5 FAIL, exit 1 So the rework is a pure refactor of how the refusal is carried, measured rather than asserted. The four enrolled witness rows all return true: nested_field_arm_and_its_successor_both_reach_the_emitted_chain, the_ordinary_two_arm_shape_still_lowers_natively, a_refutable_head_sub_pattern_refuses_rather_than_becoming_a_wildcard, a_guarded_arm_refuses_rather_than_running_unguarded. INSTRUMENT PROVENANCE, recorded because it nearly produced a false finding against this change. /cargo-target is shared across worktrees and sessions. A neighbouring session's build of v1-compiler overwrote the binary between the moment I verified it carried the rework and the moment I measured with it, so two witness rows reported false and a fixture emitted a textbook reproduction of the original bug -- from a compiler that predated the fix. Caught only because two greps of one file disagreed: the rework-only string counted 1 earlier and 0 later. Every measurement above was re-taken with a worktree-local CARGO_TARGET_DIR whose binary was verified by a string that exists only in the reworked code. The red control needs no such check: its artifact carries the two-way split and zero length-conditions, and witness row one establishes that the fixed emitter emits len() == 1 for that exact shape, so the output identifies its own producer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
bold-seal-329's point, applied: a row whose red is "this crate does not contain what the fixed emitter must emit here" survives the run that produced it; a row whose red is "the binary I ran was the right one" does not. The two refusal rows asserted only that the emitted text CONTAINS the located compile_error. That half is satisfied by any crate carrying a refusal, so the rows leaned on the positive control to rule out an emitter that refuses everything. They now also assert the emitted text does NOT contain __fm.is_empty(): a refused arm set emits the compile_error INSTEAD of the native chain, while the pre-repair emitter emits the chain and mis-lowers. So each refusal row is now red on the broken emitter in two independent ways, and both of them are readable from the retained artifact alone. All four rows re-executed against a worktree-local binary verified to carry the rework: true, true, true, true. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…rop retires by its own trigger
Review 69926 found that this PR deletes the class native_route_live_pair_standing was
pinned to, orphaning an enrolled 4b(4) probe. The manager ruled the flip is gated on the
OBSERVATION, not on resolve -- flipping on resolve alone would be the rung inflation
4b(1) names -- so the observation was executed before this edit, not predicted by it.
EXECUTED, in this order, on the emitted route:
1. v2.native_lane_fixture.control RESOLVES. Real source bytes (control.dag,
live_tree.dag, logic.dag), not an isomorphic fixture.
2. Through the emitted binary's own native_test_eval_one:
native_lane_false_control = ReturnedFalse
native_lane_true_control = Passed
That is the first observation of the pair on ANY head. It could not be observed on
main 79e745b or on gunbc#11952, because the module both controls live in refused at
prepare with resolve_ambiguous_on_global_bare on the bare SubstrateInputsOnly.
3. Standing set to LivePairRequired here, in the same change, as the trigger requires.
Receipt: dag head 5aee537 plus the two emitter files from #12026
(origin/session/sunny-ibex-112 @ 0f0ee6f, cherry-picked -- merging that branch whole
drags in main's extdeps_numeric_base16 UInt8 gap and the emitted crate will not compile);
emitting gunbc sha256 682bfa1247cd3a04; emitted closure 190 files sha256 038f40828900249f;
probe sha256 1d5a6a98ebc5dac6. Command in the PR body.
IT FLIPS, IT DOES NOT RETIRE (DESIGN 4b(4)). The pair is a permanent regression control
from here: a route that stops discriminating false from true reds this clause. What the
enrolled-red form bought was tolerance of a refusal no lane change could move, and that
refusal is gone. gunbc.rung_drop.native_lane_live_pair_expected_red is Retired by its own
trigger and by nothing else, with the three conjuncts recorded on the row;
docs/design-rung-drops.md regenerated rather than hand-edited.
The leading annotation no longer describes the enrolled arm as current. It keeps WHY that
arm pins three axes, because that is how a future stall would be declared: an arm pinned
to stage, fatal reason AND lookup class cannot be satisfied by the subject getting worse
in a new way, and cannot outlive the condition it describes -- which is exactly how this
one failed when the class was deleted underneath it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…rases CI caught this, and it is mine. floor_diff_observe refused the closure with `undefined variable 'because'` at special_cased_lowering_answers_a_narrower_question_than_its_arms_ask.dag:32:159. The retraction receipt I wrote quoted three phrases with raw double quotes inside a .dag string. The first one terminated the string early, so the prose after it parsed as source and `because` became a bare identifier. Six unescaped quotes on that line. They are backtick-quoted now, which is what the surrounding receipts already use for quoted prose and code. WHY IT REACHED CI: I verified the edit with `grep -c` and treated that as verification. A grep establishes that a string is present in a file; it establishes nothing about whether the file resolves. I parse-checked the OTHER row I edited today and skipped this one, having already touched it twice. That is the same substitution a reviewer caught in this PR one layer up -- checking that something EXISTS rather than that it WORKS -- and it is the reason the enrolled rows exist at all. Verified by execution this time: the row resolves and returns its RecurringFailureMode value with every receipt intact. Swept the other .dag files this branch touches for the same defect. The witness test and the failure-mode row are clean. A quote-balance scan of src/v1/05_emit_rust.dag reports ~1031 lines, and they are detector false positives: those are multi-argument concat() lines carrying several separate string literals, which the line-grain scan reads as one string. That file compiles and regenerates, which settles it independently. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…tinel goes Two findings, both correct. THE CENSUS CITED FIVE SYMBOLS THIS PR DELETED. e0599_emitter_decision_census named freemonoid_tail_let_from_fm and the four branch-body functions as emitter_authority, and FreeMonoidEmptyTest still carried the two-way-split emitted_literal -- the exact shape this change replaced. Deleting a symbol makes every citation of it unresolvable, and DESIGN section 3 makes that decidable rather than a matter of taste: a name is a Node-tree read, so a stale citation is enforceable. Retargeted to fm_spine_condition, fm_spine_binds and fm_head_bind_lets, which is where those emissions now live. The literals were stale independently of the names and are corrected too: the skip is by the arm's spine depth rather than always by one, and the head read is indexed by spine level rather than always zero. A DEAD ESCAPE HATCH SURVIVED ON THE ADMISSION PATH, AND AN ANNOTATION CLAIMED IT HAD NOT. Both callers still ran `if native_fm != ""` over a function that can no longer return "". It looked like harmless dead code and was not: that empty string never came from the lowering at that site -- it came from the ADMISSION PREDICATE's own else branch, so one value encoded two different facts, `these arms are not a FreeMonoid coproduct` and `the lowering declined`, with nothing downstream able to separate them. The callers now branch on arms_are_freemonoid_coproduct directly and the lowering always answers, so the sentinel has no spelling left. That is the construction rather than the check. The annotation I wrote claimed the caller-side protocol was already deleted while both tests were still standing. Section 4c is explicit that an annotation is captured authored data and must not restate what the declaration does not bear out; an annotation asserting a completed deletion is worse than silence, because it reads as confirmation and stops the next reader looking. Rewritten to state what holds, and to record that review 69977 found the residue. EVIDENCE RE-TAKEN, because this touched the admission path -- the code the enrolled rows exercise -- so their previous results described a superseded revision: four witness rows true, true, true, true list_init three-arm chain, unchanged refusals 0, unchanged len conditions 13 (2 exact, 11 floor), unchanged probe 5/5, exit 0 blocking errors 0 fixed point round two drifts std_measure.rs alone The positive control is what makes the unchanged numbers meaningful: it asserts the ordinary two-arm shape still lowers natively AND does not refuse, so it is the row positioned to catch a change in which matches reach the lowering. It holds, so the admission decides the same population with one value encoding one fact. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…otation cited a wall that was never built
The discriminating red asserted `drop_last(` to pin the third arm. That CANNOT
GO RED. `drop_last` is the fixture's own function, so the emitted module carries
`pub fn drop_last(` however the match lowers, and compile_dag_rust_emit_check is
a substring read over emitted text with no rustc step.
The annotation was worse than the assertion. It named `list_tail` as the pin --
a symbol that appears nowhere in the file -- so the row's stated coverage
argument cited a wall that was never built, while the assertion actually
standing in its place carried no information. DESIGN section 4b names this
exactly: permanently green by construction, and worse than absent because it
will be cited as coverage. It was cited as coverage, in this annotation, in the
PR body, and in three status reports claiming four rows green.
THE GAP IT LEFT IS THE ONE THAT MATTERS: a lowering that kept arms one and two
and dropped arm THREE would emit `__fm.len() == 1`, carry `pub fn drop_last(`,
and pass -- the original defect in narrower form, and the exact shape this row
exists to catch.
THE REPLACEMENTS ARE READ OFF THE ARTIFACT, which is the step whose absence
produced the decoration. Arm three is the only arm that binds anything, so
`Rc::new(__fm.skip(1))` is its tail binding and `drop_last(t.clone())` is its
body, the recursive call on that binding.
RED-ABILITY MEASURED RATHER THAN ARGUED, from the retained pre-repair emission:
v2.std.algebra list_init carries this fixture's EXACT arm shape, and its broken
emission is `if __fm.is_empty() { vec![] } else { vec![] }` with `skip(1)` at 0
occurrences and `list_init(t` at 0. Both pins are absent from the broken
lowering of this shape and present in the repaired emission of the fixture.
The two pins are NOT equally strong and the annotation says so. The skip spelling
is generic -- the pre-repair emitter emitted it 10 times in v2_std_algebra alone
-- so it discriminates for THIS fixture only because the first Cons arm's tail is
a nested Empty the old binding reader degraded to `_`. `drop_last(t.clone())` is
the unambiguous pin. Claiming both were equally discriminating would have been a
smaller instance of the same error.
Row re-executed: true.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nly for length one
THE BRIEF ASKED FOR THIS AND I HAD NOT DONE IT. Its item 2 named three controls
on the real emitted crate -- list_init, qualified_name_init, and
copied_port_derivation distinguishing 0, 1 and 3 elements. The first two were
measured and executed. The third was never tested, while being carried in the PR
narrative the whole time as the finding that makes this a rule-level defect.
Found by re-reading the assignment against the diff after the approval landed, on
the standing rule that an approval means no blocking defect found and is a
different question from whether the change does what was asked. A reviewer reads
the diff, not the brief, so this was not theirs to catch.
WHAT THE SECOND SPECIMEN ESTABLISHES that the first does not. v2.lens.cost
copied_port_derivation is `Empty => Absent | Cons { head: only, tail: Empty } =>
Present | _ => Absent`, and pre-repair it emitted `if is_empty { None } else {
Some(first) }` -- Present for a list of ANY non-zero length. So list_init
silently TRUNCATES A LIST and this one silently WIDENS A CARDINALITY CLAIM,
reporting `exactly one` for three elements. Same lowering, opposite
consequences, which is the argument that the repair belongs at the rule: a
per-site fix at either would have left the other standing.
It also shows why a two-way split cannot be patched into correctness. `if
is_empty { A } else { B }` has nowhere to distinguish 1 from 3; the
discrimination has to BE the chain.
EVIDENCE AT BOTH HALVES. The fixture supplies the arm shape and asserts the
emitted chain. The real site attests the producer emits it: the module is in the
emitted 00_compile closure, and its repaired emission is `if __fm.is_empty() {
None } else if __fm.len() == 1 { let only = (*__fm)[0].clone(); Some(only.clone())
} else { None }` against a retained pre-repair emission of `if __fm.is_empty() {
None } else { let only = (*__fm)[0].clone(); Some(only.clone()) }`. Length 0
answers Absent, length 1 answers Present, length 3 falls past both and answers
Absent.
All five rows execute: true, true, true, true, true.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Correcting a merge-time obligation recorded on this PR's handoff, so nobody waits on a ping that cannot arrive. The handoff states that
So: no ping is owed, and nothing is waiting on this merge from that direction. The mirror-ordering constraint that does still apply is between this PR, #12029 and #12034 — all three regenerate The second obligation stands unchanged and needs no action here: witty-cat-84's Pkg12 native census unblocks on this merge ( Also preserved from the handoff, because these are the parts most likely to be smoothed over by a later reader: two of the five probe rows ( — sent from snappy-deer-443 |
…ecord why two rounds came up short The earlier bytes were a correct emission of a tree without the declaration: 25ec7d3 was cut from #12026 at 0f0ee6f and 02b9e59 (#12029) was generated from a tree that also predates Pkg4 (3ab9d31); neither measure.dag declares the function. A whole-population round over d88d5cb (main 2b9d962 + this branch), by a claim_executor built from that same clean tree, drifts std_measure.rs alone and adds exactly this function. Specimens appended to the two existing classes rather than new rows: receipt_names_a_property_not_the_tree_it_holds_of (the cause) and predicate_vacuously_true_on_an_empty_domain (the empty affected-set round). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
v1_compiler_emit_rust.rs came back UU with GeneratedArtifactConcurrentDivergence: both sides changed the projection since the merge base (#12026/#12029 landed the FreeMonoid lowering and the connective operand demand; this lane changed the unestablished-resource arm), so neither side's bytes were the projection of the merged authorities. Resolved by the driver's declared route -- regenerate, do not hand-resolve -- which also installs this lane's frontier machinery into the mirror for the first time (std_measure.rs, v1_compiler_emit_rust.rs, v1_compiler_infer.rs, v1_std_core.rs). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Subject
v1.compiler.emit_rust's FreeMonoid match lowering. A nested constructor pattern in a field position was dropped and every arm after it discarded, so the emitted program compiled, ran, and returned a well-typed wrong value. DESIGN §5 fabricated plausible output, which is outside the guarantee ladder rather than low on it.Found by witty-cat-84 (Pkg12), executed rather than read. Pkg12's native census was blocked on this.
The defect, and it is in the rule
emit_native_freemonoid_matchasked two questions — which arm mentionsEmpty, which arm mentionsCons— kept the first answer to each, and emittedif __fm.is_empty() { A } else { B }. Its admission predicatearms_are_freemonoid_coproductestablished only that the arms resolve toFreeMonoid; it never asked whether they fit a two-way split.Three silent consequences — the third was not in either report:
"_"for anything that was not aBind, soCons { head: _, tail: Empty }matched every non-empty list;Consarm was discarded, because nothing read pastfirst;arm_guard.Two sites, two different consequences — which is what makes this a defect in the rule rather than at either site. A per-site repair at either would have left the other standing.
v2.std.algebra list_initemitted asif __fm.is_empty() { vec![] } else { vec![] }, soqualified_name_init(["v2","acp_user","acp_row"])returned[]instead of["v2","acp_user"]and the native resolver's ancestor walk skipped every intermediate ancestor. A global-bare fallback tier was masking it.v2.lens.cost.copied_port_derivationreports "exactly one" for a three-element list.The construction
A FreeMonoid pattern is a spine of
Conslevels terminating either inEmpty(an exact length) or in a binding/wildcard tail (a length floor). So each arm carries a decidable length predicate and its head bindings are decidable index reads at any depth. The arms become an ordered chain of those predicates, which is what a match means. Exhaustiveness is decided on the same facts, so the chain's finalelseis proven total rather than assumed and nounreachable!is fabricated to stand in for the proof.The TCO twin carried the identical defect and now shares the analysis, refusal and chain, with the body emitter the only variance.
Refusal, not widening (§5 absorbing fallback)
Shapes the analysis cannot express emit a located
compile_error!naming the shape and span: an arm guard; a refutableheadsub-pattern (a question about the element, not the list); a variant that is neitherEmptynorCons; an arm set not provably exhaustive.The refusal arm is justified by construction, not by what the generic fallback would have done. I make no claim about the generic path's behaviour on a FreeMonoid match, because I did not run it.
Controls — all executed against EMITTED code
The interpreter lowers these arm sets correctly, so no interpreted claim can discriminate this fix; a green
claim_runis evidence about the other path. Every row below ran the emitted binary.The second specimen — the control the brief named and I had missed
v2.lens.cost.copied_port_derivationisEmpty => Absent | Cons { head: only, tail: Empty } => Present | _ => Absent. Pre-repair it emittedif is_empty { None } else { Some(first) }—Presentfor a list of any non-zero length.list_initcopied_port_derivation[]for every inputSome(first)for any non-emptySame lowering, opposite consequences — which is the argument that the repair belongs at the rule. A per-site fix at either would have left the other standing.
It also shows why a two-way split cannot be patched into correctness:
if is_empty { A } else { B }has nowhere to distinguish 1 from 3. The discrimination has to be the chain.Verified at both halves. The real site is in the emitted
00_compileclosure:How it was missed: the brief's item 2 named three controls on the real emitted crate. I measured two and carried the third in the PR narrative without ever testing it. Found by re-reading the assignment against the diff after the approval landed — a reviewer reads the diff, not the brief, so this was never theirs to catch. An approval means "no blocking defect found", which is a different question from "does this do what was asked".
list_init([])list_init([1])[]for everything)list_init([1,2])[][1]list_init([1,2,3])[][1,2]qualified_name_init([v2,acp_user,acp_row])[]["v2","acp_user"]Three discriminating assertions, not five. Rows 1–2 pass in both arms and are not evidence.
Artifact-level control, same closure:
__fm.len()conditions across the closure: 0 baseline → 13 fixed.Census — both emitted closures
src/v2/compiler/00_compile.dagsrc/v2/cli/compile_cli.dagNothing in the emitted population hits a shape the analysis refuses, so no site that compiles today goes red.
A corpus-wide static census (381
Conspattern arms, 112 files) finds 13 sites carrying a refusable shape — 12 refutablehead:sub-patterns and the guarded arm inv2.workflow.floor_cost_debt_edit. All sit outside both emitted closures. Those sites are being silently mis-lowered today wherever something emits them; this change converts that silence into a refusal. Stated as a lower bound: the static census is regex over the corpus at rest, not the emitter's own walk.Self-hosting hazard, cleared by measurement
This module is emitted by the seed it fixes, so a repair authored in the broken shape would be miscompiled into the regenerated mirror. The repair therefore avoids the shape it repairs — the spine recursion tests the tail's
countrather than matchingtail: Empty. Verified by reading the regenerated mirror: the old emitter loweredfm_chain_fromcorrectly, both arms intact, so one regen round reaches the fixed point instead of two with a miscompiled emitter in between.Fixed point — proven, not assumed
The committed mirror was produced by the old emitter (correct for bootstrapping), which leaves open whether the fixed emitter emits
emit_rustidentically. Two--required-regenrounds settle it:std_measure.rs,v1_compiler_emit_rust.rsstd_measure.rsonlyv1_compiler_emit_rust.rsfalling out of the list is the proof: the committed mirror is what the fixed emitter produces.std_measure.rspersists identically across both arms, independently confirming it is #11992's drift rather than anything this change touches.Round 2 nearly ran with a stale
claim_executorstill carrying the old emitter, which would have reported a fixed point that meant nothing — the same shape as the bug being fixed here, an instrument giving a confident answer about the wrong subject. Caught by checking the binary's contents (strings | grep 'will not lower'), not its timestamp.Disposition of what it replaces
Deleted, not left standing beside the new path:
freemonoid_cons_binding,freemonoid_tail_let_from_fm,freemonoid_catchall_bind_name, and the four branch-body functions. Theim::Vector::skipreasoning is preserved onfm_tail_bind_let, now skipping by the arm's own spine depth rather than always by one.Bounded gaps, stated rather than papered over
base16'sUInt8cross-module alias, owned by wise-raven-686. Confirmed pre-existing by execution: emitting the same closure with the emitter reverted produces the same missing use-line. My probe only ran because I stubbed that module in/tmponly; nothing under version control is touched.std_measure.rsdrift on main is not mine.required-regenreports it from132c780e4a6(FABRIC-MEM-GRANT-0: one memory grant carrier, one microVM sizing policy, one grain-parameterised rounder (reconciles #11883 + #11885) #11992) landing the grain-rounder.dagwithout its mirror. Deliberately excluded — folding it in would misrepresent this diff.v1_compiler_emit_rust.rsfrom the merged base.Rework after review 69861, and the evidence re-taken
Both findings were correct and are fixed.
The refusal was an in-band sentinel.
FmArmPlan { supported: Bool, reason: String }with""meaning lowerable was the same protocol this change deletes one layer down, reintroduced one layer up. Now a coproduct —FmSpine { exact, len, head_binds, tail_bind } | FmUnsupportedArm { cause }— with a seven-variantFmLoweringRefusaland one message function. An unsupported arm now has no spine fields to misread, and the1000000bottom is anInt?. I did not reuseOperatorRealizationRefusalas the review suggested: that type is about operators, and sharing the spelling would be a §3 meaning fork rather than single authority.No enrolled discriminating evidence, and the row declared the gap unbridgeable when it is not. That was mine, and it is retracted in the row rather than softened. A subject conflation: "every claim the floor runs is interpreted" is true of the defect's consequence (a miscompiled binary answering wrongly at runtime) and false of the repair's subject (a pure
Stringfold, decidable by an interpreted claim over a fixture). §4b(2) names it exactly — "can climb now but unbuilt" reported as "cannot climb further".Enrolled as
test.claim.emitter_freemonoid_arm_chain_witness_test, all four rows execute and return true:headsub-pattern refusesThe positive control is load-bearing: without it, "refuse everything" satisfies both refusal rows while destroying all real lowering.
Evidence re-taken after the rework, since it touched
emit_native_freemonoid_matchand every earlier behavioural claim described a superseded revision:list_initlen() == 1__fm.len()conditionsPure refactor — measured, not asserted.
CI: the red belonged to main, not this branch
Two failing checks, one real failure:
witnessesis the aggregator and failed in 3s reportingcompiler=success clippy=success floor=failure. The floor carried exactly one refusal —test.claim.mtcollins1_census_image_local_wet.the_rendered_program_runs_and_its_output_parses_by_real_execution.Not mine, and established rather than assumed: that witness renders a POSIX shell script and asserts
host_capture_bind, which the FreeMonoid lowering cannot reach. #12020 ("repairs the wet-lane regression from #11987") merged at 01:19Z, andgit merge-base --is-ancestorput its commit inorigin/mainand not in this branch — 9 commits behind. Integrated by merge; not repaired here.Instrument provenance, recorded because it nearly produced a false finding
/cargo-targetis shared across worktrees and sessions. A neighbouring build ofv1-compileroverwrote the binary between my verifying it carried the rework and my measuring with it. Two witness rows reportedfalse, and a fixture emitted a textbook reproduction of the original bug — from a compiler that predated the fix.Caught only because two greps of one file disagreed: the rework-only string counted 1 earlier and 0 later. Every measurement above was re-taken with a worktree-local
CARGO_TARGET_DIR, verified by a string that exists only in the reworked code.The red control needs no such check, and the reason is worth keeping: its artifact carries the two-way split and zero length-conditions, and witness row one establishes that the fixed emitter emits
len() == 1for that exact shape. The output identifies its own producer — which is stronger than "the binary was correct when I looked."What the review floor found here, and why it is the same bug one layer up
Four findings across two reviews. All four were correct, and two were things I would have defended. They are recorded here rather than in a commit message because the pattern is worth more to the reviewer of the next change than the individual fixes are to this one.
Every one had the same shape: a surface that reads correct over a claim nobody re-derived.
FmArmPlan { supported: Bool, reason: String }!= ""on the admission path"drop_last("pinning the third armThe last one is the one worth reading
Both callers tested
if native_fm != ""over a lowering that can no longer return"". My reading was dead code, harmless. It was not, and the reason is exactly the defect this PR repairs.That empty string never came from the lowering at that site. It came from the admission predicate's own
elsebranch. So one value encoded two distinct facts —— with nothing downstream able to separate them. A future lowering that legitimately produced no text would have been indistinguishable from one that declined, and would have silently rerouted to the generic path.
That is the same class as the bug under repair:
emit_native_freemonoid_matchanswered a narrower question than its arms asked, and looked right doing it. Here a singleStringanswered a narrower question than its callers asked, and looked right doing it.The repair is the construction, not the check: the callers branch on
arms_are_freemonoid_coproductdirectly, the lowering always answers, and the sentinel has no spelling left.The lowering itself has not been challenged since the first review, where it was worked through by hand. Every finding has been about the evidence and citations around it — which is the floor doing its job, not a signal the change is unsound.
The fifth finding is the sharpest, because it was in the evidence added to fix the second
Review 70019 found that the discriminating red's third-arm pin,
"drop_last(", cannot go red:drop_lastis the fixture's own function, so the emitted module carriespub fn drop_last(however the match lowers. And the annotation namedlist_tailas that pin — a symbol appearing nowhere in the file. The row's stated coverage argument cited a wall that was never built.§4b names it: "permanently green by construction, carrying no information, and worse than absent because it will be cited as coverage." It was cited as coverage — in that annotation, in this body, and in three status reports claiming four rows green.
The gap was real: a lowering keeping arms 1–2 and dropping arm 3 would emit
__fm.len() == 1, carrypub fn drop_last(, and pass. That is the original defect in narrower form.Replaced with pins read off the artifact, and red-ability measured rather than argued —
v2.std.algebra list_initcarries this fixture's exact arm shape, and its retained pre-repair emission hasskip(1)at 0 andlist_init(tat 0:__fm.len() == 1Rc::new(__fm.skip(1))drop_last(t.clone())The annotation now also records that the two new pins are not equally strong: the skip spelling is generic (the old emitter emitted it 10 times in
v2_std_algebraalone) and discriminates here only because the firstConsarm's tail is a nestedEmptythe old binding reader degraded to_.drop_last(t.clone())is the unambiguous one.The uncomfortable part, kept because it is the lesson: this row was added in response to a finding that I had claimed evidence without producing it. The replacement evidence had a hole of the same kind, and I reported it green four times before a reviewer read the assertion rather than the claim about it.
An observation this PR does not fix, recorded because it is evidence
--required-regenreports drift instd_measure.rson this branch in both rounds. I reported that as a clean result — "round two driftsstd_measure.rsalone" — reading it as another lane's known drift.It is not noise.
kibibyte_from_byte_size_flooris declared atdag/std/measure.dag:338and consumed three times bygunbc.compute.host_capacity, and has 0 occurrences in main's mirror. That mirror does not converge, and a regeneration whose edited set contains no.dagreports a fixed point vacuously — regenerating nothing and comparing nothing.Three lanes hit this today from three directions (crisp-dove-588, snappy-seal-19, and this one). A lane owns it; it is not repaired here. It is stated because a vacuous fixed point and a real one are spelled identically at the call site, and because filing it as "known drift" three times is how it stayed invisible.
Failure mode row
gunbc.recurring_failure_mode.special_cased_lowering_answers_a_narrower_question_than_its_arms_ask— filed as a new class after checking the existing emitter rows.guarded_filter_branch_dropped_by_emitterpublishes a truncated file;accepted_source_emits_uncompilable_targetpublishes one rustc refuses. Both leave an artifact something can read. This one publishes a complete, compilable, idiomatic artifact that is semantically different from its source.Rung found at: outside the ladder. Ceiling: 3. Next-rung trigger, named as the capability: an executed emission-path differential oracle — interpreter vs emitted binary over the same inputs, disagreement reported as a located refusal. That is what the enrolled witness floor structurally cannot supply, because every claim it runs is interpreted.
🤖 Generated with Claude Code