| ... | ... | @@ -135,7 +135,6 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir { |
| 135 | 135 | var gz_instructions: std.ArrayListUnmanaged(Zir.Inst.Index) = .{}; |
| 136 | 136 | var gen_scope: GenZir = .{ |
| 137 | 137 | .force_comptime = true, |
| 138 | | .in_defer = false, |
| 139 | 138 | .parent = &top_scope.base, |
| 140 | 139 | .anon_name_strategy = .parent, |
| 141 | 140 | .decl_node_index = 0, |
| ... | ... | @@ -1856,6 +1855,16 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 1856 | 1855 | .gen_zir => { |
| 1857 | 1856 | const block_gz = scope.cast(GenZir).?; |
| 1858 | 1857 | |
| 1858 | if (block_gz.cur_defer_node != 0) { |
| 1859 | return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{ |
| 1860 | try astgen.errNoteNode( |
| 1861 | block_gz.cur_defer_node, |
| 1862 | "defer expression here", |
| 1863 | .{}, |
| 1864 | ), |
| 1865 | }); |
| 1866 | } |
| 1867 | |
| 1859 | 1868 | const block_inst = blk: { |
| 1860 | 1869 | if (break_label != 0) { |
| 1861 | 1870 | if (block_gz.label) |*label| { |
| ... | ... | @@ -1919,17 +1928,6 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 1919 | 1928 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 1920 | 1929 | .namespace => break, |
| 1921 | 1930 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 1922 | | .defer_gen => { |
| 1923 | | const defer_gen = scope.cast(Scope.DeferGen).?; |
| 1924 | | |
| 1925 | | return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{ |
| 1926 | | try astgen.errNoteNode( |
| 1927 | | defer_gen.defer_node, |
| 1928 | | "defer expression here", |
| 1929 | | .{}, |
| 1930 | | ), |
| 1931 | | }); |
| 1932 | | }, |
| 1933 | 1931 | .top => unreachable, |
| 1934 | 1932 | } |
| 1935 | 1933 | } |
| ... | ... | @@ -1953,6 +1951,16 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 1953 | 1951 | switch (scope.tag) { |
| 1954 | 1952 | .gen_zir => { |
| 1955 | 1953 | const gen_zir = scope.cast(GenZir).?; |
| 1954 | |
| 1955 | if (gen_zir.cur_defer_node != 0) { |
| 1956 | return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{ |
| 1957 | try astgen.errNoteNode( |
| 1958 | gen_zir.cur_defer_node, |
| 1959 | "defer expression here", |
| 1960 | .{}, |
| 1961 | ), |
| 1962 | }); |
| 1963 | } |
| 1956 | 1964 | const continue_block = gen_zir.continue_block; |
| 1957 | 1965 | if (continue_block == 0) { |
| 1958 | 1966 | scope = gen_zir.parent; |
| ... | ... | @@ -1985,21 +1993,9 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 1985 | 1993 | .defer_normal => { |
| 1986 | 1994 | const defer_scope = scope.cast(Scope.Defer).?; |
| 1987 | 1995 | scope = defer_scope.parent; |
| 1988 | | const expr_node = node_datas[defer_scope.defer_node].rhs; |
| 1989 | | try unusedResultDeferExpr(parent_gz, defer_scope, defer_scope.parent, expr_node); |
| 1996 | try parent_gz.addDefer(defer_scope.index, defer_scope.len); |
| 1990 | 1997 | }, |
| 1991 | 1998 | .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 1992 | | .defer_gen => { |
| 1993 | | const defer_gen = scope.cast(Scope.DeferGen).?; |
| 1994 | | |
| 1995 | | return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{ |
| 1996 | | try astgen.errNoteNode( |
| 1997 | | defer_gen.defer_node, |
| 1998 | | "defer expression here", |
| 1999 | | .{}, |
| 2000 | | ), |
| 2001 | | }); |
| 2002 | | }, |
| 2003 | 1999 | .namespace => break, |
| 2004 | 2000 | .top => unreachable, |
| 2005 | 2001 | } |
| ... | ... | @@ -2064,7 +2060,6 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke |
| 2064 | 2060 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 2065 | 2061 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 2066 | 2062 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 2067 | | .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent, |
| 2068 | 2063 | .namespace => break, |
| 2069 | 2064 | .top => unreachable, |
| 2070 | 2065 | } |
| ... | ... | @@ -2208,8 +2203,8 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2208 | 2203 | .simple_var_decl => scope = try varDecl(gz, scope, statement, block_arena_allocator, tree.simpleVarDecl(statement)), |
| 2209 | 2204 | .aligned_var_decl => scope = try varDecl(gz, scope, statement, block_arena_allocator, tree.alignedVarDecl(statement)), |
| 2210 | 2205 | |
| 2211 | | .@"defer" => scope = try makeDeferScope(gz.astgen, scope, statement, block_arena_allocator, .defer_normal), |
| 2212 | | .@"errdefer" => scope = try makeDeferScope(gz.astgen, scope, statement, block_arena_allocator, .defer_error), |
| 2206 | .@"defer" => scope = try deferStmt(gz, scope, statement, block_arena_allocator, .defer_normal), |
| 2207 | .@"errdefer" => scope = try deferStmt(gz, scope, statement, block_arena_allocator, .defer_error), |
| 2213 | 2208 | |
| 2214 | 2209 | .assign => try assign(gz, scope, statement), |
| 2215 | 2210 | |
| ... | ... | @@ -2253,28 +2248,6 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2253 | 2248 | try checkUsed(gz, parent_scope, scope); |
| 2254 | 2249 | } |
| 2255 | 2250 | |
| 2256 | | fn unusedResultDeferExpr(gz: *GenZir, defer_scope: *Scope.Defer, expr_scope: *Scope, expr_node: Ast.Node.Index) InnerError!void { |
| 2257 | | const astgen = gz.astgen; |
| 2258 | | const prev_offset = astgen.source_offset; |
| 2259 | | const prev_line = astgen.source_line; |
| 2260 | | const prev_column = astgen.source_column; |
| 2261 | | defer { |
| 2262 | | astgen.source_offset = prev_offset; |
| 2263 | | astgen.source_line = prev_line; |
| 2264 | | astgen.source_column = prev_column; |
| 2265 | | } |
| 2266 | | astgen.source_offset = defer_scope.source_offset; |
| 2267 | | astgen.source_line = defer_scope.source_line; |
| 2268 | | astgen.source_column = defer_scope.source_column; |
| 2269 | | |
| 2270 | | var defer_gen: Scope.DeferGen = .{ |
| 2271 | | .parent = expr_scope, |
| 2272 | | .defer_node = defer_scope.defer_node, |
| 2273 | | }; |
| 2274 | | |
| 2275 | | _ = try unusedResultExpr(gz, &defer_gen.base, expr_node); |
| 2276 | | } |
| 2277 | | |
| 2278 | 2251 | /// Returns AST source node of the thing that is noreturn if the statement is |
| 2279 | 2252 | /// definitely `noreturn`. Otherwise returns 0. |
| 2280 | 2253 | fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.Index { |
| ... | ... | @@ -2584,6 +2557,9 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2584 | 2557 | .validate_struct_init_ty, |
| 2585 | 2558 | .validate_deref, |
| 2586 | 2559 | => break :b true, |
| 2560 | |
| 2561 | .@"defer" => unreachable, |
| 2562 | .defer_err_code => unreachable, |
| 2587 | 2563 | } |
| 2588 | 2564 | } else switch (maybe_unused_result) { |
| 2589 | 2565 | .none => unreachable, |
| ... | ... | @@ -2603,15 +2579,12 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2603 | 2579 | return noreturn_src_node; |
| 2604 | 2580 | } |
| 2605 | 2581 | |
| 2606 | | fn countDefers(astgen: *AstGen, outer_scope: *Scope, inner_scope: *Scope) struct { |
| 2582 | fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct { |
| 2607 | 2583 | have_any: bool, |
| 2608 | 2584 | have_normal: bool, |
| 2609 | 2585 | have_err: bool, |
| 2610 | 2586 | need_err_code: bool, |
| 2611 | 2587 | } { |
| 2612 | | const tree = astgen.tree; |
| 2613 | | const node_datas = tree.nodes.items(.data); |
| 2614 | | |
| 2615 | 2588 | var have_normal = false; |
| 2616 | 2589 | var have_err = false; |
| 2617 | 2590 | var need_err_code = false; |
| ... | ... | @@ -2621,7 +2594,6 @@ fn countDefers(astgen: *AstGen, outer_scope: *Scope, inner_scope: *Scope) struct |
| 2621 | 2594 | .gen_zir => scope = scope.cast(GenZir).?.parent, |
| 2622 | 2595 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 2623 | 2596 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 2624 | | .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent, |
| 2625 | 2597 | .defer_normal => { |
| 2626 | 2598 | const defer_scope = scope.cast(Scope.Defer).?; |
| 2627 | 2599 | scope = defer_scope.parent; |
| ... | ... | @@ -2634,7 +2606,7 @@ fn countDefers(astgen: *AstGen, outer_scope: *Scope, inner_scope: *Scope) struct |
| 2634 | 2606 | |
| 2635 | 2607 | have_err = true; |
| 2636 | 2608 | |
| 2637 | | const have_err_payload = node_datas[defer_scope.defer_node].lhs != 0; |
| 2609 | const have_err_payload = defer_scope.remapped_err_code != 0; |
| 2638 | 2610 | need_err_code = need_err_code or have_err_payload; |
| 2639 | 2611 | }, |
| 2640 | 2612 | .namespace => unreachable, |
| ... | ... | @@ -2661,9 +2633,7 @@ fn genDefers( |
| 2661 | 2633 | inner_scope: *Scope, |
| 2662 | 2634 | which_ones: DefersToEmit, |
| 2663 | 2635 | ) InnerError!void { |
| 2664 | | const astgen = gz.astgen; |
| 2665 | | const tree = astgen.tree; |
| 2666 | | const node_datas = tree.nodes.items(.data); |
| 2636 | const gpa = gz.astgen.gpa; |
| 2667 | 2637 | |
| 2668 | 2638 | var scope = inner_scope; |
| 2669 | 2639 | while (scope != outer_scope) { |
| ... | ... | @@ -2671,51 +2641,40 @@ fn genDefers( |
| 2671 | 2641 | .gen_zir => scope = scope.cast(GenZir).?.parent, |
| 2672 | 2642 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 2673 | 2643 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 2674 | | .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent, |
| 2675 | 2644 | .defer_normal => { |
| 2676 | 2645 | const defer_scope = scope.cast(Scope.Defer).?; |
| 2677 | 2646 | scope = defer_scope.parent; |
| 2678 | | const expr_node = node_datas[defer_scope.defer_node].rhs; |
| 2679 | | const prev_in_defer = gz.in_defer; |
| 2680 | | gz.in_defer = true; |
| 2681 | | defer gz.in_defer = prev_in_defer; |
| 2682 | | try unusedResultDeferExpr(gz, defer_scope, defer_scope.parent, expr_node); |
| 2647 | try gz.addDefer(defer_scope.index, defer_scope.len); |
| 2683 | 2648 | }, |
| 2684 | 2649 | .defer_error => { |
| 2685 | 2650 | const defer_scope = scope.cast(Scope.Defer).?; |
| 2686 | 2651 | scope = defer_scope.parent; |
| 2687 | 2652 | switch (which_ones) { |
| 2688 | 2653 | .both_sans_err => { |
| 2689 | | const expr_node = node_datas[defer_scope.defer_node].rhs; |
| 2690 | | const prev_in_defer = gz.in_defer; |
| 2691 | | gz.in_defer = true; |
| 2692 | | defer gz.in_defer = prev_in_defer; |
| 2693 | | try unusedResultDeferExpr(gz, defer_scope, defer_scope.parent, expr_node); |
| 2654 | try gz.addDefer(defer_scope.index, defer_scope.len); |
| 2694 | 2655 | }, |
| 2695 | 2656 | .both => |err_code| { |
| 2696 | | const expr_node = node_datas[defer_scope.defer_node].rhs; |
| 2697 | | const payload_token = node_datas[defer_scope.defer_node].lhs; |
| 2698 | | const prev_in_defer = gz.in_defer; |
| 2699 | | gz.in_defer = true; |
| 2700 | | defer gz.in_defer = prev_in_defer; |
| 2701 | | var local_val_scope: Scope.LocalVal = undefined; |
| 2702 | | try gz.addDbgBlockBegin(); |
| 2703 | | const sub_scope = if (payload_token == 0) defer_scope.parent else blk: { |
| 2704 | | const ident_name = try astgen.identAsString(payload_token); |
| 2705 | | local_val_scope = .{ |
| 2706 | | .parent = defer_scope.parent, |
| 2707 | | .gen_zir = gz, |
| 2708 | | .name = ident_name, |
| 2709 | | .inst = err_code, |
| 2710 | | .token_src = payload_token, |
| 2711 | | .id_cat = .@"capture", |
| 2712 | | }; |
| 2713 | | try gz.addDbgVar(.dbg_var_val, ident_name, err_code); |
| 2714 | | break :blk &local_val_scope.base; |
| 2715 | | }; |
| 2716 | | try unusedResultDeferExpr(gz, defer_scope, sub_scope, expr_node); |
| 2717 | | try checkUsed(gz, scope, sub_scope); |
| 2718 | | try gz.addDbgBlockEnd(); |
| 2657 | if (defer_scope.remapped_err_code == 0) { |
| 2658 | try gz.addDefer(defer_scope.index, defer_scope.len); |
| 2659 | } else { |
| 2660 | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| 2661 | try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| 2662 | |
| 2663 | const payload_index = try gz.astgen.addExtra(Zir.Inst.DeferErrCode{ |
| 2664 | .remapped_err_code = defer_scope.remapped_err_code, |
| 2665 | .index = defer_scope.index, |
| 2666 | .len = defer_scope.len, |
| 2667 | }); |
| 2668 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| 2669 | gz.astgen.instructions.appendAssumeCapacity(.{ |
| 2670 | .tag = .defer_err_code, |
| 2671 | .data = .{ .defer_err_code = .{ |
| 2672 | .err_code = err_code, |
| 2673 | .payload_index = payload_index, |
| 2674 | } }, |
| 2675 | }); |
| 2676 | gz.instructions.appendAssumeCapacity(new_index); |
| 2677 | } |
| 2719 | 2678 | }, |
| 2720 | 2679 | .normal_only => continue, |
| 2721 | 2680 | } |
| ... | ... | @@ -2752,35 +2711,68 @@ fn checkUsed( |
| 2752 | 2711 | scope = s.parent; |
| 2753 | 2712 | }, |
| 2754 | 2713 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 2755 | | .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent, |
| 2756 | 2714 | .namespace => unreachable, |
| 2757 | 2715 | .top => unreachable, |
| 2758 | 2716 | } |
| 2759 | 2717 | } |
| 2760 | 2718 | } |
| 2761 | 2719 | |
| 2762 | | fn makeDeferScope( |
| 2763 | | astgen: *AstGen, |
| 2720 | fn deferStmt( |
| 2721 | gz: *GenZir, |
| 2764 | 2722 | scope: *Scope, |
| 2765 | 2723 | node: Ast.Node.Index, |
| 2766 | 2724 | block_arena: Allocator, |
| 2767 | 2725 | scope_tag: Scope.Tag, |
| 2768 | 2726 | ) InnerError!*Scope { |
| 2769 | | const tree = astgen.tree; |
| 2727 | var defer_gen = gz.makeSubBlock(scope); |
| 2728 | defer_gen.cur_defer_node = node; |
| 2729 | defer_gen.any_defer_node = node; |
| 2730 | defer defer_gen.unstack(); |
| 2731 | |
| 2732 | const tree = gz.astgen.tree; |
| 2770 | 2733 | const node_datas = tree.nodes.items(.data); |
| 2771 | 2734 | const expr_node = node_datas[node].rhs; |
| 2772 | | const token_starts = tree.tokens.items(.start); |
| 2773 | | const node_start = token_starts[tree.firstToken(expr_node)]; |
| 2735 | |
| 2736 | const payload_token = node_datas[node].lhs; |
| 2737 | var local_val_scope: Scope.LocalVal = undefined; |
| 2738 | var remapped_err_code: Zir.Inst.Index = 0; |
| 2739 | const have_err_code = scope_tag == .defer_error and payload_token != 0; |
| 2740 | const sub_scope = if (!have_err_code) &defer_gen.base else blk: { |
| 2741 | try gz.addDbgBlockBegin(); |
| 2742 | const ident_name = try gz.astgen.identAsString(payload_token); |
| 2743 | remapped_err_code = @intCast(u32, try gz.astgen.instructions.addOne(gz.astgen.gpa)); |
| 2744 | const remapped_err_code_ref = Zir.indexToRef(remapped_err_code); |
| 2745 | local_val_scope = .{ |
| 2746 | .parent = &defer_gen.base, |
| 2747 | .gen_zir = gz, |
| 2748 | .name = ident_name, |
| 2749 | .inst = remapped_err_code_ref, |
| 2750 | .token_src = payload_token, |
| 2751 | .id_cat = .@"capture", |
| 2752 | }; |
| 2753 | try gz.addDbgVar(.dbg_var_val, ident_name, remapped_err_code_ref); |
| 2754 | break :blk &local_val_scope.base; |
| 2755 | }; |
| 2756 | _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node); |
| 2757 | try checkUsed(gz, scope, sub_scope); |
| 2758 | if (have_err_code) try gz.addDbgBlockEnd(); |
| 2759 | _ = try defer_gen.addBreak(.break_inline, 0, .void_value); |
| 2760 | |
| 2761 | const body = defer_gen.instructionsSlice(); |
| 2762 | const body_len = gz.astgen.countBodyLenAfterFixups(body); |
| 2763 | |
| 2764 | const index = @intCast(u32, gz.astgen.extra.items.len); |
| 2765 | try gz.astgen.extra.ensureUnusedCapacity(gz.astgen.gpa, body_len); |
| 2766 | gz.astgen.appendBodyWithFixups(body); |
| 2767 | |
| 2774 | 2768 | const defer_scope = try block_arena.create(Scope.Defer); |
| 2775 | | astgen.advanceSourceCursor(node_start); |
| 2776 | 2769 | |
| 2777 | 2770 | defer_scope.* = .{ |
| 2778 | 2771 | .base = .{ .tag = scope_tag }, |
| 2779 | 2772 | .parent = scope, |
| 2780 | | .defer_node = node, |
| 2781 | | .source_offset = astgen.source_offset, |
| 2782 | | .source_line = astgen.source_line, |
| 2783 | | .source_column = astgen.source_column, |
| 2773 | .index = index, |
| 2774 | .len = body_len, |
| 2775 | .remapped_err_code = remapped_err_code, |
| 2784 | 2776 | }; |
| 2785 | 2777 | return &defer_scope.base; |
| 2786 | 2778 | } |
| ... | ... | @@ -3461,7 +3453,6 @@ fn fnDecl( |
| 3461 | 3453 | |
| 3462 | 3454 | var decl_gz: GenZir = .{ |
| 3463 | 3455 | .force_comptime = true, |
| 3464 | | .in_defer = false, |
| 3465 | 3456 | .decl_node_index = fn_proto.ast.proto_node, |
| 3466 | 3457 | .decl_line = astgen.source_line, |
| 3467 | 3458 | .parent = scope, |
| ... | ... | @@ -3473,7 +3464,6 @@ fn fnDecl( |
| 3473 | 3464 | |
| 3474 | 3465 | var fn_gz: GenZir = .{ |
| 3475 | 3466 | .force_comptime = false, |
| 3476 | | .in_defer = false, |
| 3477 | 3467 | .decl_node_index = fn_proto.ast.proto_node, |
| 3478 | 3468 | .decl_line = decl_gz.decl_line, |
| 3479 | 3469 | .parent = &decl_gz.base, |
| ... | ... | @@ -3812,7 +3802,6 @@ fn globalVarDecl( |
| 3812 | 3802 | .decl_line = astgen.source_line, |
| 3813 | 3803 | .astgen = astgen, |
| 3814 | 3804 | .force_comptime = true, |
| 3815 | | .in_defer = false, |
| 3816 | 3805 | .anon_name_strategy = .parent, |
| 3817 | 3806 | .instructions = gz.instructions, |
| 3818 | 3807 | .instructions_top = gz.instructions.items.len, |
| ... | ... | @@ -3964,7 +3953,6 @@ fn comptimeDecl( |
| 3964 | 3953 | |
| 3965 | 3954 | var decl_block: GenZir = .{ |
| 3966 | 3955 | .force_comptime = true, |
| 3967 | | .in_defer = false, |
| 3968 | 3956 | .decl_node_index = node, |
| 3969 | 3957 | .decl_line = astgen.source_line, |
| 3970 | 3958 | .parent = scope, |
| ... | ... | @@ -4019,7 +4007,6 @@ fn usingnamespaceDecl( |
| 4019 | 4007 | |
| 4020 | 4008 | var decl_block: GenZir = .{ |
| 4021 | 4009 | .force_comptime = true, |
| 4022 | | .in_defer = false, |
| 4023 | 4010 | .decl_node_index = node, |
| 4024 | 4011 | .decl_line = astgen.source_line, |
| 4025 | 4012 | .parent = scope, |
| ... | ... | @@ -4067,7 +4054,6 @@ fn testDecl( |
| 4067 | 4054 | |
| 4068 | 4055 | var decl_block: GenZir = .{ |
| 4069 | 4056 | .force_comptime = true, |
| 4070 | | .in_defer = false, |
| 4071 | 4057 | .decl_node_index = node, |
| 4072 | 4058 | .decl_line = astgen.source_line, |
| 4073 | 4059 | .parent = scope, |
| ... | ... | @@ -4132,7 +4118,6 @@ fn testDecl( |
| 4132 | 4118 | .local_val, .local_ptr => unreachable, // a test cannot be in a local scope |
| 4133 | 4119 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 4134 | 4120 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 4135 | | .defer_gen => s = s.cast(Scope.DeferGen).?.parent, |
| 4136 | 4121 | .namespace => { |
| 4137 | 4122 | const ns = s.cast(Scope.Namespace).?; |
| 4138 | 4123 | if (ns.decls.get(name_str_index)) |i| { |
| ... | ... | @@ -4164,7 +4149,6 @@ fn testDecl( |
| 4164 | 4149 | |
| 4165 | 4150 | var fn_block: GenZir = .{ |
| 4166 | 4151 | .force_comptime = false, |
| 4167 | | .in_defer = false, |
| 4168 | 4152 | .decl_node_index = node, |
| 4169 | 4153 | .decl_line = decl_block.decl_line, |
| 4170 | 4154 | .parent = &decl_block.base, |
| ... | ... | @@ -4288,7 +4272,6 @@ fn structDeclInner( |
| 4288 | 4272 | .decl_line = decl_line, |
| 4289 | 4273 | .astgen = astgen, |
| 4290 | 4274 | .force_comptime = true, |
| 4291 | | .in_defer = false, |
| 4292 | 4275 | .instructions = gz.instructions, |
| 4293 | 4276 | .instructions_top = gz.instructions.items.len, |
| 4294 | 4277 | }; |
| ... | ... | @@ -4489,7 +4472,6 @@ fn unionDeclInner( |
| 4489 | 4472 | .decl_line = astgen.source_line, |
| 4490 | 4473 | .astgen = astgen, |
| 4491 | 4474 | .force_comptime = true, |
| 4492 | | .in_defer = false, |
| 4493 | 4475 | .instructions = gz.instructions, |
| 4494 | 4476 | .instructions_top = gz.instructions.items.len, |
| 4495 | 4477 | }; |
| ... | ... | @@ -4773,7 +4755,6 @@ fn containerDecl( |
| 4773 | 4755 | .decl_line = astgen.source_line, |
| 4774 | 4756 | .astgen = astgen, |
| 4775 | 4757 | .force_comptime = true, |
| 4776 | | .in_defer = false, |
| 4777 | 4758 | .instructions = gz.instructions, |
| 4778 | 4759 | .instructions_top = gz.instructions.items.len, |
| 4779 | 4760 | }; |
| ... | ... | @@ -4879,7 +4860,6 @@ fn containerDecl( |
| 4879 | 4860 | .decl_line = astgen.source_line, |
| 4880 | 4861 | .astgen = astgen, |
| 4881 | 4862 | .force_comptime = true, |
| 4882 | | .in_defer = false, |
| 4883 | 4863 | .instructions = gz.instructions, |
| 4884 | 4864 | .instructions_top = gz.instructions.items.len, |
| 4885 | 4865 | }; |
| ... | ... | @@ -5110,7 +5090,15 @@ fn tryExpr( |
| 5110 | 5090 | return astgen.failNode(node, "'try' outside function scope", .{}); |
| 5111 | 5091 | }; |
| 5112 | 5092 | |
| 5113 | | if (parent_gz.in_defer) return astgen.failNode(node, "'try' not allowed inside defer expression", .{}); |
| 5093 | if (parent_gz.any_defer_node != 0) { |
| 5094 | return astgen.failNodeNotes(node, "'try' not allowed inside defer expression", .{}, &.{ |
| 5095 | try astgen.errNoteNode( |
| 5096 | parent_gz.any_defer_node, |
| 5097 | "defer expression here", |
| 5098 | .{}, |
| 5099 | ), |
| 5100 | }); |
| 5101 | } |
| 5114 | 5102 | |
| 5115 | 5103 | // Ensure debug line/column information is emitted for this try expression. |
| 5116 | 5104 | // Then we will save the line/column so that we can emit another one that goes |
| ... | ... | @@ -6656,7 +6644,15 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6656 | 6644 | return astgen.failNode(node, "'return' outside function scope", .{}); |
| 6657 | 6645 | } |
| 6658 | 6646 | |
| 6659 | | if (gz.in_defer) return astgen.failNode(node, "cannot return from defer expression", .{}); |
| 6647 | if (gz.any_defer_node != 0) { |
| 6648 | return astgen.failNodeNotes(node, "cannot return from defer expression", .{}, &.{ |
| 6649 | try astgen.errNoteNode( |
| 6650 | gz.any_defer_node, |
| 6651 | "defer expression here", |
| 6652 | .{}, |
| 6653 | ), |
| 6654 | }); |
| 6655 | } |
| 6660 | 6656 | |
| 6661 | 6657 | // Ensure debug line/column information is emitted for this return expression. |
| 6662 | 6658 | // Then we will save the line/column so that we can emit another one that goes |
| ... | ... | @@ -6683,7 +6679,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6683 | 6679 | // for detecting whether to add something to the function's inferred error set. |
| 6684 | 6680 | const ident_token = node_datas[operand_node].rhs; |
| 6685 | 6681 | const err_name_str_index = try astgen.identAsString(ident_token); |
| 6686 | | const defer_counts = countDefers(astgen, defer_outer, scope); |
| 6682 | const defer_counts = countDefers(defer_outer, scope); |
| 6687 | 6683 | if (!defer_counts.need_err_code) { |
| 6688 | 6684 | try genDefers(gz, defer_outer, scope, .both_sans_err); |
| 6689 | 6685 | try emitDbgStmt(gz, ret_line, ret_column); |
| ... | ... | @@ -6724,7 +6720,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6724 | 6720 | return Zir.Inst.Ref.unreachable_value; |
| 6725 | 6721 | }, |
| 6726 | 6722 | .maybe => { |
| 6727 | | const defer_counts = countDefers(astgen, defer_outer, scope); |
| 6723 | const defer_counts = countDefers(defer_outer, scope); |
| 6728 | 6724 | if (!defer_counts.have_err) { |
| 6729 | 6725 | // Only regular defers; no branch needed. |
| 6730 | 6726 | try genDefers(gz, defer_outer, scope, .normal_only); |
| ... | ... | @@ -6921,7 +6917,6 @@ fn localVarRef( |
| 6921 | 6917 | }, |
| 6922 | 6918 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 6923 | 6919 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 6924 | | .defer_gen => s = s.cast(Scope.DeferGen).?.parent, |
| 6925 | 6920 | .namespace => { |
| 6926 | 6921 | const ns = s.cast(Scope.Namespace).?; |
| 6927 | 6922 | if (ns.decls.get(name_str_index)) |i| { |
| ... | ... | @@ -7550,7 +7545,6 @@ fn builtinCall( |
| 7550 | 7545 | }, |
| 7551 | 7546 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 7552 | 7547 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 7553 | | .defer_gen => s = s.cast(Scope.DeferGen).?.parent, |
| 7554 | 7548 | .namespace => { |
| 7555 | 7549 | const ns = s.cast(Scope.Namespace).?; |
| 7556 | 7550 | if (ns.decls.get(decl_name)) |i| { |
| ... | ... | @@ -10046,7 +10040,6 @@ const Scope = struct { |
| 10046 | 10040 | local_ptr, |
| 10047 | 10041 | defer_normal, |
| 10048 | 10042 | defer_error, |
| 10049 | | defer_gen, |
| 10050 | 10043 | namespace, |
| 10051 | 10044 | top, |
| 10052 | 10045 | }; |
| ... | ... | @@ -10105,10 +10098,9 @@ const Scope = struct { |
| 10105 | 10098 | base: Scope, |
| 10106 | 10099 | /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`, `Namespace`. |
| 10107 | 10100 | parent: *Scope, |
| 10108 | | defer_node: Ast.Node.Index, |
| 10109 | | source_offset: u32, |
| 10110 | | source_line: u32, |
| 10111 | | source_column: u32, |
| 10101 | index: u32, |
| 10102 | len: u32, |
| 10103 | remapped_err_code: Zir.Inst.Index = 0, |
| 10112 | 10104 | }; |
| 10113 | 10105 | |
| 10114 | 10106 | /// Represents a global scope that has any number of declarations in it. |
| ... | ... | @@ -10144,13 +10136,6 @@ const Scope = struct { |
| 10144 | 10136 | const base_tag: Scope.Tag = .top; |
| 10145 | 10137 | base: Scope = Scope{ .tag = base_tag }, |
| 10146 | 10138 | }; |
| 10147 | | |
| 10148 | | const DeferGen = struct { |
| 10149 | | const base_tag: Scope.Tag = .defer_gen; |
| 10150 | | base: Scope = Scope{ .tag = base_tag }, |
| 10151 | | parent: *Scope, |
| 10152 | | defer_node: Ast.Node.Index, |
| 10153 | | }; |
| 10154 | 10139 | }; |
| 10155 | 10140 | |
| 10156 | 10141 | /// This is a temporary structure; references to it are valid only |
| ... | ... | @@ -10161,7 +10146,6 @@ const GenZir = struct { |
| 10161 | 10146 | force_comptime: bool, |
| 10162 | 10147 | /// This is set to true for inline loops; false otherwise. |
| 10163 | 10148 | is_inline: bool = false, |
| 10164 | | in_defer: bool, |
| 10165 | 10149 | c_import: bool = false, |
| 10166 | 10150 | /// How decls created in this scope should be named. |
| 10167 | 10151 | anon_name_strategy: Zir.Inst.NameStrategy = .anon, |
| ... | ... | @@ -10204,6 +10188,10 @@ const GenZir = struct { |
| 10204 | 10188 | |
| 10205 | 10189 | suspend_node: Ast.Node.Index = 0, |
| 10206 | 10190 | nosuspend_node: Ast.Node.Index = 0, |
| 10191 | /// Set if this GenZir is a defer. |
| 10192 | cur_defer_node: Ast.Node.Index = 0, |
| 10193 | // Set if this GenZir is a defer or it is inside a defer. |
| 10194 | any_defer_node: Ast.Node.Index = 0, |
| 10207 | 10195 | |
| 10208 | 10196 | /// Namespace members are lazy. When executing a decl within a namespace, |
| 10209 | 10197 | /// any references to external instructions need to be treated specially. |
| ... | ... | @@ -10244,7 +10232,6 @@ const GenZir = struct { |
| 10244 | 10232 | fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir { |
| 10245 | 10233 | return .{ |
| 10246 | 10234 | .force_comptime = gz.force_comptime, |
| 10247 | | .in_defer = gz.in_defer, |
| 10248 | 10235 | .c_import = gz.c_import, |
| 10249 | 10236 | .decl_node_index = gz.decl_node_index, |
| 10250 | 10237 | .decl_line = gz.decl_line, |
| ... | ... | @@ -10253,6 +10240,7 @@ const GenZir = struct { |
| 10253 | 10240 | .astgen = gz.astgen, |
| 10254 | 10241 | .suspend_node = gz.suspend_node, |
| 10255 | 10242 | .nosuspend_node = gz.nosuspend_node, |
| 10243 | .any_defer_node = gz.any_defer_node, |
| 10256 | 10244 | .instructions = gz.instructions, |
| 10257 | 10245 | .instructions_top = gz.instructions.items.len, |
| 10258 | 10246 | }; |
| ... | ... | @@ -11107,6 +11095,16 @@ const GenZir = struct { |
| 11107 | 11095 | }); |
| 11108 | 11096 | } |
| 11109 | 11097 | |
| 11098 | fn addDefer(gz: *GenZir, index: u32, len: u32) !void { |
| 11099 | _ = try gz.add(.{ |
| 11100 | .tag = .@"defer", |
| 11101 | .data = .{ .@"defer" = .{ |
| 11102 | .index = index, |
| 11103 | .len = len, |
| 11104 | } }, |
| 11105 | }); |
| 11106 | } |
| 11107 | |
| 11110 | 11108 | fn addDecl( |
| 11111 | 11109 | gz: *GenZir, |
| 11112 | 11110 | tag: Zir.Inst.Tag, |
| ... | ... | @@ -11670,7 +11668,6 @@ fn detectLocalShadowing( |
| 11670 | 11668 | }, |
| 11671 | 11669 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 11672 | 11670 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 11673 | | .defer_gen => s = s.cast(Scope.DeferGen).?.parent, |
| 11674 | 11671 | .top => break, |
| 11675 | 11672 | }; |
| 11676 | 11673 | } |
| ... | ... | @@ -11809,7 +11806,6 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. |
| 11809 | 11806 | .namespace => s = s.cast(Scope.Namespace).?.parent, |
| 11810 | 11807 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 11811 | 11808 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 11812 | | .defer_gen => s = s.cast(Scope.DeferGen).?.parent, |
| 11813 | 11809 | .top => break, |
| 11814 | 11810 | }; |
| 11815 | 11811 | gop.value_ptr.* = member_node; |