Sema: fix in-memory coercion of functions introducing new generic parameters

While it is not allowed for a function coercion to change whether a
function is generic, it *is* okay to make existing concrete parameters
of a generic function also generic, or vice versa. Either of these cases
implies that the result is a generic function, so comptime type checks
will happen when the function is ultimately called.

Resolves: #21099
This commit is contained in:
mlugg 2025-03-22 01:58:13 +00:00 committed by Matthew Lugg
parent 98640cbeb8
commit 26fdb81c16
2 changed files with 35 additions and 14 deletions

View File

@ -30422,20 +30422,17 @@ fn coerceInMemoryAllowedFns(
} };
}
switch (src_param_ty.toIntern()) {
.generic_poison_type => {},
else => {
// Note: Cast direction is reversed here.
const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, dest_is_mut, target, dest_src, src_src, null);
if (param != .ok) {
return .{ .fn_param = .{
.child = try param.dupe(sema.arena),
.actual = src_param_ty,
.wanted = dest_param_ty,
.index = param_i,
} };
}
},
if (!src_param_ty.isGenericPoison() and !dest_param_ty.isGenericPoison()) {
// Note: Cast direction is reversed here.
const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, dest_is_mut, target, dest_src, src_src, null);
if (param != .ok) {
return .{ .fn_param = .{
.child = try param.dupe(sema.arena),
.actual = src_param_ty,
.wanted = dest_param_ty,
.index = param_i,
} };
}
}
}

View File

@ -732,3 +732,27 @@ test "inline function return type is evaluated at comptime" {
comptime assert(@TypeOf(result) == u16);
try expect(result == 123);
}
test "coerce generic function making concrete parameter generic" {
const S = struct {
fn foo(_: anytype, x: u32) u32 {
comptime assert(@TypeOf(x) == u32);
return x;
}
};
const coerced: fn (anytype, anytype) u32 = S.foo;
const result = coerced({}, 123);
try expect(result == 123);
}
test "coerce generic function making generic parameter concrete" {
const S = struct {
fn foo(_: anytype, x: anytype) u32 {
comptime assert(@TypeOf(x) == u32);
return x;
}
};
const coerced: fn (anytype, u32) u32 = S.foo;
const result = coerced({}, 123);
try expect(result == 123);
}