ir: convert remaining s64 var-init fallbacks + fix stale s64 sentinel checks

Var-init placeholders that could leak when a lookup failed now init to
.unresolved: struct field-not-found (lowerFieldAccess/store), match payload
variant-not-found, deref-of-non-pointer pointee, array-literal element type.

Also fixes checks that used .s64 as the "resolution failed" sentinel and broke
when the producing functions started returning .unresolved instead:
- array-literal: `resolved != .s64` -> `!= .unresolved`.
- parameterized type-alias registration and pack-fn return-type resolution:
  `!= .s64` -> `!= .unresolved` (also fixes a latent bug where a genuine
  `s64` alias / `-> s64` return was treated as a failure).
- the variadic Any-boxing refinement (infer, then upgrade via getRefType) now
  triggers on .unresolved, not .s64, matching the honest inferExprType.

Every silent s64 fallback in the codebase is now gone; only genuine s64<->name
mappings and the defined int-literal/tag-width defaults remain. 236 + unit green.
This commit is contained in:
agra
2026-05-30 00:54:07 +03:00
parent f21b99c811
commit 3731a200c3

View File

@@ -665,7 +665,7 @@ pub const Lowering = struct {
// under the alias name so `Vec4` in expression // under the alias name so `Vec4` in expression
// position can `const_type(<vector tid>)`. // position can `const_type(<vector tid>)`.
const result_ty = type_bridge.resolveAstType(cd.value, &self.module.types); const result_ty = type_bridge.resolveAstType(cd.value, &self.module.types);
if (result_ty != .void and result_ty != .s64) { if (result_ty != .void and result_ty != .unresolved) {
self.type_alias_map.put(cd.name, result_ty) catch {}; self.type_alias_map.put(cd.name, result_ty) catch {};
} }
} }
@@ -1904,7 +1904,7 @@ pub const Lowering = struct {
const struct_fields = self.getStructFields(obj_ty); const struct_fields = self.getStructFields(obj_ty);
var field_idx: u32 = 0; var field_idx: u32 = 0;
var field_ty: TypeId = .s64; var field_ty: TypeId = .unresolved;
for (struct_fields, 0..) |f, i| { for (struct_fields, 0..) |f, i| {
if (f.name == field_name_id) { if (f.name == field_name_id) {
field_idx = @intCast(i); field_idx = @intCast(i);
@@ -3636,7 +3636,7 @@ pub const Lowering = struct {
} else { } else {
// Resolve actual variant index and payload type from the subject's type // Resolve actual variant index and payload type from the subject's type
var variant_idx: u32 = @intCast(i); var variant_idx: u32 = @intCast(i);
var payload_ty: TypeId = .s64; var payload_ty: TypeId = .unresolved;
if (arm.pattern) |arm_pat| { if (arm.pattern) |arm_pat| {
const pat_name = switch (arm_pat.data) { const pat_name = switch (arm_pat.data) {
.enum_literal => |el| el.name, .enum_literal => |el| el.name,
@@ -4664,14 +4664,14 @@ pub const Lowering = struct {
defer elems.deinit(self.alloc); defer elems.deinit(self.alloc);
// Determine element type: explicit type_expr > target_type > inference // Determine element type: explicit type_expr > target_type > inference
var elem_ty: TypeId = .s64; var elem_ty: TypeId = .unresolved;
var from_target = false; var from_target = false;
var is_vector = false; var is_vector = false;
// First, check explicit type annotation on the literal (e.g. Vector(3,f32).[1,2,3]) // First, check explicit type annotation on the literal (e.g. Vector(3,f32).[1,2,3])
if (al.type_expr) |te| { if (al.type_expr) |te| {
const resolved = self.resolveArrayLiteralType(te); const resolved = self.resolveArrayLiteralType(te);
if (resolved != .s64) { if (resolved != .unresolved) {
if (!resolved.isBuiltin()) { if (!resolved.isBuiltin()) {
const info = self.module.types.get(resolved); const info = self.module.types.get(resolved);
switch (info) { switch (info) {
@@ -4965,7 +4965,7 @@ pub const Lowering = struct {
const ptr = self.lowerExpr(de.operand); const ptr = self.lowerExpr(de.operand);
// Resolve pointee type from the pointer type // Resolve pointee type from the pointer type
const ptr_ty = self.inferExprType(de.operand); const ptr_ty = self.inferExprType(de.operand);
var pointee_ty: TypeId = .s64; var pointee_ty: TypeId = .unresolved;
if (!ptr_ty.isBuiltin()) { if (!ptr_ty.isBuiltin()) {
const info = self.module.types.get(ptr_ty); const info = self.module.types.get(ptr_ty);
if (info == .pointer) { if (info == .pointer) {
@@ -7740,7 +7740,7 @@ pub const Lowering = struct {
const field_name_id = self.module.types.internString(fa.field); const field_name_id = self.module.types.internString(fa.field);
const struct_fields = self.getStructFields(obj_ty); const struct_fields = self.getStructFields(obj_ty);
var field_idx: u32 = 0; var field_idx: u32 = 0;
var field_ty: TypeId = .s64; var field_ty: TypeId = .unresolved;
for (struct_fields, 0..) |f, fi| { for (struct_fields, 0..) |f, fi| {
if (f.name == field_name_id) { if (f.name == field_name_id) {
field_idx = @intCast(fi); field_idx = @intCast(fi);
@@ -8191,7 +8191,7 @@ pub const Lowering = struct {
var val = self.lowerExpr(arg); var val = self.lowerExpr(arg);
var source_ty = self.inferExprType(arg); var source_ty = self.inferExprType(arg);
// If AST-based inference falls back to .s64 but the lowered ref is a string/struct, use that // If AST-based inference falls back to .s64 but the lowered ref is a string/struct, use that
if (source_ty == .s64) { if (source_ty == .unresolved) {
const ref_ty = self.builder.getRefType(val); const ref_ty = self.builder.getRefType(val);
if (ref_ty == .string or ref_ty == .f32 or ref_ty == .f64 or ref_ty == .bool) { if (ref_ty == .string or ref_ty == .f32 or ref_ty == .f64 or ref_ty == .bool) {
source_ty = ref_ty; source_ty = ref_ty;
@@ -8336,9 +8336,9 @@ pub const Lowering = struct {
if (is_any) { if (is_any) {
var source_ty = self.inferExprType(c.args[fixed_count + i]); var source_ty = self.inferExprType(c.args[fixed_count + i]);
// If AST-based inference falls back to .s64 but the lowered ref has a richer type, use that // If AST-based inference falls back to .s64 but the lowered ref has a richer type, use that
if (source_ty == .s64) { if (source_ty == .unresolved) {
const ref_ty = self.builder.getRefType(val); const ref_ty = self.builder.getRefType(val);
if (ref_ty != .s64 and ref_ty != .void) source_ty = ref_ty; if (ref_ty != .unresolved and ref_ty != .void) source_ty = ref_ty;
} }
// Auto-unwrap optionals: box inner value if present, else box string "null" // Auto-unwrap optionals: box inner value if present, else box string "null"
if (!source_ty.isBuiltin()) { if (!source_ty.isBuiltin()) {
@@ -8606,7 +8606,7 @@ pub const Lowering = struct {
const ret_ty: TypeId = blk: { const ret_ty: TypeId = blk: {
if (fd.return_type) |rt| { if (fd.return_type) |rt| {
if (rt.data == .type_expr) { if (rt.data == .type_expr) {
if (type_bridge.resolveAstType(rt, &self.module.types) != .s64) { if (type_bridge.resolveAstType(rt, &self.module.types) != .unresolved) {
break :blk type_bridge.resolveAstType(rt, &self.module.types); break :blk type_bridge.resolveAstType(rt, &self.module.types);
} }
} }