authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-05-10 12:27:59+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-05-11 12:23:57+03:00
log67afd2a470153681d3a2323ec388e3ecd545cef1
treebf56ba22e7df644571ff8faf071a2e5adb9519ab
parent73f283e3e2326c5c8a7f5b87de5c7eed7b7ea099

Sema: make `@call` compile errors match regular calls

Closes #15642

2 files changed, 118 insertions(+), 91 deletions(-)

src/Sema.zig+112-91
......@@ -5217,7 +5217,7 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.I
52175217 if (block.is_comptime) {
52185218 return sema.fail(block, src, "encountered @panic at comptime", .{});
52195219 }
5220 try sema.panicWithMsg(block, src, msg_inst);
5220 try sema.panicWithMsg(block, msg_inst);
52215221 return always_noreturn;
52225222}
52235223
......@@ -6295,7 +6295,6 @@ fn zirCall(
62956295 } else {
62966296 resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_len);
62976297 }
6298 const total_args = args_len + @boolToInt(bound_arg_src != null);
62996298
63006299 const callee_ty = sema.typeOf(func);
63016300 const func_ty = func_ty: {
......@@ -6311,45 +6310,16 @@ fn zirCall(
63116310 }
63126311 return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(sema.mod)});
63136312 };
6314 const func_ty_info = func_ty.fnInfo();
6315
6316 const fn_params_len = func_ty_info.param_types.len;
6317 check_args: {
6318 if (func_ty_info.is_var_args) {
6319 assert(func_ty_info.cc == .C);
6320 if (total_args >= fn_params_len) break :check_args;
6321 } else if (fn_params_len == total_args) {
6322 break :check_args;
6323 }
6324
6325 const maybe_decl = try sema.funcDeclSrc(func);
6326 const member_str = if (bound_arg_src != null) "member function " else "";
6327 const variadic_str = if (func_ty_info.is_var_args) "at least " else "";
6328 const msg = msg: {
6329 const msg = try sema.errMsg(
6330 block,
6331 func_src,
6332 "{s}expected {s}{d} argument(s), found {d}",
6333 .{
6334 member_str,
6335 variadic_str,
6336 fn_params_len - @boolToInt(bound_arg_src != null),
6337 args_len,
6338 },
6339 );
6340 errdefer msg.destroy(sema.gpa);
6341
6342 if (maybe_decl) |fn_decl| try sema.mod.errNoteNonLazy(fn_decl.srcLoc(), msg, "function declared here", .{});
6343 break :msg msg;
6344 };
6345 return sema.failWithOwnedErrorMsg(msg);
6346 }
6313 const total_args = args_len + @boolToInt(bound_arg_src != null);
6314 try sema.checkCallArgumentCount(block, func, func_src, func_ty, total_args, bound_arg_src != null);
63476315
63486316 const args_body = sema.code.extra[extra.end..];
63496317
63506318 var input_is_error = false;
63516319 const block_index = @intCast(Air.Inst.Index, block.instructions.items.len);
63526320
6321 const func_ty_info = func_ty.fnInfo();
6322 const fn_params_len = func_ty_info.param_types.len;
63536323 const parent_comptime = block.is_comptime;
63546324 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
63556325 var extra_index: usize = 0;
......@@ -6398,7 +6368,7 @@ fn zirCall(
63986368 !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace))
63996369 {
64006370 const call_inst: Air.Inst.Ref = if (modifier == .always_tail) undefined else b: {
6401 break :b try sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node);
6371 break :b try sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node);
64026372 };
64036373
64046374 const return_ty = sema.typeOf(call_inst);
......@@ -6427,12 +6397,84 @@ fn zirCall(
64276397 }
64286398
64296399 if (modifier == .always_tail) // Perform the call *after* the restore, so that a tail call is possible.
6430 return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node);
6400 return sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node);
64316401
64326402 return call_inst;
64336403 } else {
6434 return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node);
6404 return sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node);
6405 }
6406}
6407
6408fn checkCallArgumentCount(
6409 sema: *Sema,
6410 block: *Block,
6411 func: Air.Inst.Ref,
6412 func_src: LazySrcLoc,
6413 func_ty: Type,
6414 total_args: usize,
6415 member_fn: bool,
6416) !void {
6417 const func_ty_info = func_ty.fnInfo();
6418 const fn_params_len = func_ty_info.param_types.len;
6419 const args_len = total_args - @boolToInt(member_fn);
6420 if (func_ty_info.is_var_args) {
6421 assert(func_ty_info.cc == .C);
6422 if (total_args >= fn_params_len) return;
6423 } else if (fn_params_len == total_args) {
6424 return;
64356425 }
6426
6427 const maybe_decl = try sema.funcDeclSrc(func);
6428 const member_str = if (member_fn) "member function " else "";
6429 const variadic_str = if (func_ty_info.is_var_args) "at least " else "";
6430 const msg = msg: {
6431 const msg = try sema.errMsg(
6432 block,
6433 func_src,
6434 "{s}expected {s}{d} argument(s), found {d}",
6435 .{
6436 member_str,
6437 variadic_str,
6438 fn_params_len - @boolToInt(member_fn),
6439 args_len,
6440 },
6441 );
6442 errdefer msg.destroy(sema.gpa);
6443
6444 if (maybe_decl) |fn_decl| try sema.mod.errNoteNonLazy(fn_decl.srcLoc(), msg, "function declared here", .{});
6445 break :msg msg;
6446 };
6447 return sema.failWithOwnedErrorMsg(msg);
6448}
6449
6450fn callBuiltin(
6451 sema: *Sema,
6452 block: *Block,
6453 builtin_fn: Air.Inst.Ref,
6454 modifier: std.builtin.CallModifier,
6455 args: []const Air.Inst.Ref,
6456) !void {
6457 const callee_ty = sema.typeOf(builtin_fn);
6458 const func_ty = func_ty: {
6459 switch (callee_ty.zigTypeTag()) {
6460 .Fn => break :func_ty callee_ty,
6461 .Pointer => {
6462 const ptr_info = callee_ty.ptrInfo().data;
6463 if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Fn) {
6464 break :func_ty ptr_info.pointee_type;
6465 }
6466 },
6467 else => {},
6468 }
6469 std.debug.panic("type '{}' is not a function calling builtin fn", .{callee_ty.fmt(sema.mod)});
6470 };
6471
6472 const func_ty_info = func_ty.fnInfo();
6473 const fn_params_len = func_ty_info.param_types.len;
6474 if (args.len != fn_params_len or (func_ty_info.is_var_args and args.len < fn_params_len)) {
6475 std.debug.panic("parameter count mismatch calling builtin fn, expected {d}, found {d}", .{ fn_params_len, args.len });
6476 }
6477 _ = try sema.analyzeCall(block, builtin_fn, func_ty, sema.src, sema.src, modifier, false, args, null, null);
64366478}
64376479
64386480const GenericCallAdapter = struct {
......@@ -6509,6 +6551,7 @@ fn analyzeCall(
65096551 sema: *Sema,
65106552 block: *Block,
65116553 func: Air.Inst.Ref,
6554 func_ty: Type,
65126555 func_src: LazySrcLoc,
65136556 call_src: LazySrcLoc,
65146557 modifier: std.builtin.CallModifier,
......@@ -6519,22 +6562,10 @@ fn analyzeCall(
65196562) CompileError!Air.Inst.Ref {
65206563 const mod = sema.mod;
65216564
6522 const callee_ty = sema.typeOf(func);
6523 const func_ty = func_ty: {
6524 switch (callee_ty.zigTypeTag()) {
6525 .Fn => break :func_ty callee_ty,
6526 .Pointer => {
6527 const ptr_info = callee_ty.ptrInfo().data;
6528 if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Fn) {
6529 break :func_ty ptr_info.pointee_type;
6530 }
6531 },
6532 else => {},
6533 }
6534 return sema.fail(block, func_src, "type '{}' is not a function", .{callee_ty.fmt(sema.mod)});
6535 };
65366565
6566 const callee_ty = sema.typeOf(func);
65376567 const func_ty_info = func_ty.fnInfo();
6568 const fn_params_len = func_ty_info.param_types.len;
65386569 const cc = func_ty_info.cc;
65396570 if (cc == .Naked) {
65406571 const maybe_decl = try sema.funcDeclSrc(func);
......@@ -6552,27 +6583,6 @@ fn analyzeCall(
65526583 };
65536584 return sema.failWithOwnedErrorMsg(msg);
65546585 }
6555 const fn_params_len = func_ty_info.param_types.len;
6556 if (func_ty_info.is_var_args) {
6557 assert(cc == .C);
6558 if (uncasted_args.len < fn_params_len) {
6559 // TODO add error note: declared here
6560 return sema.fail(
6561 block,
6562 func_src,
6563 "expected at least {d} argument(s), found {d}",
6564 .{ fn_params_len, uncasted_args.len },
6565 );
6566 }
6567 } else if (fn_params_len != uncasted_args.len) {
6568 // TODO add error note: declared here
6569 return sema.fail(
6570 block,
6571 call_src,
6572 "expected {d} argument(s), found {d}",
6573 .{ fn_params_len, uncasted_args.len },
6574 );
6575 }
65766586
65776587 const call_tag: Air.Inst.Tag = switch (modifier) {
65786588 .auto,
......@@ -11822,9 +11832,6 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
1182211832 .as_node => try sema.zirAsNode(block, inst),
1182311833 .field_val => try sema.zirFieldVal(block, inst),
1182411834 .@"unreachable" => {
11825 const inst_data = sema.code.instructions.items(.data)[inst].@"unreachable";
11826 const src = inst_data.src();
11827
1182811835 if (!sema.mod.comp.formatted_panics) {
1182911836 try sema.safetyPanic(block, .unwrap_error);
1183011837 return true;
......@@ -11833,18 +11840,17 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
1183311840 const panic_fn = try sema.getBuiltin("panicUnwrapError");
1183411841 const err_return_trace = try sema.getErrorReturnTrace(block);
1183511842 const args: [2]Air.Inst.Ref = .{ err_return_trace, operand };
11836 _ = try sema.analyzeCall(block, panic_fn, src, src, .auto, false, &args, null, null);
11843 try sema.callBuiltin(block, panic_fn, .auto, &args);
1183711844 return true;
1183811845 },
1183911846 .panic => {
1184011847 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
11841 const src = inst_data.src();
1184211848 const msg_inst = try sema.resolveInst(inst_data.operand);
1184311849
1184411850 const panic_fn = try sema.getBuiltin("panic");
1184511851 const err_return_trace = try sema.getErrorReturnTrace(block);
1184611852 const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value };
11847 _ = try sema.analyzeCall(block, panic_fn, src, src, .auto, false, &args, null, null);
11853 try sema.callBuiltin(block, panic_fn, .auto, &args);
1184811854 return true;
1184911855 },
1185011856 else => unreachable,
......@@ -17258,7 +17264,7 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir
1725817264
1725917265 if (sema.wantErrorReturnTracing(sema.fn_ret_ty)) {
1726017266 const is_non_err = try sema.analyzePtrIsNonErr(block, src, ret_ptr);
17261 return sema.retWithErrTracing(block, src, is_non_err, .ret_load, ret_ptr);
17267 return sema.retWithErrTracing(block, is_non_err, .ret_load, ret_ptr);
1726217268 }
1726317269
1726417270 _ = try block.addUnOp(.ret_load, ret_ptr);
......@@ -17268,7 +17274,6 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir
1726817274fn retWithErrTracing(
1726917275 sema: *Sema,
1727017276 block: *Block,
17271 src: LazySrcLoc,
1727217277 is_non_err: Air.Inst.Ref,
1727317278 ret_tag: Air.Inst.Tag,
1727417279 operand: Air.Inst.Ref,
......@@ -17290,7 +17295,7 @@ fn retWithErrTracing(
1729017295 const args: [1]Air.Inst.Ref = .{err_return_trace};
1729117296
1729217297 if (!need_check) {
17293 _ = try sema.analyzeCall(block, return_err_fn, src, src, .never_inline, false, &args, null, null);
17298 try sema.callBuiltin(block, return_err_fn, .never_inline, &args);
1729417299 _ = try block.addUnOp(ret_tag, operand);
1729517300 return always_noreturn;
1729617301 }
......@@ -17301,7 +17306,7 @@ fn retWithErrTracing(
1730117306
1730217307 var else_block = block.makeSubBlock();
1730317308 defer else_block.instructions.deinit(gpa);
17304 _ = try sema.analyzeCall(&else_block, return_err_fn, src, src, .never_inline, false, &args, null, null);
17309 try sema.callBuiltin(&else_block, return_err_fn, .never_inline, &args);
1730517310 _ = try else_block.addUnOp(ret_tag, operand);
1730617311
1730717312 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len +
......@@ -17447,7 +17452,7 @@ fn analyzeRet(
1744717452 // Avoid adding a frame to the error return trace in case the value is comptime-known
1744817453 // to be not an error.
1744917454 const is_non_err = try sema.analyzeIsNonErr(block, src, operand);
17450 return sema.retWithErrTracing(block, src, is_non_err, .ret, operand);
17455 return sema.retWithErrTracing(block, is_non_err, .ret, operand);
1745117456 }
1745217457
1745317458 _ = try block.addUnOp(.ret, operand);
......@@ -21657,8 +21662,25 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2165721662 resolved.* = try sema.tupleFieldValByIndex(block, args_src, args, @intCast(u32, i), args_ty);
2165821663 }
2165921664 }
21665
21666 const callee_ty = sema.typeOf(func);
21667 const func_ty = func_ty: {
21668 switch (callee_ty.zigTypeTag()) {
21669 .Fn => break :func_ty callee_ty,
21670 .Pointer => {
21671 const ptr_info = callee_ty.ptrInfo().data;
21672 if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Fn) {
21673 break :func_ty ptr_info.pointee_type;
21674 }
21675 },
21676 else => {},
21677 }
21678 return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(sema.mod)});
21679 };
21680 try sema.checkCallArgumentCount(block, func, func_src, func_ty, resolved_args.len, bound_arg_src != null);
21681
2166021682 const ensure_result_used = extra.flags.ensure_result_used;
21661 return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, null);
21683 return sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, null);
2166221684}
2166321685
2166421686fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -23469,7 +23491,6 @@ fn addSafetyCheckExtra(
2346923491fn panicWithMsg(
2347023492 sema: *Sema,
2347123493 block: *Block,
23472 src: LazySrcLoc,
2347323494 msg_inst: Air.Inst.Ref,
2347423495) !void {
2347523496 const mod = sema.mod;
......@@ -23492,7 +23513,7 @@ fn panicWithMsg(
2349223513 Value.null,
2349323514 );
2349423515 const args: [3]Air.Inst.Ref = .{ msg_inst, null_stack_trace, .null_value };
23495 _ = try sema.analyzeCall(block, panic_fn, src, src, .auto, false, &args, null, null);
23516 try sema.callBuiltin(block, panic_fn, .auto, &args);
2349623517}
2349723518
2349823519fn panicUnwrapError(
......@@ -23530,7 +23551,7 @@ fn panicUnwrapError(
2353023551 const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand);
2353123552 const err_return_trace = try sema.getErrorReturnTrace(&fail_block);
2353223553 const args: [2]Air.Inst.Ref = .{ err_return_trace, err };
23533 _ = try sema.analyzeCall(&fail_block, panic_fn, sema.src, sema.src, .auto, false, &args, null, null);
23554 try sema.callBuiltin(&fail_block, panic_fn, .auto, &args);
2353423555 }
2353523556 }
2353623557 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
......@@ -23615,7 +23636,7 @@ fn panicSentinelMismatch(
2361523636 else {
2361623637 const panic_fn = try sema.getBuiltin("checkNonScalarSentinel");
2361723638 const args: [2]Air.Inst.Ref = .{ expected_sentinel, actual_sentinel };
23618 _ = try sema.analyzeCall(parent_block, panic_fn, sema.src, sema.src, .auto, false, &args, null, null);
23639 try sema.callBuiltin(parent_block, panic_fn, .auto, &args);
2361923640 return;
2362023641 };
2362123642
......@@ -23652,7 +23673,7 @@ fn safetyCheckFormatted(
2365223673 _ = try fail_block.addNoOp(.trap);
2365323674 } else {
2365423675 const panic_fn = try sema.getBuiltin(func);
23655 _ = try sema.analyzeCall(&fail_block, panic_fn, sema.src, sema.src, .auto, false, args, null, null);
23676 try sema.callBuiltin(&fail_block, panic_fn, .auto, args);
2365623677 }
2365723678 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
2365823679}
......@@ -23671,7 +23692,7 @@ fn safetyPanic(
2367123692 )).?;
2367223693
2367323694 const msg_inst = try sema.analyzeDeclVal(block, sema.src, msg_decl_index);
23674 try sema.panicWithMsg(block, sema.src, msg_inst);
23695 try sema.panicWithMsg(block, msg_inst);
2367523696}
2367623697
2367723698fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
test/cases/compile_errors/member_function_arg_mismatch.zig+6
......@@ -6,6 +6,10 @@ pub export fn entry() void {
66 var s: S = undefined;
77 s.foo(true);
88}
9pub export fn entry2() void {
10 var s: S = undefined;
11 @call(.auto, s.foo, .{true});
12}
913
1014// error
1115// backend=stage2
......@@ -13,3 +17,5 @@ pub export fn entry() void {
1317//
1418// :7:6: error: member function expected 2 argument(s), found 1
1519// :3:5: note: function declared here
20// :11:19: error: member function expected 2 argument(s), found 1
21// :3:5: note: function declared here