diff --git a/NOW.md b/NOW.md index f23cf7d144..e5e1ba848f 100644 --- a/NOW.md +++ b/NOW.md @@ -2,6 +2,11 @@ Last updated: 2026-08-08 +## gen-rust: array literals emit elements, not empty vec![] (Closes #1938) + +- ExprArrayLiteral keeps element text in extra_size with no children; the Rust emitter mapped children only, so every spec array literal compiled to an empty Vec-typed vec![] (E0308 against a [T; N] return). Emits `[a, b, c]` / `[v; n]` from the text now, mirroring the Zig/C fixes +- FROZEN_HASH resealed + ## opt+gen-zig: typed aliases stay materialized; @"primitive" idents; unused tuple elements (Closes #1936) - copy_propagate ignored the declared type: `let lo: u16 = byte_param;` propagated the bare u8 identifier into every use, silently narrowing the arithmetic (u8 shift/add where the spec wrote u16 math) -- typed aliases are the widening idiom and are no longer propagated (all backends) diff --git a/bootstrap/src/compiler.rs b/bootstrap/src/compiler.rs index 01f45ecbf4..c790d2b6c0 100644 --- a/bootstrap/src/compiler.rs +++ b/bootstrap/src/compiler.rs @@ -14156,12 +14156,26 @@ impl RustCodegen { format!("{}({})", node.name, args.join(", ")) } NodeKind::ExprArrayLiteral => { - let elems: Vec = node - .children - .iter() - .map(|c| self.expr_to_rust(c)) - .collect(); - format!("vec![{}]", elems.join(", ")) + if node.children.is_empty() && !node.extra_size.trim().is_empty() { + // The parser stores the literal's ELEMENT TEXT in + // extra_size ("a,b,c" for a list, "v;n" for a repeat) + // with no children; emitting from children alone + // produced an empty (and Vec-typed) literal for a + // [T; N] return. Element text is valid Rust as-is. + let txt = node.extra_size.trim(); + if let Some((val, count)) = txt.rsplit_once(';') { + format!("[{}; {}]", val.trim(), count.trim()) + } else { + format!("[{}]", txt) + } + } else { + let elems: Vec = node + .children + .iter() + .map(|c| self.expr_to_rust(c)) + .collect(); + format!("[{}]", elems.join(", ")) + } } NodeKind::ExprTuple => { let elems: Vec = node diff --git a/bootstrap/stage0/FROZEN_HASH b/bootstrap/stage0/FROZEN_HASH index 928cce0ecc..4095f9a1ce 100644 --- a/bootstrap/stage0/FROZEN_HASH +++ b/bootstrap/stage0/FROZEN_HASH @@ -1 +1 @@ -686003784746e4fccdcf481f581adf533c03e7f5421e7d99975fb69b5c7e47ea +44c15f58d25650f0b0a4b3c89db3b844bdbb41b81040b01a8c7cd4b022f94bfd diff --git a/docs/NOW.md b/docs/NOW.md index e9af060e76..480ecdc9c7 100644 --- a/docs/NOW.md +++ b/docs/NOW.md @@ -2,6 +2,11 @@ Last updated: 2026-08-08 +## gen-rust: array literals emit elements, not empty vec![] (Closes #1938) + +- ExprArrayLiteral keeps element text in extra_size with no children; the Rust emitter mapped children only, so every spec array literal compiled to an empty Vec-typed vec![] (E0308 against a [T; N] return). Emits `[a, b, c]` / `[v; n]` from the text now, mirroring the Zig/C fixes +- FROZEN_HASH resealed + ## opt+gen-zig: typed aliases stay materialized; @"primitive" idents; unused tuple elements (Closes #1936) - copy_propagate ignored the declared type: `let lo: u16 = byte_param;` propagated the bare u8 identifier into every use, silently narrowing the arithmetic (u8 shift/add where the spec wrote u16 math) -- typed aliases are the widening idiom and are no longer propagated (all backends)