ir: type value-pack mono params from lowered args, not pre-lowering inference
lowerPackFnCall computed pack arg types via inferExprType *before* lowering the args, then lowered them anyway. For a value-pack (..xs: P) the lowered value has an authoritative concrete type, so take the pack type from getRefType of the lowered Ref instead of a speculative inferExprType guess -- this removes the dependency that made a monomorphised pack param able to end up wrong/.unresolved from incomplete static inference. Comptime ..$args packs keep inferExprType (their args may be type-position). Also drops the dead runtime_arg_types list (collected, never read). 236/236 green.
This commit is contained in:
@@ -8933,33 +8933,56 @@ pub const Lowering = struct {
|
|||||||
// value into the mangle (NOT a runtime IR param).
|
// value into the mangle (NOT a runtime IR param).
|
||||||
// - pack param (always last) → consume the remaining call args
|
// - pack param (always last) → consume the remaining call args
|
||||||
// as the pack expansion.
|
// as the pack expansion.
|
||||||
var runtime_arg_types = std.ArrayList(TypeId).empty;
|
|
||||||
defer runtime_arg_types.deinit(self.alloc);
|
|
||||||
var pack_arg_types = std.ArrayList(TypeId).empty;
|
var pack_arg_types = std.ArrayList(TypeId).empty;
|
||||||
defer pack_arg_types.deinit(self.alloc);
|
defer pack_arg_types.deinit(self.alloc);
|
||||||
var pack_start: usize = call_node.args.len;
|
var pack_start: usize = call_node.args.len;
|
||||||
// Constraint protocol of the pack param (`..xs: P`), if any. The
|
// Constraint protocol of the pack param (`..xs: P`), if any. The
|
||||||
// comptime type-pack `..$args` has no constraint to check.
|
// comptime type-pack `..$args` has no constraint to check.
|
||||||
var pack_protocol: ?[]const u8 = null;
|
var pack_protocol: ?[]const u8 = null;
|
||||||
var fi: usize = 0;
|
var pack_is_comptime = false;
|
||||||
for (fd.params) |p| {
|
{
|
||||||
if (isPackParam(p)) {
|
var fi: usize = 0;
|
||||||
pack_start = fi;
|
for (fd.params) |p| {
|
||||||
if (p.is_pack and p.type_expr.data == .type_expr) {
|
if (isPackParam(p)) {
|
||||||
pack_protocol = p.type_expr.data.type_expr.name;
|
pack_start = fi;
|
||||||
|
pack_is_comptime = p.is_comptime;
|
||||||
|
if (p.is_pack and p.type_expr.data == .type_expr) {
|
||||||
|
pack_protocol = p.type_expr.data.type_expr.name;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
if (fi >= call_node.args.len) break;
|
||||||
|
fi += 1;
|
||||||
}
|
}
|
||||||
if (fi >= call_node.args.len) break;
|
|
||||||
if (!p.is_comptime) {
|
|
||||||
runtime_arg_types.append(self.alloc, self.inferExprType(call_node.args[fi])) catch return self.builder.constInt(0, .void);
|
|
||||||
}
|
|
||||||
// Comptime non-pack: consumed but not added to runtime types.
|
|
||||||
fi += 1;
|
|
||||||
}
|
}
|
||||||
if (pack_start <= call_node.args.len) {
|
|
||||||
for (call_node.args[pack_start..]) |a| {
|
// Lower the runtime prefix args and the pack args up front, taking each
|
||||||
|
// pack type from the lowered value (`getRefType`) rather than a
|
||||||
|
// pre-lowering `inferExprType` guess: a lowered value always has a
|
||||||
|
// concrete type, so a monomorphised pack param can never end up
|
||||||
|
// `.unresolved` from incomplete static inference. (A comptime `..$args`
|
||||||
|
// pack still uses `inferExprType` — its args may be type-position.)
|
||||||
|
var args = std.ArrayList(Ref).empty;
|
||||||
|
defer args.deinit(self.alloc);
|
||||||
|
{
|
||||||
|
var ri: usize = 0;
|
||||||
|
for (fd.params) |p| {
|
||||||
|
if (isPackParam(p)) break;
|
||||||
|
if (ri >= call_node.args.len) break;
|
||||||
|
if (!p.is_comptime) {
|
||||||
|
args.append(self.alloc, self.lowerExpr(call_node.args[ri])) catch return self.builder.constInt(0, .void);
|
||||||
|
}
|
||||||
|
ri += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (call_node.args[pack_start..]) |a| {
|
||||||
|
if (pack_is_comptime) {
|
||||||
|
args.append(self.alloc, self.lowerExpr(a)) catch return self.builder.constInt(0, .void);
|
||||||
pack_arg_types.append(self.alloc, self.inferExprType(a)) catch return self.builder.constInt(0, .void);
|
pack_arg_types.append(self.alloc, self.inferExprType(a)) catch return self.builder.constInt(0, .void);
|
||||||
|
} else {
|
||||||
|
const r = self.lowerExpr(a);
|
||||||
|
args.append(self.alloc, r) catch return self.builder.constInt(0, .void);
|
||||||
|
pack_arg_types.append(self.alloc, self.builder.getRefType(r)) catch return self.builder.constInt(0, .void);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9007,23 +9030,6 @@ pub const Lowering = struct {
|
|||||||
self.monomorphizePackFn(fd, mangled, pack_arg_types.items, call_node);
|
self.monomorphizePackFn(fd, mangled, pack_arg_types.items, call_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lower ONLY runtime args (skip comptime non-pack args; their
|
|
||||||
// values are folded into the mangle, not passed at runtime).
|
|
||||||
var args = std.ArrayList(Ref).empty;
|
|
||||||
defer args.deinit(self.alloc);
|
|
||||||
var ri: usize = 0;
|
|
||||||
for (fd.params) |p| {
|
|
||||||
if (isPackParam(p)) break;
|
|
||||||
if (ri >= call_node.args.len) break;
|
|
||||||
if (!p.is_comptime) {
|
|
||||||
args.append(self.alloc, self.lowerExpr(call_node.args[ri])) catch return self.builder.constInt(0, .void);
|
|
||||||
}
|
|
||||||
ri += 1;
|
|
||||||
}
|
|
||||||
for (call_node.args[pack_start..]) |a| {
|
|
||||||
args.append(self.alloc, self.lowerExpr(a)) catch return self.builder.constInt(0, .void);
|
|
||||||
}
|
|
||||||
|
|
||||||
const fid = self.resolveFuncByName(mangled) orelse return self.builder.constInt(0, .void);
|
const fid = self.resolveFuncByName(mangled) orelse return self.builder.constInt(0, .void);
|
||||||
const func = &self.module.functions.items[@intFromEnum(fid)];
|
const func = &self.module.functions.items[@intFromEnum(fid)];
|
||||||
const ret_ty = func.ret;
|
const ret_ty = func.ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user