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.
This commit is contained in:
agra
2026-05-29 22:33:47 +03:00
parent 171c694f6c
commit b91b7f882c
2 changed files with 8 additions and 3 deletions

View File

@@ -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" {

View File

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