zig
zig copied to clipboard
InternPool unreachable when coercing extern function (`// use getExternFunc() instead`)
Zig Version
0.13.0
Steps to Reproduce and Observed Behavior
const c = @cImport({
@cInclude("pwd.h");
});
pub fn main() !void {
callback(c.getpwuid);
}
fn callback(cb: fn (c.uid_t) callconv(.C) ?*c.passwd) void {
_ = cb(0);
}
this code works in some previous version, but panic compiler in 0.13.0.
change ?*c.passwd to [*c]c.passwd can fix the problem.
Expected Behavior
give some error tips rather than panic
Cannot reproduce on 0.14.0-dev.302+d404d8a36:
a.zig:19:15: error: expected type 'fn (c_uint) ?*cimport.struct_passwd', found 'fn (c_uint) callconv(.C) [*c]cimport.struct_passwd'
callback(c.getpwuid);
~^~~~~~~~~
a.zig:19:15: note: calling convention 'C' cannot cast into calling convention 'Unspecified'
a.zig:22:17: note: parameter type declared here
fn callback(cb: fn (c.uid_t) ?*c.passwd) void {
^~~~~~~~~~~~~~~~~~~~~~~
Cannot reproduce on
0.14.0-dev.302+d404d8a36:a.zig:19:15: error: expected type 'fn (c_uint) ?*cimport.struct_passwd', found 'fn (c_uint) callconv(.C) [*c]cimport.struct_passwd' callback(c.getpwuid); ~^~~~~~~~~ a.zig:19:15: note: calling convention 'C' cannot cast into calling convention 'Unspecified' a.zig:22:17: note: parameter type declared here fn callback(cb: fn (c.uid_t) ?*c.passwd) void { ^~~~~~~~~~~~~~~~~~~~~~~
oh, forget the callconv(.C). this panics compiler fn callback(cb: fn (c.uid_t) callconv(.C) ?*c.passwd) void { _ = cb(0); }
thread 15270 panic: reached unreachable code
Analyzing a.zig
%61 = ret_type() node_offset:18:1 to :18:7
%62 = dbg_stmt(2, 5)
%63 = decl_val("callback") token_offset:19:5 to :19:13
%64 = dbg_stmt(2, 13)
> %65 = call(nodiscard .auto, %63, [
{
%66 = decl_val("c") token_offset:19:14 to :19:15
%67 = dbg_stmt(2, 15)
%68 = field_val(%66, "getpwuid") node_offset:19:14 to :19:24
%69 = break_inline(%65, %68)
},
]) node_offset:19:5 to :19:25
%70 = restore_err_ret_index_unconditional(.none) node_offset:18:1 to :18:7
%71 = ret_implicit(@void_value) token_offset:20:1 to :20:1
For full context, use the command
zig ast-check -t a.zig
in lib/std/start.zig
> %1888 = is_non_err(%1887) node_offset:513:28 to :513:45
in lib/std/start.zig
> %1890 = block({%1885..%1889}) node_offset:513:28 to :513:45
in lib/std/start.zig
> %1852 = switch_block(%1848,
else => {%1870..%1949},
@void_type => {%1853..%1861},
@noreturn_type, @u8_type => {%1862..%1869}) node_offset:502:5 to :502:11
in lib/std/start.zig
> %1653 = call(.auto, %1651, []) node_offset:473:12 to :473:22
in lib/std/start.zig
> %1772 = call(.auto, %1770, [
{%1773..%1776},
{%1777..%1784},
{%1785},
]) node_offset:488:12 to :488:99
/home/vexu/Documents/zig/zig/src/InternPool.zig:6908:25: 0xa095e0d in get (zig)
.extern_func => unreachable, // use getExternFunc() instead
^
/home/vexu/Documents/zig/zig/src/InternPool.zig:9436:26: 0xa93ac23 in getCoerced (zig)
return ip.get(gpa, tid, .{ .extern_func = .{
^
/home/vexu/Documents/zig/zig/src/Zcu/PerThread.zig:2752:64: 0xa5f52b9 in getCoerced (zig)
return Value.fromInterned(try pt.zcu.intern_pool.getCoerced(pt.zcu.gpa, pt.tid, val.toIntern(), new_ty.toIntern()));
^
/home/vexu/Documents/zig/zig/src/Sema.zig:29866:53: 0xa8e410c in coerceInMemory (zig)
return Air.internedToRef((try sema.pt.getCoerced(val, dst_ty)).toIntern());
^
/home/vexu/Documents/zig/zig/src/Sema.zig:29195:39: 0xa57c201 in coerceExtra (zig)
return sema.coerceInMemory(val, dest_ty);
^
/home/vexu/Documents/zig/zig/src/Sema.zig:7399:44: 0xb2c7300 in analyzeArg (zig)
else => return sema.coerceExtra(
^
/home/vexu/Documents/zig/zig/src/Sema.zig:8301:49: 0xb2c9679 in instantiateGenericCall (zig)
const arg_ref = try args_info.analyzeArg(sema, block, arg_index, param_ty, generic_owner_ty_info, func);
^
/home/vexu/Documents/zig/zig/src/Sema.zig:7606:40: 0xae0a2e7 in analyzeCall (zig)
if (sema.instantiateGenericCall(
^
/home/vexu/Documents/zig/zig/src/Sema.zig:7088:43: 0xad36884 in zirCall__anon_95166 (zig)
const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call);
^
/home/vexu/Documents/zig/zig/src/Sema.zig:1044:62: 0xa8a9ba0 in analyzeBodyInner (zig)
.call => try sema.zirCall(block, inst, .direct),
^
/home/vexu/Documents/zig/zig/src/Sema.zig:914:26: 0xb17a381 in analyzeFnBody (zig)
sema.analyzeBodyInner(block, body) catch |err| switch (err) {
^
/home/vexu/Documents/zig/zig/src/Zcu/PerThread.zig:2187:23: 0xacded2d in analyzeFnBody (zig)
sema.analyzeFnBody(&inner_block, fn_info.body) catch |err| switch (err) {
^
A better repro:
extern fn foo() [*c]u32;
pub fn main() !void {
_ = @as(fn () callconv(.C) ?*u32, foo);
}