Repository navigation
Conversation
Closes #7319, Closes #2645) The number lexer took any run of digits, x X b B _ (and hex letters after 0x) as one number, and gen-c wrote what it read: 010 and 0_10 reached C as the octal constant 8, 08 and 0b102 did not compile, and 1_, 1__0 and 0x_1F were quietly normalized. The parser now refuses each by name and line: a leading zero, a digit outside its radix, a misplaced separator, two decimal points, a letter inside a decimal. 0o17 lexed as 0 followed by the identifier o17. The lexer now reads an octal literal after a lone leading 0 and hands it on as the decimal it denotes, since no two backends spell octal alike. Part of #5980. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Parked: this PR is over the foreign-line budget that #7399 (owner rule 2026-10-07, #7371) put on master while it waited for CI. It is now a draft, with auto-merge off.
No exception and no label lifts this limit. Splitting the same Rust into 80-line PRs would get around the rule rather than follow it, so I have not done that. The fix itself is still correct and tested on the t27c lab: the regression tests fail on master's compiler and pass with the fix. Landing it needs the literal lowering written in .t27 (gen-rust into |
|
A draft since 2026-10-07 (last update 2026-10-07); its base is 1438 commits behind master, and the rules it predates (Only t27 2026-10-05, the foreign-line budget 2026-10-07/09, seal schema v2) would each need a rework before it could merge. Closed in the PR sweep of 2026-10-19 on the owner's decision (stale drafts from before 2026-10-10); reopen it if the work is still wanted. 🤖 Generated with Claude Code |
Closes #7319
Closes #2645
Part of #5980
What was wrong
#7319. The number lexer takes any run of digits,
.,x X b B _(and hex letters after0x) as one number, and gen-c wrote what it read. So010and0_10reached C as the octal constant 8 (a test assertingD == 10compiled and trapped),08and0b102did not compile, and1_,1__0and0x_1Fwere quietly normalized. All exited 0.#2645.
0o17lexed as the number0followed by the identifiero17, soconst E: u32 = 0o777;was0. The issue text says this was fixed; on master the probe still writes#define D 0.What changes
_that is not between two digits, two decimal points, a letter inside a decimal. Example:malformed number literal `010` at line 2:16: a leading zero; C reads it as an octal constant (write `0o` for octal).RUST-04) or a tuple index is not a literal, and the token stream is unchanged, so the lexer conformance table (lex_conform.rs) still holds._before the suffix:10_usize,2.0_f64and0x7FFFFFFF_i32are in the corpus and still pass.0xbefore a non-hex letter (0xT27B007, the corpus item The lexer turns 0o777 into 0; and the nested-literal group needs the parser, not the emitter #2645 lists) is unchanged.0odirectly after a lone leading0as octal. No two backends spell octal alike (C017, Zig and Rust0o17, Verilog none), so a well-formed octal literal is handed on as the decimal it denotes, suffix kept;0o18,0o_7,0o7_and0oare refused by name.The self-hosted core keeps refusing all of these with E_LEX (including
0o); gen-c now refuses them too, or (for octal) writes the right value, so nothing the core accepts changes.Tests
bootstrap/tests/genc_number_literals.rs, 8 tests: the issue's seven literals refused by name and line; the issue's seven well-formed literals pass and are written as C reads them; fractions and exponents pass; more misplaced separators and foreign digits refused; typed literals and aRUST-04module segment pass; octal values (0o17= 15,0o1_7,0o0,0o777= 511); malformed octal refused; and a generated test that asserts10,0o777 == 511and1_000 == 1000is compiled and run.Lab (t27c-lab): 8 passed on this branch; with
compiler.rsandFROZEN_HASHreverted to master, 5 failed (the 3 that pass there are the guards for forms that already worked).core_selfhostpasses (fixpoint, fixtures, refusals, corpus differential); the compiler's own unit tests pass (1845).Corpus
t27c gen-cover every tracked spec underspecs/, master binary vs this branch: 0 outputs change. No reseal is needed and no seal goes stale.t27c parseover all 1686 tracked.t27files, master vs branch: 6 go from parsing to refused, all of thembootstrap/tests/fixtures/core_selfhost/refuse/e1_*.t27, the core's own refusal fixtures for exactly these literals (0b102,1__0,010,0_10,0x_1F,1_). No spec underspecs/stops parsing. (A first cut that checked every number token also refused prose and module names in 7 specs,4x4in a bench description,RUST-04,1.2.3inside a mis-escaped string; checking only value sites fixed that, and the typed-suffix rule kept10_usizeand friends.)Foreign code
This edits Rust (
bootstrap/src/compiler.rs+ itsFROZEN_HASHseal, and a new test file), so it carriesowner-approved-foreignand atools/policy/foreign-exceptions.txtentry naming #7319 and #2645.🤖 Generated with Claude Code