Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@errorCast into an inferred error set causes compiler crash #21222

Open
NicoElbers opened this issue Aug 27, 2024 · 3 comments · May be fixed by #21349
Open

@errorCast into an inferred error set causes compiler crash #21222

NicoElbers opened this issue Aug 27, 2024 · 3 comments · May be fixed by #21349
Labels
bug Observed behavior contradicts documented or intended behavior frontend Tokenization, parsing, AstGen, Sema, and Liveness.
Milestone

Comments

@NicoElbers
Copy link
Contributor

Zig Version

0.14.0-dev.1307+849c31a6c

Steps to Reproduce and Observed Behavior

bug.zig:

fn func() !void {
    return;
}

pub fn main() !void {
    const res = func();

    const err = @as(@TypeOf(res), @errorCast(error.Err));
    _ = try err;
}

run zig build-exe bug.zig

observe:

❯ zig build-exe bug.zig
[4]    99609 segmentation fault (core dumped)  zig build-exe bug.zig

full dump of a debug compiler here: https://pastebin.com/9bncrwdm

Expected Behavior

A compiling program, as what would happen if func returned anyerror!void

@NicoElbers NicoElbers added the bug Observed behavior contradicts documented or intended behavior label Aug 27, 2024
@NicoElbers
Copy link
Contributor Author

for additional information, a program where error.Err should be in the inferred error set also crashes:

fn func() !void {
    return error.Err;
}

pub fn main() !void {
    const res = func();

    const err = @as(@TypeOf(res), @errorCast(error.Err));
    _ = try err;
}

@nektro
Copy link
Contributor

nektro commented Aug 27, 2024

debug compiler stack trace
thread 104550 panic: reached unreachable code
Analyzing bug.zig
      %9 = ret_type() node_offset:5:1 to :5:7
      %10 = dbg_stmt(2, 5)
      %11 = decl_val("func") token_offset:6:17 to :6:21
      %12 = dbg_stmt(2, 21)
      %13 = call(.auto, %11, []) node_offset:6:17 to :6:23
      %14 = dbg_var_val(%13, "res")
      %15 = save_err_ret_index(%13)
      %16 = dbg_stmt(4, 5)
      %17 = block_comptime({
        %18 = typeof_builtin({
          %19 = break_inline(%18, %13)
        }) node_offset:8:21 to :8:33
        %20 = break(%17, %18)
      }) node_offset:8:21 to :8:33
      %21 = dbg_stmt(4, 35)
      %22 = error_value("Err") token_offset:8:52 to :8:55
    > %23 = extended(error_cast(%17, %22)) node_offset:8:35 to :8:56
      %24 = as_node(%17, %23) node_offset:8:35 to :8:56
      %25 = dbg_var_val(%24, "err")
      %26 = save_err_ret_index(%24)
      %27 = dbg_stmt(5, 9)
      %28 = try(%24, {
        %29 = err_union_code(%24) node_offset:9:9 to :9:16
        %30 = dbg_stmt(5, 9)
        %31 = ret_node(%29) node_offset:9:9 to :9:16
      }) node_offset:9:9 to :9:16
      %32 = ensure_result_non_error(%28) node_offset:9:9 to :9:16
      %33 = restore_err_ret_index_unconditional(.none) node_offset:5:1 to :5:7
      %34 = ret_implicit(@void_value) token_offset:10:1 to :10:1
    For full context, use the command
      zig ast-check -t bug.zig

  in /home/nico/personal-projects/zig/compiler/stage3/lib/zig/std/start.zig
    > %1937 = is_non_err(%1936) 
  in /home/nico/personal-projects/zig/compiler/stage3/lib/zig/std/start.zig
    > %1939 = block({%1934..%1938}) 
  in /home/nico/personal-projects/zig/compiler/stage3/lib/zig/std/start.zig
    > %1901 = switch_block(%1897,
        else => {%1919..%2022},
        @void_type => {%1902..%1910},
        @noreturn_type, @u8_type => {%1911..%1918}) 
  in /home/nico/personal-projects/zig/compiler/stage3/lib/zig/std/start.zig
    > %1698 = call(.auto, %1696, []) 
  in /home/nico/personal-projects/zig/compiler/stage3/lib/zig/std/start.zig
    > %1533 = call(.auto, %1531, [
        {%1534},
        {%1535},
        {%1536},
      ]) 
  in /home/nico/personal-projects/zig/compiler/stage3/lib/zig/std/start.zig
    > %1530 = field_call(nodiscard .auto, %1528, "exit", [
        {%1531..%1537},
      ]) 

/home/nico/personal-projects/zig/compiler/src/Type.zig:3003:22: 0xb5e66c5 in errorSetNames (zig)
            .none => unreachable, // unresolved inferred error set
                     ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:22993:53: 0xb1a95e1 in zirErrorCast (zig)
        const dest_err_names = dest_ty.errorSetNames(mod);
                                                    ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:1272:65: 0xacfab8b in analyzeBodyInner (zig)
                    .error_cast         => try sema.zirErrorCast(         block, extended),
                                                                ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:915:26: 0xb5fbde1 in analyzeFnBody (zig)
    sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                         ^
