Skip to content

XL-0-CARRIER: two emitter decisions that fabricate where they cannot answer, and the projection a sealed carrier owed - #9855

Merged
gunbai-bot[bot] merged 9 commits into
mainfrom
session/gentle-koi-869-carrier
Sep 1, 2026
Merged

gunbai-bot[bot] merged 9 commits into
mainfrom
session/gentle-koi-869-carrier

Conversation

@briansrls

@briansrls briansrls commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor

What this is

XL-0-CARRIER. Five emitted-typeck rows were dispatched to me as one hypothesised class ("carrier-shape decided in two places"). They are three defects, and the pair that shares a root is not the pair that was grouped. This PR repairs two of them and states what happened to the third.

Base is #9850's head (471e8d8), not main, and that is deliberate. My rows are defined against the 66-error population that #9850 produces; on main they are hidden inside the 155. When #9850 squash-merges I will merge origin/main in (not rebase, not cherry-pick) and read what git actually reports.

Correction to the dispatch list

The row dispatched as v1_compile.rs:288 Witness nesting is v2_compiler_compile.rs:288:108, module v2.compiler.compile (src/v2/compiler/00_compile.dag). Not v1.

The measurement route

tools.emission_entry_instrument measure_entry_emission over src/v2/compiler/00_compile.dag, i.e.

gunbc run --source-root dag --source-root src/v2 \
  --entry dag/gunbc/instruments/emission_entry_instrument.dag \
  --function measure --arg entry=src/v2/compiler/00_compile.dag --arg report=<path>

with gunbc built from source in the same dispatch (the baked /usr/local/bin/gunbc cannot parse the current corpus) and GUNBC_MEMORY_BUDGET_BYTES exported inside it. Baseline for this PR is that instrument at 471e8d8: 66 error identities, all five of my rows present.


PRE-REGISTERED PREDICTION — written before the post-repair measurement was run

Predicted REMOVED (3):

  • src/v2_compiler_target_carriers.rs:105:90 E0308
  • src/v2_compiler_compile.rs:288:108 E0308
  • src/v2_compiler_source_authority.rs:1007:8 E0308

Predicted to SURVIVE (2) — Class 3, reassigned to stern-ferret-752, untouched here:

  • src/v2_std_collection.rs:93:13 E0308
  • src/v2_std_collection.rs:94:5 E0560

Predicted ADDITIONS: zero. Two named mechanisms could produce some, and both are falsifiers, not excuses:

  • A1 — the witness-carrier repair makes a source DECLINE. The terminal arm of that chain is rust_witness_variant_ctor_path's refusal, compile_error!("witness carrier type arg unresolved for variant ..."). If any site previously took the fabricated carrier and now reaches the refusal, that is a located refusal replacing silent wrongness — the correct arm — but it MUST be counted and reported, never absorbed. I predict 0 occurrences of that string in the emitted closure.
  • A2 — the unwrap repair stops injecting .expect(..) at every generic-parameter call site, not only mine. Where the instantiated T is genuinely non-optional and the argument is optional, the site now produces a rustc error instead of a runtime panic. I predict 0 such sites.

I am not predicting a remaining total. A census classifies additions; removing a masking error exposes successors, so "this leaves N" would be a forecast wearing a measurement's clothes.

Falsifiers, stated so the scoreboard can go red in both directions:

# If observed What it refutes
F1 :105 survives the injected unwrap is not the cause, or the parameter is not recognised as a type variable
F2 :288 survives expected_type is not the source, or a second source fabricates too
F3 :1007 survives .root is not the only mismatch at that call
F4 any new witness carrier type arg unresolved A1 fired: the decline moved a fabrication into a refusal at sites beyond mine — report the count and the sites
F5 the collection pair disappears my attribution of Class 3 to the realization selector is wrong; something here touched it
F6 a row I predicted to survive is removed the same shape that cost bold-carp a wrong 139/139 score — a survivor set is scored, not assumed

Class 1 — two rows, ONE root: an emitter decision whose input cannot answer, answering anyway

Both sites are in v1.compiler.emit_rust. Neither .dag source is wrong; neither consumer is wrong. This is DESIGN §5's fabricated default living inside the Rust emitter's type decisions.

target_carriers.rs:105 — rust_call_arg_fail_closed_unwrap

The emitted line was:

Outcome::Accepted { value: child, .. } => outcome_accepted(
    Some(child.clone()).expect("fail-closed: an optional value flowed into non-optional parameter 0 of outcome_accepted (empty Optional at runtime)"))

