From 8681b72b47df2dfbe8c49281db5a4d91ed8c07ab Mon Sep 17 00:00:00 2001 From: agra Date: Fri, 29 May 2026 22:53:53 +0300 Subject: [PATCH] ir: type-resolution fallbacks return .unresolved, not .s64 (batch A) resolveFieldType (field-not-found, tuple OOB/parse-fail), getElementType (element-of-a-non-collection), resolveArrayLiteralType, and the named-type lookup in the type-call resolver all guessed .s64 when resolution failed -- the issue-0042 silent-default class. Return .unresolved so a genuine resolution failure surfaces (and trips the sizeOf/toLLVMType panic) instead of fabricating an 8-byte int. Genuine results (.len => .s64) unchanged. --- src/ir/lower.zig | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/ir/lower.zig b/src/ir/lower.zig index b1e8d6a..e1abdc8 100644 --- a/src/ir/lower.zig +++ b/src/ir/lower.zig @@ -4094,17 +4094,17 @@ pub const Lowering = struct { } // Try numeric index const idx = std.fmt.parseInt(usize, field, 10) catch { - return .s64; + return .unresolved; }; if (idx < tuple.fields.len) return tuple.fields[idx]; - return .s64; + return .unresolved; } } const struct_fields = self.getStructFields(ty); for (struct_fields) |f| { if (f.name == field_name_id) return f.ty; } - return .s64; + return .unresolved; } fn lowerFieldAccess(self: *Lowering, fa: *const ast.FieldAccess, span: ast.Span) Ref { @@ -4720,7 +4720,7 @@ pub const Lowering = struct { const callee_name = switch (cl.callee.data) { .identifier => |id| id.name, .field_access => |fa| fa.field, - else => return .s64, + else => return .unresolved, }; if (std.mem.eql(u8, callee_name, "Vector")) { if (cl.args.len == 2) { @@ -4736,20 +4736,20 @@ pub const Lowering = struct { if (self.struct_template_map.getPtr(callee_name)) |tmpl| { return self.instantiateGenericStruct(tmpl, cl.args); } - return .s64; + return .unresolved; }, .parameterized_type_expr => |pt| return self.resolveParameterizedWithBindings(&pt), .identifier => |id| { const name_id = self.module.types.internString(id.name); - return self.module.types.findByName(name_id) orelse .s64; + return self.module.types.findByName(name_id) orelse .unresolved; }, .type_expr => return type_bridge.resolveAstType(te, &self.module.types), .field_access => |fa| { // Module.Type — try to resolve the field as a type name const name_id = self.module.types.internString(fa.field); - return self.module.types.findByName(name_id) orelse .s64; + return self.module.types.findByName(name_id) orelse .unresolved; }, - else => return .s64, + else => return .unresolved, } } @@ -11118,7 +11118,7 @@ pub const Lowering = struct { } // Try as a named type const name_id = self.module.types.internString(callee_name); - return self.module.types.findByName(name_id) orelse .s64; + return self.module.types.findByName(name_id) orelse .unresolved; } /// Resolve a parameterized type expr, substituting bindings for type/value params. @@ -13979,17 +13979,19 @@ pub const Lowering = struct { return null; } - /// Get the element type for a slice/array/string type. Returns .s64 for unknown types. + /// Get the element type for a slice/array/string type. A non-collection + /// type has no element type — return `.unresolved` (asking for it is a bug) + /// rather than a plausible `.s64`. fn getElementType(self: *Lowering, ty: TypeId) TypeId { if (ty == .string) return .u8; - if (ty.isBuiltin()) return .s64; + if (ty.isBuiltin()) return .unresolved; const info = self.module.types.get(ty); return switch (info) { .slice => |s| s.element, .array => |a| a.element, .vector => |v| v.element, .many_pointer => |p| p.element, - else => .s64, + else => .unresolved, }; }