| ... | @@ -2418,6 +2418,32 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T | ... | @@ -2418,6 +2418,32 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T |
| 2418 | }); | 2418 | }); |
| 2419 | } | 2419 | } |
| 2420 | | 2420 | |
| | 2421 | fn failWithInvalidSwitchTagCapture(sema: *Sema, block: *Block, tag_capture_src: LazySrcLoc, operand_ty: Type) CompileError { |
| | 2422 | const pt = sema.pt; |
| | 2423 | const zcu = pt.zcu; |
| | 2424 | |
| | 2425 | if (operand_ty.zigTypeTag(zcu) == .@"union") { |
| | 2426 | assert(operand_ty.containerLayout(zcu) == .@"packed"); |
| | 2427 | return sema.failWithOwnedErrorMsg(block, msg: { |
| | 2428 | const msg = try sema.errMsg(tag_capture_src, "cannot capture tag of packed union", .{}); |
| | 2429 | errdefer msg.destroy(sema.gpa); |
| | 2430 | try sema.addDeclaredHereNote(msg, operand_ty); |
| | 2431 | if (operand_ty.srcLocOrNull(zcu)) |ty_src| { |
| | 2432 | try sema.errNote(ty_src, msg, "consider using a tagged union", .{}); |
| | 2433 | } |
| | 2434 | break :msg msg; |
| | 2435 | }); |
| | 2436 | } |
| | 2437 | return sema.failWithOwnedErrorMsg(block, msg: { |
| | 2438 | const msg = try sema.errMsg(tag_capture_src, "cannot capture tag of non-union type '{f}'", .{ |
| | 2439 | operand_ty.fmt(pt), |
| | 2440 | }); |
| | 2441 | errdefer msg.destroy(sema.gpa); |
| | 2442 | try sema.addDeclaredHereNote(msg, operand_ty); |
| | 2443 | break :msg msg; |
| | 2444 | }); |
| | 2445 | } |
| | 2446 | |
| 2421 | fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non_optional_ty: Type) CompileError { | 2447 | fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non_optional_ty: Type) CompileError { |
| 2422 | const pt = sema.pt; | 2448 | const pt = sema.pt; |
| 2423 | const msg = msg: { | 2449 | const msg = msg: { |
| ... | @@ -10216,7 +10242,7 @@ fn analyzeSwitchBlock( | ... | @@ -10216,7 +10242,7 @@ fn analyzeSwitchBlock( |
| 10216 | | 10242 | |
| 10217 | const case_vals = validated_switch.case_vals; | 10243 | const case_vals = validated_switch.case_vals; |
| 10218 | | 10244 | |
| 10219 | const body, const capture, const has_tag_capture = find_prong: { | 10245 | const case_idx, const body, const capture, const has_tag_capture = find_prong: { |
| 10220 | var case_val_idx: usize = 0; | 10246 | var case_val_idx: usize = 0; |
| 10221 | var case_it = zir_switch.iterateCases(); | 10247 | var case_it = zir_switch.iterateCases(); |
| 10222 | var extra_index = zir_switch.end; | 10248 | var extra_index = zir_switch.end; |
| ... | @@ -10239,12 +10265,12 @@ fn analyzeSwitchBlock( | ... | @@ -10239,12 +10265,12 @@ fn analyzeSwitchBlock( |
| 10239 | } | 10265 | } |
| 10240 | continue; | 10266 | continue; |
| 10241 | } | 10267 | } |
| 10242 | break :find_prong .{ prong_body, prong_info.capture, prong_info.has_tag_capture }; | 10268 | break :find_prong .{ case.index, prong_body, prong_info.capture, prong_info.has_tag_capture }; |
| 10243 | } | 10269 | } |
| 10244 | if (has_else) { | 10270 | if (has_else) { |
| 10245 | // This *has* to be checked after iterating all regular cases because | 10271 | // This *has* to be checked after iterating all regular cases because |
| 10246 | // we allow simple noreturn else prongs when switching on error sets! | 10272 | // we allow simple noreturn else prongs when switching on error sets! |
| 10247 | break :find_prong .{ else_case.body, else_case.capture, else_case.has_tag_capture }; | 10273 | break :find_prong .{ else_case.index, else_case.body, else_case.capture, else_case.has_tag_capture }; |
| 10248 | } | 10274 | } |
| 10249 | unreachable; // malformed validated switch | 10275 | unreachable; // malformed validated switch |
| 10250 | }; | 10276 | }; |
| ... | @@ -10289,6 +10315,13 @@ fn analyzeSwitchBlock( | ... | @@ -10289,6 +10315,13 @@ fn analyzeSwitchBlock( |
| 10289 | | 10315 | |
| 10290 | const tag_inst: Zir.Inst.Index = if (has_tag_capture) inst: { | 10316 | const tag_inst: Zir.Inst.Index = if (has_tag_capture) inst: { |
| 10291 | const tag_inst = zir_switch.tag_capture_placeholder.unwrap() orelse switch_inst; | 10317 | const tag_inst = zir_switch.tag_capture_placeholder.unwrap() orelse switch_inst; |
| | 10318 | if (!tagged_union_originally) { |
| | 10319 | const tag_capture_src = block.src(.{ .switch_tag_capture = .{ |
| | 10320 | .switch_node_offset = src_node_offset, |
| | 10321 | .case_idx = case_idx, |
| | 10322 | } }); |
| | 10323 | return sema.failWithInvalidSwitchTagCapture(block, tag_capture_src, operand_ty); |
| | 10324 | } |
| 10292 | sema.inst_map.putAssumeCapacity(tag_inst, .fromValue(item_opv)); | 10325 | sema.inst_map.putAssumeCapacity(tag_inst, .fromValue(item_opv)); |
| 10293 | break :inst tag_inst; | 10326 | break :inst tag_inst; |
| 10294 | } else undefined; | 10327 | } else undefined; |
| ... | @@ -12157,26 +12190,7 @@ fn analyzeSwitchCaptures( | ... | @@ -12157,26 +12190,7 @@ fn analyzeSwitchCaptures( |
| 12157 | .base_node_inst = capture_src.base_node_inst, | 12190 | .base_node_inst = capture_src.base_node_inst, |
| 12158 | .offset = .{ .switch_tag_capture = capture_src.offset.switch_capture }, | 12191 | .offset = .{ .switch_tag_capture = capture_src.offset.switch_capture }, |
| 12159 | }; | 12192 | }; |
| 12160 | if (operand_ty.zigTypeTag(zcu) == .@"union") { | 12193 | return sema.failWithInvalidSwitchTagCapture(case_block, tag_capture_src, operand_ty); |
| 12161 | assert(operand_ty.containerLayout(zcu) == .@"packed"); | | |
| 12162 | return sema.failWithOwnedErrorMsg(case_block, msg: { | | |
| 12163 | const msg = try sema.errMsg(tag_capture_src, "cannot capture tag of packed union", .{}); | | |
| 12164 | errdefer msg.destroy(sema.gpa); | | |
| 12165 | try sema.addDeclaredHereNote(msg, operand_ty); | | |
| 12166 | if (operand_ty.srcLocOrNull(zcu)) |ty_src| { | | |
| 12167 | try sema.errNote(ty_src, msg, "consider using a tagged union", .{}); | | |
| 12168 | } | | |
| 12169 | break :msg msg; | | |
| 12170 | }); | | |
| 12171 | } | | |
| 12172 | return sema.failWithOwnedErrorMsg(case_block, msg: { | | |
| 12173 | const msg = try sema.errMsg(tag_capture_src, "cannot capture tag of non-union type '{f}'", .{ | | |
| 12174 | operand_ty.fmt(pt), | | |
| 12175 | }); | | |
| 12176 | errdefer msg.destroy(sema.gpa); | | |
| 12177 | try sema.addDeclaredHereNote(msg, operand_ty); | | |
| 12178 | break :msg msg; | | |
| 12179 | }); | | |
| 12180 | } | 12194 | } |
| 12181 | | 12195 | |
| 12182 | return .{ .payload_ref = payload_ref, .tag_ref = .none }; | 12196 | return .{ .payload_ref = payload_ref, .tag_ref = .none }; |