from outcome_accepted(value: Present { value: child }) in a function returning Outcome<Optional<Node>>. The callee is outcome_accepted<T>(value: T). param_required was computed from the declared parameter type — a type VARIABLE — and a type variable carries no answer about optionality at all, because optionality is a property of the instantiation. Answering "required" injected an unwrap that strips exactly the Option the return type demands: expected Option<Rc<Node>>, found Rc<Node>.

This predicate has now been wrong about three spellings of one question, and that is the finding rather than the fix. Its own header records the second repair: the T? cardinality flag was the first source, the applied Optional<T> carrier spelling was added after it "earned a fail-closed .expect(..) that unwrapped the very value the callee exists to inspect (E0308 at six sites)". The generic-variable spelling is the third. So I did not add a fourth spelling. The repair is that an input which cannot answer DECLINES and nothing is injected.

What "decline" means here, since that word can hide a fabrication one frame down: there is no second source and none is needed. Passing the argument as written is the correct emission for a generic parameter — the instantiated parameter type is what the callee actually asks for. Where the instantiation is genuinely non-optional the result is a located rustc refusal at the call, not a silent widen and not a runtime panic. Nothing downstream guesses.

Next-rung trigger, which is worth more than the repair: the fix that closes this class for every future spelling is reading the INSTANTIATED parameter type. It is not reachable at this site: the emitter holds the callee's declared params (ItemInfo.params) and the argument's resolved type, and no per-call type-argument substitution. What would make it reachable is inference recording the call's type-argument substitution on the call node — the same shape as the existing __applied_type_args property on type nodes — at which point this predicate reads one instantiated type and the spelling enumeration dissolves.

v2_compiler_compile.rs:288 — the witness carrier's expected-type source

The emitted line was Witness::<Rc<Outcome<Rc<Witness<Rc<Node>>>>>>::Violates where Witness<Rc<Node>> was wanted — one level of nesting too many. Source (apply_compile_lens_introspect) is correct.

rust_witness_type_arg_for_variant reads emit_info.expected_type first for a bare Violates. At this site that is Outcome<Witness<Node>> — the type expected of the whole expression, the ENCLOSING call's type, which says nothing about the witness carrier. rust_witness_carrier_from_type_node peels Rc, sees head Outcome ≠ Witness, and takes its else arm, which returns the whole type AS the carrier.

That function's own header already states the correct discipline for its compiler-error case — "an erased first source must DECLINE so the second is consulted, never render its own refusal" — and the non-Witness head is simply the case it was not asked about. The repair adds rust_witness_carrier_from_expected_type_node, which admits an expected type only when its peeled head is Witness.

The terminal arm here already refuses and is unchanged: when every source declines, rust_witness_variant_ctor_path emits compile_error!("witness carrier type arg unresolved for variant <name>"). That is a located stop in the emitted crate, not a default carrier and not a silently-omitted turbofish. Falsifier A1/F4 above exists precisely to count whether the decline pushed anything into it.

Class 2 — one row, a SOURCE defect, and its second fact is filed elsewhere

v2.compiler.source_authority normalized_source_ast_equal_witness passes original.tree / reparsed.tree to source_authority_node_equal(left: Node, right: Node). NormalizedDagSourceAst.tree is a NormalizedTree, which BL-1 sealed from an alias for Node into a sole-constructor record so wrapper-retention evidence could not reach resolve as a bare Node. The call site never learned. Its neighbour source_ast_equal_witness at :992 reads identically and compiles only because DagSourceAst.tree is a ParseTree, still an alias — the two sites look the same and are not.

Repair is .root, the projection v2.compiler.normalized_tree already owns.

The second fact — that v1 inference ACCEPTED an ordinary-floor argument type error (DESIGN §4b, "applications bind in exact bijection") — is not carried here. bright-ram-778 is dispatching it as its own lane so it is not reviewed as a side note inside a typeck-repair PR.

Class 3 — two rows, REASSIGNED, not fixed

v2_std_collection.rs:93 (E0308) + :94 (E0560) are one construction: v2.std.collection map_insert returns Map<K,V>, which renders in TYPE position as the host realization Rc<im::HashMap<K,V>>, and open-codes a structural literal Map { lookup: ... }, which renders as Rc<FinitelySupportedFunction<_,_>>. One alias, two realizations in one body.

