Skip to content

Commit 26fdb81

Browse files
committed
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
1 parent 98640cb commit 26fdb81

File tree

2 files changed

+35
-14
lines changed

2 files changed

+35
-14
lines changed

src/Sema.zig

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30422,20 +30422,17 @@ fn coerceInMemoryAllowedFns(
3042230422
} };
3042330423
}
3042430424

30425-
switch (src_param_ty.toIntern()) {
30426-
.generic_poison_type => {},
30427-
else => {
30428-
// Note: Cast direction is reversed here.
30429-
const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, dest_is_mut, target, dest_src, src_src, null);
30430-
if (param != .ok) {
30431-
return .{ .fn_param = .{
30432-
.child = try param.dupe(sema.arena),
30433-
.actual = src_param_ty,
30434-
.wanted = dest_param_ty,
30435-
.index = param_i,
30436-
} };
30437-
}
30438-
},
30425+
if (!src_param_ty.isGenericPoison() and !dest_param_ty.isGenericPoison()) {
30426+
// Note: Cast direction is reversed here.
30427+
const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, dest_is_mut, target, dest_src, src_src, null);
30428+
if (param != .ok) {
30429+
return .{ .fn_param = .{
30430+
.child = try param.dupe(sema.arena),
30431+
.actual = src_param_ty,
30432+
.wanted = dest_param_ty,
30433+
.index = param_i,
30434+
} };
30435+
}
3043930436
}
3044030437
}
3044130438

test/behavior/fn.zig

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,3 +732,27 @@ test "inline function return type is evaluated at comptime" {
732732
comptime assert(@TypeOf(result) == u16);
733733
try expect(result == 123);
734734
}
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+
}

0 commit comments

Comments
 (0)