/home/nico/personal-projects/zig/compiler/src/Zcu/PerThread.zig:2176:23: 0xb0b752d in analyzeFnBody (zig)
    sema.analyzeFnBody(&inner_block, fn_info.body) catch |err| switch (err) {
                      ^
/home/nico/personal-projects/zig/compiler/src/Zcu/PerThread.zig:792:35: 0xacae04d in ensureFuncBodyAnalyzedInner (zig)
    var air = try pt.analyzeFnBody(func_index);
                                  ^
/home/nico/personal-projects/zig/compiler/src/Zcu/PerThread.zig:698:81: 0xa86a713 in ensureFuncBodyAnalyzed (zig)
    const ies_outdated, const analysis_fail = if (pt.ensureFuncBodyAnalyzedInner(func_index, func_outdated)) |result|
                                                                                ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:35950:38: 0xad2114d in resolveInferredErrorSet (zig)
        try pt.ensureFuncBodyAnalyzed(func_index);
                                     ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:32616:69: 0xb1d6421 in analyzeIsNonErrComptimeOnly (zig)
                const resolved_ty = try sema.resolveInferredErrorSet(block, src, set_ty);
                                                                    ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:32645:56: 0xb67e8c9 in analyzeIsNonErr (zig)
    const result = try sema.analyzeIsNonErrComptimeOnly(block, src, operand);
                                                       ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:19294:32: 0xb12cc22 in zirIsNonErr (zig)
    return sema.analyzeIsNonErr(block, src, operand);
                               ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:1087:66: 0xacf4729 in analyzeBodyInner (zig)
            .is_non_err                   => try sema.zirIsNonErr(block, inst),
                                                                 ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:6016:34: 0xb6a8db8 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:5993:33: 0xb1d9378 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:1593:49: 0xad011f7 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[@intFromEnum(inst)] == .block_comptime);
                                                ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:6016:34: 0xb6a8db8 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:10972:45: 0xb69f5fd in resolveProngComptime (zig)
                return sema.resolveBlockBody(spa.parent_block, src, child_block, prong_body, spa.switch_block_inst, merges);
                                            ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:13244:36: 0xb69f1e5 in resolveSwitchComptime (zig)
    return spa.resolveProngComptime(
                                   ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:12364:37: 0xb13d8f8 in zirSwitchBlock (zig)
        return resolveSwitchComptime(
                                    ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:1110:69: 0xacf5555 in analyzeBodyInner (zig)
            .switch_block                 => try sema.zirSwitchBlock(block, inst, false),
                                                                    ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:915:26: 0xb5fbde1 in analyzeFnBody (zig)
    sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                         ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:7812:31: 0xb1f2df4 in analyzeCall (zig)
            sema.analyzeFnBody(&child_block, fn_info.body) catch |err| switch (err) {
                              ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:6986:43: 0xb11d298 in zirCall__anon_408486 (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/nico/personal-projects/zig/compiler/src/Sema.zig:1045:62: 0xacf2ce9 in analyzeBodyInner (zig)
            .call                         => try sema.zirCall(block, inst, .direct),
                                                             ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:915:26: 0xb5fbde1 in analyzeFnBody (zig)
    sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                         ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:7812:31: 0xb1f2df4 in analyzeCall (zig)
            sema.analyzeFnBody(&child_block, fn_info.body) catch |err| switch (err) {
                              ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:6986:43: 0xb11d298 in zirCall__anon_408486 (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/nico/personal-projects/zig/compiler/src/Sema.zig:1045:62: 0xacf2ce9 in analyzeBodyInner (zig)
            .call                         => try sema.zirCall(block, inst, .direct),
                                                             ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:933:30: 0xa89a2d7 in analyzeInlineBody (zig)
    if (sema.analyzeBodyInner(block, body)) |_| {
                             ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:959:39: 0xa57ea3e in resolveInlineBody (zig)
    return (try sema.analyzeInlineBody(block, body, break_target)) orelse .unreachable_value;
                                      ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:7278:65: 0xb74acb5 in analyzeArg (zig)
                const uncoerced_arg = try sema.resolveInlineBody(block, arg_body, zir_call.call_inst);
                                                                ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:7865:49: 0xb1f430b in analyzeCall (zig)
            arg_out.* = try args_info.analyzeArg(sema, block, arg_idx, param_ty, func_ty_info, func);
                                                ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:6986:43: 0xb11e5d3 in zirCall__anon_408488 (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/nico/personal-projects/zig/compiler/src/Sema.zig:1046:62: 0xacf2d86 in analyzeBodyInner (zig)
            .field_call                   => try sema.zirCall(block, inst, .field),
                                                             ^
/home/nico/personal-projects/zig/compiler/src/Sema.zig:915:26: 0xb5fbde1 in analyzeFnBody (zig)
    sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                         ^
/home/nico/personal-projects/zig/compiler/src/Zcu/PerThread.zig:2176:23: 0xb0b752d in analyzeFnBody (zig)
    sema.analyzeFnBody(&inner_block, fn_info.body) catch |err| switch (err) {
                      ^
/home/nico/personal-projects/zig/compiler/src/Zcu/PerThread.zig:792:35: 0xacae04d in ensureFuncBodyAnalyzedInner (zig)
    var air = try pt.analyzeFnBody(func_index);
                                  ^
/home/nico/personal-projects/zig/compiler/src/Zcu/PerThread.zig:698:81: 0xa86a713 in ensureFuncBodyAnalyzed (zig)
    const ies_outdated, const analysis_fail = if (pt.ensureFuncBodyAnalyzedInner(func_index, func_outdated)) |result|
                                                                                ^
/home/nico/personal-projects/zig/compiler/src/Compilation.zig:3693:38: 0xa554237 in processOneJob (zig)
            pt.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {
                                     ^
/home/nico/personal-projects/zig/compiler/src/Compilation.zig:3638:30: 0xa2d5d51 in performAllTheWorkInner (zig)
            try processOneJob(@intFromEnum(Zcu.PerThread.Id.main), comp, job, main_progress_node);
                             ^
/home/nico/personal-projects/zig/compiler/src/Compilation.zig:3508:36: 0xa16d460 in performAllTheWork (zig)
    try comp.performAllTheWorkInner(main_progress_node);
                                   ^
/home/nico/personal-projects/zig/compiler/src/Compilation.zig:2269:31: 0xa168c09 in update (zig)
    try comp.performAllTheWork(main_progress_node);
                              ^
/home/nico/personal-projects/zig/compiler/src/main.zig:4453:20: 0xa16eb7d in updateModule (zig)
    try comp.update(prog_node);
                   ^
/home/nico/personal-projects/zig/compiler/src/main.zig:3500:21: 0xa1d7f0a in buildOutputType (zig)
        updateModule(comp, color, root_prog_node) catch |err| switch (err) {
                    ^
/home/nico/personal-projects/zig/compiler/src/main.zig:258:31: 0xa020046 in mainArgs (zig)
        return buildOutputType(gpa, arena, args, .{ .build = .Exe });
                              ^
/home/nico/personal-projects/zig/compiler/src/main.zig:199:20: 0xa01d015 in main (zig)
    return mainArgs(gpa, arena, args);
                   ^
/nix/store/046rjdgb75qdq31pqjx0hqy9gdg8m8gv-zig-0.14.0-dev.1261+c26206112/lib/std/start.zig:614:37: 0xa01cb3e in main (zig)
            const result = root.main() catch |err| {
                                    ^
???:?:?: 0x7f825837714d in ??? (libc.so.6)
Unwind information for `libc.so.6:0x7f825837714d` was not available, trace may be incomplete

[2]    104550 IOT instruction (core dumped)  ../../compiler/stage3/bin/zig build-exe bug.zig

@rohlem
Copy link
Contributor

rohlem commented Aug 28, 2024

Maybe known, but you can work around the current bug by stripping the error set's identity (undocumented - #20862):

fn func() !void {
    return;
}
fn StripErrorSetIdentity(T: type) type {
    return switch (@typeInfo(T)) {
        else => |tag| @compileError("invalid input type: " ++ @typeName(T) ++ " | " ++ @tagName(tag)),
        .ErrorSet => T || error{},
        .ErrorUnion => |u| StripErrorSetIdentity(u.error_set)!u.payload,
    };
}
pub fn main() !void {
    const res = func();
    const Res = StripErrorSetIdentity(@TypeOf(res));

    const err = @as(Res, @errorCast(error.Err));
    _ = try err;
}

@Vexu Vexu added the frontend Tokenization, parsing, AstGen, Sema, and Liveness. label Sep 1, 2024
@Vexu Vexu added this to the 0.15.0 milestone Sep 1, 2024
NicoElbers added a commit to NicoElbers/ztest that referenced this issue Sep 7, 2024
Due to a compiler bug involving inferred error sets
(ziglang/zig#21222) I have to use this
workaround
@Rexicon226 Rexicon226 linked a pull request Sep 8, 2024 that will close this issue
NicoElbers added a commit to NicoElbers/ztest that referenced this issue Sep 11, 2024
Due to a compiler bug involving inferred error sets
(ziglang/zig#21222) I have to use this
workaround
NicoElbers added a commit to NicoElbers/ztest that referenced this issue Sep 30, 2024
Due to a compiler bug involving inferred error sets
(ziglang/zig#21222) I have to use this
workaround
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior frontend Tokenization, parsing, AstGen, Sema, and Liveness.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants