Skip to content

switch on error doesn't validate operand type #18592

Description

@Techatrix

Zig Version

0.12.0-dev.2255+50457482b

Steps to Reproduce and Observed Behavior

Run the following code with zig run file.zig:

pub fn main() !void {
    false catch |err| switch (err) {
        else => {},
    };
}

This produces the following crash:

Click Me
thread 430912 panic: access of union field 'error_union_type' while field 'simple_type' is active
Analyzing sample2.zig: sample2.zig:main
    %3 = dbg_block_begin()
    %4 = dbg_stmt(2, 5)
    %5 = dbg_stmt(2, 5)
  > %6 = switch_block_err_union(@bool_false,
      non_err => {
        %7 = dbg_block_begin()
        %8 = err_union_payload_unsafe(@bool_false) node_offset:2:5 to :2:16
        %9 = dbg_block_end()
        %10 = break(%6, %8)
      },
      else => {
        %12 = dbg_block_begin()
        %13 = block({
          %14 = restore_err_ret_index(%13.none)
          %15 = break(%13, @void_value)
        }) node_offset:3:17 to :3:19
        %16 = dbg_block_end()
        %17 = break(%6, @void_value)
      }) node_offset:2:23 to :2:29
    %18 = ensure_result_used(%6) node_offset:2:5 to :2:16
    %19 = dbg_block_end()
    %20 = restore_err_ret_index(%2.none)
    %21 = break(%2, @void_value)
  For full context, use the command
    zig ast-check -t sample2.zig

in sample2.zig: sample2.zig:main
  > %2 = block({%3..%21}) node_offset:1:21 to :1:21
in /home/techatrix/repos/zig/lib/std/start.zig: start.zig:callMain
  > %2851 = is_non_err(%2850) 
in /home/techatrix/repos/zig/lib/std/start.zig: start.zig:callMain
  > %2853 = block({%2847..%2852}) 
in /home/techatrix/repos/zig/lib/std/start.zig: start.zig:callMain
  > %2844 = block({%2845..%2991}) 
in /home/techatrix/repos/zig/lib/std/start.zig: start.zig:callMain
  > %2755 = switch_block(%2753,
      else => {%2994..%3000},
      %2756 => {%2757..%2769},
      %2770 => {%2771..%2789},
      by_val %2790 => {%2791..%2841},
      %2842 => {%2843..%2993}) 
in /home/techatrix/repos/zig/lib/std/start.zig: start.zig:callMain
  > %2739 = block({%2740..%3004}) 
in /home/techatrix/repos/zig/lib/std/start.zig: start.zig:initEventLoopAndCallMain
  > %2462 = builtin_call(%2460, %2461, @empty_struct) 
in /home/techatrix/repos/zig/lib/std/start.zig: start.zig:initEventLoopAndCallMain
  > %2307 = block({%2308..%2469}) 
in /home/techatrix/repos/zig/lib/std/start.zig: start.zig:callMainWithArgs
  > %2084 = call(.auto, %2082, []) 
in /home/techatrix/repos/zig/lib/std/start.zig: start.zig:callMainWithArgs
  > %2047 = block({%2048..%2091}) 
in /home/techatrix/repos/zig/lib/std/start.zig: start.zig:posixCallMainAndExit
  > %1873 = builtin_call(%1870, %1871, %1872) 
in /home/techatrix/repos/zig/lib/std/start.zig: start.zig:posixCallMainAndExit
  > %1869 = field_call(nodiscard .auto, %1866, "exit", [
      {%1870..%1874},
    ]) 
in /home/techatrix/repos/zig/lib/std/start.zig: start.zig:posixCallMainAndExit
  > %1478 = block({%1479..%1877}) 

/home/techatrix/repos/zig/src/InternPool.zig:7216:29: 0x1edfec2 in errorUnionSet (zig)
  return ip.indexToKey(ty).error_union_type.error_set_type;
                          ^
/home/techatrix/repos/zig/src/type.zig:1959:63: 0x1bcaa2b in errorUnionSet (zig)
      return Type.fromInterned(mod.intern_pool.errorUnionSet(ty.toIntern()));
                                                            ^
/home/techatrix/repos/zig/src/Sema.zig:11261:33: 0x220a072 in zirSwitchBlockErrUnion (zig)
      operand_ty.errorUnionSet(mod);
                              ^
