Surface rename of the signed integer family: s1..s64 become i1..i64
(u1..u64, usize, isize unchanged). 'string' keeps the s-prefix arm in
name classification; width parsing moves to the i-prefix arm next to
isize.
Internal TypeId tags follow the surface (.s8/.s16/.s32/.s64 ->
.i8/.i16/.i32/.i64), as do mono-key mangle fragments (ptr_i64,
tu_i64_bool) and all display/diagnostic formatting (i{d}).
Migrated in the same sweep: stdlib + examples + issue repros + FFI C
companions (shared symbol names like ffi_id_i64), expected
stdout/stderr/ir snapshots, specs.md, readme.md, CLAUDE.md/AGENTS.md,
implementation_plan.md, docs/, issue writeups. Vendored stb_image and
historical flow state left untouched.
zig build test: 426/426; examples suite: 595/595.
3.6 KiB
0067 — tuple literal used as a type silently accepts non-type elements
RESOLVED (2026-06-02). Root cause:
type_bridge.resolveTupleLiteralAsTypetreated a tuple literal as a tuple TYPE and, for any element that wasn't type-shaped, emitted astd.debug.printand substituted.i64for that field — a silent fabricated type (the forbidden silent-fallback pattern). The stateful caller (Lowering.resolveTypeArg, used bysize_of) delegated.tuple_literalstraight to that path, sosize_of((i32, 1))compiled and printed16. Fix:
type_bridge.resolveTupleLiteralAsTypenow returns.unresolved(no.i64, no debug print) when any element is not type-shaped — it refuses to fabricate a tuple. (type_bridge is stateless, so this is the binding-free backstop.)- New stateful
Lowering.resolveTupleLiteralTypeArgvalidates each element viatype_bridge.isTypeShapedAstNode, emits a user-facing diagnostic at the offending element's span, and returns.unresolved. It is wired into BOTHresolveTypeArg(size_of/align_of/…) and theresolveTypeWithBindingsname-fallback; type_bridge builds the tuple only after validation passes. Regression test:examples/1116-diagnostics-tuple-type-nontype-element-rejected.sx(exit 1 + diagnostic). Valid(i32, i32)still works (examples/0115-types-compound-type-in-expression.sx). Suite 351/0.
Symptom
size_of((i32, 1)) treats the tuple literal as a tuple TYPE even though 1 is
not a type. The compiler prints an internal type_bridge debug line, then
silently substitutes .i64 for that slot and compiles successfully.
Observed:
type_bridge: tuple literal element is not a type (tag=int_literal) — cannot use as tuple type
bad tuple type size = 16
Expected: a user-facing compiler diagnostic rejecting the non-type tuple element, with no fabricated tuple type and no successful run.
Reproduction
#import "modules/std.sx";
main :: () -> i32 {
print("bad tuple type size = {}\n", size_of((i32, 1)));
0
}
Run:
./zig-out/bin/sx run .sx-tmp/probe-tuple-literal-type-fallback.sx
The repro is standalone; the inline source above is sufficient to recreate the
scratch file under .sx-tmp/.
Investigation prompt
Fix issue 0067: tuple literals reinterpreted as tuple types must reject non-type
elements instead of silently fabricating .i64 fields.
Suspected area:
src/ir/type_bridge.zig,resolveTupleLiteralAsType- The current non-type branch does
std.debug.print(...)andfield_ids.append(alloc, .i64), which violates the compiler fallback rules. - Related callers:
type_bridge.resolveAstTypefor.tuple_literal, andLowering.resolveTypeWithBindingsfallback paths that reachtype_bridge.
Likely fix:
- Replace the
.i64substitution with a real diagnostic path and an unmistakable failure result (.unresolved, or a nullable/result return that forces callers to handle the failure). - Make the diagnostic user-facing via the lowering diagnostics plumbing, not
std.debug.print. - Preserve the valid behavior pinned by
examples/0115-types-compound-type-in-expression.sx, where(i32, i32)in a type-demanding site resolves as a tuple type.
Verification:
- Add a focused diagnostics example in the
11xxblock forsize_of((i32, 1))expecting exit 1 and a clear diagnostic. - Run:
zig build
zig build test
bash tests/run_examples.sh
Expected result: the new invalid tuple-type repro fails with a diagnostic, the
valid 0115 tuple-type example still passes, and the full suite remains green.