| ... | @@ -857,13 +857,10 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -857,13 +857,10 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 857 | const if_full = tree.fullIf(node).?; | 857 | const if_full = tree.fullIf(node).?; |
| 858 | no_switch_on_err: { | 858 | no_switch_on_err: { |
| 859 | const error_token = if_full.error_token orelse break :no_switch_on_err; | 859 | const error_token = if_full.error_token orelse break :no_switch_on_err; |
| 860 | switch (node_tags[if_full.ast.else_expr]) { | 860 | const full_switch = tree.fullSwitch(if_full.ast.else_expr) orelse break :no_switch_on_err; |
| 861 | .@"switch", .switch_comma => {}, | 861 | if (full_switch.label_token != null) break :no_switch_on_err; |
| 862 | else => break :no_switch_on_err, | 862 | if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err; |
| 863 | } | 863 | if (!mem.eql(u8, tree.tokenSlice(error_token), tree.tokenSlice(main_tokens[full_switch.ast.condition]))) break :no_switch_on_err; |
| 864 | const switch_operand = node_datas[if_full.ast.else_expr].lhs; | | |
| 865 | if (node_tags[switch_operand] != .identifier) break :no_switch_on_err; | | |
| 866 | if (!mem.eql(u8, tree.tokenSlice(error_token), tree.tokenSlice(main_tokens[switch_operand]))) break :no_switch_on_err; | | |
| 867 | return switchExprErrUnion(gz, scope, ri.br(), node, .@"if"); | 864 | return switchExprErrUnion(gz, scope, ri.br(), node, .@"if"); |
| 868 | } | 865 | } |
| 869 | return ifExpr(gz, scope, ri.br(), node, if_full); | 866 | return ifExpr(gz, scope, ri.br(), node, if_full); |
| ... | @@ -1049,13 +1046,10 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -1049,13 +1046,10 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1049 | null; | 1046 | null; |
| 1050 | no_switch_on_err: { | 1047 | no_switch_on_err: { |
| 1051 | const capture_token = payload_token orelse break :no_switch_on_err; | 1048 | const capture_token = payload_token orelse break :no_switch_on_err; |
| 1052 | switch (node_tags[node_datas[node].rhs]) { | 1049 | const full_switch = tree.fullSwitch(node_datas[node].rhs) orelse break :no_switch_on_err; |
| 1053 | .@"switch", .switch_comma => {}, | 1050 | if (full_switch.label_token != null) break :no_switch_on_err; |
| 1054 | else => break :no_switch_on_err, | 1051 | if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err; |
| 1055 | } | 1052 | if (!mem.eql(u8, tree.tokenSlice(capture_token), tree.tokenSlice(main_tokens[full_switch.ast.condition]))) break :no_switch_on_err; |
| 1056 | const switch_operand = node_datas[node_datas[node].rhs].lhs; | | |
| 1057 | if (node_tags[switch_operand] != .identifier) break :no_switch_on_err; | | |
| 1058 | if (!mem.eql(u8, tree.tokenSlice(capture_token), tree.tokenSlice(main_tokens[switch_operand]))) break :no_switch_on_err; | | |
| 1059 | return switchExprErrUnion(gz, scope, ri.br(), node, .@"catch"); | 1053 | return switchExprErrUnion(gz, scope, ri.br(), node, .@"catch"); |
| 1060 | } | 1054 | } |
| 1061 | switch (ri.rl) { | 1055 | switch (ri.rl) { |
| ... | @@ -2160,11 +2154,6 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn | ... | @@ -2160,11 +2154,6 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2160 | if (break_label != 0) { | 2154 | if (break_label != 0) { |
| 2161 | if (block_gz.label) |*label| { | 2155 | if (block_gz.label) |*label| { |
| 2162 | if (try astgen.tokenIdentEql(label.token, break_label)) { | 2156 | if (try astgen.tokenIdentEql(label.token, break_label)) { |
| 2163 | const maybe_switch_tag = astgen.instructions.items(.tag)[@intFromEnum(label.block_inst)]; | | |
| 2164 | switch (maybe_switch_tag) { | | |
| 2165 | .switch_block, .switch_block_ref => return astgen.failNode(node, "cannot break from switch", .{}), | | |
| 2166 | else => {}, | | |
| 2167 | } | | |
| 2168 | label.used = true; | 2157 | label.used = true; |
| 2169 | break :blk label.block_inst; | 2158 | break :blk label.block_inst; |
| 2170 | } | 2159 | } |
| ... | @@ -2278,6 +2267,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) | ... | @@ -2278,6 +2267,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2278 | } | 2267 | } |
| 2279 | | 2268 | |
| 2280 | label.used = true; | 2269 | label.used = true; |
| | 2270 | label.used_for_continue = true; |
| 2281 | break :blk; | 2271 | break :blk; |
| 2282 | } | 2272 | } |
| 2283 | } | 2273 | } |
| ... | @@ -7760,7 +7750,7 @@ fn switchExpr( | ... | @@ -7760,7 +7750,7 @@ fn switchExpr( |
| 7760 | const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node); | 7750 | const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node); |
| 7761 | const item_ri: ResultInfo = .{ .rl = .none }; | 7751 | const item_ri: ResultInfo = .{ .rl = .none }; |
| 7762 | | 7752 | |
| 7763 | // If this switch is labeled, it will have `continue`s targeting it, and thus we need the operand type | 7753 | // If this switch is labeled, it may have `continue`s targeting it, and thus we need the operand type |
| 7764 | // to provide a result type. | 7754 | // to provide a result type. |
| 7765 | const raw_operand_ty_ref = if (switch_full.label_token != null) t: { | 7755 | const raw_operand_ty_ref = if (switch_full.label_token != null) t: { |
| 7766 | break :t try parent_gz.addUnNode(.typeof, raw_operand, operand_node); | 7756 | break :t try parent_gz.addUnNode(.typeof, raw_operand, operand_node); |
| ... | @@ -7790,7 +7780,9 @@ fn switchExpr( | ... | @@ -7790,7 +7780,9 @@ fn switchExpr( |
| 7790 | const switch_block = try parent_gz.makeBlockInst(switch_tag, node); | 7780 | const switch_block = try parent_gz.makeBlockInst(switch_tag, node); |
| 7791 | | 7781 | |
| 7792 | if (switch_full.label_token) |label_token| { | 7782 | if (switch_full.label_token) |label_token| { |
| | 7783 | block_scope.break_block = switch_block.toOptional(); |
| 7793 | block_scope.continue_block = switch_block.toOptional(); | 7784 | block_scope.continue_block = switch_block.toOptional(); |
| | 7785 | // `break_result_info` already set above |
| 7794 | block_scope.continue_result_info = .{ | 7786 | block_scope.continue_result_info = .{ |
| 7795 | .rl = if (any_payload_is_ref) | 7787 | .rl = if (any_payload_is_ref) |
| 7796 | .{ .ref_coerced_ty = raw_operand_ty_ref } | 7788 | .{ .ref_coerced_ty = raw_operand_ty_ref } |
| ... | @@ -8024,7 +8016,7 @@ fn switchExpr( | ... | @@ -8024,7 +8016,7 @@ fn switchExpr( |
| 8024 | .has_under = special_prong == .under, | 8016 | .has_under = special_prong == .under, |
| 8025 | .any_has_tag_capture = any_has_tag_capture, | 8017 | .any_has_tag_capture = any_has_tag_capture, |
| 8026 | .any_non_inline_capture = any_non_inline_capture, | 8018 | .any_non_inline_capture = any_non_inline_capture, |
| 8027 | .has_continue = switch_full.label_token != null, | 8019 | .has_continue = switch_full.label_token != null and block_scope.label.?.used_for_continue, |
| 8028 | .scalar_cases_len = @intCast(scalar_cases_len), | 8020 | .scalar_cases_len = @intCast(scalar_cases_len), |
| 8029 | }, | 8021 | }, |
| 8030 | }); | 8022 | }); |
| ... | @@ -11963,6 +11955,7 @@ const GenZir = struct { | ... | @@ -11963,6 +11955,7 @@ const GenZir = struct { |
| 11963 | token: Ast.TokenIndex, | 11955 | token: Ast.TokenIndex, |
| 11964 | block_inst: Zir.Inst.Index, | 11956 | block_inst: Zir.Inst.Index, |
| 11965 | used: bool = false, | 11957 | used: bool = false, |
| | 11958 | used_for_continue: bool = false, |
| 11966 | }; | 11959 | }; |
| 11967 | | 11960 | |
| 11968 | /// Assumes nothing stacked on `gz`. | 11961 | /// Assumes nothing stacked on `gz`. |