| author | |
| committer | |
| log | 26fdb81c16760b5aabbd1905ef96cefdf596fc3d |
| tree | 1468581a8ea931bdc0ae4ad1ca962b682ec95901 |
| parent | 98640cbeb8a714a451821a51f3aa4ebbd488d291 |
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: #210992 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 | } |
| 30424 | 30424 | ||
| 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 | } |
| 30441 | 30438 |
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 | |||
| 736 | test "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 | |||
| 748 | test "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 | } |