Skip to content

t27o: five refusal classes from the roadmap dogfood convert (Closes #10526) - #10593

Merged
gHashTag merged 7 commits into
masterfrom
t27o/refusal-classes-10526
Oct 18, 2026
Merged

gHashTag merged 7 commits into
masterfrom
t27o/refusal-classes-10526

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Lane C of #10522. Five first-refusal classes of the roadmap dogfood now convert (or, where the type cannot be known, refuse under a name that says why). Only specs/tools/t27o/rust_convert.t27 carries rules; gen/rust/tools/t27o/rust_convert.rs is t27c gen-rust of it and the seal is re-saved.

What changed, per class

  1. Ok(..) / Err(..) in a test's assert_eq! / assert_ne! (result_assert). A Result is ?T, so assert_eq!(e, Ok(v)) is assert(e.? == v), with a call read once into t27o_r<offset> and assert(t != null) first; assert_eq!(e, Err(..)) is assert(e == null) under the comment // t27o: Err payload dropped (Result is ?T); assert_ne! negates both (t == null or t.? != v). A Result<(), E> call is a bool in t27o, so Ok(()) is == true and an Err == false. assert!(e.is_ok()) / is_err() already converted. Stay refused: Ok(()) of something that is not a call of this file's Result<(), E> fn (a bool cannot be told from a ?void), and a struct payload (== of structs).
  2. for x in &[a, b, c] is the loop over the literal [a, b, c] (same typed local, same t27 for-each). &mut [..], unsuffixed integer elements and .iter() on the literal stay refused.
  3. &[] as an argument: the callee is looked up among the file's own fn declarations (a free fn, Type::f(..) or x.f(..); every declaration of the name must agree), the parameter the argument lands on is &[T], and the argument is [0]T{}. Also let a: [T; 0] = []; (15 of the 306 sites) as = []. Where the type cannot be known locally the refusal stays and now says so: empty slice with no known element type (new R_EMPTY) instead of block as a value ]``.
  4. Raw strings r"..", r#".."#, r##".."## become the ordinary t27 string with the same bytes (backslash, quote, newline, tab take the escapes t27 reads; CR LF is the LF Rust reads; other control bytes and non-ASCII stay refused). Raw strings are texts in ==, match arms, class inference and the out-buffer form. r#ident (raw identifier) stays refused.
  5. \ + newline inside a string literal (Rust's line continuation: the backslash, the newline and the next line's whitespace go) is joined, for put_string and for the literal pieces of an out-buffer format!. The cited example (bootstrap/tests/assert_paren_binary.rs:55) is a format!; its last argument followed by a newline before ) also needed a trim to convert. Only \ right before a newline joins: \<space>, \\+newline and \r stay refused.

Before / after

Protocol of docs/nona-03-manifest/T27O-COMPETITORS-AND-DOGFOOD.md: every tracked .rs file (not under gen/ or target/) of the five repos at the commits it names (t27 7496ed2, trios 483dd9ee, trinity 0770abb9, trinity-fpga 20bf4c418, 999-multibots-telegraf 6e5512881), 30 s cap per file, the same 5 t27 files over the cap excluded from both columns. File counts equal the doc (382 / 786 / 23 / 30 / 167). "Before" is the converter of master 0c98c96, "after" this branch; both are t27c gen-rust output compiled into a small driver that calls convert (what tri t27o FILE prints), not a rebuilt tri.

First refusal Before After
type Ok 474 2
type Err 609 0
for over an iterator & 380 4
block as a value ] (now empty slice with no known element type) 306 59
literal r# / r" 154 0
literal \? (line continuation) 88 0
Before After
fns converted (1,383 files, 16,765 fns seen) 1,573 (9.4%) 1,667 (9.9%)
#[test] fns converted 504 593
t27 repo only 627 of 7,108 638
trios only 884 of 8,220 967

