Skip to content

Commit d7f3a73

Browse files
fix(codegen-rust): correct fixed-size array types and usize indices (#1457)
Second codegen fix after the optimizer removal. Makes the Rust backend emit correct array types and indices so generated modules compile under rustc. t27_type_to_rust: - `[T; N]` (Rust-style, element before `;`) previously took the empty suffix after `]` and emitted `Vec<>` -> E0107. Now emits `[T; N as usize]` (element parsed correctly; length cast to usize as arrays require). - Zig-style `[N]T` still lowers to `Vec<T>`. expr_to_rust (ExprIndex): - Array/Vec indices must be `usize`; t27 index expressions are u32. Non-literal indices now emit `[(idx) as usize]`. Integer literals are left uncast (they infer usize and casting them would trip clippy::unnecessary_cast). Verified: t27c suite unchanged at 1494 passed / 1 failed (the remaining failure is the pre-existing Verilog HIR let-binding test, untouched). Regenerating gHashTag/tri-net with #1456 + this drops the wired-module error count from 400+ to a handful of genuine SPEC bugs (a bool-vs-u32 return type, a Q8.8 fixed-point 256-in-u8 literal, a couple of `let`-that-should-be-`var`), i.e. the codegen itself now produces compiling Rust. FROZEN_HASH re-sealed (M5). phi^2 + phi^-2 = 3
1 parent 4a4af13 commit d7f3a73

2 files changed

Lines changed: 27 additions & 11 deletions

File tree

bootstrap/src/compiler.rs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8079,12 +8079,21 @@ impl RustCodegen {
80798079
format!("Vec<{}>", Self::t27_type_to_rust(inner))
80808080
}
80818081
t if t.starts_with('[') && t.contains(']') => {
8082-
// [N]T format - convert to Vec
8083-
if let Some(bracket_end) = t.find(']') {
8084-
let inner = &t[bracket_end + 1..];
8085-
format!("Vec<{}>", Self::t27_type_to_rust(inner))
8082+
let end = t.rfind(']').unwrap();
8083+
let inside = &t[1..end];
8084+
if let Some(semi) = inside.find(';') {
8085+
// Rust-style fixed-size array `[T; N]`: element before `;`,
8086+
// size after. (Previously only the Zig-style `[N]T` form was
8087+
// handled; `[T; N]` took the empty suffix after `]` and emitted
8088+
// `Vec<>` -> E0107. #1457.) Array lengths must be `usize`, and
8089+
// spec size consts are u32, so cast in the const-expr position.
8090+
let elem = inside[..semi].trim();
8091+
let size = inside[semi + 1..].trim();
8092+
format!("[{}; {} as usize]", Self::t27_type_to_rust(elem), size)
80868093
} else {
8087-
t.to_string()
8094+
// Zig-style `[N]T`: size in brackets, element after `]`.
8095+
let after = &t[end + 1..];
8096+
format!("Vec<{}>", Self::t27_type_to_rust(after))
80888097
}
80898098
}
80908099
t => t.to_string(), // Custom type name
@@ -8167,11 +8176,18 @@ impl RustCodegen {
81678176
}
81688177
NodeKind::ExprIndex => {
81698178
if node.children.len() >= 2 {
8170-
format!(
8171-
"{}[{}]",
8172-
Self::expr_to_rust(&node.children[0]),
8173-
Self::expr_to_rust(&node.children[1])
8174-
)
8179+
let base = Self::expr_to_rust(&node.children[0]);
8180+
let idx = &node.children[1];
8181+
let idx_str = Self::expr_to_rust(idx);
8182+
// Array/Vec indices must be `usize`. t27 index expressions are
8183+
// u32, so cast non-literal indices. Integer literals already
8184+
// infer `usize` in index position, so casting them would trip
8185+
// clippy::unnecessary_cast under `-D warnings`. #1457.
8186+
if idx.kind == NodeKind::ExprLiteral {
8187+
format!("{}[{}]", base, idx_str)
8188+
} else {
8189+
format!("{}[({}) as usize]", base, idx_str)
8190+
}
81758191
} else {
81768192
"()".to_string()
81778193
}

bootstrap/stage0/FROZEN_HASH

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6eb632b838e907f160934965972f408839d8bb2916e0447c0c1bade5bda98b18 bootstrap/src/compiler.rs
1+
c25b7a6f4e2fca73607b4eb8dac697964b57071b2ba1e2d59997aca82a39d138 bootstrap/src/compiler.rs

0 commit comments

Comments
 (0)