Repository navigation
t27o: three converter defects -- static mut name, text-field str_chain, 64-bit unsigned int_ok - #11064
Merged
Conversation
…oses #10829) const_item read the item name from the token it stopped at, which for a static mut is the keyword mut: the refused item went into the name table as mut, and every later fn that spells mut (a let mut, a &mut) was refused with it. item_named had the same blind spot for declared_type (a static mut S declared mut, not S), and index_decls added both tokens. const_item now steps over the mut before it reads the name, item_named skips a mut after const and static the way const_hit already did, and index_decls enters only the name. The refusal names COUNT, a fn that spells mut converts, and a fn that reads COUNT is refused as a user of a refused name, not as one that reads an undeclared name. The test that pinned the defect (known_defect_a_static_mut_is_named_mut_...) now states the fixed behaviour; it failed on master before the change. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… let t = n.value.trim() binds a text (Closes #10834) The field branch of str_chain asked for a ( right after the field name, i.e. node.value( -- a method call, not a field -- so for node.value.trim() the token after value is a dot, the branch was never taken, base stayed false and the binding was no text. recv_class reads the same step with !tok_is(.., "("); str_chain now does too. let t = n.value.trim(); t.starts_with("a") converts like the inline n.value.trim().starts_with("a"): t is a text and takes the text entry of the std table. A field of another type, a field the struct does not have and a method call (x.value(), x.trim()) are still no text chain. The test that pinned the defect (known_defect_str_chain_...) now states the fixed behaviour with fourteen heads and the end-to-end repro of the issue; it failed on master before the change. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…computing 2^64, so usize / u64 / u128 parameters are sampled from the body (Closes #10864) int_ok asked an unsigned type for m < bit(w), and bit(64) is 2^64: one doubling past what a usize holds. Under t27b and t27c test-report the call trapped (integer overflow, * on u64); in the compiled converter it wrapped to 0, so m < 0 was false for every sample. Either way a usize, u64 or u128 parameter got none of the body-derived samples of #9102 (the signed 64-bit types and every narrower type were fine). Every sample num_value returns is below 2^62 and the samples beside it are at most 2^62, so an unsigned type of 63 bits or more holds them all; int_ok now says so without computing bit(w). A negative sample is still no sample of an unsigned type, and the narrower widths and the signed types are unchanged. Oracle of fn g(x: usize) -> bool { x == 5 }, and u64 and u128 likewise: before, 0 1 2 7 10 100 18446744073709551615 only; now 4 5 6 follow, as they do for u32. The int_ok test holds the 64-bit unsigned cases (a direct call trapped on master), and a new test walks derived_at and dcount for u32, i64, u64, usize, u128, i128 and isize. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
9 of 12 tasks
Contributor
This was referenced Oct 19, 2026
gHashTag
marked this pull request as ready for review
October 19, 2026 14:17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #10829
Closes #10834
Closes #10864
Three open defects of the Rust-to-.t27 converter (
specs/tools/t27o/rust_convert.t27), one commit each. In each commit the spec is the rule: the test that pinned or exposed the defect was written first and failed on the merge-base code undert27b test, then the rule was fixed,t27c gen-rustregeneratedgen/rust/tools/t27o/rust_convert.rs, and the seal was re-saved. No hand-written Rust and no glue changed.The three defects
static mutrecorded asmuta_static_mut_is_named_by_its_name_not_by_the_mut_before_it(assert failed) and theconst mutrow ofconst_item_struct_item_and_enum_item_write_the_declarations; the oldknown_defect_a_static_mut_...pin was replacedconst_itemsteps overmutbefore it reads the name;item_namedskips amutafterconst/static(asconst_hitalready did);index_declsenters only the name. The refusal now namesCOUNT,sum(alet mut) converts, andfn cnt() { COUNT }is "uses refusedCOUNT", not "undeclared"str_chainnever opens with a text fieldstr_chain_opens_with_a_text_field_of_the_head_names_struct(14 chains plus the end-to-end repro of the issue; assert failed); the oldknown_defect_str_chain_...pin was replaced(after the field (asrecv_classdoes), not for one.let t = n.value.trim(); t.starts_with("a")now converts to the same call as the inline chainint_ok(64, unsigned)overflows inbit(64)int_type_width_int_type_signed_and_int_ok_say_what_an_integer_type_holds(new 64-bit unsigned asserts) anda_64_bit_unsigned_parameter_is_sampled_from_its_body_like_the_narrower_ones(u32, i64, u64, usize, u128, i128, isize): both failed withinteger overflow at line 3991 (* on u64)int_okanswers true without computingbit(w); a negative sample is still no sample of an unsigned type, narrower widths and signed types are unchanged. Oracle offn g(x: usize) -> bool { x == 5 }(and u64, u128): was0 1 2 7 10 100 18446744073709551615only, now4 5 6follow, as for u32Dogfood, before and after
The converter was compiled from the generated Rust of the merge base and of this branch (same
#[path]filecli/trimounts, same buffers ascmd_t27o) and run per file with a 60 s cap. "Before" is the merge base.$TMPDIR/t27o-loop/sample-files.txt, 29 files: fns seen / convertedt27b testis not a passt27c test-reportwould judge;capflags.rs,firmware.rs).rsof t27 (489 files): fns seen / converted.rsof trios, trinity, trinity-fpga (839 files): fns seen / converted--oracle), 1,326 files: sample callst27b testof spec + samples): files that passThe convert counts do not move by design: the shapes of the three defects (
static mutnext to alet mut, aletover a text field, a usize body-derived sample) change refusals and samples in rare places, none in these files. What moves is the oracle: usize / u64 / u128 parameters now get their body-derived samples (+8.5 k calls, +3 passing oracle tests, no failing one). The other verdicts of those 91 files are identical before and after: 15 stop at a t27b parse or typecheck error of the converted spec (an existing converter output defect, unrelated), 5 at "unsupported", 4 at a harness that does not compile alone; a few rows only moved a line number because more assert lines precede the failing one. Three harnesses (verilog_emit,verilog_plan,rust_convert) hit my 90 s rustc cap in the first "after" run while two jobs ran at once; re-run alone they compile in 5 to 51 s and give the same verdict as before (counted in the 15 and 5 above).Checks
t27b test specs/tools/t27o/rust_convert.t27: 333 passed (332 before; the two pins became two tests and one test grew).t27c test-report: 333 / 333,vacuous passes 0 of 333.t27c coverage: 395 / 395 fns (100 %).rust_std.t27: 51 / 51, vacuous 0, coverage 149 / 149.t27c gen-rustofrust_convert.t27is byte-identical to the committedgen/rust/tools/t27o/rust_convert.rs;zig_convert.t27andspice_convert.t27generate byte-identical Rust to what is committed.t27c seal --verify: rust_convert (re-saved, tests 333 / 333 under Zig), rust_std, zig_convert, spice_convert, zig_std, ledger, golden, install, service all MATCH. No dependent seal needed a re-save andspice_convert.t27is untouched.python3 -I tools/dupe_scan.py: 738 of 15,471 bodies in 218 groups at the merge base and at the head; the 15 findings are the same set, none is new (no helper was added).python3 -I tools/check_devhome_paths.py: OK. The spec has 0 non-ASCII bytes.gen/c/policy/own_language.c,git diff --numstat --no-renames BASE...HEAD): 179 added / 58 deleted lines in three files (specs/tools/t27o/rust_convert.t27153 / 39, generatedgen/rust/tools/t27o/rust_convert.rs17 / 10,.trinity/seals/t27o_T27oRust.json9 / 9); hand-written foreign lines added: 0; the gate prints nothing and exits 0.tri types ratchethas nothing to ratchet.Not run
cargo build -p triand the realtri t27o/tri t27o --checkbinary: the disk was short, and nothing incli/changed. I compiled the same generated file withrustcand replayed the steps of--check(oracle harness, rustc, run,t27b testof spec plus samples) by hand on the 91 files whose harness changes; the files that need#[path]neighbours (4 of them) did not compile alone, before or after.tri t27o-sweepwith its cache,t27c suite,./scripts/tri test, and the CI workflows beyond the gates listed above;docs/reports/t27b_expectations.jsonand every ledger were left to their owners.t27c test-reportof the two dogfood outputs thatt27bcalls unsupported: their text is byte-identical before and after.built_byfield now names thet27cI used (b258b9007), an earlier build than the one that sealed master.Not set to auto-merge.
🤖 Generated with Claude Code