| author | |
| committer | |
| log | eedfce92b0363af1b6783ab626690be0aebf4e94 |
| tree | 46737c202817453f4ebe2bcbf529b29c51946d09 |
| parent | 7b9e482ed6aaf9c1ec25970f599ae8f7ef83ad47 |
| signature |
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| ... | @@ -31031,20 +31031,17 @@ fn coerceInMemoryAllowedFns( | ... | @@ -31031,20 +31031,17 @@ fn coerceInMemoryAllowedFns( |
| 31031 | } }; | 31031 | } }; |
| 31032 | } | 31032 | } |
| 31033 | 31033 | ||
| 31034 | switch (src_param_ty.toIntern()) { | 31034 | if (!src_param_ty.isGenericPoison() and !dest_param_ty.isGenericPoison()) { |
| 31035 | .generic_poison_type => {}, | 31035 | // Note: Cast direction is reversed here. |
| 31036 | else => { | 31036 | const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, dest_is_mut, target, dest_src, src_src, null); |
| 31037 | // Note: Cast direction is reversed here. | 31037 | if (param != .ok) { |
| 31038 | const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, dest_is_mut, target, dest_src, src_src, null); | 31038 | return .{ .fn_param = .{ |
| 31039 | if (param != .ok) { | 31039 | .child = try param.dupe(sema.arena), |
| 31040 | return .{ .fn_param = .{ | 31040 | .actual = src_param_ty, |
| 31041 | .child = try param.dupe(sema.arena), | 31041 | .wanted = dest_param_ty, |
| 31042 | .actual = src_param_ty, | 31042 | .index = param_i, |
| 31043 | .wanted = dest_param_ty, | 31043 | } }; |
| 31044 | .index = param_i, | 31044 | } |
| 31045 | } }; | ||
| 31046 | } | ||
| 31047 | }, | ||
| 31048 | } | 31045 | } |
| 31049 | } | 31046 | } |
| 31050 | 31047 |
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 | } |