From b91b7f882c631293aa58e8615106f649ad787823 Mon Sep 17 00:00:00 2001 From: agra Date: Fri, 29 May 2026 22:33:47 +0300 Subject: [PATCH] ir: resolveAstType null-node returns .unresolved, not .s64 A null type node means a caller reached type resolution without a type node. Every current caller passes a non-optional node or handles the "no type" case itself (returning .void), so a null here is a caller bug; .s64 silently fabricated an 8-byte int. Return the .unresolved sentinel so it surfaces (trips the sizeOf/toLLVMType panic at codegen). The only thing relying on the old behavior was a unit test asserting null => .s64 -- i.e. a test pinning the silent default. Updated it to pin .unresolved. --- src/ir/type_bridge.test.zig | 4 ++-- src/ir/type_bridge.zig | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ir/type_bridge.test.zig b/src/ir/type_bridge.test.zig index 807adba..de2380a 100644 --- a/src/ir/type_bridge.test.zig +++ b/src/ir/type_bridge.test.zig @@ -102,12 +102,12 @@ test "resolveAstType: optional slice" { } } -test "resolveAstType: null returns default" { +test "resolveAstType: null surfaces as .unresolved (no silent s64 default)" { const alloc = std.testing.allocator; var table = TypeTable.init(alloc); defer table.deinit(); - try std.testing.expectEqual(TypeId.s64, type_bridge.resolveAstType(null, &table)); + try std.testing.expectEqual(TypeId.unresolved, type_bridge.resolveAstType(null, &table)); } test "resolveAstType: TypeTable.aliases resolves named alias" { diff --git a/src/ir/type_bridge.zig b/src/ir/type_bridge.zig index 91254d0..d497951 100644 --- a/src/ir/type_bridge.zig +++ b/src/ir/type_bridge.zig @@ -14,7 +14,12 @@ const StringId = ir_types.StringId; // we only have the parsed AST (no codegen type registry). pub fn resolveAstType(node: ?*const Node, table: *TypeTable) TypeId { - const n = node orelse return .s64; // no annotation → default + // A null node means a caller reached type resolution without a type node. + // Every current caller either passes a non-optional node or handles the + // "no type" case itself (returning `.void`), so this is a caller bug — and + // `.s64` here would silently fabricate an 8-byte int. Surface it via the + // `.unresolved` sentinel (trips the sizeOf/toLLVMType panic at codegen). + const n = node orelse return .unresolved; return switch (n.data) { .type_expr => |te| resolveTypeName(te.name, table), .identifier => |id| resolveTypeName(id.name, table),