diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2025-01-29 06:39:29 +0000 |
|---|---|---|
| committer | Matthew Lugg <mlugg@mlugg.co.uk> | 2025-01-29 18:43:24 +0000 |
| commit | 107b65ec5dccd360410b4a693bb0caf0015312f3 (patch) | |
| tree | 7cd66974406b4f3423e746f1ca24c0e7f0cabb94 /src | |
| parent | 484f72311eae288ed5c7a648ec016b02f4547f48 (diff) | |
| download | zig-107b65ec5dccd360410b4a693bb0caf0015312f3.tar.gz zig-107b65ec5dccd360410b4a693bb0caf0015312f3.zip | |
Sema: explain why we tried to call an `extern fn` at comptime
I recently saw a user hit the "comptime call of extern function" error,
and get confused because they didn't know why the scope was `comptime`.
So, use `explainWhyBlockIsComptime` on this and related errors to add
all the relevant notes.
The added test case shows the motivating situation.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index f38a82659c..2fe4aac581 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8021,26 +8021,49 @@ fn analyzeCall( // This is an inline call. The function must be comptime-known. We will analyze its body directly using this `Sema`. - const call_type: []const u8 = if (block.isComptime()) "comptime" else "inline"; + if (func_ty_info.is_noinline and !block.isComptime()) { + return sema.fail(block, call_src, "inline call of noinline function", .{}); + } + const call_type: []const u8 = if (block.isComptime()) "comptime" else "inline"; if (modifier == .never_inline) { - return sema.fail(block, call_src, "cannot perform {s} call with 'never_inline' modifier", .{call_type}); - } - if (func_ty_info.is_noinline and !block.isComptime()) { - return sema.fail(block, call_src, "{s} call of noinline function", .{call_type}); + const msg, const fail_block = msg: { + const msg = try sema.errMsg(call_src, "cannot perform {s} call with 'never_inline' modifier", .{call_type}); + errdefer msg.destroy(gpa); + const fail_block = if (block.isComptime()) b: { + break :b try block.explainWhyBlockIsComptime(msg); + } else block; + break :msg .{ msg, fail_block }; + }; + return sema.failWithOwnedErrorMsg(fail_block, msg); } if (func_ty_info.is_var_args) { - return sema.fail(block, call_src, "{s} call of variadic function", .{call_type}); + const msg, const fail_block = msg: { + const msg = try sema.errMsg(call_src, "{s} call of variadic function", .{call_type}); + errdefer msg.destroy(gpa); + const fail_block = if (block.isComptime()) b: { + break :b try block.explainWhyBlockIsComptime(msg); + } else block; + break :msg .{ msg, fail_block }; + }; + return sema.failWithOwnedErrorMsg(fail_block, msg); } - if (func_val == null) { if (func_is_extern) { - return sema.fail(block, call_src, "{s} call of extern function", .{call_type}); + const msg, const fail_block = msg: { + const msg = try sema.errMsg(call_src, "{s} call of extern function", .{call_type}); + errdefer msg.destroy(gpa); + const fail_block = if (block.isComptime()) b: { + break :b try block.explainWhyBlockIsComptime(msg); + } else block; + break :msg .{ msg, fail_block }; + }; + return sema.failWithOwnedErrorMsg(fail_block, msg); } return sema.failWithNeededComptime( block, func_src, - .{ .simple = if (block.isComptime()) .comptime_call_target else .inline_call_target }, + if (block.isComptime()) null else .{ .simple = .inline_call_target }, ); } |
