| ... | @@ -10747,8 +10747,6 @@ fn analyzeSwitchBlock( | ... | @@ -10747,8 +10747,6 @@ fn analyzeSwitchBlock( |
| 10747 | const operand_src = block.src(.{ .node_offset_switch_operand = src_node_offset }); | 10747 | const operand_src = block.src(.{ .node_offset_switch_operand = src_node_offset }); |
| 10748 | | 10748 | |
| 10749 | const has_else = zir_switch.else_case != null; | 10749 | const has_else = zir_switch.else_case != null; |
| 10750 | const has_under = zir_switch.has_under; | | |
| 10751 | | | |
| 10752 | const else_case = validated_switch.else_case; | 10750 | const else_case = validated_switch.else_case; |
| 10753 | | 10751 | |
| 10754 | const operand: SwitchOperand, const operand_ty: Type, const maybe_operand_opv: ?Value, const item_ty: Type = operand: { | 10752 | const operand: SwitchOperand, const operand_ty: Type, const maybe_operand_opv: ?Value, const item_ty: Type = operand: { |
| ... | @@ -10813,11 +10811,6 @@ fn analyzeSwitchBlock( | ... | @@ -10813,11 +10811,6 @@ fn analyzeSwitchBlock( |
| 10813 | .loop => |l| l.init_cond, | 10811 | .loop => |l| l.init_cond, |
| 10814 | }; | 10812 | }; |
| 10815 | | 10813 | |
| 10816 | // We treat `else` and `_` the same, except if both are present. | | |
| 10817 | const else_is_named_only = has_else and has_under; | | |
| 10818 | const catch_all_case: CatchAllSwitchCase = | | |
| 10819 | if (has_under) .under else if (has_else) .@"else" else .none; | | |
| 10820 | | | |
| 10821 | resolve_at_comptime: { | 10814 | resolve_at_comptime: { |
| 10822 | // always runtime; evaluation in comptime scope uses `simple` | 10815 | // always runtime; evaluation in comptime scope uses `simple` |
| 10823 | if (operand == .loop) break :resolve_at_comptime; | 10816 | if (operand == .loop) break :resolve_at_comptime; |
| ... | @@ -10834,8 +10827,6 @@ fn analyzeSwitchBlock( | ... | @@ -10834,8 +10827,6 @@ fn analyzeSwitchBlock( |
| 10834 | cur_operand, | 10827 | cur_operand, |
| 10835 | raw_operand_ty, | 10828 | raw_operand_ty, |
| 10836 | cur_cond_val, | 10829 | cur_cond_val, |
| 10837 | catch_all_case, | | |
| 10838 | else_is_named_only, | | |
| 10839 | merges, | 10830 | merges, |
| 10840 | switch_inst, | 10831 | switch_inst, |
| 10841 | zir_switch, | 10832 | zir_switch, |
| ... | @@ -10958,6 +10949,11 @@ fn analyzeSwitchBlock( | ... | @@ -10958,6 +10949,11 @@ fn analyzeSwitchBlock( |
| 10958 | } | 10949 | } |
| 10959 | }, | 10950 | }, |
| 10960 | }; | 10951 | }; |
| | 10952 | const prong_kind: SwitchProngKind = kind: { |
| | 10953 | if (is_inline) break :kind .{ .inline_ref = .fromValue(item_opv) }; |
| | 10954 | if (is_special) break :kind .special; |
| | 10955 | break :kind .{ .item_refs = &.{.fromValue(item_opv)} }; |
| | 10956 | }; |
| 10961 | break :payload_ref try sema.analyzeSwitchPayloadCapture( | 10957 | break :payload_ref try sema.analyzeSwitchPayloadCapture( |
| 10962 | &case_block, | 10958 | &case_block, |
| 10963 | operand, | 10959 | operand, |
| ... | @@ -10970,8 +10966,7 @@ fn analyzeSwitchBlock( | ... | @@ -10970,8 +10966,7 @@ fn analyzeSwitchBlock( |
| 10970 | .case_idx = index, | 10966 | .case_idx = index, |
| 10971 | } }), | 10967 | } }), |
| 10972 | capture == .by_ref, | 10968 | capture == .by_ref, |
| 10973 | if (is_special) .special else .{ .item_refs = &.{.fromValue(item_opv)} }, | 10969 | prong_kind, |
| 10974 | if (is_inline) .fromValue(item_opv) else .none, | | |
| 10975 | validated_switch.else_err_ty, | 10970 | validated_switch.else_err_ty, |
| 10976 | ); | 10971 | ); |
| 10977 | }, | 10972 | }, |
| ... | @@ -11094,8 +11089,6 @@ fn finishSwitchBr( | ... | @@ -11094,8 +11089,6 @@ fn finishSwitchBr( |
| 11094 | const cond_dbg_node_index: Zir.Inst.Index = @enumFromInt(@intFromEnum(switch_inst) - 1); | 11089 | const cond_dbg_node_index: Zir.Inst.Index = @enumFromInt(@intFromEnum(switch_inst) - 1); |
| 11095 | | 11090 | |
| 11096 | const else_is_named_only = has_else and has_under; | 11091 | const else_is_named_only = has_else and has_under; |
| 11097 | const catch_all_case: CatchAllSwitchCase = | | |
| 11098 | if (has_under) .under else if (has_else) .@"else" else .none; | | |
| 11099 | | 11092 | |
| 11100 | const item_ty = switch (operand_ty.zigTypeTag(zcu)) { | 11093 | const item_ty = switch (operand_ty.zigTypeTag(zcu)) { |
| 11101 | .@"union" => operand_ty.unionTagType(zcu).?, | 11094 | .@"union" => operand_ty.unionTagType(zcu).?, |
| ... | @@ -11216,8 +11209,7 @@ fn finishSwitchBr( | ... | @@ -11216,8 +11209,7 @@ fn finishSwitchBr( |
| 11216 | } }), | 11209 | } }), |
| 11217 | prong_info.capture, | 11210 | prong_info.capture, |
| 11218 | prong_info.has_tag_capture, | 11211 | prong_info.has_tag_capture, |
| 11219 | item_ref, | 11212 | .{ .inline_ref = item_ref }, |
| 11220 | .{ .item_refs = &.{item_ref} }, | | |
| 11221 | validated_switch.else_err_ty, | 11213 | validated_switch.else_err_ty, |
| 11222 | switch_inst, | 11214 | switch_inst, |
| 11223 | zir_switch, | 11215 | zir_switch, |
| ... | @@ -11308,8 +11300,7 @@ fn finishSwitchBr( | ... | @@ -11308,8 +11300,7 @@ fn finishSwitchBr( |
| 11308 | } }), | 11300 | } }), |
| 11309 | prong_info.capture, | 11301 | prong_info.capture, |
| 11310 | prong_info.has_tag_capture, | 11302 | prong_info.has_tag_capture, |
| 11311 | item_ref, | 11303 | .{ .inline_ref = item_ref }, |
| 11312 | .has_ranges, | | |
| 11313 | validated_switch.else_err_ty, | 11304 | validated_switch.else_err_ty, |
| 11314 | switch_inst, | 11305 | switch_inst, |
| 11315 | zir_switch, | 11306 | zir_switch, |
| ... | @@ -11333,6 +11324,9 @@ fn finishSwitchBr( | ... | @@ -11333,6 +11324,9 @@ fn finishSwitchBr( |
| 11333 | if (prong_info.is_inline) continue; // handled above | 11324 | if (prong_info.is_inline) continue; // handled above |
| 11334 | | 11325 | |
| 11335 | if (is_under_prong) { | 11326 | if (is_under_prong) { |
| | 11327 | // We will handle this later. If there are any named items specified |
| | 11328 | // along with the `_`, we don't have to actually emit any AIR for them |
| | 11329 | // as they will be 'absorbed' by the `_` (the catch-all prong) anyway. |
| 11336 | under_prong = .{ | 11330 | under_prong = .{ |
| 11337 | .index = case.index, | 11331 | .index = case.index, |
| 11338 | .body = prong_body, | 11332 | .body = prong_body, |
| ... | @@ -11359,8 +11353,7 @@ fn finishSwitchBr( | ... | @@ -11359,8 +11353,7 @@ fn finishSwitchBr( |
| 11359 | } }), | 11353 | } }), |
| 11360 | prong_info.capture, | 11354 | prong_info.capture, |
| 11361 | prong_info.has_tag_capture, | 11355 | prong_info.has_tag_capture, |
| 11362 | .none, | 11356 | if (range_refs.len > 0) .has_ranges else .{ .item_refs = item_refs }, |
| 11363 | .{ .item_refs = item_refs }, | | |
| 11364 | validated_switch.else_err_ty, | 11357 | validated_switch.else_err_ty, |
| 11365 | switch_inst, | 11358 | switch_inst, |
| 11366 | zir_switch, | 11359 | zir_switch, |
| ... | @@ -11385,7 +11378,7 @@ fn finishSwitchBr( | ... | @@ -11385,7 +11378,7 @@ fn finishSwitchBr( |
| 11385 | } | 11378 | } |
| 11386 | | 11379 | |
| 11387 | const catch_all_extra: []const u32 = catch_all_extra: { | 11380 | const catch_all_extra: []const u32 = catch_all_extra: { |
| 11388 | if (catch_all_case == .none and !case_block.wantSafety()) { | 11381 | if (!has_else and !has_under and !case_block.wantSafety()) { |
| 11389 | try branch_hints.append(gpa, .none); | 11382 | try branch_hints.append(gpa, .none); |
| 11390 | break :catch_all_extra &.{}; | 11383 | break :catch_all_extra &.{}; |
| 11391 | } | 11384 | } |
| ... | @@ -11445,8 +11438,7 @@ fn finishSwitchBr( | ... | @@ -11445,8 +11438,7 @@ fn finishSwitchBr( |
| 11445 | } }), | 11438 | } }), |
| 11446 | else_case.capture, | 11439 | else_case.capture, |
| 11447 | else_case.has_tag_capture, | 11440 | else_case.has_tag_capture, |
| 11448 | item_ref, | 11441 | .{ .inline_ref = item_ref }, |
| 11449 | .special, | | |
| 11450 | validated_switch.else_err_ty, | 11442 | validated_switch.else_err_ty, |
| 11451 | switch_inst, | 11443 | switch_inst, |
| 11452 | zir_switch, | 11444 | zir_switch, |
| ... | @@ -11473,7 +11465,7 @@ fn finishSwitchBr( | ... | @@ -11473,7 +11465,7 @@ fn finishSwitchBr( |
| 11473 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 11465 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 11474 | | 11466 | |
| 11475 | if (zcu.backendSupportsFeature(.is_named_enum_value) and | 11467 | if (zcu.backendSupportsFeature(.is_named_enum_value) and |
| 11476 | catch_all_case != .none and block.wantSafety() and | 11468 | (has_else or has_under) and block.wantSafety() and |
| 11477 | item_ty.zigTypeTag(zcu) == .@"enum" and | 11469 | item_ty.zigTypeTag(zcu) == .@"enum" and |
| 11478 | (!operand_ty.isNonexhaustiveEnum(zcu) or union_originally)) | 11470 | (!operand_ty.isNonexhaustiveEnum(zcu) or union_originally)) |
| 11479 | { | 11471 | { |
| ... | @@ -11508,7 +11500,6 @@ fn finishSwitchBr( | ... | @@ -11508,7 +11500,6 @@ fn finishSwitchBr( |
| 11508 | } }), | 11500 | } }), |
| 11509 | else_case.capture, | 11501 | else_case.capture, |
| 11510 | else_case.has_tag_capture, | 11502 | else_case.has_tag_capture, |
| 11511 | .none, | | |
| 11512 | .special, | 11503 | .special, |
| 11513 | validated_switch.else_err_ty, | 11504 | validated_switch.else_err_ty, |
| 11514 | switch_inst, | 11505 | switch_inst, |
| ... | @@ -11548,10 +11539,12 @@ fn finishSwitchBr( | ... | @@ -11548,10 +11539,12 @@ fn finishSwitchBr( |
| 11548 | } | 11539 | } |
| 11549 | | 11540 | |
| 11550 | const analyze_catch_all_body = analyze_body: { | 11541 | const analyze_catch_all_body = analyze_body: { |
| 11551 | switch (catch_all_case) { | 11542 | if (has_under) { |
| 11552 | .none => break :analyze_body false, // we still may want a safety check! | 11543 | break :analyze_body true; // can't be a union or an error set, never inlined |
| 11553 | .under => break :analyze_body true, // can't be a union anyway | 11544 | } else if (has_else) { |
| 11554 | .@"else" => if (else_case.is_inline) break :analyze_body false, | 11545 | if (else_case.is_inline) break :analyze_body false; // already handled above |
| | 11546 | } else { |
| | 11547 | break :analyze_body false; // we still may want a safety check! |
| 11555 | } | 11548 | } |
| 11556 | if (union_originally) { | 11549 | if (union_originally) { |
| 11557 | const union_obj = zcu.typeToUnion(operand_ty).?; | 11550 | const union_obj = zcu.typeToUnion(operand_ty).?; |
| ... | @@ -11574,11 +11567,10 @@ fn finishSwitchBr( | ... | @@ -11574,11 +11567,10 @@ fn finishSwitchBr( |
| 11574 | | 11567 | |
| 11575 | const catch_all_hint = hint: { | 11568 | const catch_all_hint = hint: { |
| 11576 | if (analyze_catch_all_body) { | 11569 | if (analyze_catch_all_body) { |
| 11577 | const index, const body, const capture, const has_tag_capture = switch (catch_all_case) { | 11570 | const index, const body, const capture, const has_tag_capture = if (under_prong) |under| |
| 11578 | .@"else" => .{ else_case.index, else_case.body, else_case.capture, else_case.has_tag_capture }, | 11571 | .{ under.index, under.body, under.capture, under.has_tag_capture } |
| 11579 | .under => .{ under_prong.?.index, under_prong.?.body, under_prong.?.capture, under_prong.?.has_tag_capture }, | 11572 | else |
| 11580 | .none => unreachable, | 11573 | .{ else_case.index, else_case.body, else_case.capture, else_case.has_tag_capture }; |
| 11581 | }; | | |
| 11582 | break :hint try sema.analyzeSwitchProng( | 11574 | break :hint try sema.analyzeSwitchProng( |
| 11583 | &case_block, | 11575 | &case_block, |
| 11584 | operand, | 11576 | operand, |
| ... | @@ -11591,7 +11583,6 @@ fn finishSwitchBr( | ... | @@ -11591,7 +11583,6 @@ fn finishSwitchBr( |
| 11591 | } }), | 11583 | } }), |
| 11592 | capture, | 11584 | capture, |
| 11593 | has_tag_capture, | 11585 | has_tag_capture, |
| 11594 | .none, | | |
| 11595 | .special, | 11586 | .special, |
| 11596 | validated_switch.else_err_ty, | 11587 | validated_switch.else_err_ty, |
| 11597 | switch_inst, | 11588 | switch_inst, |
| ... | @@ -12072,9 +12063,9 @@ fn validateSwitchBlock( | ... | @@ -12072,9 +12063,9 @@ fn validateSwitchBlock( |
| 12072 | const msg = try sema.errMsg( | 12063 | const msg = try sema.errMsg( |
| 12073 | operand_src, | 12064 | operand_src, |
| 12074 | "ranges not allowed when switching on type '{f}'", | 12065 | "ranges not allowed when switching on type '{f}'", |
| 12075 | .{operand_ty.fmt(sema.pt)}, | 12066 | .{operand_ty.fmt(pt)}, |
| 12076 | ); | 12067 | ); |
| 12077 | errdefer msg.destroy(sema.gpa); | 12068 | errdefer msg.destroy(gpa); |
| 12078 | try sema.errNote( | 12069 | try sema.errNote( |
| 12079 | range_src, | 12070 | range_src, |
| 12080 | msg, | 12071 | msg, |
| ... | @@ -12309,8 +12300,6 @@ fn resolveSwitchBlock( | ... | @@ -12309,8 +12300,6 @@ fn resolveSwitchBlock( |
| 12309 | operand: SwitchOperand, | 12300 | operand: SwitchOperand, |
| 12310 | raw_operand_ty: Type, | 12301 | raw_operand_ty: Type, |
| 12311 | maybe_lazy_cond_val: Value, | 12302 | maybe_lazy_cond_val: Value, |
| 12312 | catch_all_case: CatchAllSwitchCase, | | |
| 12313 | else_is_named_only: bool, | | |
| 12314 | merges: *Block.Merges, | 12303 | merges: *Block.Merges, |
| 12315 | switch_inst: Zir.Inst.Index, | 12304 | switch_inst: Zir.Inst.Index, |
| 12316 | zir_switch: *const Zir.UnwrappedSwitchBlock, | 12305 | zir_switch: *const Zir.UnwrappedSwitchBlock, |
| ... | @@ -12377,6 +12366,11 @@ fn resolveSwitchBlock( | ... | @@ -12377,6 +12366,11 @@ fn resolveSwitchBlock( |
| 12377 | // This prong should be unreachable! | 12366 | // This prong should be unreachable! |
| 12378 | return .unreachable_value; | 12367 | return .unreachable_value; |
| 12379 | } | 12368 | } |
| | 12369 | const prong_kind: SwitchProngKind = kind: { |
| | 12370 | if (prong_info.is_inline) break :kind .{ .inline_ref = cond_ref }; |
| | 12371 | if (range_refs.len > 0) break :kind .has_ranges; |
| | 12372 | break :kind .{ .item_refs = item_refs }; |
| | 12373 | }; |
| 12380 | return sema.resolveSwitchProng( | 12374 | return sema.resolveSwitchProng( |
| 12381 | block, | 12375 | block, |
| 12382 | child_block, | 12376 | child_block, |
| ... | @@ -12389,8 +12383,7 @@ fn resolveSwitchBlock( | ... | @@ -12389,8 +12383,7 @@ fn resolveSwitchBlock( |
| 12389 | } }), | 12383 | } }), |
| 12390 | prong_info.capture, | 12384 | prong_info.capture, |
| 12391 | prong_info.has_tag_capture, | 12385 | prong_info.has_tag_capture, |
| 12392 | if (prong_info.is_inline) cond_ref else .none, | 12386 | prong_kind, |
| 12393 | .{ .item_refs = item_refs }, | | |
| 12394 | validated_switch.else_err_ty, | 12387 | validated_switch.else_err_ty, |
| 12395 | merges, | 12388 | merges, |
| 12396 | switch_inst, | 12389 | switch_inst, |
| ... | @@ -12404,6 +12397,10 @@ fn resolveSwitchBlock( | ... | @@ -12404,6 +12397,10 @@ fn resolveSwitchBlock( |
| 12404 | if ((try sema.compareAll(cond_val, .gte, first_val, item_ty)) and | 12397 | if ((try sema.compareAll(cond_val, .gte, first_val, item_ty)) and |
| 12405 | (try sema.compareAll(cond_val, .lte, last_val, item_ty))) | 12398 | (try sema.compareAll(cond_val, .lte, last_val, item_ty))) |
| 12406 | { | 12399 | { |
| | 12400 | const prong_kind: SwitchProngKind = if (prong_info.is_inline) |
| | 12401 | .{ .inline_ref = cond_ref } |
| | 12402 | else |
| | 12403 | .has_ranges; |
| 12407 | return sema.resolveSwitchProng( | 12404 | return sema.resolveSwitchProng( |
| 12408 | block, | 12405 | block, |
| 12409 | child_block, | 12406 | child_block, |
| ... | @@ -12416,8 +12413,7 @@ fn resolveSwitchBlock( | ... | @@ -12416,8 +12413,7 @@ fn resolveSwitchBlock( |
| 12416 | } }), | 12413 | } }), |
| 12417 | prong_info.capture, | 12414 | prong_info.capture, |
| 12418 | prong_info.has_tag_capture, | 12415 | prong_info.has_tag_capture, |
| 12419 | if (prong_info.is_inline) cond_ref else .none, | 12416 | prong_kind, |
| 12420 | .has_ranges, | | |
| 12421 | validated_switch.else_err_ty, | 12417 | validated_switch.else_err_ty, |
| 12422 | merges, | 12418 | merges, |
| 12423 | switch_inst, | 12419 | switch_inst, |
| ... | @@ -12428,11 +12424,16 @@ fn resolveSwitchBlock( | ... | @@ -12428,11 +12424,16 @@ fn resolveSwitchBlock( |
| 12428 | } | 12424 | } |
| 12429 | | 12425 | |
| 12430 | const else_case = validated_switch.else_case; | 12426 | const else_case = validated_switch.else_case; |
| | 12427 | const else_is_named_only = zir_switch.else_case != null and under_prong != null; |
| 12431 | | 12428 | |
| 12432 | // named-only prong | 12429 | // named-only prong |
| 12433 | | 12430 | |
| 12434 | if (else_is_named_only and item_ty.enumTagFieldIndex(cond_val, zcu) != null) { | 12431 | if (else_is_named_only and item_ty.enumTagFieldIndex(cond_val, zcu) != null) { |
| 12435 | assert(item_ty.isNonexhaustiveEnum(zcu)); | 12432 | assert(item_ty.isNonexhaustiveEnum(zcu)); |
| | 12433 | const prong_kind: SwitchProngKind = if (else_case.is_inline) |
| | 12434 | .{ .inline_ref = cond_ref } |
| | 12435 | else |
| | 12436 | .special; |
| 12436 | return sema.resolveSwitchProng( | 12437 | return sema.resolveSwitchProng( |
| 12437 | block, | 12438 | block, |
| 12438 | child_block, | 12439 | child_block, |
| ... | @@ -12445,8 +12446,7 @@ fn resolveSwitchBlock( | ... | @@ -12445,8 +12446,7 @@ fn resolveSwitchBlock( |
| 12445 | } }), | 12446 | } }), |
| 12446 | else_case.capture, | 12447 | else_case.capture, |
| 12447 | else_case.has_tag_capture, | 12448 | else_case.has_tag_capture, |
| 12448 | if (else_case.is_inline) cond_ref else .none, | 12449 | prong_kind, |
| 12449 | .special, | | |
| 12450 | validated_switch.else_err_ty, | 12450 | validated_switch.else_err_ty, |
| 12451 | merges, | 12451 | merges, |
| 12452 | switch_inst, | 12452 | switch_inst, |
| ... | @@ -12456,11 +12456,10 @@ fn resolveSwitchBlock( | ... | @@ -12456,11 +12456,10 @@ fn resolveSwitchBlock( |
| 12456 | | 12456 | |
| 12457 | // catch-all prong | 12457 | // catch-all prong |
| 12458 | | 12458 | |
| 12459 | const index, const body, const capture, const has_tag_capture, const is_inline = switch (catch_all_case) { | 12459 | const index, const body, const capture, const has_tag_capture, const is_inline = if (under_prong) |under| |
| 12460 | .@"else" => .{ else_case.index, else_case.body, else_case.capture, else_case.has_tag_capture, else_case.is_inline }, | 12460 | .{ under.index, under.body, under.capture, under.has_tag_capture, false } |
| 12461 | .under => .{ under_prong.?.index, under_prong.?.body, under_prong.?.capture, under_prong.?.has_tag_capture, false }, | 12461 | else |
| 12462 | .none => unreachable, | 12462 | .{ else_case.index, else_case.body, else_case.capture, else_case.has_tag_capture, else_case.is_inline }; |
| 12463 | }; | | |
| 12464 | if (err_set) try sema.maybeErrorUnwrapComptime(child_block, body, cond_ref); | 12463 | if (err_set) try sema.maybeErrorUnwrapComptime(child_block, body, cond_ref); |
| 12465 | if (union_originally) { | 12464 | if (union_originally) { |
| 12466 | for (validated_switch.seen_enum_fields, 0..) |maybe_seen, field_i| { | 12465 | for (validated_switch.seen_enum_fields, 0..) |maybe_seen, field_i| { |
| ... | @@ -12471,6 +12470,10 @@ fn resolveSwitchBlock( | ... | @@ -12471,6 +12470,10 @@ fn resolveSwitchBlock( |
| 12471 | return .unreachable_value; | 12470 | return .unreachable_value; |
| 12472 | } | 12471 | } |
| 12473 | } | 12472 | } |
| | 12473 | const prong_kind: SwitchProngKind = if (is_inline) |
| | 12474 | .{ .inline_ref = cond_ref } |
| | 12475 | else |
| | 12476 | .special; |
| 12474 | return sema.resolveSwitchProng( | 12477 | return sema.resolveSwitchProng( |
| 12475 | block, | 12478 | block, |
| 12476 | child_block, | 12479 | child_block, |
| ... | @@ -12483,8 +12486,7 @@ fn resolveSwitchBlock( | ... | @@ -12483,8 +12486,7 @@ fn resolveSwitchBlock( |
| 12483 | } }), | 12486 | } }), |
| 12484 | capture, | 12487 | capture, |
| 12485 | has_tag_capture, | 12488 | has_tag_capture, |
| 12486 | if (is_inline) cond_ref else .none, | 12489 | prong_kind, |
| 12487 | .special, | | |
| 12488 | validated_switch.else_err_ty, | 12490 | validated_switch.else_err_ty, |
| 12489 | merges, | 12491 | merges, |
| 12490 | switch_inst, | 12492 | switch_inst, |
| ... | @@ -12520,9 +12522,9 @@ const SwitchOperand = union(enum) { | ... | @@ -12520,9 +12522,9 @@ const SwitchOperand = union(enum) { |
| 12520 | }, | 12522 | }, |
| 12521 | }; | 12523 | }; |
| 12522 | | 12524 | |
| 12523 | const CatchAllSwitchCase = enum { none, @"else", under }; | | |
| 12524 | | | |
| 12525 | const SwitchProngKind = union(enum) { | 12525 | const SwitchProngKind = union(enum) { |
| | 12526 | /// Prefer populating this field over the others, if possible. |
| | 12527 | inline_ref: Air.Inst.Ref, |
| 12526 | item_refs: []const Air.Inst.Ref, | 12528 | item_refs: []const Air.Inst.Ref, |
| 12527 | has_ranges, | 12529 | has_ranges, |
| 12528 | special, | 12530 | special, |
| ... | @@ -12541,7 +12543,6 @@ fn resolveSwitchProng( | ... | @@ -12541,7 +12543,6 @@ fn resolveSwitchProng( |
| 12541 | capture_src: LazySrcLoc, | 12543 | capture_src: LazySrcLoc, |
| 12542 | capture: Zir.Inst.SwitchBlock.ProngInfo.Capture, | 12544 | capture: Zir.Inst.SwitchBlock.ProngInfo.Capture, |
| 12543 | has_tag_capture: bool, | 12545 | has_tag_capture: bool, |
| 12544 | inline_case_capture: Air.Inst.Ref, | | |
| 12545 | kind: SwitchProngKind, | 12546 | kind: SwitchProngKind, |
| 12546 | else_err_ty: ?Type, | 12547 | else_err_ty: ?Type, |
| 12547 | merges: *Block.Merges, | 12548 | merges: *Block.Merges, |
| ... | @@ -12569,7 +12570,6 @@ fn resolveSwitchProng( | ... | @@ -12569,7 +12570,6 @@ fn resolveSwitchProng( |
| 12569 | capture_src, | 12570 | capture_src, |
| 12570 | capture == .by_ref, | 12571 | capture == .by_ref, |
| 12571 | kind, | 12572 | kind, |
| 12572 | inline_case_capture, | | |
| 12573 | else_err_ty, | 12573 | else_err_ty, |
| 12574 | ); | 12574 | ); |
| 12575 | assert(!sema.typeOf(payload_ref).isNoReturn(sema.pt.zcu)); | 12575 | assert(!sema.typeOf(payload_ref).isNoReturn(sema.pt.zcu)); |
| ... | @@ -12585,7 +12585,6 @@ fn resolveSwitchProng( | ... | @@ -12585,7 +12585,6 @@ fn resolveSwitchProng( |
| 12585 | operand.simple.by_val, | 12585 | operand.simple.by_val, |
| 12586 | sema.typeOf(operand.simple.by_val), | 12586 | sema.typeOf(operand.simple.by_val), |
| 12587 | capture_src, | 12587 | capture_src, |
| 12588 | inline_case_capture, | | |
| 12589 | kind, | 12588 | kind, |
| 12590 | ); | 12589 | ); |
| 12591 | sema.inst_map.putAssumeCapacity(tag_inst, tag_ref); | 12590 | sema.inst_map.putAssumeCapacity(tag_inst, tag_ref); |
| ... | @@ -12637,7 +12636,6 @@ fn analyzeSwitchProng( | ... | @@ -12637,7 +12636,6 @@ fn analyzeSwitchProng( |
| 12637 | capture_src: LazySrcLoc, | 12636 | capture_src: LazySrcLoc, |
| 12638 | capture: Zir.Inst.SwitchBlock.ProngInfo.Capture, | 12637 | capture: Zir.Inst.SwitchBlock.ProngInfo.Capture, |
| 12639 | has_tag_capture: bool, | 12638 | has_tag_capture: bool, |
| 12640 | inline_case_capture: Air.Inst.Ref, | | |
| 12641 | kind: SwitchProngKind, | 12639 | kind: SwitchProngKind, |
| 12642 | else_err_ty: ?Type, | 12640 | else_err_ty: ?Type, |
| 12643 | switch_inst: Zir.Inst.Index, | 12641 | switch_inst: Zir.Inst.Index, |
| ... | @@ -12664,7 +12662,7 @@ fn analyzeSwitchProng( | ... | @@ -12664,7 +12662,7 @@ fn analyzeSwitchProng( |
| 12664 | // No need to load the operand for this prong! | 12662 | // No need to load the operand for this prong! |
| 12665 | break :load_operand .{ undefined, undefined }; | 12663 | break :load_operand .{ undefined, undefined }; |
| 12666 | } | 12664 | } |
| 12667 | if (inline_case_capture != .none and | 12665 | if (kind == .inline_ref and |
| 12668 | !(capture != .none and operand_ty.zigTypeTag(zcu) == .@"union")) | 12666 | !(capture != .none and operand_ty.zigTypeTag(zcu) == .@"union")) |
| 12669 | { | 12667 | { |
| 12670 | // We only need to load the operand if there's a union payload capture | 12668 | // We only need to load the operand if there's a union payload capture |
| ... | @@ -12698,7 +12696,6 @@ fn analyzeSwitchProng( | ... | @@ -12698,7 +12696,6 @@ fn analyzeSwitchProng( |
| 12698 | capture_src, | 12696 | capture_src, |
| 12699 | capture == .by_ref, | 12697 | capture == .by_ref, |
| 12700 | kind, | 12698 | kind, |
| 12701 | inline_case_capture, | | |
| 12702 | else_err_ty, | 12699 | else_err_ty, |
| 12703 | ); | 12700 | ); |
| 12704 | assert(!sema.typeOf(payload_ref).isNoReturn(sema.pt.zcu)); | 12701 | assert(!sema.typeOf(payload_ref).isNoReturn(sema.pt.zcu)); |
| ... | @@ -12714,7 +12711,6 @@ fn analyzeSwitchProng( | ... | @@ -12714,7 +12711,6 @@ fn analyzeSwitchProng( |
| 12714 | operand_val, | 12711 | operand_val, |
| 12715 | operand_ty, | 12712 | operand_ty, |
| 12716 | capture_src, | 12713 | capture_src, |
| 12717 | inline_case_capture, | | |
| 12718 | kind, | 12714 | kind, |
| 12719 | ); | 12715 | ); |
| 12720 | sema.inst_map.putAssumeCapacity(tag_inst, tag_ref); | 12716 | sema.inst_map.putAssumeCapacity(tag_inst, tag_ref); |
| ... | @@ -12735,7 +12731,6 @@ fn analyzeSwitchTagCapture( | ... | @@ -12735,7 +12731,6 @@ fn analyzeSwitchTagCapture( |
| 12735 | operand_val: Air.Inst.Ref, | 12731 | operand_val: Air.Inst.Ref, |
| 12736 | operand_ty: Type, | 12732 | operand_ty: Type, |
| 12737 | capture_src: LazySrcLoc, | 12733 | capture_src: LazySrcLoc, |
| 12738 | inline_case_capture: Air.Inst.Ref, | | |
| 12739 | kind: SwitchProngKind, | 12734 | kind: SwitchProngKind, |
| 12740 | ) CompileError!Air.Inst.Ref { | 12735 | ) CompileError!Air.Inst.Ref { |
| 12741 | const pt = sema.pt; | 12736 | const pt = sema.pt; |
| ... | @@ -12751,12 +12746,11 @@ fn analyzeSwitchTagCapture( | ... | @@ -12751,12 +12746,11 @@ fn analyzeSwitchTagCapture( |
| 12751 | operand_ty.fmt(pt), | 12746 | operand_ty.fmt(pt), |
| 12752 | }); | 12747 | }); |
| 12753 | } | 12748 | } |
| 12754 | if (inline_case_capture != .none) { | | |
| 12755 | return inline_case_capture; // this already is the tag, it's what we're switching on! | | |
| 12756 | } | | |
| 12757 | switch (kind) { | 12749 | switch (kind) { |
| 12758 | .has_ranges, .special => {}, | 12750 | .has_ranges => unreachable, |
| | 12751 | .inline_ref => |ref| return ref, |
| 12759 | .item_refs => |refs| if (refs.len == 1) return refs[0], | 12752 | .item_refs => |refs| if (refs.len == 1) return refs[0], |
| | 12753 | .special => {}, |
| 12760 | } | 12754 | } |
| 12761 | const tag_ty = operand_ty.unionTagType(zcu).?; | 12755 | const tag_ty = operand_ty.unionTagType(zcu).?; |
| 12762 | return sema.unionToTag(case_block, tag_ty, operand_val, tag_capture_src); | 12756 | return sema.unionToTag(case_block, tag_ty, operand_val, tag_capture_src); |
| ... | @@ -12775,8 +12769,6 @@ fn analyzeSwitchPayloadCapture( | ... | @@ -12775,8 +12769,6 @@ fn analyzeSwitchPayloadCapture( |
| 12775 | capture_src: LazySrcLoc, | 12769 | capture_src: LazySrcLoc, |
| 12776 | capture_by_ref: bool, | 12770 | capture_by_ref: bool, |
| 12777 | kind: SwitchProngKind, | 12771 | kind: SwitchProngKind, |
| 12778 | /// If this is not `.none`, this is an inline capture. | | |
| 12779 | inline_case_capture: Air.Inst.Ref, | | |
| 12780 | else_err_ty: ?Type, | 12772 | else_err_ty: ?Type, |
| 12781 | ) CompileError!Air.Inst.Ref { | 12773 | ) CompileError!Air.Inst.Ref { |
| 12782 | const pt = sema.pt; | 12774 | const pt = sema.pt; |
| ... | @@ -12785,8 +12777,8 @@ fn analyzeSwitchPayloadCapture( | ... | @@ -12785,8 +12777,8 @@ fn analyzeSwitchPayloadCapture( |
| 12785 | | 12777 | |
| 12786 | const switch_node_offset = operand_src.offset.node_offset_switch_operand; | 12778 | const switch_node_offset = operand_src.offset.node_offset_switch_operand; |
| 12787 | | 12779 | |
| 12788 | if (inline_case_capture != .none) { | 12780 | if (kind == .inline_ref) { |
| 12789 | const item_val = sema.resolveConstDefinedValue(case_block, .unneeded, inline_case_capture, undefined) catch unreachable; | 12781 | const item_val = sema.resolveConstDefinedValue(case_block, .unneeded, kind.inline_ref, undefined) catch unreachable; |
| 12790 | if (operand_ty.zigTypeTag(zcu) == .@"union") { | 12782 | if (operand_ty.zigTypeTag(zcu) == .@"union") { |
| 12791 | const field_index: u32 = @intCast(operand_ty.unionTagFieldIndex(item_val, zcu).?); | 12783 | const field_index: u32 = @intCast(operand_ty.unionTagFieldIndex(item_val, zcu).?); |
| 12792 | const union_obj = zcu.typeToUnion(operand_ty).?; | 12784 | const union_obj = zcu.typeToUnion(operand_ty).?; |
| ... | @@ -12812,7 +12804,7 @@ fn analyzeSwitchPayloadCapture( | ... | @@ -12812,7 +12804,7 @@ fn analyzeSwitchPayloadCapture( |
| 12812 | } else if (capture_by_ref) { | 12804 | } else if (capture_by_ref) { |
| 12813 | return sema.uavRef(item_val.toIntern()); | 12805 | return sema.uavRef(item_val.toIntern()); |
| 12814 | } else { | 12806 | } else { |
| 12815 | return inline_case_capture; | 12807 | return kind.inline_ref; |
| 12816 | } | 12808 | } |
| 12817 | } | 12809 | } |
| 12818 | | 12810 | |
| ... | @@ -13155,7 +13147,7 @@ fn analyzeSwitchPayloadCapture( | ... | @@ -13155,7 +13147,7 @@ fn analyzeSwitchPayloadCapture( |
| 13155 | return operand_ptr; | 13147 | return operand_ptr; |
| 13156 | } | 13148 | } |
| 13157 | switch (kind) { | 13149 | switch (kind) { |
| 13158 | .special => unreachable, | 13150 | .inline_ref, .special => unreachable, |
| 13159 | .item_refs => |case_vals| { | 13151 | .item_refs => |case_vals| { |
| 13160 | // If there's only a single item, the capture is comptime-known! | 13152 | // If there's only a single item, the capture is comptime-known! |
| 13161 | if (case_vals.len == 1) return case_vals[0]; | 13153 | if (case_vals.len == 1) return case_vals[0]; |