aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2025-01-29 06:39:29 +0000
committerMatthew Lugg <mlugg@mlugg.co.uk>2025-01-29 18:43:24 +0000
commit107b65ec5dccd360410b4a693bb0caf0015312f3 (patch)
tree7cd66974406b4f3423e746f1ca24c0e7f0cabb94 /src
parent484f72311eae288ed5c7a648ec016b02f4547f48 (diff)
downloadzig-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.zig41
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 },
);
}