mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
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.
This commit is contained in:
parent
484f72311e
commit
107b65ec5d
@ -749,7 +749,6 @@ pub const SimpleComptimeReason = enum(u32) {
|
|||||||
atomic_order,
|
atomic_order,
|
||||||
array_mul_factor,
|
array_mul_factor,
|
||||||
slice_cat_operand,
|
slice_cat_operand,
|
||||||
comptime_call_target,
|
|
||||||
inline_call_target,
|
inline_call_target,
|
||||||
generic_call_target,
|
generic_call_target,
|
||||||
wasm_memory_index,
|
wasm_memory_index,
|
||||||
@ -830,7 +829,6 @@ pub const SimpleComptimeReason = enum(u32) {
|
|||||||
.atomic_order => "atomic order must be comptime-known",
|
.atomic_order => "atomic order must be comptime-known",
|
||||||
.array_mul_factor => "array multiplication factor must be comptime-known",
|
.array_mul_factor => "array multiplication factor must be comptime-known",
|
||||||
.slice_cat_operand => "slice being concatenated must be comptime-known",
|
.slice_cat_operand => "slice being concatenated must be comptime-known",
|
||||||
.comptime_call_target => "function being called at comptime must be comptime-known",
|
|
||||||
.inline_call_target => "function being called inline must be comptime-known",
|
.inline_call_target => "function being called inline must be comptime-known",
|
||||||
.generic_call_target => "generic function being called must be comptime-known",
|
.generic_call_target => "generic function being called must be comptime-known",
|
||||||
.wasm_memory_index => "wasm memory index must be comptime-known",
|
.wasm_memory_index => "wasm memory index must be comptime-known",
|
||||||
|
|||||||
43
src/Sema.zig
43
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`.
|
// 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 (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()) {
|
if (func_ty_info.is_noinline and !block.isComptime()) {
|
||||||
return sema.fail(block, call_src, "{s} call of noinline function", .{call_type});
|
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) {
|
||||||
|
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) {
|
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_val == null) {
|
||||||
if (func_is_extern) {
|
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(
|
return sema.failWithNeededComptime(
|
||||||
block,
|
block,
|
||||||
func_src,
|
func_src,
|
||||||
.{ .simple = if (block.isComptime()) .comptime_call_target else .inline_call_target },
|
if (block.isComptime()) null else .{ .simple = .inline_call_target },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,40 @@
|
|||||||
|
extern fn next_id() u32;
|
||||||
|
|
||||||
|
const Foo = struct {
|
||||||
|
bar: Bar,
|
||||||
|
|
||||||
|
fn init() Foo {
|
||||||
|
return .{ .bar = .init() };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const Bar = struct {
|
||||||
|
qux: ?Qux,
|
||||||
|
id: u32,
|
||||||
|
|
||||||
|
fn init() Bar {
|
||||||
|
return .{
|
||||||
|
.qux = null,
|
||||||
|
.id = next_id(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const Qux = struct {
|
||||||
|
handleThing: fn () void,
|
||||||
|
};
|
||||||
|
|
||||||
|
export fn entry() void {
|
||||||
|
const foo: Foo = .init();
|
||||||
|
_ = foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// error
|
||||||
|
//
|
||||||
|
// :17:26: error: comptime call of extern function
|
||||||
|
// :7:31: note: called at comptime from here
|
||||||
|
// :26:27: note: called at comptime from here
|
||||||
|
// :26:27: note: call to function with comptime-only return type 'tmp.Foo' is evaluated at comptime
|
||||||
|
// :6:15: note: return type declared here
|
||||||
|
// :4:10: note: struct requires comptime because of this field
|
||||||
|
// :11:10: note: struct requires comptime because of this field
|
||||||
|
// :22:18: note: struct requires comptime because of this field
|
||||||
|
// :22:18: note: use '*const fn () void' for a function pointer type
|
||||||
@ -6,4 +6,4 @@ export fn entry() void {
|
|||||||
// error
|
// error
|
||||||
//
|
//
|
||||||
// :3:14: error: unable to resolve comptime value
|
// :3:14: error: unable to resolve comptime value
|
||||||
// :3:14: note: function being called at comptime must be comptime-known
|
// :3:5: note: 'comptime' keyword forces comptime evaluation
|
||||||
|
|||||||
@ -7,3 +7,4 @@ export fn entry() i32 {
|
|||||||
// error
|
// error
|
||||||
//
|
//
|
||||||
// :2:14: error: comptime call of extern function
|
// :2:14: error: comptime call of extern function
|
||||||
|
// :2:14: note: initializer of container-level variable must be comptime-known
|
||||||
|
|||||||
@ -11,4 +11,5 @@ export fn entry1() void {
|
|||||||
// error
|
// error
|
||||||
//
|
//
|
||||||
// :4:15: error: comptime call of extern function
|
// :4:15: error: comptime call of extern function
|
||||||
|
// :4:5: note: 'comptime' keyword forces comptime evaluation
|
||||||
// :8:5: error: inline call of extern function
|
// :8:5: error: inline call of extern function
|
||||||
|
|||||||
@ -9,3 +9,4 @@ export fn f() void {
|
|||||||
// error
|
// error
|
||||||
//
|
//
|
||||||
// :2:16: error: comptime call of extern function
|
// :2:16: error: comptime call of extern function
|
||||||
|
// :2:12: note: types must be comptime-known
|
||||||
|
|||||||
@ -11,3 +11,4 @@ export fn entry() usize {
|
|||||||
// error
|
// error
|
||||||
//
|
//
|
||||||
// :4:27: error: comptime call of extern function
|
// :4:27: error: comptime call of extern function
|
||||||
|
// :4:14: note: initializer of container-level variable must be comptime-known
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user