authorgravatar for rmehri01@tutamail.comRyan Mehri <rmehri01@tutamail.com> 2026-06-18 20:33:35-04:00
committergravatar for justusk@noreply.codeberg.orgJustus Klausecker <justusk@noreply.codeberg.org> 2026-06-24 14:24:34+02:00
logefe73c787a89f71de37bf876c3ef7bcfddebebba
treed8066be93c8e15630441b431add55d212bff630f
parent7208ca510cbab5d91c566c053b27f554617cfe16

Sema: also do comptime check on bound arg

Currently, if there is a bound arg then `analyzeArg` will break out of the uncoerced arg block immediately without checking if the bound arg is not comptime known despite the block or parameter being comptime. This makes it so that we do the same checks on the bound and regular args but only do resolution on regular args.

2 files changed, 43 insertions(+), 21 deletions(-)

src/Sema.zig+21-21
...@@ -6468,22 +6468,6 @@ const CallArgsInfo = union(enum) {...@@ -6468,22 +6468,6 @@ const CallArgsInfo = union(enum) {
6468 const uncoerced_arg: Air.Inst.Ref = switch (cai) {6468 const uncoerced_arg: Air.Inst.Ref = switch (cai) {
6469 inline .resolved, .call_builtin => |resolved| resolved.args[arg_index],6469 inline .resolved, .call_builtin => |resolved| resolved.args[arg_index],
6470 .zir_call => |zir_call| arg_val: {6470 .zir_call => |zir_call| arg_val: {
6471 const has_bound_arg = zir_call.bound_arg != .none;
6472 if (arg_index == 0 and has_bound_arg) {
6473 break :arg_val zir_call.bound_arg;
6474 }
6475 const real_arg_idx = arg_index - @intFromBool(has_bound_arg);
6476
6477 const arg_body = if (real_arg_idx == 0) blk: {
6478 const start = zir_call.num_args;
6479 const end = @intFromEnum(zir_call.args_body[0]);
6480 break :blk zir_call.args_body[start..end];
6481 } else blk: {
6482 const start = @intFromEnum(zir_call.args_body[real_arg_idx - 1]);
6483 const end = @intFromEnum(zir_call.args_body[real_arg_idx]);
6484 break :blk zir_call.args_body[start..end];
6485 };
6486
6487 // Generate args to comptime params in comptime block6471 // Generate args to comptime params in comptime block
6488 const parent_comptime = block.comptime_reason;6472 const parent_comptime = block.comptime_reason;
6489 defer block.comptime_reason = parent_comptime;6473 defer block.comptime_reason = parent_comptime;
...@@ -6505,11 +6489,27 @@ const CallArgsInfo = union(enum) {...@@ -6505,11 +6489,27 @@ const CallArgsInfo = union(enum) {
6505 };6489 };
6506 }6490 }
6507 }6491 }
6508 // Give the arg its result type6492
6509 const provide_param_ty: Type = maybe_param_ty orelse .generic_poison;6493 const has_bound_arg = zir_call.bound_arg != .none;
6510 sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(provide_param_ty.toIntern()));6494 const uncoerced_arg = if (arg_index == 0 and has_bound_arg) zir_call.bound_arg else arg: {
6511 // Resolve the arg!6495 const real_arg_idx = arg_index - @intFromBool(has_bound_arg);
6512 const uncoerced_arg = try sema.resolveInlineBody(block, arg_body, zir_call.call_inst);6496
6497 const arg_body = if (real_arg_idx == 0) blk: {
6498 const start = zir_call.num_args;
6499 const end = @intFromEnum(zir_call.args_body[0]);
6500 break :blk zir_call.args_body[start..end];
6501 } else blk: {
6502 const start = @intFromEnum(zir_call.args_body[real_arg_idx - 1]);
6503 const end = @intFromEnum(zir_call.args_body[real_arg_idx]);
6504 break :blk zir_call.args_body[start..end];
6505 };
6506
6507 // Give the arg its result type
6508 const provide_param_ty: Type = maybe_param_ty orelse .generic_poison;
6509 sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(provide_param_ty.toIntern()));
6510 // Resolve the arg!
6511 break :arg try sema.resolveInlineBody(block, arg_body, zir_call.call_inst);
6512 };
65136513
6514 if (block.isComptime() and !try sema.isComptimeKnown(uncoerced_arg)) {6514 if (block.isComptime() and !try sema.isComptimeKnown(uncoerced_arg)) {
6515 return sema.failWithNeededComptime(block, cai.argSrc(block, arg_index), null);6515 return sema.failWithNeededComptime(block, cai.argSrc(block, arg_index), null);
test/cases/compile_errors/runtime_bound_arg_with_comptime_param.zig created+22
...@@ -0,0 +1,22 @@
1pub const A = enum {
2 a1,
3 a2,
4
5 pub fn x(comptime _: A) usize {
6 return 0;
7 }
8
9 pub fn y(self: A) usize {
10 return self.x();
11 }
12};
13
14pub fn main() void {
15 _ = A.y(.a1);
16}
17
18// error
19//
20// :10:20: error: unable to resolve comptime value
21// :10:20: note: argument to comptime parameter must be comptime-known
22// :5:14: note: parameter declared comptime here