zig icon indicating copy to clipboard operation
zig copied to clipboard

Cannot use a struct literal in for loop else branch

Open unworthyEnzyme opened this issue 1 year ago • 1 comments

Zig Version

0.11.0-dev.3387+f04e65bc0

Steps to Reproduce and Observed Behavior

This doesn't compile

pub fn main() void {
    const S = struct { x: u8 };
    var x = for ([_]S{.{ .x = 42 }}) |s| {
        break s;
    } else S{ .x = 42 };
    _ = x;
}

and the compiler error is this

src\main.zig:3:13: error: incompatible types: 'main.main.S' and 'void'
    var x = for ([_]S{.{ .x = 42 }}) |s| {
            ^~~
src\main.zig:4:15: note: type 'main.main.S' here
        break s;

The weird thing is if we annotate x:

pub fn main() void {
    const S = struct { x: u8 };
    var x: S = for ([_]S{.{ .x = 42 }}) |s| {
        break s;
    } else S{ .x = 42 };
    _ = x;
}

It compiles fine.

Expected Behavior

Both of these code snippets should compile.

unworthyEnzyme avatar Jun 12 '23 15:06 unworthyEnzyme

Probably an AstGen bug:

 # Source bytes:       155B
 # Tokens:             59 (319B)
 # AST Nodes:          26 (458B)
 # Total ZIR bytes:    1.19921875KiB
 # Instructions:       65 (585B)
 # String Table Bytes: 15B
 # Extra Data Items:   141 (564B)
 %0 = extended(struct_decl(parent, Auto, {
   [133] export entry line(0) hash(34fbe0545d7f84aec7615dcececb4dd0): %1 = block_inline({
     %63 = func([email protected]_type, body={
       %2 = block({
         %3 = dbg_block_begin()
         %4 = dbg_stmt(2, 5)
         %5 = extended(struct_decl(known_non_opv, dbg_var, Auto, {}, {
           x: @Zir.Inst.Ref.u8_type,
         }) node_offset:2:15 to :2:31
         %6 = dbg_var_val(%5, "S")
         %7 = dbg_stmt(3, 5)
         %8 = alloc_inferred_mut() node_offset:3:5 to :3:8
         %9 = alloc(@Zir.Inst.Ref.usize_type) node_offset:3:13 to :3:16
         %10 = store(%9, @Zir.Inst.Ref.zero_usize)
         %11 = dbg_stmt(3, 18)
         %12 = int(1)
         %13 = block_comptime({
           %14 = break(%13, %5)
         }) node_offset:3:21 to :3:22
         %15 = array_type(%12, %13) node_offset:3:18 to :3:22
         %16 = field_type(%13, x) node_offset:3:31 to :3:33
         %17 = int(42)
         %18 = as_node(%16, %17) node_offset:3:31 to :3:33
         %19 = struct_init_anon([x=%18]) node_offset:3:23 to :3:35
         %20 = array_init(%15{%19}) node_offset:3:18 to :3:36
         %21 = for_len({%20}) node_offset:3:13 to :3:16
         %22 = loop({
           %23 = load(%9) node_offset:3:13 to :3:16
           %26 = block({
             %24 = cmp_lt(%23, %21) node_offset:3:13 to :3:16
             %25 = condbr(%24, {
               %30 = dbg_block_begin()
               %31 = elem_val(%20, %23) node_offset:3:18 to :3:36
               %32 = dbg_var_val(%31, "s")
               %33 = block({
                 %34 = dbg_block_begin()
                 %35 = dbg_stmt(4, 9)
                 %36 = store_to_block_ptr(%8, %31)
                 %37 = restore_err_ret_index(%22, @Zir.Inst.Ref.none)
-                %38 = break(%22, %31)
+                %38 = break(%22, @Zir.Inst.Ref.void_value)
                 %39 = dbg_block_end()
                 %40 = restore_err_ret_index(%33, @Zir.Inst.Ref.none)
                 %41 = break(%33, @Zir.Inst.Ref.void_value)
               }) node_offset:3:42 to :3:43
               %42 = dbg_block_end()
               %51 = break(%26, @Zir.Inst.Ref.void_value)
             }, {
               %43 = block_comptime({
                 %44 = break(%43, %5)
               }) node_offset:5:12 to :5:13
               %45 = validate_struct_init_ty(%43) node_offset:5:12 to :5:24
               %46 = coerce_result_ptr(%43, %8) node_offset:5:12 to :5:24
               %47 = field_ptr_init(%46, "x") node_offset:5:20 to :5:22
               %48 = int(42)
               %49 = store_node(%47, %48) node_offset:5:20 to :5:22
               %50 = validate_struct_init({
                 %47 = field_ptr_init(%46, "x") node_offset:5:20 to :5:22
               }) node_offset:5:12 to :5:24
               %52 = break(%22, @Zir.Inst.Ref.void_value)
             }) node_offset:3:13 to :3:16
           }) node_offset:3:13 to :3:16
           %27 = add_unsafe(%23, @Zir.Inst.Ref.one_usize) node_offset:3:13 to :3:16
           %28 = store(%9, %27)
           %29 = repeat() node_offset:3:13 to :3:16
         }) node_offset:3:13 to :3:16
         %53 = resolve_inferred_alloc(%8) node_offset:3:5 to :3:8
         %54 = dbg_var_ptr(%8, "x")
         %55 = dbg_stmt(6, 5)
         %56 = load(%8) node_offset:6:9 to :6:10
         %57 = ensure_result_non_error(%56) node_offset:6:9 to :6:10
         %58 = dbg_block_end()
         %59 = restore_err_ret_index(%2, @Zir.Inst.Ref.none)
         %60 = break(%2, @Zir.Inst.Ref.void_value)
       }) node_offset:1:24 to :1:25
       %61 = restore_err_ret_index(@Zir.Inst.Ref.none, @Zir.Inst.Ref.none)
       %62 = ret_implicit(@Zir.Inst.Ref.void_value) token_offset:7:1 to :7:2
     }) (lbrace=1:24,rbrace=7:1) node_offset:1:1 to :1:10
     %64 = break_inline(%1, %63)
   }) node_offset:1:1 to :1:23
 }, {}, {})

%31 and @Zir.Inst.Ref.void_value do not PTR Related to my complaint about inferred alloc using both block ptr and block result in #13410

jacobly0 avatar Jun 12 '23 16:06 jacobly0