Owner: stern-ferret-752 (ruling msg_c1686fb1). It is the same selector as their PartialFunction→HashMap row: dag/extdeps/languages/rust/types.dag gives FinitelySupportedFunction the inhabitant HashMap<{0}, {1}>, consulted in declaration position while a record literal lowers to the algebra struct — a fork dag/std/types.dag already documents in the note above type Set<element> = FinitePowerSet<element>. I touched no file in that class. Two measured facts handed over rather than re-derived:

  • The #9055 repair shape — delete the literal — is closed on the Map side. src/v2/test/claim/map_carrier_shape_gate_test.dag is an enrolled gate recording that map_insert was switched to its primitive delegate after measuring zero cross-module references in the emitted tree (true, and true only of the emitted path) and 14 floor witnesses died with call depth exceeded 100000 at fn 'map_insert_primitive_delegate'. A review approved that diff; the defect was not in the diff.
  • Consequently map_insert's own return value is the last record-shaped Map producer in the corpus, and the gate states the remaining condition is a HOST fact (the interpreter's free_call.map_insert arm accepting the record shape), not a corpus one.

This row is not silently unaccounted for: it leaves my population and enters theirs, by name.

Enrolled evidence (§4b(4)), and the revert arm

Both Class 1 repairs ship with a discriminating RED and a positive control, in v1.compiler.compiler_tests_rust, executed by cargo test --release -p v1-compiler --lib:

  • generic_parameter_declines_the_fail_closed_unwrap — arm 1: a callee whose parameter type is T and an optional argument must produce the argument unchanged (RED before the repair). Arm 2, the control: a callee whose parameter type is the concrete Node and the same optional argument must still take the .expect(, so a repair that simply stopped injecting goes red here.
  • witness_carrier_declines_a_non_witness_expected_type — arm 1: an Outcome<Witness<Node>> expected type must yield none (RED before the repair). Arm 2, the control: a Witness<Node> expected type must still answer Node, so a repair that made the source answer nothing goes red here.

Both stay enrolled after the fix as permanent regression controls; they do not retire.

Scoreboard — scored in BOTH directions

Same instrument, same entry, on the regenerated tree of this branch. Baseline 471e8d8 = 66 blocking rows (the report's own cargo_error_population, excluding the irrefutable_let_patterns line and the two spanless rustc summary rows). After: 64.

Prediction Row Observed Verdict
REMOVED v2_compiler_target_carriers.rs:105:90 E0308 absent held
REMOVED v2_compiler_source_authority.rs:1007:8 E0308 absent held
REMOVED v2_compiler_compile.rs:288:108 E0308 present as uncoded witness carrier type arg unresolved for variant Violates FALSIFIED
SURVIVE v2_std_collection.rs:93:13 E0308 present, unchanged held
SURVIVE v2_std_collection.rs:94:5 E0560 present, unchanged held
ADDITIONS = 0 — one planted refusal, at the predicted site with the predicted message A1 fired, pre-registered

codeless = 1, coded = 63. Unit tests: 614 passed, 0 failed. cargo test --release -p v1-compiler --lib is the executing consumer.

:288 is not repaired and I am not banking it as one. The carrier there is genuinely underivable: no source the emitter holds is Witness-headed, so the site takes rust_witness_variant_ctor_path's refusal and the emitted crate carries one located compile_error! naming the variant. That is a row whose IDENTITY changed from a plausible wrong type to a named refusal — a §5 repair that is correct and insufficient, not a step toward the goal that arrived. It becomes unreachable by construction when calm-boar-314's per-call type-argument substitution lands; the two compose and that is the order to land them in.

What the pre-registration actually caught — twice

Both are recorded here because the count moved in the direction that looks like progress each time.

  1. First round. Making only the expected-type source decline removed :288's E0308 and produced E0573 expected type, found variant Holds at the same line, column 118. Count 66 → 64. A count-based scoreboard scores that as clean. The real event was the SECOND source — the variant's own resolved type — answering with a coproduct ARM sitting in the applied-type-argument position. The fabrication had moved one frame down while the diff read as a principled fail-closed repair. Fixed by declining any rendered type argument that emit_info.variant_to_enum says is a coproduct arm — the corpus's own authority, so arms of coproducts nobody has written yet are declined by construction rather than added to a list.
  2. Second round. With both sources declining, the refusal fired — and produced four rows at that one site: 288:183 uncoded struct literal body without path, 288:183 uncoded expected one of ), ,, ., ?, or an operator, found {, 288:108 uncoded witness carrier type arg unresolved, and 288:100 E0061. Count 66 → 67. rust_witness_variant_ctor_path returned the compile_error! in path position and the caller then appended the variant's field body, so the planted refusal was followed by { diagnostic: .. } — a refusal that emits a syntax error is not a located refusal, it is noise at a location. Fixed by typing the verdict (WitnessCtorPathVerdict) so the caller drops the field body and emits the refusal alone.

Neither would have been visible from the diff, and the first would have shipped on a −2.

codeless moves off zero, by one, and that is the repair working

Pre-registered with neat-hawk-884 before landing. A spanned uncoded diagnostic is a shape the board has never carried, and codeless (uncoded ∧ level=error) is a watched field. level=error is forced by rustc for compile_error! and no repair here can change it; the discriminator is not the level but the join to the emitted source — a planted refusal is uncoded, spanned, its message byte-identical to a string v1.compiler.emit_rust authored, and its span lands on a real compile_error! macro invocation in the emitted file. Expected: exactly 1, file v2_compiler_compile.rs, message witness carrier type arg unresolved for variant Violates. Any other count, file or message is not this event.

Revert arm

Each repair is reverted independently against this tree and its own arm must go red for its own reason; the unmodified tree is the positive control. Results in a comment below.

Also present and NOT on the critical path

v2_compiler_source_authority.rs:186:340 irrefutable_let_patterns is level=warning, outside cargo_error_population, and does not block. Real, worth fixing on its own merits, deliberately not scheduled here (measured by neat-hawk-884 from rustc's level field).

gunbc-ci-auto-heal and others added 5 commits August 31, 2026 23:30
…key use-line derivation on the resolved kernel identity

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfYKNQTD3VfYyQcnJpxNU
…ion_equal=true)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfYKNQTD3VfYyQcnJpxNU
…ng, and the projection a sealed carrier owed

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fvtg2xUDav2QbLiEdutpq
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fvtg2xUDav2QbLiEdutpq
…ion_equal=true)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fvtg2xUDav2QbLiEdutpq
@gunbai-bot gunbai-bot Bot changed the title XL-0-CARRIER: root-cause the Rc/Node/Witness carrier-shape survivors as one class before repairing three sites XL-0-CARRIER: two emitter decisions that fabricate where they cannot answer, and the projection a sealed carrier owed Sep 1, 2026
Brian Searls and others added 4 commits September 1, 2026 01:49
… carriers

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fvtg2xUDav2QbLiEdutpq
… so the caller drops the field body

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fvtg2xUDav2QbLiEdutpq
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fvtg2xUDav2QbLiEdutpq
@gunbai-bot

gunbai-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Revert arm — run against this branch's tree (3edf34b), one revert per repair

Each repair is disabled independently in the emitted mirror and the two enrolled tests are re-run; the unmodified tree is the positive control. Executing consumer: cargo test --release -p v1-compiler --lib.

Arm What was disabled generic_parameter_declines_the_fail_closed_unwrap witness_carrier_declines_a_non_witness_expected_type
control nothing ok ok
A rust_param_type_is_type_variable forced to false FAILED ok
B the != "Witness" head guard on the expected-type source ok FAILED
C the variant_to_enum coproduct-arm decline ok FAILED

Each arm reds, and it reds for its own reason rather than by breaking the build:

  • A — left: "child.clone().expect(\"fail-closed: an optional value flowed into non-optional parameter 0 of outcome_accepted (empty Optional at runtime)\")" against right: "child.clone()". That is the exact injected unwrap from v2_compiler_target_carriers.rs:105, reproduced in a unit test.
  • C — fails on the assertion "the Violates fallback must decline a non-Witness resolved type too, or the fabrication only moves one frame down", i.e. the arm that exists because the first round of this repair moved the fabrication rather than removing it.
  • B — fails the same test as C but at a different assertion (the expected-type arm rather than the fallback arm). My log filter did not capture B's assertion text, so I am reporting the arm as red-at-a-different-assertion rather than quoting it; A and C are quoted because they were captured.

Both tests stay enrolled after the fix as permanent regression controls (§4b(4)); they do not retire.

@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review September 1, 2026 04:56
@gunbai-bot
gunbai-bot Bot merged commit 5998d60 into main Sep 1, 2026
6 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/gentle-koi-869-carrier branch September 1, 2026 05:12
@briansrls
briansrls restored the session/gentle-koi-869-carrier branch September 1, 2026 05:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant