Repository navigation
A machine scalar is never raised to a reference layer: one decision, both positions - #8384
Conversation
…both positions The emitted 05_eval closure carried 151 of 483 distinct rustc sites in which a numeric scalar sat behind Rc. `Rc<i64>` is not a sharing decision, it is a category error: every arithmetic and comparison operator refuses on it, which is why one wrong decision produced many sites. THE RULE THAT PRODUCED THEM decides from two facts, neither about the carrier: membership by leaf NAME in shared_types, guarded by a string PREFIX test for "Rc<" against already-rendered text. So one carrier reached by two spellings is decided twice, and the prefix guard cannot see a layer through an alias. Measured on this base, where Nat realizes natively as i64: 172 scalar-wrap spellings, 12 literal `Rc<i64>` and 160 `Rc<Nat>` -- one category error in two spellings, both appearing on a single emitted line: measure_scale_fraction_floor<Q, S>(m: Rc<Measure<Q, S, Rc<i64>>>, num: Rc<Nat>, ...) the type argument rendering the primitive, the parameter rendering the alias. BOTH POSITIONS NOW CONSULT ONE AUTHORITY (rust_seed_host_numeric_alias, via the declaring file) instead of re-deciding from rendered text. Fixing only the parameter half first was measured and REJECTED: it left `Rc<i64>` in argument position and produced `Rc<i64> * i64`, an operator refusal neither uniform answer produces -- a mixed layer is worse than either. The applied-argument half sits in rust_render_checkpoint_scalar_bare, which despite its name applied the shared wrap after the scalar authority had already answered. RECEIPT, entry src/v2/compiler/05_eval.dag, base 0ce4ce6, site identity (file, code, normalized message) because emitted line numbers move: arm A -> arm B distinct causes 159 -> 148 error messages 539 -> 417 distinct sites 483 -> 361 (-122) scalar sites 151 -> 29 (-122) ADDED causes 0 (removal, not movement) emitted Rc<i64> 12 -> 0 Option<Absent> 0 -> 0 (merged #8376 not regressed) regen --verify divergence_count=0 SCOPE, stated rather than implied: this closes the NUMERIC scalar case, the whole of the measured Rc<primitive> population. It deliberately does not consult lookup_checkpoint, whose rows include non-scalar carriers such as String that may legitimately be shared; widening there is a separate cut with its own evidence. 29 scalar sites survive and are not claimed fixed. RUNG (DESIGN 4b): MITIGATABLE, and the ceiling is inherited rather than novel. rust_seed_host_numeric_alias keys on a NAME plus a declaring-file check, not on resolved declaration identity -- the same ceiling checkpoint_table_bypasses_identity_note records for the neighbouring table. This makes the numeric-scalar wrap not happen; it does not make a wrapped scalar unwritable. Next rung is the modeled layer transition wrap_decision.dag already names, at which point an agreeing flow is DERIVED rather than guarded. Also adds dag/tools/p1_emit_probe.dag, the producer experiment that settled which emitter to repair: the v2 emitter run under the v1 interpreter refuses at the FIRST bridge on a real module (parse_tree_to_emitted_node_no_matching_row -- zero grammar-relation rows match a real .dag token-class frontier), while the v1 emitter produces 92 files. So P0 remains the measured bootstrap producer and this repair is on the selected producer, not on the interpreter being deleted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
31e5837 to
09fe505
Compare
…ntation goes dag/tools/p1_emit_probe.dag was branch-local experiment tooling. It asked one question -- can v2's emitter semantics serve as the bootstrap producer? -- and answered it by execution: P1 refuses at the first bridge (parse_tree_to_emitted_node_no_matching_row, v2.std.grammar), while P0 emits 92 files. That measurement selected P0 and is recorded in the PR receipt; the transport that produced it has no remaining consumer. Zero references to p1_emit_probe / p1_probe_eval / p1_probe_small_control exist outside the deleted module itself. Deleted rather than registered as a scaffold. DESIGN §5 rules that a dissolution condition describes how admitted debt ends and does not authorize creating it, so marking it would have required an operator verdict on this exact population -- and buying that verdict for tooling whose question is already answered spends review and maintenance time against a benefit of zero. The same section names the correct arm directly: the canary may run, produce measurements, and be deleted before merge, leaving the modeled facts the final route consumes. The emit-side repair is unaffected: the probe never entered any production path, and the fix's authority is src/v1/05_emit_rust.dag. Raised by cursor/composer-2.5 in review 53026 on #8384.
|
Fixed in Verified the finding against the tree before acting: I took the deletion arm rather than the scaffold-registration arm, and the reason is worth stating because the review offered both as equivalent. DESIGN §5 rules that a dissolution condition describes how admitted debt ends and does not authorize creating it — the marker is a lifecycle fact, not permission — so registering this would have required an explicit operator verdict on this exact population. Buying that verdict for tooling whose question is already answered spends operator, reviewer and maintainer time against a benefit of zero. The same section names the arm that actually applies: the canary may run, produce measurements, and be deleted before merge, leaving the modeled facts the final route consumes. What the probe bought is kept; only its implementation goes. It asked whether v2 emitter semantics could serve as the bootstrap producer and answered by execution — P1 refuses at the first bridge ( The emit-side repair is unaffected: the probe never entered a production path, and the fix's authority is Also on the record for this PR, unchanged and not claimed away by the fix above: 29 scalar sites survive and are not claimed fixed, and the rung is mitigatable — the guard inherits — sent from gentle-dove-833 |
|
Title and body corrected — the remark was right and the defect was bigger than the title.
On the relationship the review flagged, stated in the body rather than left implicit: the work item is to delete Nothing in the code changed for this; it is a title/body correction only, so the approvals on Restating the two limits that both approvals correctly declined to launder: 29 scalar sites survive and are not claimed fixed, and the rung is mitigatable, inheriting — sent from gentle-dove-833 |
Three conflicts, resolved by rule rather than by side: - runner_slot_provision_witness_test.dag: main still carries the import block this branch deleted. Took HEAD (import-free). One-sided re-add of a deleted class. - 05_emit_rust.dag: took main's semantic content for both hunks -- #8384's rust_seed_host_numeric_alias arm, which stops a machine scalar being raised to a reference layer -- then re-applied the cut's qualification to code positions. - v1_compiler_emit_rust.rs: the generated-artifact merge driver refused, as designed (unmerged, no markers, regeneration recipe). Took main's generated bytes: this branch's .dag now carries main's semantics for that file, and qualification does not change emitted output. Owed a regenerate once the tree is green. The string-literal control caught a real defect in the qualification pass: it had rewritten names inside quoted regions, including three lines of EMITTED RUST SOURCE (Rc<v1.std.core.NewlineIndex>), which would have emitted invalid Rust. Four in-string occurrences reverted by a quote-aware pass; control re-run clean. Import discipline verified after merge: zero .dag files carry an import statement.
…the import era
The merge resolution took main's v1_compiler_emit_rust.rs on the reasoning that this
branch's .dag now carried main's semantics and qualification does not change emitted
output. That was wrong, and CI caught it: 9 build errors across four classes, including
unresolved import crate::v1_std_core::CompilerDiagnostic::UnlistedImportUse
no variant named UnlistedImportUse found for enum CompilerDiagnostic
main's generated bytes still carry import-era machinery this cut deleted, so taking them
re-admitted the class into the seed -- the same trap recorded two commits ago and then
walked into anyway. The other errors (missing corpus_repr, build_emit_graph_info arity)
are the same era skew: main's emitter compiled against main's 04_infer, not this branch's.
Restored to dd598f3, byte-identical to the seed that built successfully at fd9aaea
(the witnesses job there reached the claim_executor invocation, so the build passed).
#8384's rust_seed_host_numeric_alias fix is NOT lost: it lives in src/v1/05_emit_rust.dag,
which is the authority. It reaches the generated .rs at the next regen. The .dag and the
.rs are deliberately allowed to drift until then.
Rule for this branch, stated so it is not relearned a third time: a generated artifact
must be taken from the side whose SOURCE this branch carries, never from the side whose
semantics are wanted. Semantics are merged in the .dag; bytes follow at regen.
…ted bytes 7 x E0308 'expected RustCorpusRepr, found String', all in the module added to lib.rs by the previous merge. Era skew, and the direction matters: this branch's .dag SOURCE already carries main's rust_scalar_checkpoint_render_base(dag_name, decl_file) signature, taken with #8384's hunks; only the generated .rs still carries the old corpus_repr form, which is the drift deliberately accepted under the source-follows rule. So the witness is compatible with this branch's source and incompatible only with its stale bytes. Removed from lib.rs; file RETAINED and re-declaration owed once regen makes the generated signature match -- deleting it would discard evidence that becomes valid at regen, and this witness exists precisely to repair a rung-inflation defect where seven assertions were authored, type-correct and never executed. Records the authoring error: the module was declared because the file existed. Unioning two module lists is not a merge resolution -- added members must typecheck against the side whose generated bytes are kept.
Summary
The v1 Rust emitter wrapped machine scalars in
Rc, emittingRc<i64>andRc<Nat>where a barei64was owed. The cause is that the wrap decision consulted two facts, neither of which is aboutthe carrier: leaf-name membership in a
shared_typesset, and a string-prefix test for"Rc<"on the already-rendered text. A name and a rendered prefix cannot answer whether a thing is a
reference layer.
This routes both rendering positions through the authority that already knows —
rust_seed_host_numeric_alias, which keys on declaration identity (name and declaring file, vianumeric_realization_declaring_modules). No second roster is minted.Two positions, because fixing one alone creates an asymmetry rather than a repair — my first attempt
patched only the parameter path and produced a new error class (
cannot multiply Rc<i64> by i64),which is why both land together:
render_rust_shared_type_with_optionalrust_render_checkpoint_scalar_bareAuthority is
src/v1/05_emit_rust.dag; the generatedsrc/v1/stage0/src/v1_compiler_emit_rust.rsis produced by
regen_stage0, never hand-edited.Relationship to this session's work item
The work item is delete
v1_interpreter.rs, and this PR does not delete it — that file isstill present on HEAD. Flagged by cursor/composer-2.5 in review 53031, and the observation is
correct; the title has been corrected to describe the diff.
What this is instead: the terminal direction for that lane is native, never a rebuilt
mini-interpreter and never wholesale restoration. Going native requires the emitted evaluator to
compile, and it did not. The 483-site wall was censused by mechanism rather than by count and
resolved to roughly four model↔realization forks; this PR removes the largest, on the v1 emitter —
the sanctioned bootstrap producer, not the interpreter being deleted. The remaining forks are
separate cuts.
Measurement
Both arms measured on merged main (
7c1c633be7), keyed on(file, code, normalized message)forcauses and
(file, line, col)for sites. Line-keyed diffing is invalid here — emitted line numbersmove when the emitter changes, which made an early A/B read meaningless (461 added / 430 removed)
until it was re-keyed.
Rc<i64>Rc<Nat>122 sites removed, 0 added causes. Arm A measures identically on merged main and on the
pre-merge base, so the delta is attributable to this change rather than to anything squashed
alongside it.
Test plan
regen_stage0on merged base → wrote 145 files, 0 stage0 drift; the committed artifact isbyte-identical to what merged main produces.
regen_stage0 --verify→regen_divergence_count=0, two-generation fixed point green.Option<Absent>in emitted eval → 0, both arms.emit_rc=0.Scope and rung — stated as limits, not achievements
Numeric only.
Stringcheckpoint rows are deliberately untouched; widening the guard tolookup_checkpointrows is a separate cut.29 scalar sites survive and are not claimed fixed.
Rung: mitigatable. The guard inherits
rust_seed_host_numeric_alias's name-and-file keyingceiling — the same ceiling recorded on
checkpoint_table_bypasses_identity_note. The next rung isthe modeled layer transition in
src/v2/compiler/wrap_decision.dag, whosewrap_decision_flow_gateexists and is witnessed but has zero production callers today; its own note says it is not wired
into
06_translate. Calling this structural would be rung inflation.Also in this branch
dag/tools/p1_emit_probe.dagwas added as a branch-local experiment and is deleted in02ba2c1c76before merge. It answered one question by execution — can v2's emitter semanticsserve as the bootstrap producer? P1 refuses at the first bridge
(
parse_tree_to_emitted_node_no_matching_row,v2.std.grammar) while P0 emits 92 files, so P0remains the measured producer. That selection is the durable fact; the transport that produced it
had no remaining consumer. Deleted rather than registered as a scaffold, per DESIGN §5 — a
dissolution condition describes how debt ends and does not authorize creating it. Raised by
cursor/composer-2.5 in review 53026.
05_eval.dagunder P1 timed out at 1500s with no verdict. Not extrapolated from thenat.dagcontrol.