Repository navigation
The lexer turns 0o777 into 0; and the nested-literal group needs the parser, not the emitter #2645
Description
Grouping walls by line shape (#2643) put 31 specs in a "const declaration"
group. It is four different defects, and the interesting one is not a wall at
all.
The lexer drops octal, silently
const E: u32 = 0o777; -> const E: u32 = 0;
The number lexer accepts x, X, b, B as prefixes and not o. So 0o777
lexes as 0 and o777 walks off as an identifier. A wrong value, compiled
without complaint — the worst thing a lexer can do.
Zero occurrences in this corpus. I found it with a synthetic probe while
checking the neighbouring hex case, and fixed it anyway: a silent wrong number
is not the same category as a missing optimisation, and the fix is one
condition. Stricter than the x/b branches beside it — only directly after a
leading zero — so nothing else changes. Measured: 142 valid, 102 asserting,
1153 errors, all unchanged, 0 regressed.
What const BOOT_MAGIC: u32 = 0x; actually is
Not an emitter bug. The spec says 0xT27B007 — T is not a hex digit, so the
lexer stops and emits 0x. Someone wrote a "T27" magic number in a hex literal.
4 such sites in 2 files: 0xT27B007 twice, and 0x3u32 / 0x2u32, which are
Rust's typed-literal syntax. Corpus items, listed for the record.
The 11 nested literals need parser work, and here is exactly why
var patterns = [ IgnorePattern { pattern = "node_modules", isDir = true } ]
reaches the emitter as
extra_size: "IgnorePattern{pattern=node_modules,isDir=true,},"
— the array-length field again (#2633), holding the whole nested literal as
text. Two things are wrong with it, and only one is fixable here:
- field names lack Zig's leading dot — fixable
- the string quotes are gone —
"node_modules"arrived asnode_modules
Recovering the quotes means guessing which bare words were strings. isDir=true
is a bool, node_modules is a string, and nothing in the text says so. Adding
the dots alone leaves an unquoted string and does not make one spec valid.
Not attempted. The information is destroyed before the emitter runs, so this is
a parser change — the nested literal must become nodes rather than lossy text —
and starting it blind is how #2596 went.
Remaining in the group
3 specs emit const = struct { with an empty name, 1 emits const dir = ;
with an empty value. Both look like the same parser loss and are unexamined.
Boundary
bootstrap/src/compiler.rs
User Scenarios
- Given a const declaration with an octal literal
const E: u32 = 0o777;, When the lexer processes it, Then it should produce the value 511 (0o777) not 0 - Given a nested struct literal with string fields like
IgnorePattern { pattern = "node_modules", isDir = true }, When the parser processes it, Then it should preserve string quotes and field structure as AST nodes, not lossy text
Requirements
- FR-001: The lexer MUST accept
oandOas octal prefixes immediately after a leading zero, with the same strictness asx/Xfor hex andb/Bfor binary - FR-002: The parser MUST represent nested struct and array literals as structured AST nodes preserving string literals, field names, and types, not as lossy text strings
Success Criteria
bootstrap/src/compiler.rscompiles andcargo testexits 0 with new octal lexer tests passingspecs/compiler/lexer.t27contains at least 5 tests covering octal literals (valid0o777,0O777, invalid0o888, prefix-only0o, mixed with hex/binary)- The nested literal parser changes make at least 11 previously failing specs in the "const declaration" group pass
Activity
fix(lexer): accept the octal prefix, which was silently producing zero
dmitrii-f-t27 commentedon Oct 3, 2026
The octal fix described here is not on master f88f759: the lexer prefix check at compiler.rs:868-874 still has no
o/O.const E: u32 = 0o777;emitsconst E: u32 = 0;in Zig and#define E 0in C, with exit 0. The nested-literal part was not re-measured.Checked with t27c 0.4.0 built from f88f759; commands and inputs available on request.
t27core: numeric literal forms and pub var, byte-identical to gen-c (C…
fix(t27c): refuse a malformed number literal by name, read 0o as octal (
gHashTag commentedon Oct 7, 2026
The fix in #7421 is parked as a draft: it is over the foreign-line budget (#7371). compiler.rs +159, tests +231, 390 in total, against limits of 40 per file and 80 per PR. Details are on #7421.