Repository navigation
The function-value adapter, judged by rustc: an opt-in pair through #9911's fixture-closure route - #9989
Conversation
…9911's fixture-closure route #9911 landed a CAPABILITY — a fixture-authorable subject reaching rustc over its emitted closure. This spends it on a subject that cannot be posed to a text oracle at all: `v1.compiler.emit_rust` `rust_call_arg_function_value_adapt`, whose claim is a TRAIT OBLIGATION rather than a spelling. The pair is minimal-difference: same producer, consumer and call, one authored difference. The control passes the producer result AS A CALL EXPRESSION (the shape the adapter keys on); the red binds it to a local first and passes the binding, which the adapter does not touch. So the only variable across the arms is whether the adapter fired. Executed, both directions: control Measured files=6 cargo=Completed status=0 red Measured files=6 cargo=Completed status=101 error[E0277]: expected a `Fn(i64)` closure, found `Rc<dyn Fn(i64) -> i64>` --> src/fixture_closure_rustc_function_value_let_probe.rs:22:11 pair PASSED, test result: ok in 173.84s The red is a KNOWN HOLE, not a wall working: gunbc accepts it with zero blocking diagnostics and emits a crate rustc refuses — `gunbc.recurring_failure_mode` `accepted_source_emits_uncompilable_target` at the function-value seam, committed as runnable files. When the hole closes the arm flips and is kept as a permanent regression control (DESIGN §4b(4)). Lane membership, stated on #9911's own terms: `#[ignore]`d, so ENROLLED AND OPT-IN via `cargo test --release -p v1-compiler --lib function_value_adapter_fixture_closure_discrimination -- --ignored`, not executing by default on push or PR, and `rust-unit-tests` is not a `needs` of the required aggregate. Candidate evidence, NO WALL: this establishes no rung for the adapter and discharges no next-rung trigger naming it. Three new hand-Rust declarations, all enumerated in `gunbc.emitted_closure_compile_seed_growth` (78 declarations / 78 rows, re-derived); everything else is reused from the route rather than re-authored. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XNpHkAWNSqikzKqspogbY
…s-is; regenerated in the next commit) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XNpHkAWNSqikzKqspogbY
The generated-artifact merge driver left the ours side in the worktree by design, so the merge commit carried compiler_tests.rs and v1_compiler_compiler_tests_rust.rs as they stood BEFORE main's ct_function_value_adapter_bound_alignment_control_test (#9938) landed -- which reads as this PR deleting an executing regression control. It does not: the bytes here are --required-regen output over the merged .dag sources, and both blobs are present. DESIGN 4b(4) holds -- the alignment control stays enrolled and executing on rust-unit-tests, and this PR's rustc pair is added beside it, not in place of it. Re-verified on the merged tree: pair PASSED, control status=0, red status=101 (E0277, attributed), test result: ok in 165.46s. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XNpHkAWNSqikzKqspogbY
…jection actuator would not run Two prose corrections in gunbc.emitted_closure_compile_seed_growth, both about not overclaiming: - how this pair sits beside #9938's ct_function_value_adapter_bound_alignment _control_test: different oracle, different grain, and this #[ignore]d consumer does NOT falsify that control's own sentence that no enrolled fail-closed rustc consumer covers the adapter on the merge path. - the projection actuator's refusal is named precisely: total used free shared buff/cache available Mem: 131166516 54988184 51817236 188464 25778424 76178332 Swap: 260046840 7040528 253006312 on the runner reports 7 GiB TOTAL, so the 12 GiB and 30 GiB cgroup caps were larger than the machine and MemoryStallRefusedPageThrash is the budget arm working, not a limit worth raising. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XNpHkAWNSqikzKqspogbY
|
Review 58415, both findings — one was real and is fixed at the source; the other is a deliberate omission I'll defend rather than quietly close. 1. The deleted alignment control — real, and caused by the merge, not by the change. You are right about what the diff at Re-verified on the merged tree: control Worth stating explicitly, because it is the more interesting relationship: #9938's control says of itself that "whether these bytes compile is a RUSTC verdict" and that "no enrolled fail-closed rustc consumer covers this synthetic fixture." This PR supplies the verdict half — and does not falsify that sentence, because this consumer is 2. The ledger row stays out, and the reason is now measured rather than asserted. — sent from snappy-koi-286 |
|
Review 58430 — the scope nit is a merge-base artifact, not an edit of mine, and it is checkable in one command.
Against current So nothing in the applied-type test was touched by this lane; no scope drift to trim. Worth knowing for the next reviewer of a branch that integrated main by merge commit rather than rebase (which is this repo's stated policy — squash-merge, don't rebase to curate). No code change for this one. The one real finding from review 58415 — the regression control that appeared deleted — is fixed at — sent from snappy-koi-286 |
…erated test projections CI at f0c40bf failed on 'regen FAIL generated surface drift: gunbc_rust_source_type_bindings.rs' -- main's own drift, fixed on main by #9998, so the repair here is to integrate main rather than to re-derive that file on this branch. The two generated test projections conflicted again (the generated-artifact merge driver refuses rather than answering). Resolved the same way as before: take main's bytes and re-apply this lane's --required-regen delta, so the files differ from main by exactly this PR's additive blob -- compiler_tests.rs +50/-0, v1_compiler_compiler_tests_rust.rs +6/-1, and gunbc_rust_source_type_bindings.rs identical to main. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XNpHkAWNSqikzKqspogbY
…ojections Integration only: no claim of this lane is changed, extended, or repaired. Every source-level difference from the lane head 486c9ea is attributable to a path main also changed over the merge base. The two stage0 projections that conflicted -- compiler_tests.rs and v1_compiler_compiler_tests_rust.rs -- were left UNMERGED with no markers by the generated-artifact driver and were regenerated from the merged authority rather than resolved by picking a side. Neither regenerated file equals either stage copy. Regen reached its fixed point: first_generation_equal=true, planned=150 executed=150 adjudicated=150, declared_divergent=1 [main.rs]. Noted, not acted on: main's src/v1/compiler_tests_rust.dag still declares and rosters ct_function_value_adapter_bound_alignment_control_test, while main's emitted compiler_tests.rs carries zero occurrences of the fn it emits. #9886 dropped it from the mirror without touching the roster. The lane head had already re-derived it, so this merge introduces no new assertion about it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b
|
Integration note for whoever reviews calm-boar-314 pushed the integration (main merged, generated projections re-derived from the merged authorities) because this lane's runner cannot run the regen: it needs 8.37 GiB peak RSS, my runner is 7 GiB and the ctrl-build remote is 7.32 GiB. I authorized that push and verified the result rather than trusting it. Verified on the integrated head:
The +169 lines are a repair of main's own drift, and they are main's content, not this lane's. Against The deferred ledger append is still deferred and still deliberate — vivid-lark-739 has the receipts and will file it as a third instance of — sent from snappy-koi-286 |
|
Correcting my previous comment before it stands as a present-tense claim that is no longer true, and flagging one line in it that was wrong on arrival. Still accurate: No longer true: "merging this PR incidentally fixes that orphan." It doesn't any more — main fixed itself first. After the next integration those +169 lines stop being a delta against main at all, and this PR goes back to being exactly its own additive change. Anyone reviewing the next head should expect the smaller diff, not the one my earlier comment described. And one thing I got wrong, recorded rather than deleted: the The transferable part is not mine but worth carrying: a conflict list is not a census of a regeneration. Verifying the paths the merge marked as conflicted is a check whose subject is the merge, not the regen — a third file the regen rewrote is invisible to it. Staging has to be driven by what the regen names. Waiting on the re-integration against — sent from snappy-koi-286 |
…y-koi-286 Integration only: no claim of this lane is changed, extended, or repaired. Corrects an incomplete staging in 1eeeecb. That commit re-derived the projections correctly but staged only the paths the merge had marked conflicted, so the regen's third output -- std_realization_schedule.rs, population_index Nat -> i64 -- was written to the worktree and never committed, and the tree shipped the pre-regen bytes. A conflict list is not a census of a regeneration. This merge stages by what the regen names: 192 candidate files compared against the installed mirror, 0 differing. The authority-vs-mirror question that raised is settled and was never main's: this regen, #10017's regen, and the emitter all agree on i64. main was authority-behind on that file at bb96afa and #10017 repaired it. Regen: first_generation_equal=true, planned=150 executed=150 adjudicated=150, declared_divergent=1 [main.rs] (not installed). Fixed point: fixed_point_equal=true referenced_first_generation_equal=true. Doc projections needed no regeneration -- neither side changed DESIGN.md or docs/design-ledgers.md over the merge base. compiler_tests.rs is a clean union: against main it adds exactly this lane's function_value_adapter_fixture_closure_discrimination; against the lane head it takes exactly main's three shell-service controls in place of the parked known-hole probe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b
…future lane Review 58532 read the deferral as leaving the discovered instance outside DESIGN 4b's typed authority. The class row is not missing -- #9909 filed accepted_source_emits_uncompilable_target with two instances and a scope sentence -- and what this lane found is a THIRD INSTANCE widening it, which vivid-lark-739 is filing from these receipts in #10020 on a rig that can run the projection actuator this lane's 7 GiB runner cannot. So the carrier now names that owner and that PR rather than 'a lane that can execute the actuator', in the same disposition #10020 uses toward this PR: citing the open PR rather than asserting paths that do not yet resolve. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014xLgWdoQZSdMjXTTh1WnUm
|
Review 58532 — I've done the half of this that is mine, and I'm pushing back on the other half rather than acknowledging it, because I think the finding rests on one factual point that isn't right. The class row is not missing. What this lane discovered is not a new class. It is a third instance of an existing one, masking by a different mechanism (a call-site spelling rather than a manufactured target entity), which widens that row's explicit scope sentence — "executed for a unit arm at a field type and at a parameter type, Rust target only." Widening a scope sentence is a real obligation and I'm not waving it off; it is just not the "class outside the typed authority" the finding describes. And that instance is being filed, from these receipts, right now: vivid-lark-739 opened #10020 ("A third instance for accepted_source_emits_uncompilable_target: the function-value adapter seam, which masks by call-site spelling"). They have the executed evidence — source handed to the compiler, gunbc's accept, rustc's Why it is not in this diff, which is the part the finding calls impermissible semantic deferral. That row is projected into There is a second reason, independent of capacity: What I changed in response ( If the ruling is still that it must be in this diff, then it needs someone with a box above 8.37 GiB to author it here, and I'd rather that be an explicit routing decision than me shipping a carrier without its projection. — sent from snappy-koi-286 |
|
CI red on The failure: It fails on main. Run 33596615712 is The subject is #9886's shell service-emission climb, not this lane. Nothing in this PR touches I am not repairing it here. Fusing an emitter fix into a fixture PR would put a service-emission change under a review that read this diff as a test-route addition, and it would make this PR's own scope claim false. It wants its own lane; flagging it for routing rather than absorbing it. Separately, and this one IS mine: review 58546 correctly found that — sent from snappy-koi-286 |
…t it has one Review 58546, and it was right: fixture_discrimination_passed asks four questions -- control compiled, red reached rustc, red did not compile, red named its own emitted module -- and none of them is about the Fn bound. A syntax error or any unrelated emission defect in the red fixture's own module answers all four, so this arm would have gone on passing while the adapter discrimination it claims to measure had silently stopped existing. The consumer now adjudicates the red arm's actual diagnostic: error[E0277] AND Rc<dyn Fn AND let_apply. The three are chosen to pin the SEAM rather than rustc's prose -- a stable error code for the trait-obligation class, the function-VALUE rendering, and the consumer whose parameter carries the impl Fn(..) + Clone bound -- so a rustc release that rephrases its message cannot quietly turn this into a check of nothing. The SHARED predicate is deliberately not tightened: it also serves #9911's text-boundary pair, whose red is a different diagnostic, so baking one subject's error code into it would fork it or make it false for the other consumer. Each claim site adjudicates its own expected diagnostic. Re-run with the assertion in place: control status=0, red status=101 E0277 attributed, pair PASSED, test result: ok in 165.27s. Regen fixed point over three passes, staged by regen output rather than by conflict list: 192 candidates, 0 differing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014xLgWdoQZSdMjXTTh1WnUm
|
Review 58546's finding is repaired in The fix. The consumer now adjudicates the red arm's actual diagnostic instead of accepting any attributed refusal: Chosen to pin the seam rather than rustc's prose: a stable error code for the trait-obligation class, the function-VALUE rendering ( The check of the check — one conjunct swapped for a rendering the diagnostic cannot contain ( It goes red. So the conjunct carries information rather than being permanently green by construction — which is the property §4b asks for before a check is worth writing, and the one the review correctly noticed the pair's shared predicate did not have for this subject. With the assertion in place, unmodified: control Not tightened: the shared predicate. Worth someone's lane, and not repaired here: the same gap exists at the other consumer. #9911's — sent from snappy-koi-286 |
…e merged authorities Integration done in the order the driver requires: merge commit, rebuild the seed FROM the merged tree, regenerate, then commit once -- session branches are pushed automatically, so an intermediate commit would reach origin and the drift gate would correctly red on it. Ran locally, which is where this actuator has to run: gunbc refuses HostBudgetUnreadable on BuildBuddy (no cgroup limit binds that process) and the whole-corpus resolve does not fit that runner's 7 GiB anyway. It fits here. - seed regen to a FIXED POINT over three passes, staged by what the regen NAMES rather than by what the merge marked as conflicted: pass 1 installed v1_compiler_compiler_tests_rust.rs, pass 2 compiler_tests.rs, pass 3 installed 0 of 192 with first_generation_equal=true. - projection gate (generated_artifact_gate main_wet) re-derived DESIGN.md and docs/design-ledgers.md; both are now byte-identical to main, which is the right answer -- this lane adds no ledger row, and #10020 owns the append. - compiler_tests.rs against main: +74/-0, which is this lane's #[ignore]d consumer plus its new diagnostic adjudication. No removals. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014xLgWdoQZSdMjXTTh1WnUm
…apacity claim this lane has since cleared INTEGRATION, in the order the driver requires: merge commit, rebuild the seed FROM the merged tree, regen to a fixed point, gate, then one commit -- pass 1 installed v1_compiler_compiler_tests_rust.rs, pass 2 compiler_tests.rs, pass 3 installed 0 of 192 at first_generation_equal=true, then generated_artifact_gate main_wet re-derived DESIGN.md and docs/design-ledgers.md. THE CORRECTION: this carrier said the projection actuator could not run here, and review 58670 quoted it back as the reason the ledger append is deferred. That was true of the BuildBuddy runner (7 GiB total, measured) and was never true of the session container (125 GiB host, 31 GiB cap) -- which is where this lane just ran it, twice, to integrate main. Capacity no longer defers anything. What defers the append is OWNERSHIP: #10020 holds the third instance, authored from this lane's receipts, and projection-touching branches land one at a time. A receipt that keeps citing a limit the lane has since cleared is the class this file exists to catch, so the measurement stays recorded against the runner it belongs to and stops standing in for a reason it no longer supplies. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014xLgWdoQZSdMjXTTh1WnUm
… seed The generated-artifact driver refused src/v1/stage0/src/v1_compiler_emit_rust.rs: both sides changed that projection since the merge base (#10017, #10025, #10046 and #9989 on the main side), so neither side's bytes are the projection of the merged authorities and picking a side would silently drop the other's. Regenerated rather than resolved. The seed had to come from main's mirrors to build at all. The merged tree's own mirror is the ours side, which predates main's new `FileVerb::FileWriteCreateNew` variant, so building it fails E0004 non-exhaustive-patterns -- and the regen needs a working seed. The seed is only the TOOL: built from main's self-consistent bytes, it emits from the MERGED .dag authority, which carries this branch's constructor. Pass two then rebuilds from the installed result, which is what makes the fixed point mean anything. EVIDENCE, two passes as the driver's own instructions require, because pass one runs a binary that predates the change it emits and can self-verify at divergence 0 for the wrong reason: pass 1 build from main's seed -> FAIL generated surface drift: v1_compiler_emit_rust.rs installed 1 file; main.rs skipped (declared_divergent=1, expected) pass 2 rebuild FROM the installed seed -> first_generation_equal=true, rc=0 census every file in the candidate tree vs the installed mirror: 222 compared, 0 differing -- the regeneration is the subject, not the conflict list fixed point --required-regen-fixed-point rc=0 The tree committed here is the tree those checks ran against, established by content and not by which paths a patch happened to carry: sha256 of all 238 .rs files under src/v1/stage0/src, taken in the same dispatch that ran the fixed point, compared entry-for-entry against the applied tree. 238/238 identical, both directions, so a file present on one side and absent on the other would have been as loud as a hash mismatch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G9q7HZqy1inoJYfnNdBB5J
What was missing
#9911 landed a capability:
fixture_closure_rustc_verdict/run_fixture_closure_discrimination— a fixture a test can author, emitted through the samecompile_sources, written by the same crate writer, handed to the samerun_cargo, and judged by rustc. Its own pair proves the route works, over the text-boundary fixture.This PR spends that capability on a second subject, chosen because it is one a text oracle cannot judge at all:
v1.compiler.emit_rustrust_call_arg_function_value_adapt.An arrow type has two Rust renderings, both correct for what they carry — a function value is
Rc<dyn Fn(..) -> ..>(callable_type_template), a function-typed parameter isimpl Fn(..) -> .. + Clone(emit_rust_param_type) — andRc<F>has no blanketimpl Fnin std the wayBox<F>does. The adapter closes that seam at the call position. Its claim is a TRAIT OBLIGATION, and a trait obligation is not a spelling:compile_dag_rust_emit_checkcan assert__adapt_fappears in the emitted bytes and still say nothing about whether the wrapper satisfies the bound.The pair is minimal-difference by construction
Both arms declare the same producer, the same consumer, the same call. They differ in one authored spelling:
fixtures/fixture_closure_rustc/function_value_adapter_probe.dag— passes the producer's result as a call expression, the shape the adapter keys on.fixtures/fixture_closure_rustc/function_value_let_probe.dag— binds that identical result to aletfirst and passes the binding, which the adapter deliberately does not touch.So a green here is not "some crate compiled" and the red is not "something in the tree is broken": the only variable across the arms is whether the adapter fired.
Executed, both directions
cargo test --release -p v1-compiler --lib function_value_adapter_fixture_closure_discrimination -- --ignored --nocapture, one BuildBuddy runner:Attributed to the fixture's own emitted module, which is what separates "rustc refused this fixture" from "the closure was already red".
The red arm is a KNOWN HOLE, not a wall working
gunbc accepts the red fixture with zero blocking diagnostics and emits a crate rustc refuses —
gunbc.recurring_failure_modeaccepted_source_emits_uncompilable_target, at the function-value seam rather than at that row's coproduct-variant construction, and committed here as runnable files, which that row records its own specimen never was. What this instance adds to the class: the mask is a call-site spelling, so the discriminator for this shape is to re-spell an accepted call through aletand re-emit.When the hole closes — the emitter adapting a let-bound arrow value, or the front end refusing the construction — the arm flips and is kept as a permanent regression control (DESIGN §4b(4)). What changes then is the pair's expectation, not the fixture.
Where it executes — the honest grain, on #9911's own terms and with nothing added
#[ignore]d. ENROLLED AND OPT-IN viacargo test --release -p v1-compiler --lib function_value_adapter_fixture_closure_discrimination -- --ignored; does not execute by default on push or PR; andrust-unit-testsis not aneedsof the required aggregate, so even un-ignored a red would be visible and would not block through the required context.Candidate evidence, no wall. An
#[ignore]is a cost decision and NOT a rung: this establishes no rung for the adapter and discharges no next-rung trigger naming it. The reversal condition is the one that carrier already states (rust-unit-testspromoted into the required aggregate) and is not re-minted here.Seed growth
Three declarations, enumerated rather than counted, in
gunbc.emitted_closure_compile_seed_growth:FIXTURE_ADAPTER_GREEN_PATH,FIXTURE_ADAPTER_RED_PATH,run_function_value_adapter_discrimination. Everything else is reused:fixture_arm_verdictruns each arm,fixture_discrimination_passedadjudicates,fixture_discrimination_reportprints — a second discrimination, not a second harness. Census re-derived against the file: 78 declarations / 78 rows, zero stale, zero unaccounted. Thecli_run#[cfg(test)]re-export list is ExistingSeedItemModified. No edit to the emitter, no row onrequired_emit_compile_entries, no CLI flag, no workflow change, no production re-export.The blob carries its
gunbc.language_source_scaffold_indexrow. Noted while there: fivect_*blobs on main have no row (ct_fixture_closure_rustc_discrimination_test,ct_generic_param_declines_fail_closed_unwrap_test,ct_import_lines_follow_resolved_binding_identity_test,ct_shell_service_output_projection_known_hole_probe_test,ct_witness_carrier_declines_non_witness_expected_type_test), socompiler_tests_rust_blobs_are_all_rosteredis already short — pre-existing, not repaired here.What is deliberately NOT in this diff
The
accepted_source_emits_uncompilable_targetledger row is not appended, and the reason is an instrument that would not run rather than an omission: that row is projected intodocs/design-ledgers.md, so editing it requires re-runninggunbc run --entry dag/gunbc/instruments/generated_artifact_gate.dag --function main_wet. Measured on the runner available to this lane:HostBudgetUnreadablewith no cgroup limit, andMemoryStallRefusedPageThrashunder a 12 GiB and again a 30 GiB cgroup during the whole-corpus resolve. Landing the carrier edit without its projection is exactly the drift the gate exists to catch, so the instance is recorded ingunbc.emitted_closure_compile_seed_growthand in the two fixture files, and the ledger append is left to a lane that can execute that actuator.Checks
cargo fmt --all --check(pre-commit hook),cargo clippy --all-targets -- -D warningsclean, and the two generated projections (compiler_tests.rs,v1_compiler_compiler_tests_rust.rs) are--required-regenoutput installed to a fixed point (a third pass installs nothing).🤖 Generated with Claude Code
https://claude.ai/code/session_015XNpHkAWNSqikzKqspogbY