Skip to content

switch on error doesn't validate operand type #18592

@Techatrix

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.

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