The issue's counts (473 / 612 / 380 / 306 / 152 + 2 r" / 88) are reproduced within 3. The doc's trios row says 8,230 fns seen; this run counts 8,220 on the same 786 files. What remains: 2 Ok(()) whose callee is declared in another file; 4 for (a, b) in &self.field loops; 59 &[] whose callee is another module's or a std method or has a generic element (&[Behavior<'_>]), e.g. bootstrap/src/behavior_sva_v2.rs:765 still refuses because build_behavior_sva_bind_block itself does not convert (owned String result, lifetime-generic element).

Tests

  • t27b test specs/tools/t27o/rust_convert.t27: 81 passed, 0 failed (66 before, 15 new).
  • t27c test-report specs/tools/t27o/rust_convert.t27: 81/81, vacuous passes 0 of 81.
  • t27c seal specs/tools/t27o/rust_convert.t27 --verify: all hashes MATCH (rust_std.t27 untouched, its seal verifies too).
  • rustc --edition 2021 --crate-type lib gen/rust/tools/t27o/rust_convert.rs compiles.
  • Differential checks (not committed): a Rust test file using every Ok/Err form passes under rustc --test, its converted t27 passes in t27b, and with two wrong expectations the converted test fails; a file using &[] arguments, let a: [T; 0] = [] and methods passes in t27b and in the zig reference (t27c test-report).

Negative controls

Each class has a test that a near-miss form is still refused with the exact message, and each rule was removed in turn from a copy of the spec; these tests then fail in t27b:

Rule removed Failing tests
class 1 (result_assert hook) ok_and_err_comparisons_in_a_test_read_a_result_as_an_optional, negative_control_ok_unit_of_a_local_and_a_struct_payload_stay_refused
class 2 (& before the literal) a_for_over_a_borrowed_array_literal_is_a_for_over_the_literal, negative_control_a_mutable_or_unsuffixed_or_iterated_array_literal_loop_stays_refused
class 3 (empty_arg) an_empty_slice_argument_takes_its_parameters_element_type, negative_control_an_empty_slice_with_no_known_element_type_is_refused_and_says_so
class 3 (typed = []) an_empty_slice_argument_takes_its_parameters_element_type
class 4 (raw string branch) five tests: raw_strings_become_ordinary_strings, a_raw_string_is_a_text_in_a_comparison_and_a_match, negative_control_a_raw_identifier_and_an_unterminated_raw_string_stay_refused, a_control_byte_in_a_raw_string_is_refused, a_raw_strings_crlf_is_the_lf_rust_reads
class 5 (is_cont) a_backslash_before_a_newline_joins_the_string, a_continuation_with_crlf_skips_the_carriage_return_too

CR bytes in tests are built with put(.., B_CR) because the specs are ASCII-only.

Notes for the reviewer

  • The committed gen/rust/tools/t27o/rust_convert.rs on master was one spec change behind (65 tests in its header, the old coverage-report order); regenerating it brings that in as well.
  • Err comparisons are weaker than Rust's (any error passes). Every converted one carries the // t27o: Err payload dropped comment, as the issue asked.
  • Not touched: cli/tri/src/main.rs, spice_convert.t27, ledger.t27, rust_std.t27.

Part of #10522.

🤖 Generated with Claude Code

claude and others added 7 commits October 19, 2026 01:01
#10526)

Classes 4 and 5 of #10526. A raw string r"..", r#".."# is written as the ordinary
t27 string with the same bytes (backslash, quote, newline and tab take the escapes
t27 reads; CR LF is the LF Rust reads; other control bytes and non-ASCII stay
refused). A backslash right before a newline inside a string literal is Rust's line
continuation: the backslash, the newline and the next line's leading whitespace are
joined out of the text. Raw strings are texts in ==, match arms, class inference and
the out-buffer form. Tests and negative controls added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…oses #10526)

Class 2 of #10526. `for x in &[a, b, c]` is read exactly as `for x in [a, b, c]`
(typed local, then t27's for-each); `&mut [..]`, unsuffixed integer elements and
`.iter()` on the literal stay refused. Test plus negative control.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…loses #10526)

Class 1 of #10526. assert_eq!(e, Ok(v)) is `e.? == v` with e read once into a temp
when it calls something and asserted not null first; assert_eq!(e, Err(..)) is
`e == null` with a comment that the payload is dropped (Result is ?T); assert_ne!
negates each. A Result<(), E> call is a bool, so Ok(()) is `== true` and an Err
`== false`. An Ok(()) of a non-call, and a struct payload, stay refused. The
converted test was checked against rustc: same verdicts in t27b, and wrong
expectations fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Closes #10526)

Class 3 of #10526. `f(a, &[])`, `x.f(&[])` and `Type::f(&[])` look the callee up in the
file's own fn declarations (every declaration of the name must agree): the parameter
the argument lands on is `&[T]`, so the argument is `[0]T{}`, which a `[]const T`
parameter takes (checked against t27b and the zig reference with t27c test-report).
`let a: [T; 0] = [];` is the typed local `= []`. Where the element type cannot be known
locally the refusal stays but names itself: "empty slice with no known element type"
(R_EMPTY) instead of "block as a value `]`". Tests and negative controls added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…w rules (Closes #10526)

gen/rust/tools/t27o/rust_convert.rs is `t27c gen-rust` of the spec (it also picks up the
coverage-report change that the committed copy was missing); the seal is re-saved and
`t27c seal --verify` prints all hashes MATCH.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y end its line (Closes #10526)

The cited example of class 5 (bootstrap/tests/assert_paren_binary.rs:55) is a format!
string; the out-buffer form copies its literal pieces on its own, so they join the
`\` newline continuation as put_string does, and the last argument of a multi-line
format!( .. ) no longer carries the white space before its `)` into the name lookup.
Test added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t! piece rule (Closes #10526)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gHashTag

Copy link
Copy Markdown
Owner Author

Review (orchestrator, Opus), before auto-merge:

  • Re-ran on the PR head: t27b test specs/tools/t27o/rust_convert.t27 81 passed, 0 failed (2.0 s); t27c seal --verify all hashes MATCH; cargo check -p tri with the regenerated rust_convert.rs clean. Only spec, generated file and seal change, so own-language counts nothing.
  • DRY: the 15 new pub fns checked with t27c dupes --name; the one hit, param_at, shares only the name with specs/tri/t27b/verilog_plan.t27:153 (a different function: the k-th line of a text), not a body.
  • Semantics of the Result rule, read from the new test's expected text: assert_eq!(e, Ok(v)) -> e read once, != null, .? == v; assert_eq!(e, Err(_)) -> e == null with a comment that the payload is dropped (the oracle's own reading); assert_ne!(e, Ok(v)) -> t == null or t.? != v (exact). One edge for the record: assert_ne!(e, Err(A)) becomes e != null, which is stricter than Rust when e is Err(B). It can only make a converted test fail visibly, never pass silently, so it does not block; a follow-up can refuse that form instead.
  • Measured gain on the five roadmap repositories (lane's drivers, before = master 0c98c96): converted fns 1,573 -> 1,667, converted tests 504 -> 593; first refusals type Ok 474 -> 2, Err 609 -> 0, for over & 380 -> 4, ] 306 -> 59, raw strings 154 -> 0, line continuations 88 -> 0.

@gHashTag
gHashTag enabled auto-merge (squash) October 18, 2026 18:25
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 19:29:52 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 45
PRs with All Checks Green 5
READY 0
FAILING 45
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 45 + 0 + 0 = 45, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=fad12492937a != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag merged commit f8bafc3 into master Oct 18, 2026
34 of 36 checks passed
gHashTag added a commit that referenced this pull request Oct 18, 2026
…eeper Rust, Python, TypeScript, shell (Closes #10599) (#10601)

Section 7 of the t27o dogfood document: per language the files, distinct
fns and the share inside a stated first subset, with the top first
blockers and the roadmap stage each maps to. Zig (coarse) 36,495 fns,
10.4-38.1 % in a first subset, tests as the oracle; TypeScript 2.5 %
(26 % async); Python 3.7 %; shell is orchestration. The Rust section gets
#10593's measured gain (1,573 -> 1,667 fns, 504 -> 593 tests).

Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag deleted the t27o/refusal-classes-10526 branch October 20, 2026 04:46
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.

2 participants