authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-03-22 01:58:13+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-03-24 04:32:45+00:00
log26fdb81c16760b5aabbd1905ef96cefdf596fc3d
tree1468581a8ea931bdc0ae4ad1ca962b682ec95901
parent98640cbeb8a714a451821a51f3aa4ebbd488d291

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

2 files changed, 35 insertions(+), 14 deletions(-)

src/Sema.zig+11-14
...@@ -30422,20 +30422,17 @@ fn coerceInMemoryAllowedFns(...@@ -30422,20 +30422,17 @@ fn coerceInMemoryAllowedFns(
30422 } };30422 } };
30423 }30423 }
3042430424
30425 switch (src_param_ty.toIntern()) {30425 if (!src_param_ty.isGenericPoison() and !dest_param_ty.isGenericPoison()) {
30426 .generic_poison_type => {},30426 // Note: Cast direction is reversed here.
30427 else => {30427 const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, dest_is_mut, target, dest_src, src_src, null);
30428 // Note: Cast direction is reversed here.30428 if (param != .ok) {
30429 const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, dest_is_mut, target, dest_src, src_src, null);30429 return .{ .fn_param = .{
30430 if (param != .ok) {30430 .child = try param.dupe(sema.arena),
30431 return .{ .fn_param = .{30431 .actual = src_param_ty,
30432 .child = try param.dupe(sema.arena),30432 .wanted = dest_param_ty,
30433 .actual = src_param_ty,30433 .index = param_i,
30434 .wanted = dest_param_ty,30434 } };
30435 .index = param_i,30435 }
30436 } };
30437 }
30438 },
30439 }30436 }
30440 }30437 }
3044130438
test/behavior/fn.zig+24
...@@ -732,3 +732,27 @@ test "inline function return type is evaluated at comptime" {...@@ -732,3 +732,27 @@ test "inline function return type is evaluated at comptime" {
732 comptime assert(@TypeOf(result) == u16);732 comptime assert(@TypeOf(result) == u16);
733 try expect(result == 123);733 try expect(result == 123);
734}734}
735
736test "coerce generic function making concrete parameter generic" {
737 const S = struct {
738 fn foo(_: anytype, x: u32) u32 {
739 comptime assert(@TypeOf(x) == u32);
740 return x;
741 }
742 };
743 const coerced: fn (anytype, anytype) u32 = S.foo;
744 const result = coerced({}, 123);
745 try expect(result == 123);
746}
747
748test "coerce generic function making generic parameter concrete" {
749 const S = struct {
750 fn foo(_: anytype, x: anytype) u32 {
751 comptime assert(@TypeOf(x) == u32);
752 return x;
753 }
754 };
755 const coerced: fn (anytype, u32) u32 = S.foo;
756 const result = coerced({}, 123);
757 try expect(result == 123);
758}