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),