/home/techatrix/repos/zig/src/Sema.zig:1100:77: 0x1e0364b in analyzeBodyInner (zig)
          .switch_block_err_union       => try sema.zirSwitchBlockErrUnion(block, inst),
                                                                          ^
/home/techatrix/repos/zig/src/Sema.zig:5887:34: 0x276da2d in resolveBlockBody (zig)
      if (sema.analyzeBodyInner(child_block, body)) |_| {
                               ^
/home/techatrix/repos/zig/src/Sema.zig:5870:33: 0x22a48ef in zirBlock (zig)
  return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                              ^
/home/techatrix/repos/zig/src/Sema.zig:1582:49: 0x1e10ce2 in analyzeBodyInner (zig)
                  break :blk try sema.zirBlock(block, inst, tags[@intFromEnum(inst)] == .block_comptime);
                                              ^
/home/techatrix/repos/zig/src/Sema.zig:921:30: 0x2106108 in analyzeBody (zig)
  _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                           ^
/home/techatrix/repos/zig/src/Module.zig:4575:21: 0x1ddee6c in analyzeFnBody (zig)
  sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
                  ^
/home/techatrix/repos/zig/src/Module.zig:3272:40: 0x1b30ae4 in ensureFuncBodyAnalyzed (zig)
          var air = zcu.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
                                     ^
/home/techatrix/repos/zig/src/Sema.zig:32162:31: 0x2813c6d in ensureFuncBodyAnalyzed (zig)
  mod.ensureFuncBodyAnalyzed(func) catch |err| {
                            ^
/home/techatrix/repos/zig/src/Sema.zig:36109:40: 0x22cf29b in resolveInferredErrorSet (zig)
      try sema.ensureFuncBodyAnalyzed(func_index);
                                     ^
/home/techatrix/repos/zig/src/Sema.zig:32491:69: 0x22a10b6 in analyzeIsNonErrComptimeOnly (zig)
              const resolved_ty = try sema.resolveInferredErrorSet(block, src, set_ty);
                                                                  ^
/home/techatrix/repos/zig/src/Sema.zig:32520:56: 0x2744059 in analyzeIsNonErr (zig)
  const result = try sema.analyzeIsNonErrComptimeOnly(block, src, operand);
                                                     ^
/home/techatrix/repos/zig/src/Sema.zig:18755:32: 0x21f8e4e in zirIsNonErr (zig)
  return sema.analyzeIsNonErr(block, src, operand);
                             ^
/home/techatrix/repos/zig/src/Sema.zig:1075:66: 0x1e023d8 in analyzeBodyInner (zig)
          .is_non_err                   => try sema.zirIsNonErr(block, inst),
                                                               ^
/home/techatrix/repos/zig/src/Sema.zig:5887:34: 0x276da2d in resolveBlockBody (zig)
      if (sema.analyzeBodyInner(child_block, body)) |_| {
                               ^
/home/techatrix/repos/zig/src/Sema.zig:5870:33: 0x22a48ef in zirBlock (zig)
  return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                              ^
/home/techatrix/repos/zig/src/Sema.zig:1582:49: 0x1e10ce2 in analyzeBodyInner (zig)
                  break :blk try sema.zirBlock(block, inst, tags[@intFromEnum(inst)] == .block_comptime);
                                              ^
/home/techatrix/repos/zig/src/Sema.zig:5887:34: 0x276da2d in resolveBlockBody (zig)
      if (sema.analyzeBodyInner(child_block, body)) |_| {
                               ^
/home/techatrix/repos/zig/src/Sema.zig:5870:33: 0x22a48ef in zirBlock (zig)
  return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                              ^
/home/techatrix/repos/zig/src/Sema.zig:1582:49: 0x1e10ce2 in analyzeBodyInner (zig)
                  break :blk try sema.zirBlock(block, inst, tags[@intFromEnum(inst)] == .block_comptime);
                                              ^
/home/techatrix/repos/zig/src/Sema.zig:5887:34: 0x276da2d in resolveBlockBody (zig)
      if (sema.analyzeBodyInner(child_block, body)) |_| {
                               ^
/home/techatrix/repos/zig/src/Sema.zig:10622:45: 0x2764550 in resolveProngComptime (zig)
              return sema.resolveBlockBody(spa.parent_block, src, child_block, prong_body, spa.switch_block_inst, merges);
                                          ^
/home/techatrix/repos/zig/src/Sema.zig:12768:48: 0x2762ddf in resolveSwitchComptime (zig)
              return spa.resolveProngComptime(
                                             ^
/home/techatrix/repos/zig/src/Sema.zig:12009:37: 0x220846f in zirSwitchBlock (zig)
      return resolveSwitchComptime(
                                  ^
/home/techatrix/repos/zig/src/Sema.zig:1098:69: 0x1e034cd in analyzeBodyInner (zig)
          .switch_block                 => try sema.zirSwitchBlock(block, inst, false),
                                                                  ^
/home/techatrix/repos/zig/src/Sema.zig:5887:34: 0x276da2d in resolveBlockBody (zig)
      if (sema.analyzeBodyInner(child_block, body)) |_| {
                               ^
/home/techatrix/repos/zig/src/Sema.zig:5870:33: 0x22a48ef in zirBlock (zig)
  return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                              ^
/home/techatrix/repos/zig/src/Sema.zig:1582:49: 0x1e10ce2 in analyzeBodyInner (zig)
                  break :blk try sema.zirBlock(block, inst, tags[@intFromEnum(inst)] == .block_comptime);
                                              ^
/home/techatrix/repos/zig/src/Sema.zig:921:30: 0x2106108 in analyzeBody (zig)
  _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                           ^
/home/techatrix/repos/zig/src/Sema.zig:7515:33: 0x2730012 in analyzeCall (zig)
              sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) {
                              ^
/home/techatrix/repos/zig/src/Sema.zig:24369:28: 0x223e719 in zirBuiltinCall (zig)
  return sema.analyzeCall(
                         ^
/home/techatrix/repos/zig/src/Sema.zig:1151:69: 0x1e05be0 in analyzeBodyInner (zig)
          .builtin_call                 => try sema.zirBuiltinCall(block, inst),
                                                                  ^
/home/techatrix/repos/zig/src/Sema.zig:5887:34: 0x276da2d in resolveBlockBody (zig)
      if (sema.analyzeBodyInner(child_block, body)) |_| {
                               ^
/home/techatrix/repos/zig/src/Sema.zig:5870:33: 0x22a48ef in zirBlock (zig)
  return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                              ^
/home/techatrix/repos/zig/src/Sema.zig:1582:49: 0x1e10ce2 in analyzeBodyInner (zig)
                  break :blk try sema.zirBlock(block, inst, tags[@intFromEnum(inst)] == .block_comptime);
                                              ^
/home/techatrix/repos/zig/src/Sema.zig:921:30: 0x2106108 in analyzeBody (zig)
  _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                           ^
/home/techatrix/repos/zig/src/Sema.zig:7515:33: 0x2730012 in analyzeCall (zig)
              sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) {
                              ^
/home/techatrix/repos/zig/src/Sema.zig:6725:43: 0x21e9d9c in zirCall__anon_98476 (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/techatrix/repos/zig/src/Sema.zig:1032:62: 0x1e003c6 in analyzeBodyInner (zig)
          .call                         => try sema.zirCall(block, inst, .direct),
                                                           ^
/home/techatrix/repos/zig/src/Sema.zig:5887:34: 0x276da2d in resolveBlockBody (zig)
      if (sema.analyzeBodyInner(child_block, body)) |_| {
                               ^
/home/techatrix/repos/zig/src/Sema.zig:5870:33: 0x22a48ef in zirBlock (zig)
  return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                              ^
/home/techatrix/repos/zig/src/Sema.zig:1582:49: 0x1e10ce2 in analyzeBodyInner (zig)
                  break :blk try sema.zirBlock(block, inst, tags[@intFromEnum(inst)] == .block_comptime);
                                              ^
/home/techatrix/repos/zig/src/Sema.zig:921:30: 0x2106108 in analyzeBody (zig)
  _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                           ^
/home/techatrix/repos/zig/src/Sema.zig:7515:33: 0x2730012 in analyzeCall (zig)
              sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) {
                              ^
/home/techatrix/repos/zig/src/Sema.zig:24369:28: 0x223e719 in zirBuiltinCall (zig)
  return sema.analyzeCall(
                         ^
/home/techatrix/repos/zig/src/Sema.zig:1151:69: 0x1e05be0 in analyzeBodyInner (zig)
          .builtin_call                 => try sema.zirBuiltinCall(block, inst),
                                                                  ^
/home/techatrix/repos/zig/src/Sema.zig:938:45: 0x1b51cca in analyzeBodyBreak (zig)
  const break_inst = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                                          ^
/home/techatrix/repos/zig/src/Sema.zig:887:50: 0x2726703 in resolveBody (zig)
  const break_data = (try sema.analyzeBodyBreak(block, body)) orelse
                                               ^
/home/techatrix/repos/zig/src/Sema.zig:7014:59: 0x2c78265 in analyzeArg (zig)
              const uncoerced_arg = try sema.resolveBody(block, arg_body, zir_call.call_inst);
                                                        ^
/home/techatrix/repos/zig/src/Sema.zig:7579:49: 0x2731073 in analyzeCall (zig)
          arg_out.* = try args_info.analyzeArg(sema, block, arg_idx, param_ty, func_ty_info, func);
                                              ^
/home/techatrix/repos/zig/src/Sema.zig:6725:43: 0x21eaf1e in zirCall__anon_98477 (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/techatrix/repos/zig/src/Sema.zig:1033:62: 0x1e00482 in analyzeBodyInner (zig)
          .field_call                   => try sema.zirCall(block, inst, .field),
                                                           ^
/home/techatrix/repos/zig/src/Sema.zig:5887:34: 0x276da2d in resolveBlockBody (zig)
      if (sema.analyzeBodyInner(child_block, body)) |_| {
                               ^
/home/techatrix/repos/zig/src/Sema.zig:5870:33: 0x22a48ef in zirBlock (zig)
  return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                              ^
/home/techatrix/repos/zig/src/Sema.zig:1582:49: 0x1e10ce2 in analyzeBodyInner (zig)
                  break :blk try sema.zirBlock(block, inst, tags[@intFromEnum(inst)] == .block_comptime);
                                              ^
/home/techatrix/repos/zig/src/Sema.zig:921:30: 0x2106108 in analyzeBody (zig)
  _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                           ^
/home/techatrix/repos/zig/src/Module.zig:4575:21: 0x1ddee6c in analyzeFnBody (zig)
  sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
                  ^
/home/techatrix/repos/zig/src/Module.zig:3272:40: 0x1b30ae4 in ensureFuncBodyAnalyzed (zig)
          var air = zcu.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
                                     ^
/home/techatrix/repos/zig/src/Compilation.zig:3539:42: 0x1b2ee4f in processOneJob (zig)
          module.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {
                                       ^
/home/techatrix/repos/zig/src/Compilation.zig:3476:30: 0x18f7ba0 in performAllTheWork (zig)
          try processOneJob(comp, work_item, main_progress_node);
                           ^
/home/techatrix/repos/zig/src/Compilation.zig:2186:31: 0x18f384e in update (zig)
  try comp.performAllTheWork(main_progress_node);
                            ^
/home/techatrix/repos/zig/src/main.zig:4478:24: 0x1922e3c in updateModule (zig)
      try comp.update(main_progress_node);
                     ^
/home/techatrix/repos/zig/src/main.zig:3342:17: 0x1941143 in buildOutputType (zig)
  updateModule(comp, color) catch |err| switch (err) {
              ^
/home/techatrix/repos/zig/src/main.zig:285:31: 0x1739cb7 in mainArgs (zig)
      return buildOutputType(gpa, arena, args, .run);
                            ^
/home/techatrix/repos/zig/src/main.zig:223:20: 0x1736cc5 in main (zig)
  return mainArgs(gpa, arena, args);
                 ^
/home/techatrix/repos/zig/build/stage3/lib/zig/std/start.zig:585:37: 0x1736746 in main (zig)
          const result = root.main() catch |err| {
                                  ^
???:?:?: 0x7fffeb23ffcd in ??? (libc.so.6)
Unwind information for `libc.so.6:0x7fffeb23ffcd` was not available, trace may be incomplete

Aborted (core dumped)

Expected Behavior

file.zig:2:11: error: expected error union type, found 'bool'
    false catch |err| switch (err) {

The zirSwitchBlockErrUnion function doesn't properly check if the operand is a Error Union.

Probably caused by #18173.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behaviorfrontendTokenization, parsing, AstGen, Sema, and Liveness.regressionIt worked in a previous version of Zig, but stopped working.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions