authorgravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2023-12-15 13:35:49+11:00
committergravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2024-01-09 14:42:12+11:00
log6a18cee3af8021bcebbca40413056b18f33af8c7
treee7675a562337ed5f1fed4d86c62872c7b5893413
parentb7eb59fc140f3263b608a80fbe4e1ab56e04b318

astgen/sema: use switch_block_err_union for if-else-switch


3 files changed, 186 insertions(+), 30 deletions(-)

src/AstGen.zig+145-20
...@@ -839,7 +839,18 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -839,7 +839,18 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
839839
840 .if_simple,840 .if_simple,
841 .@"if",841 .@"if",
842 => return ifExpr(gz, scope, ri.br(), node, tree.fullIf(node).?),842 => {
843 const if_full = tree.fullIf(node).?;
844 if (if_full.error_token) |error_token| {
845 const tag = node_tags[if_full.ast.else_expr];
846 if ((tag == .@"switch" or tag == .switch_comma) and
847 std.mem.eql(u8, tree.tokenSlice(error_token), tree.tokenSlice(error_token + 4)))
848 {
849 return switchExprErrUnion(gz, scope, ri.br(), node, .@"if");
850 }
851 }
852 return ifExpr(gz, scope, ri.br(), node, if_full);
853 },
843854
844 .while_simple,855 .while_simple,
845 .while_cont,856 .while_cont,
...@@ -1020,7 +1031,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1020,7 +1031,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1020 token_tags[catch_token + 4] == .keyword_switch)1031 token_tags[catch_token + 4] == .keyword_switch)
1021 {1032 {
1022 if (std.mem.eql(u8, tree.tokenSlice(catch_token + 2), tree.tokenSlice(catch_token + 6))) {1033 if (std.mem.eql(u8, tree.tokenSlice(catch_token + 2), tree.tokenSlice(catch_token + 6))) {
1023 return switchExprErrUnion(gz, scope, ri.br(), node);1034 return switchExprErrUnion(gz, scope, ri.br(), node, .@"catch");
1024 }1035 }
1025 }1036 }
1026 break :blk catch_token + 2;1037 break :blk catch_token + 2;
...@@ -6869,7 +6880,8 @@ fn switchExprErrUnion(...@@ -6869,7 +6880,8 @@ fn switchExprErrUnion(
6869 parent_gz: *GenZir,6880 parent_gz: *GenZir,
6870 scope: *Scope,6881 scope: *Scope,
6871 ri: ResultInfo,6882 ri: ResultInfo,
6872 catch_node: Ast.Node.Index,6883 catch_or_if_node: Ast.Node.Index,
6884 node_ty: enum { @"catch", @"if" },
6873) InnerError!Zir.Inst.Ref {6885) InnerError!Zir.Inst.Ref {
6874 const astgen = parent_gz.astgen;6886 const astgen = parent_gz.astgen;
6875 const gpa = astgen.gpa;6887 const gpa = astgen.gpa;
...@@ -6878,21 +6890,42 @@ fn switchExprErrUnion(...@@ -6878,21 +6890,42 @@ fn switchExprErrUnion(
6878 const node_tags = tree.nodes.items(.tag);6890 const node_tags = tree.nodes.items(.tag);
6879 const main_tokens = tree.nodes.items(.main_token);6891 const main_tokens = tree.nodes.items(.main_token);
6880 const token_tags = tree.tokens.items(.tag);6892 const token_tags = tree.tokens.items(.tag);
6881 const operand_node = node_datas[catch_node].lhs;6893
6882 const switch_node = node_datas[catch_node].rhs;6894 const if_full = switch (node_ty) {
6895 .@"catch" => undefined,
6896 .@"if" => tree.fullIf(catch_or_if_node).?,
6897 };
6898
6899 const switch_node, const operand_node, const error_payload = switch (node_ty) {
6900 .@"catch" => .{
6901 node_datas[catch_or_if_node].rhs,
6902 node_datas[catch_or_if_node].lhs,
6903 main_tokens[catch_or_if_node] + 2,
6904 },
6905 .@"if" => .{
6906 if_full.ast.else_expr,
6907 if_full.ast.cond_expr,
6908 if_full.error_token.?,
6909 },
6910 };
6911 assert(node_tags[switch_node] == .@"switch" or node_tags[switch_node] == .switch_comma);
6912
6883 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);6913 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
6884 const case_nodes = tree.extra_data[extra.start..extra.end];6914 const case_nodes = tree.extra_data[extra.start..extra.end];
68856915
6886 const need_rl = astgen.nodes_need_rl.contains(catch_node);6916 const need_rl = astgen.nodes_need_rl.contains(catch_or_if_node);
6887 const block_ri: ResultInfo = if (need_rl) ri else .{6917 const block_ri: ResultInfo = if (need_rl) ri else .{
6888 .rl = switch (ri.rl) {6918 .rl = switch (ri.rl) {
6889 .ptr => .{ .ty = (try ri.rl.resultType(parent_gz, catch_node)).? },6919 .ptr => .{ .ty = (try ri.rl.resultType(parent_gz, catch_or_if_node)).? },
6890 .inferred_ptr => .none,6920 .inferred_ptr => .none,
6891 else => ri.rl,6921 else => ri.rl,
6892 },6922 },
6893 .ctx = ri.ctx,6923 .ctx = ri.ctx,
6894 };6924 };
68956925
6926 const payload_is_ref = node_ty == .@"if" and
6927 if_full.payload_token != null and token_tags[if_full.payload_token.?] == .asterisk;
6928
6896 // We need to call `rvalue` to write through to the pointer only if we had a6929 // We need to call `rvalue` to write through to the pointer only if we had a
6897 // result pointer and aren't forwarding it.6930 // result pointer and aren't forwarding it.
6898 const LocTag = @typeInfo(ResultInfo.Loc).Union.tag_type.?;6931 const LocTag = @typeInfo(ResultInfo.Loc).Union.tag_type.?;
...@@ -6960,12 +6993,15 @@ fn switchExprErrUnion(...@@ -6960,12 +6993,15 @@ fn switchExprErrUnion(
6960 }6993 }
6961 }6994 }
69626995
6963 const operand_ri: ResultInfo = .{ .rl = .none, .ctx = .error_handling_expr };6996 const operand_ri: ResultInfo = .{
6997 .rl = if (payload_is_ref) .ref else .none,
6998 .ctx = .error_handling_expr,
6999 };
69647000
6965 astgen.advanceSourceCursorToNode(operand_node);7001 astgen.advanceSourceCursorToNode(operand_node);
6966 const operand_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };7002 const operand_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
69677003
6968 const raw_operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, node_datas[catch_node].rhs);7004 const raw_operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, switch_node);
6969 const item_ri: ResultInfo = .{ .rl = .none };7005 const item_ri: ResultInfo = .{ .rl = .none };
69707006
6971 // This contains the data that goes into the `extra` array for the SwitchBlockErrUnion, except7007 // This contains the data that goes into the `extra` array for the SwitchBlockErrUnion, except
...@@ -7006,13 +7042,93 @@ fn switchExprErrUnion(...@@ -7006,13 +7042,93 @@ fn switchExprErrUnion(
70067042
7007 try case_scope.addDbgBlockBegin();7043 try case_scope.addDbgBlockBegin();
70087044
7009 const unwrapped_payload = try case_scope.addUnNode(.err_union_payload_unsafe, raw_operand, catch_node);7045 const unwrap_payload_tag: Zir.Inst.Tag = if (payload_is_ref)
7010 const case_result = switch (ri.rl) {7046 .err_union_payload_unsafe_ptr
7011 .ref, .ref_coerced_ty => unwrapped_payload,7047 else
7012 else => try rvalue(&case_scope, block_scope.break_result_info, unwrapped_payload, catch_node),7048 .err_union_payload_unsafe;
7013 };7049
7014 try case_scope.addDbgBlockEnd();7050 const unwrapped_payload = try case_scope.addUnNode(
7015 _ = try case_scope.addBreakWithSrcNode(.@"break", switch_block, case_result, catch_node);7051 unwrap_payload_tag,
7052 raw_operand,
7053 catch_or_if_node,
7054 );
7055
7056 switch (node_ty) {
7057 .@"catch" => {
7058 const case_result = switch (ri.rl) {
7059 .ref, .ref_coerced_ty => unwrapped_payload,
7060 else => try rvalue(
7061 &case_scope,
7062 block_scope.break_result_info,
7063 unwrapped_payload,
7064 catch_or_if_node,
7065 ),
7066 };
7067 try case_scope.addDbgBlockEnd();
7068 _ = try case_scope.addBreakWithSrcNode(
7069 .@"break",
7070 switch_block,
7071 case_result,
7072 catch_or_if_node,
7073 );
7074 },
7075 .@"if" => {
7076 var payload_val_scope: Scope.LocalVal = undefined;
7077
7078 try case_scope.addDbgBlockBegin();
7079 const then_node = if_full.ast.then_expr;
7080 const then_sub_scope = s: {
7081 assert(if_full.error_token != null);
7082 if (if_full.payload_token) |payload_token| {
7083 const token_name_index = payload_token + @intFromBool(payload_is_ref);
7084 const ident_name = try astgen.identAsString(token_name_index);
7085 const token_name_str = tree.tokenSlice(token_name_index);
7086 if (mem.eql(u8, "_", token_name_str))
7087 break :s &case_scope.base;
7088 try astgen.detectLocalShadowing(
7089 &case_scope.base,
7090 ident_name,
7091 token_name_index,
7092 token_name_str,
7093 .capture,
7094 );
7095 payload_val_scope = .{
7096 .parent = &case_scope.base,
7097 .gen_zir = &case_scope,
7098 .name = ident_name,
7099 .inst = unwrapped_payload,
7100 .token_src = payload_token,
7101 .id_cat = .capture,
7102 };
7103 try case_scope.addDbgVar(.dbg_var_val, ident_name, unwrapped_payload);
7104 break :s &payload_val_scope.base;
7105 } else {
7106 _ = try case_scope.addUnNode(
7107 .ensure_err_union_payload_void,
7108 raw_operand,
7109 catch_or_if_node,
7110 );
7111 break :s &case_scope.base;
7112 }
7113 };
7114 const then_result = try expr(
7115 &case_scope,
7116 then_sub_scope,
7117 block_scope.break_result_info,
7118 then_node,
7119 );
7120 try checkUsed(parent_gz, &case_scope.base, then_sub_scope);
7121 if (!case_scope.endsWithNoReturn()) {
7122 try case_scope.addDbgBlockEnd();
7123 _ = try case_scope.addBreakWithSrcNode(
7124 .@"break",
7125 switch_block,
7126 then_result,
7127 then_node,
7128 );
7129 }
7130 },
7131 }
70167132
7017 const case_slice = case_scope.instructionsSlice();7133 const case_slice = case_scope.instructionsSlice();
7018 // Since we use the switch_block_err_union instruction itself to refer7134 // Since we use the switch_block_err_union instruction itself to refer
...@@ -7029,9 +7145,18 @@ fn switchExprErrUnion(...@@ -7029,9 +7145,18 @@ fn switchExprErrUnion(
7029 };7145 };
7030 const body_len = refs_len + astgen.countBodyLenAfterFixups(case_slice);7146 const body_len = refs_len + astgen.countBodyLenAfterFixups(case_slice);
7031 try payloads.ensureUnusedCapacity(gpa, body_len);7147 try payloads.ensureUnusedCapacity(gpa, body_len);
7148 const capture: Zir.Inst.SwitchBlock.ProngInfo.Capture = switch (node_ty) {
7149 .@"catch" => .none,
7150 .@"if" => if (if_full.payload_token == null)
7151 .none
7152 else if (payload_is_ref)
7153 .by_ref
7154 else
7155 .by_val,
7156 };
7032 payloads.items[body_len_index] = @bitCast(Zir.Inst.SwitchBlock.ProngInfo{7157 payloads.items[body_len_index] = @bitCast(Zir.Inst.SwitchBlock.ProngInfo{
7033 .body_len = @intCast(body_len),7158 .body_len = @intCast(body_len),
7034 .capture = .none,7159 .capture = capture,
7035 .is_inline = false,7160 .is_inline = false,
7036 .has_tag_capture = false,7161 .has_tag_capture = false,
7037 });7162 });
...@@ -7041,8 +7166,7 @@ fn switchExprErrUnion(...@@ -7041,8 +7166,7 @@ fn switchExprErrUnion(
7041 appendBodyWithFixupsArrayList(astgen, payloads, case_slice);7166 appendBodyWithFixupsArrayList(astgen, payloads, case_slice);
7042 }7167 }
70437168
7044 const err_name, const error_payload = blk: {7169 const err_name = blk: {
7045 const error_payload = main_tokens[catch_node] + 2;
7046 const err_str = tree.tokenSlice(error_payload);7170 const err_str = tree.tokenSlice(error_payload);
7047 if (mem.eql(u8, err_str, "_")) {7171 if (mem.eql(u8, err_str, "_")) {
7048 return astgen.failTok(error_payload, "discard of error capture; omit it instead", .{});7172 return astgen.failTok(error_payload, "discard of error capture; omit it instead", .{});
...@@ -7050,7 +7174,7 @@ fn switchExprErrUnion(...@@ -7050,7 +7174,7 @@ fn switchExprErrUnion(
7050 const err_name = try astgen.identAsString(error_payload);7174 const err_name = try astgen.identAsString(error_payload);
7051 try astgen.detectLocalShadowing(scope, err_name, error_payload, err_str, .capture);7175 try astgen.detectLocalShadowing(scope, err_name, error_payload, err_str, .capture);
70527176
7053 break :blk .{ err_name, error_payload };7177 break :blk err_name;
7054 };7178 };
70557179
7056 // allocate a shared dummy instruction for the error capture7180 // allocate a shared dummy instruction for the error capture
...@@ -7241,6 +7365,7 @@ fn switchExprErrUnion(...@@ -7241,6 +7365,7 @@ fn switchExprErrUnion(
7241 .has_else = has_else,7365 .has_else = has_else,
7242 .scalar_cases_len = @intCast(scalar_cases_len),7366 .scalar_cases_len = @intCast(scalar_cases_len),
7243 .any_uses_err_capture = any_uses_err_capture,7367 .any_uses_err_capture = any_uses_err_capture,
7368 .payload_is_ref = payload_is_ref,
7244 },7369 },
7245 });7370 });
72467371
src/Sema.zig+39-9
...@@ -8939,10 +8939,14 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -8939,10 +8939,14 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
8939 const tracy = trace(@src());8939 const tracy = trace(@src());
8940 defer tracy.end();8940 defer tracy.end();
89418941
8942 const mod = sema.mod;
8943 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;8942 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
8944 const src = inst_data.src();8943 const src = inst_data.src();
8945 const operand = try sema.resolveInst(inst_data.operand);8944 const operand = try sema.resolveInst(inst_data.operand);
8945 return sema.analyzeErrUnionCodePtr(block, src, operand);
8946}
8947
8948fn analyzeErrUnionCodePtr(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref {
8949 const mod = sema.mod;
8946 const operand_ty = sema.typeOf(operand);8950 const operand_ty = sema.typeOf(operand);
8947 assert(operand_ty.zigTypeTag(mod) == .Pointer);8951 assert(operand_ty.zigTypeTag(mod) == .Pointer);
89488952
...@@ -8957,7 +8961,10 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -8957,7 +8961,10 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
8957 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {8961 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
8958 if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| {8962 if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| {
8959 assert(val.getErrorName(mod) != .none);8963 assert(val.getErrorName(mod) != .none);
8960 return Air.internedToRef(val.toIntern());8964 return Air.internedToRef((try mod.intern(.{ .err = .{
8965 .ty = result_ty.toIntern(),
8966 .name = mod.intern_pool.indexToKey(val.toIntern()).error_union.val.err_name,
8967 } })));
8961 }8968 }
8962 }8969 }
89638970
...@@ -11174,7 +11181,6 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11174,7 +11181,6 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11174 const extra = sema.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index);11181 const extra = sema.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index);
1117511182
11176 const raw_operand_val = try sema.resolveInst(extra.data.operand);11183 const raw_operand_val = try sema.resolveInst(extra.data.operand);
11177 assert(sema.typeOf(raw_operand_val).zigTypeTag(mod) == .ErrorUnion);
1117811184
11179 // AstGen guarantees that the instruction immediately preceding11185 // AstGen guarantees that the instruction immediately preceding
11180 // switch_block_err_union is a dbg_stmt11186 // switch_block_err_union is a dbg_stmt
...@@ -11205,6 +11211,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11205,6 +11211,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11205 const NonError = struct {11211 const NonError = struct {
11206 body: []const Zir.Inst.Index,11212 body: []const Zir.Inst.Index,
11207 end: usize,11213 end: usize,
11214 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
11208 };11215 };
1120911216
11210 const non_error_case: NonError = non_error: {11217 const non_error_case: NonError = non_error: {
...@@ -11213,6 +11220,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11213,6 +11220,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11213 break :non_error .{11220 break :non_error .{
11214 .body = sema.code.bodySlice(extra_body_start, info.body_len),11221 .body = sema.code.bodySlice(extra_body_start, info.body_len),
11215 .end = extra_body_start + info.body_len,11222 .end = extra_body_start + info.body_len,
11223 .capture = info.capture,
11216 };11224 };
11217 };11225 };
1121811226
...@@ -11237,7 +11245,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11237,7 +11245,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11237 .body = sema.code.bodySlice(extra_body_start, info.body_len),11245 .body = sema.code.bodySlice(extra_body_start, info.body_len),
11238 .end = extra_body_start + info.body_len,11246 .end = extra_body_start + info.body_len,
11239 .is_inline = info.is_inline,11247 .is_inline = info.is_inline,
11240 .has_capture = info.capture == .by_val,11248 .has_capture = info.capture != .none,
11241 };11249 };
11242 };11250 };
1124311251
...@@ -11245,7 +11253,10 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11245,7 +11253,10 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11245 defer seen_errors.deinit();11253 defer seen_errors.deinit();
1124611254
11247 const operand_ty = sema.typeOf(raw_operand_val);11255 const operand_ty = sema.typeOf(raw_operand_val);
11248 const operand_err_set_ty = operand_ty.errorUnionSet(mod);11256 const operand_err_set_ty = if (extra.data.bits.payload_is_ref)
11257 operand_ty.childType(mod).errorUnionSet(mod)
11258 else
11259 operand_ty.errorUnionSet(mod);
1124911260
11250 const block_inst: Air.Inst.Index = @enumFromInt(sema.air_instructions.len);11261 const block_inst: Air.Inst.Index = @enumFromInt(sema.air_instructions.len);
11251 try sema.air_instructions.append(gpa, .{11262 try sema.air_instructions.append(gpa, .{
...@@ -11313,7 +11324,12 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11313,7 +11324,12 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11313 .tag_capture_inst = undefined,11324 .tag_capture_inst = undefined,
11314 };11325 };
1131511326
11316 if (try sema.resolveDefinedValue(&child_block, src, raw_operand_val)) |operand_val| {11327 if (try sema.resolveDefinedValue(&child_block, src, raw_operand_val)) |ov| {
11328 const operand_val = if (extra.data.bits.payload_is_ref)
11329 (try sema.pointerDeref(&child_block, src, ov, operand_ty)).?
11330 else
11331 ov;
11332
11317 if (operand_val.errorUnionIsPayload(mod)) {11333 if (operand_val.errorUnionIsPayload(mod)) {
11318 return sema.resolveBlockBody(block, operand_src, &child_block, non_error_case.body, inst, merges);11334 return sema.resolveBlockBody(block, operand_src, &child_block, non_error_case.body, inst, merges);
11319 } else {11335 } else {
...@@ -11323,7 +11339,10 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11323,7 +11339,10 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11323 .name = operand_val.getErrorName(mod).unwrap().?,11339 .name = operand_val.getErrorName(mod).unwrap().?,
11324 },11340 },
11325 }));11341 }));
11326 spa.operand = try sema.analyzeErrUnionCode(block, operand_src, raw_operand_val);11342 spa.operand = if (extra.data.bits.payload_is_ref)
11343 try sema.analyzeErrUnionCodePtr(block, operand_src, raw_operand_val)
11344 else
11345 try sema.analyzeErrUnionCode(block, operand_src, raw_operand_val);
1132711346
11328 if (extra.data.bits.any_uses_err_capture) {11347 if (extra.data.bits.any_uses_err_capture) {
11329 sema.inst_map.putAssumeCapacity(err_capture_inst, spa.operand);11348 sema.inst_map.putAssumeCapacity(err_capture_inst, spa.operand);
...@@ -11367,7 +11386,14 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11367,7 +11386,14 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11367 unreachable;11386 unreachable;
11368 }11387 }
1136911388
11370 const cond = try sema.analyzeIsNonErr(block, src, raw_operand_val);11389 const cond = if (extra.data.bits.payload_is_ref) blk: {
11390 try sema.checkErrorType(block, src, sema.typeOf(raw_operand_val).elemType2(mod));
11391 const loaded = try sema.analyzeLoad(block, src, raw_operand_val, src);
11392 break :blk try sema.analyzeIsNonErr(block, src, loaded);
11393 } else blk: {
11394 try sema.checkErrorType(block, src, sema.typeOf(raw_operand_val));
11395 break :blk try sema.analyzeIsNonErr(block, src, raw_operand_val);
11396 };
1137111397
11372 var sub_block = child_block.makeSubBlock();11398 var sub_block = child_block.makeSubBlock();
11373 sub_block.runtime_loop = null;11399 sub_block.runtime_loop = null;
...@@ -11379,7 +11405,11 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11379,7 +11405,11 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11379 const true_instructions = try sub_block.instructions.toOwnedSlice(gpa);11405 const true_instructions = try sub_block.instructions.toOwnedSlice(gpa);
11380 defer gpa.free(true_instructions);11406 defer gpa.free(true_instructions);
1138111407
11382 spa.operand = try sema.analyzeErrUnionCode(&sub_block, operand_src, raw_operand_val);11408 spa.operand = if (extra.data.bits.payload_is_ref)
11409 try sema.analyzeErrUnionCodePtr(&sub_block, operand_src, raw_operand_val)
11410 else
11411 try sema.analyzeErrUnionCode(&sub_block, operand_src, raw_operand_val);
11412
11383 if (extra.data.bits.any_uses_err_capture) {11413 if (extra.data.bits.any_uses_err_capture) {
11384 sema.inst_map.putAssumeCapacity(err_capture_inst, spa.operand);11414 sema.inst_map.putAssumeCapacity(err_capture_inst, spa.operand);
11385 }11415 }
src/Zir.zig+2-1
...@@ -2793,9 +2793,10 @@ pub const Inst = struct {...@@ -2793,9 +2793,10 @@ pub const Inst = struct {
2793 /// If true, there is an else prong. This is mutually exclusive with `has_under`.2793 /// If true, there is an else prong. This is mutually exclusive with `has_under`.
2794 has_else: bool,2794 has_else: bool,
2795 any_uses_err_capture: bool,2795 any_uses_err_capture: bool,
2796 payload_is_ref: bool,
2796 scalar_cases_len: ScalarCasesLen,2797 scalar_cases_len: ScalarCasesLen,
27972798
2798 pub const ScalarCasesLen = u29;2799 pub const ScalarCasesLen = u28;
2799 };2800 };
28002801
2801 pub const MultiProng = struct {2802 pub const MultiProng = struct {