| ... | @@ -10099,6 +10099,8 @@ fn zirSwitchCapture( | ... | @@ -10099,6 +10099,8 @@ fn zirSwitchCapture( |
| 10099 | const switch_info = zir_datas[capture_info.switch_inst].pl_node; | 10099 | const switch_info = zir_datas[capture_info.switch_inst].pl_node; |
| 10100 | const switch_extra = sema.code.extraData(Zir.Inst.SwitchBlock, switch_info.payload_index); | 10100 | const switch_extra = sema.code.extraData(Zir.Inst.SwitchBlock, switch_info.payload_index); |
| 10101 | const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = switch_info.src_node }; | 10101 | const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = switch_info.src_node }; |
| | 10102 | const cond = try sema.resolveInst(switch_extra.data.operand); |
| | 10103 | const cond_ty = sema.typeOf(cond); |
| 10102 | const cond_inst = Zir.refToIndex(switch_extra.data.operand).?; | 10104 | const cond_inst = Zir.refToIndex(switch_extra.data.operand).?; |
| 10103 | const cond_info = zir_datas[cond_inst].un_node; | 10105 | const cond_info = zir_datas[cond_inst].un_node; |
| 10104 | const cond_tag = sema.code.instructions.items(.tag)[cond_inst]; | 10106 | const cond_tag = sema.code.instructions.items(.tag)[cond_inst]; |
| ... | @@ -10175,6 +10177,8 @@ fn zirSwitchCapture( | ... | @@ -10175,6 +10177,8 @@ fn zirSwitchCapture( |
| 10175 | } | 10177 | } |
| 10176 | } | 10178 | } |
| 10177 | | 10179 | |
| | 10180 | // Note that these are the *uncasted* prong items. |
| | 10181 | // Also note that items from ranges are not included so this only works for non-ranged types. |
| 10178 | const items = switch_extra.data.getProng(sema.code, switch_extra.end, capture_info.prong_index).items; | 10182 | const items = switch_extra.data.getProng(sema.code, switch_extra.end, capture_info.prong_index).items; |
| 10179 | | 10183 | |
| 10180 | switch (operand_ty.zigTypeTag(mod)) { | 10184 | switch (operand_ty.zigTypeTag(mod)) { |
| ... | @@ -10182,7 +10186,8 @@ fn zirSwitchCapture( | ... | @@ -10182,7 +10186,8 @@ fn zirSwitchCapture( |
| 10182 | const union_obj = mod.typeToUnion(operand_ty).?; | 10186 | const union_obj = mod.typeToUnion(operand_ty).?; |
| 10183 | const first_item = try sema.resolveInst(items[0]); | 10187 | const first_item = try sema.resolveInst(items[0]); |
| 10184 | // Previous switch validation ensured this will succeed | 10188 | // Previous switch validation ensured this will succeed |
| 10185 | const first_item_val = sema.resolveConstValue(block, .unneeded, first_item, "") catch unreachable; | 10189 | const first_item_coerced = try sema.coerce(block, cond_ty, first_item, .unneeded); |
| | 10190 | const first_item_val = sema.resolveConstValue(block, .unneeded, first_item_coerced, "") catch unreachable; |
| 10186 | | 10191 | |
| 10187 | const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, mod).?); | 10192 | const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, mod).?); |
| 10188 | const first_field = union_obj.fields.values()[first_field_index]; | 10193 | const first_field = union_obj.fields.values()[first_field_index]; |
| ... | @@ -10190,7 +10195,8 @@ fn zirSwitchCapture( | ... | @@ -10190,7 +10195,8 @@ fn zirSwitchCapture( |
| 10190 | for (items[1..], 0..) |item, i| { | 10195 | for (items[1..], 0..) |item, i| { |
| 10191 | const item_ref = try sema.resolveInst(item); | 10196 | const item_ref = try sema.resolveInst(item); |
| 10192 | // Previous switch validation ensured this will succeed | 10197 | // Previous switch validation ensured this will succeed |
| 10193 | const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable; | 10198 | const item_coerced = try sema.coerce(block, cond_ty, item_ref, .unneeded); |
| | 10199 | const item_val = sema.resolveConstValue(block, .unneeded, item_coerced, "") catch unreachable; |
| 10194 | | 10200 | |
| 10195 | const field_index = operand_ty.unionTagFieldIndex(item_val, mod).?; | 10201 | const field_index = operand_ty.unionTagFieldIndex(item_val, mod).?; |
| 10196 | const field = union_obj.fields.values()[field_index]; | 10202 | const field = union_obj.fields.values()[field_index]; |
| ... | @@ -10406,6 +10412,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10406,6 +10412,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10406 | break :blk multi_cases_len; | 10412 | break :blk multi_cases_len; |
| 10407 | } else 0; | 10413 | } else 0; |
| 10408 | | 10414 | |
| | 10415 | var case_vals = try std.ArrayListUnmanaged(Air.Inst.Ref).initCapacity(gpa, scalar_cases_len + 2 * multi_cases_len); |
| | 10416 | defer case_vals.deinit(gpa); |
| | 10417 | |
| 10409 | const special_prong = extra.data.bits.specialProng(); | 10418 | const special_prong = extra.data.bits.specialProng(); |
| 10410 | const special: struct { body: []const Zir.Inst.Index, end: usize, is_inline: bool } = switch (special_prong) { | 10419 | const special: struct { body: []const Zir.Inst.Index, end: usize, is_inline: bool } = switch (special_prong) { |
| 10411 | .none => .{ .body = &.{}, .end = header_extra_index, .is_inline = false }, | 10420 | .none => .{ .body = &.{}, .end = header_extra_index, .is_inline = false }, |
| ... | @@ -10491,14 +10500,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10491,14 +10500,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10491 | extra_index += 1; | 10500 | extra_index += 1; |
| 10492 | extra_index += body_len; | 10501 | extra_index += body_len; |
| 10493 | | 10502 | |
| 10494 | try sema.validateSwitchItemEnum( | 10503 | case_vals.appendAssumeCapacity(try sema.validateSwitchItemEnum( |
| 10495 | block, | 10504 | block, |
| 10496 | seen_enum_fields, | 10505 | seen_enum_fields, |
| 10497 | &range_set, | 10506 | &range_set, |
| 10498 | item_ref, | 10507 | item_ref, |
| | 10508 | operand_ty, |
| 10499 | src_node_offset, | 10509 | src_node_offset, |
| 10500 | .{ .scalar = scalar_i }, | 10510 | .{ .scalar = scalar_i }, |
| 10501 | ); | 10511 | )); |
| 10502 | } | 10512 | } |
| 10503 | } | 10513 | } |
| 10504 | { | 10514 | { |
| ... | @@ -10513,15 +10523,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10513,15 +10523,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10513 | const items = sema.code.refSlice(extra_index, items_len); | 10523 | const items = sema.code.refSlice(extra_index, items_len); |
| 10514 | extra_index += items_len + body_len; | 10524 | extra_index += items_len + body_len; |
| 10515 | | 10525 | |
| | 10526 | try case_vals.ensureUnusedCapacity(gpa, items.len); |
| 10516 | for (items, 0..) |item_ref, item_i| { | 10527 | for (items, 0..) |item_ref, item_i| { |
| 10517 | try sema.validateSwitchItemEnum( | 10528 | case_vals.appendAssumeCapacity(try sema.validateSwitchItemEnum( |
| 10518 | block, | 10529 | block, |
| 10519 | seen_enum_fields, | 10530 | seen_enum_fields, |
| 10520 | &range_set, | 10531 | &range_set, |
| 10521 | item_ref, | 10532 | item_ref, |
| | 10533 | operand_ty, |
| 10522 | src_node_offset, | 10534 | src_node_offset, |
| 10523 | .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } }, | 10535 | .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } }, |
| 10524 | ); | 10536 | )); |
| 10525 | } | 10537 | } |
| 10526 | | 10538 | |
| 10527 | try sema.validateSwitchNoRange(block, ranges_len, operand_ty, src_node_offset); | 10539 | try sema.validateSwitchNoRange(block, ranges_len, operand_ty, src_node_offset); |
| ... | @@ -10588,13 +10600,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10588,13 +10600,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10588 | extra_index += 1; | 10600 | extra_index += 1; |
| 10589 | extra_index += body_len; | 10601 | extra_index += body_len; |
| 10590 | | 10602 | |
| 10591 | try sema.validateSwitchItemError( | 10603 | case_vals.appendAssumeCapacity(try sema.validateSwitchItemError( |
| 10592 | block, | 10604 | block, |
| 10593 | &seen_errors, | 10605 | &seen_errors, |
| 10594 | item_ref, | 10606 | item_ref, |
| | 10607 | operand_ty, |
| 10595 | src_node_offset, | 10608 | src_node_offset, |
| 10596 | .{ .scalar = scalar_i }, | 10609 | .{ .scalar = scalar_i }, |
| 10597 | ); | 10610 | )); |
| 10598 | } | 10611 | } |
| 10599 | } | 10612 | } |
| 10600 | { | 10613 | { |
| ... | @@ -10609,14 +10622,16 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10609,14 +10622,16 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10609 | const items = sema.code.refSlice(extra_index, items_len); | 10622 | const items = sema.code.refSlice(extra_index, items_len); |
| 10610 | extra_index += items_len + body_len; | 10623 | extra_index += items_len + body_len; |
| 10611 | | 10624 | |
| | 10625 | try case_vals.ensureUnusedCapacity(gpa, items.len); |
| 10612 | for (items, 0..) |item_ref, item_i| { | 10626 | for (items, 0..) |item_ref, item_i| { |
| 10613 | try sema.validateSwitchItemError( | 10627 | case_vals.appendAssumeCapacity(try sema.validateSwitchItemError( |
| 10614 | block, | 10628 | block, |
| 10615 | &seen_errors, | 10629 | &seen_errors, |
| 10616 | item_ref, | 10630 | item_ref, |
| | 10631 | operand_ty, |
| 10617 | src_node_offset, | 10632 | src_node_offset, |
| 10618 | .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } }, | 10633 | .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } }, |
| 10619 | ); | 10634 | )); |
| 10620 | } | 10635 | } |
| 10621 | | 10636 | |
| 10622 | try sema.validateSwitchNoRange(block, ranges_len, operand_ty, src_node_offset); | 10637 | try sema.validateSwitchNoRange(block, ranges_len, operand_ty, src_node_offset); |
| ... | @@ -10728,13 +10743,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10728,13 +10743,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10728 | extra_index += 1; | 10743 | extra_index += 1; |
| 10729 | extra_index += body_len; | 10744 | extra_index += body_len; |
| 10730 | | 10745 | |
| 10731 | try sema.validateSwitchItem( | 10746 | case_vals.appendAssumeCapacity(try sema.validateSwitchItemInt( |
| 10732 | block, | 10747 | block, |
| 10733 | &range_set, | 10748 | &range_set, |
| 10734 | item_ref, | 10749 | item_ref, |
| | 10750 | operand_ty, |
| 10735 | src_node_offset, | 10751 | src_node_offset, |
| 10736 | .{ .scalar = scalar_i }, | 10752 | .{ .scalar = scalar_i }, |
| 10737 | ); | 10753 | )); |
| 10738 | } | 10754 | } |
| 10739 | } | 10755 | } |
| 10740 | { | 10756 | { |
| ... | @@ -10749,16 +10765,19 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10749,16 +10765,19 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10749 | const items = sema.code.refSlice(extra_index, items_len); | 10765 | const items = sema.code.refSlice(extra_index, items_len); |
| 10750 | extra_index += items_len; | 10766 | extra_index += items_len; |
| 10751 | | 10767 | |
| | 10768 | try case_vals.ensureUnusedCapacity(gpa, items.len); |
| 10752 | for (items, 0..) |item_ref, item_i| { | 10769 | for (items, 0..) |item_ref, item_i| { |
| 10753 | try sema.validateSwitchItem( | 10770 | case_vals.appendAssumeCapacity(try sema.validateSwitchItemInt( |
| 10754 | block, | 10771 | block, |
| 10755 | &range_set, | 10772 | &range_set, |
| 10756 | item_ref, | 10773 | item_ref, |
| | 10774 | operand_ty, |
| 10757 | src_node_offset, | 10775 | src_node_offset, |
| 10758 | .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } }, | 10776 | .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } }, |
| 10759 | ); | 10777 | )); |
| 10760 | } | 10778 | } |
| 10761 | | 10779 | |
| | 10780 | try case_vals.ensureUnusedCapacity(gpa, 2 * ranges_len); |
| 10762 | var range_i: u32 = 0; | 10781 | var range_i: u32 = 0; |
| 10763 | while (range_i < ranges_len) : (range_i += 1) { | 10782 | while (range_i < ranges_len) : (range_i += 1) { |
| 10764 | const item_first = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 10783 | const item_first = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| ... | @@ -10766,14 +10785,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10766,14 +10785,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10766 | const item_last = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 10785 | const item_last = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 10767 | extra_index += 1; | 10786 | extra_index += 1; |
| 10768 | | 10787 | |
| 10769 | try sema.validateSwitchRange( | 10788 | const vals = try sema.validateSwitchRange( |
| 10770 | block, | 10789 | block, |
| 10771 | &range_set, | 10790 | &range_set, |
| 10772 | item_first, | 10791 | item_first, |
| 10773 | item_last, | 10792 | item_last, |
| | 10793 | operand_ty, |
| 10774 | src_node_offset, | 10794 | src_node_offset, |
| 10775 | .{ .range = .{ .prong = multi_i, .item = range_i } }, | 10795 | .{ .range = .{ .prong = multi_i, .item = range_i } }, |
| 10776 | ); | 10796 | ); |
| | 10797 | case_vals.appendAssumeCapacity(vals[0]); |
| | 10798 | case_vals.appendAssumeCapacity(vals[1]); |
| 10777 | } | 10799 | } |
| 10778 | | 10800 | |
| 10779 | extra_index += body_len; | 10801 | extra_index += body_len; |
| ... | @@ -10817,14 +10839,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10817,14 +10839,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10817 | extra_index += 1; | 10839 | extra_index += 1; |
| 10818 | extra_index += body_len; | 10840 | extra_index += body_len; |
| 10819 | | 10841 | |
| 10820 | try sema.validateSwitchItemBool( | 10842 | case_vals.appendAssumeCapacity(try sema.validateSwitchItemBool( |
| 10821 | block, | 10843 | block, |
| 10822 | &true_count, | 10844 | &true_count, |
| 10823 | &false_count, | 10845 | &false_count, |
| 10824 | item_ref, | 10846 | item_ref, |
| 10825 | src_node_offset, | 10847 | src_node_offset, |
| 10826 | .{ .scalar = scalar_i }, | 10848 | .{ .scalar = scalar_i }, |
| 10827 | ); | 10849 | )); |
| 10828 | } | 10850 | } |
| 10829 | } | 10851 | } |
| 10830 | { | 10852 | { |
| ... | @@ -10839,15 +10861,16 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10839,15 +10861,16 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10839 | const items = sema.code.refSlice(extra_index, items_len); | 10861 | const items = sema.code.refSlice(extra_index, items_len); |
| 10840 | extra_index += items_len + body_len; | 10862 | extra_index += items_len + body_len; |
| 10841 | | 10863 | |
| | 10864 | try case_vals.ensureUnusedCapacity(gpa, items.len); |
| 10842 | for (items, 0..) |item_ref, item_i| { | 10865 | for (items, 0..) |item_ref, item_i| { |
| 10843 | try sema.validateSwitchItemBool( | 10866 | case_vals.appendAssumeCapacity(try sema.validateSwitchItemBool( |
| 10844 | block, | 10867 | block, |
| 10845 | &true_count, | 10868 | &true_count, |
| 10846 | &false_count, | 10869 | &false_count, |
| 10847 | item_ref, | 10870 | item_ref, |
| 10848 | src_node_offset, | 10871 | src_node_offset, |
| 10849 | .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } }, | 10872 | .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } }, |
| 10850 | ); | 10873 | )); |
| 10851 | } | 10874 | } |
| 10852 | | 10875 | |
| 10853 | try sema.validateSwitchNoRange(block, ranges_len, operand_ty, src_node_offset); | 10876 | try sema.validateSwitchNoRange(block, ranges_len, operand_ty, src_node_offset); |
| ... | @@ -10899,13 +10922,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10899,13 +10922,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10899 | extra_index += 1; | 10922 | extra_index += 1; |
| 10900 | extra_index += body_len; | 10923 | extra_index += body_len; |
| 10901 | | 10924 | |
| 10902 | try sema.validateSwitchItemSparse( | 10925 | case_vals.appendAssumeCapacity(try sema.validateSwitchItemSparse( |
| 10903 | block, | 10926 | block, |
| 10904 | &seen_values, | 10927 | &seen_values, |
| 10905 | item_ref, | 10928 | item_ref, |
| | 10929 | operand_ty, |
| 10906 | src_node_offset, | 10930 | src_node_offset, |
| 10907 | .{ .scalar = scalar_i }, | 10931 | .{ .scalar = scalar_i }, |
| 10908 | ); | 10932 | )); |
| 10909 | } | 10933 | } |
| 10910 | } | 10934 | } |
| 10911 | { | 10935 | { |
| ... | @@ -10920,14 +10944,16 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10920,14 +10944,16 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10920 | const items = sema.code.refSlice(extra_index, items_len); | 10944 | const items = sema.code.refSlice(extra_index, items_len); |
| 10921 | extra_index += items_len + body_len; | 10945 | extra_index += items_len + body_len; |
| 10922 | | 10946 | |
| | 10947 | try case_vals.ensureUnusedCapacity(gpa, items.len); |
| 10923 | for (items, 0..) |item_ref, item_i| { | 10948 | for (items, 0..) |item_ref, item_i| { |
| 10924 | try sema.validateSwitchItemSparse( | 10949 | case_vals.appendAssumeCapacity(try sema.validateSwitchItemSparse( |
| 10925 | block, | 10950 | block, |
| 10926 | &seen_values, | 10951 | &seen_values, |
| 10927 | item_ref, | 10952 | item_ref, |
| | 10953 | operand_ty, |
| 10928 | src_node_offset, | 10954 | src_node_offset, |
| 10929 | .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } }, | 10955 | .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } }, |
| 10930 | ); | 10956 | )); |
| 10931 | } | 10957 | } |
| 10932 | | 10958 | |
| 10933 | try sema.validateSwitchNoRange(block, ranges_len, operand_ty, src_node_offset); | 10959 | try sema.validateSwitchNoRange(block, ranges_len, operand_ty, src_node_offset); |
| ... | @@ -10997,7 +11023,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10997,7 +11023,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10997 | { | 11023 | { |
| 10998 | var scalar_i: usize = 0; | 11024 | var scalar_i: usize = 0; |
| 10999 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 11025 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| 11000 | const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | | |
| 11001 | extra_index += 1; | 11026 | extra_index += 1; |
| 11002 | const body_len = @truncate(u31, sema.code.extra[extra_index]); | 11027 | const body_len = @truncate(u31, sema.code.extra[extra_index]); |
| 11003 | const is_inline = sema.code.extra[extra_index] >> 31 != 0; | 11028 | const is_inline = sema.code.extra[extra_index] >> 31 != 0; |
| ... | @@ -11005,8 +11030,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11005,8 +11030,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11005 | const body = sema.code.extra[extra_index..][0..body_len]; | 11030 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 11006 | extra_index += body_len; | 11031 | extra_index += body_len; |
| 11007 | | 11032 | |
| 11008 | const item = try sema.resolveInst(item_ref); | 11033 | const item = case_vals.items[scalar_i]; |
| 11009 | // Validation above ensured these will succeed. | | |
| 11010 | const item_val = sema.resolveConstLazyValue(&child_block, .unneeded, item, "") catch unreachable; | 11034 | const item_val = sema.resolveConstLazyValue(&child_block, .unneeded, item, "") catch unreachable; |
| 11011 | if (resolved_operand_val.eql(item_val, operand_ty, mod)) { | 11035 | if (resolved_operand_val.eql(item_val, operand_ty, mod)) { |
| 11012 | if (is_inline) child_block.inline_case_capture = operand; | 11036 | if (is_inline) child_block.inline_case_capture = operand; |
| ... | @@ -11018,6 +11042,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11018,6 +11042,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11018 | } | 11042 | } |
| 11019 | { | 11043 | { |
| 11020 | var multi_i: usize = 0; | 11044 | var multi_i: usize = 0; |
| | 11045 | var case_val_idx: usize = scalar_cases_len; |
| 11021 | while (multi_i < multi_cases_len) : (multi_i += 1) { | 11046 | while (multi_i < multi_cases_len) : (multi_i += 1) { |
| 11022 | const items_len = sema.code.extra[extra_index]; | 11047 | const items_len = sema.code.extra[extra_index]; |
| 11023 | extra_index += 1; | 11048 | extra_index += 1; |
| ... | @@ -11025,13 +11050,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11025,13 +11050,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11025 | extra_index += 1; | 11050 | extra_index += 1; |
| 11026 | const body_len = @truncate(u31, sema.code.extra[extra_index]); | 11051 | const body_len = @truncate(u31, sema.code.extra[extra_index]); |
| 11027 | const is_inline = sema.code.extra[extra_index] >> 31 != 0; | 11052 | const is_inline = sema.code.extra[extra_index] >> 31 != 0; |
| 11028 | extra_index += 1; | 11053 | extra_index += 1 + items_len; |
| 11029 | const items = sema.code.refSlice(extra_index, items_len); | | |
| 11030 | extra_index += items_len; | | |
| 11031 | const body = sema.code.extra[extra_index + 2 * ranges_len ..][0..body_len]; | 11054 | const body = sema.code.extra[extra_index + 2 * ranges_len ..][0..body_len]; |
| 11032 | | 11055 | |
| 11033 | for (items) |item_ref| { | 11056 | const items = case_vals.items[case_val_idx..][0..items_len]; |
| 11034 | const item = try sema.resolveInst(item_ref); | 11057 | case_val_idx += items_len; |
| | 11058 | |
| | 11059 | for (items) |item| { |
| 11035 | // Validation above ensured these will succeed. | 11060 | // Validation above ensured these will succeed. |
| 11036 | const item_val = sema.resolveConstLazyValue(&child_block, .unneeded, item, "") catch unreachable; | 11061 | const item_val = sema.resolveConstLazyValue(&child_block, .unneeded, item, "") catch unreachable; |
| 11037 | if (resolved_operand_val.eql(item_val, operand_ty, mod)) { | 11062 | if (resolved_operand_val.eql(item_val, operand_ty, mod)) { |
| ... | @@ -11044,16 +11069,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11044,16 +11069,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11044 | | 11069 | |
| 11045 | var range_i: usize = 0; | 11070 | var range_i: usize = 0; |
| 11046 | while (range_i < ranges_len) : (range_i += 1) { | 11071 | while (range_i < ranges_len) : (range_i += 1) { |
| 11047 | const item_first = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 11072 | const range_items = case_vals.items[case_val_idx..][0..2]; |
| 11048 | extra_index += 1; | 11073 | extra_index += 2; |
| 11049 | const item_last = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 11074 | case_val_idx += 2; |
| 11050 | extra_index += 1; | | |
| 11051 | | 11075 | |
| 11052 | // Validation above ensured these will succeed. | 11076 | // Validation above ensured these will succeed. |
| 11053 | const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, "") catch unreachable; | 11077 | const first_val = sema.resolveConstValue(&child_block, .unneeded, range_items[0], "") catch unreachable; |
| 11054 | const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last, "") catch unreachable; | 11078 | const last_val = sema.resolveConstValue(&child_block, .unneeded, range_items[1], "") catch unreachable; |
| 11055 | if ((try sema.compareAll(resolved_operand_val, .gte, first_tv.val, operand_ty)) and | 11079 | if ((try sema.compareAll(resolved_operand_val, .gte, first_val, operand_ty)) and |
| 11056 | (try sema.compareAll(resolved_operand_val, .lte, last_tv.val, operand_ty))) | 11080 | (try sema.compareAll(resolved_operand_val, .lte, last_val, operand_ty))) |
| 11057 | { | 11081 | { |
| 11058 | if (is_inline) child_block.inline_case_capture = operand; | 11082 | if (is_inline) child_block.inline_case_capture = operand; |
| 11059 | if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand); | 11083 | if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand); |
| ... | @@ -11115,7 +11139,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11115,7 +11139,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11115 | | 11139 | |
| 11116 | var scalar_i: usize = 0; | 11140 | var scalar_i: usize = 0; |
| 11117 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 11141 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| 11118 | const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | | |
| 11119 | extra_index += 1; | 11142 | extra_index += 1; |
| 11120 | const body_len = @truncate(u31, sema.code.extra[extra_index]); | 11143 | const body_len = @truncate(u31, sema.code.extra[extra_index]); |
| 11121 | const is_inline = sema.code.extra[extra_index] >> 31 != 0; | 11144 | const is_inline = sema.code.extra[extra_index] >> 31 != 0; |
| ... | @@ -11130,7 +11153,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11130,7 +11153,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11130 | case_block.wip_capture_scope = wip_captures.scope; | 11153 | case_block.wip_capture_scope = wip_captures.scope; |
| 11131 | case_block.inline_case_capture = .none; | 11154 | case_block.inline_case_capture = .none; |
| 11132 | | 11155 | |
| 11133 | const item = try sema.resolveInst(item_ref); | 11156 | const item = case_vals.items[scalar_i]; |
| 11134 | if (is_inline) case_block.inline_case_capture = item; | 11157 | if (is_inline) case_block.inline_case_capture = item; |
| 11135 | // `item` is already guaranteed to be constant known. | 11158 | // `item` is already guaranteed to be constant known. |
| 11136 | | 11159 | |
| ... | @@ -11165,6 +11188,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11165,6 +11188,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11165 | defer gpa.free(prev_then_body); | 11188 | defer gpa.free(prev_then_body); |
| 11166 | | 11189 | |
| 11167 | var cases_len = scalar_cases_len; | 11190 | var cases_len = scalar_cases_len; |
| | 11191 | var case_val_idx: usize = scalar_cases_len; |
| 11168 | var multi_i: u32 = 0; | 11192 | var multi_i: u32 = 0; |
| 11169 | while (multi_i < multi_cases_len) : (multi_i += 1) { | 11193 | while (multi_i < multi_cases_len) : (multi_i += 1) { |
| 11170 | const items_len = sema.code.extra[extra_index]; | 11194 | const items_len = sema.code.extra[extra_index]; |
| ... | @@ -11173,9 +11197,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11173,9 +11197,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11173 | extra_index += 1; | 11197 | extra_index += 1; |
| 11174 | const body_len = @truncate(u31, sema.code.extra[extra_index]); | 11198 | const body_len = @truncate(u31, sema.code.extra[extra_index]); |
| 11175 | const is_inline = sema.code.extra[extra_index] >> 31 != 0; | 11199 | const is_inline = sema.code.extra[extra_index] >> 31 != 0; |
| 11176 | extra_index += 1; | 11200 | extra_index += 1 + items_len; |
| 11177 | const items = sema.code.refSlice(extra_index, items_len); | 11201 | |
| 11178 | extra_index += items_len; | 11202 | const items = case_vals.items[case_val_idx..][0..items_len]; |
| | 11203 | case_val_idx += items_len; |
| 11179 | | 11204 | |
| 11180 | case_block.instructions.shrinkRetainingCapacity(0); | 11205 | case_block.instructions.shrinkRetainingCapacity(0); |
| 11181 | case_block.wip_capture_scope = child_block.wip_capture_scope; | 11206 | case_block.wip_capture_scope = child_block.wip_capture_scope; |
| ... | @@ -11189,14 +11214,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11189,14 +11214,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11189 | | 11214 | |
| 11190 | var range_i: u32 = 0; | 11215 | var range_i: u32 = 0; |
| 11191 | while (range_i < ranges_len) : (range_i += 1) { | 11216 | while (range_i < ranges_len) : (range_i += 1) { |
| 11192 | const first_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 11217 | const range_items = case_vals.items[case_val_idx..][0..2]; |
| 11193 | extra_index += 1; | 11218 | extra_index += 2; |
| 11194 | const last_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 11219 | case_val_idx += 2; |
| 11195 | extra_index += 1; | 11220 | |
| | 11221 | const item_first_ref = range_items[0]; |
| | 11222 | const item_last_ref = range_items[1]; |
| 11196 | | 11223 | |
| 11197 | const item_first_ref = try sema.resolveInst(first_ref); | | |
| 11198 | var item = sema.resolveConstValue(block, .unneeded, item_first_ref, undefined) catch unreachable; | 11224 | var item = sema.resolveConstValue(block, .unneeded, item_first_ref, undefined) catch unreachable; |
| 11199 | const item_last_ref = try sema.resolveInst(last_ref); | | |
| 11200 | const item_last = sema.resolveConstValue(block, .unneeded, item_last_ref, undefined) catch unreachable; | 11225 | const item_last = sema.resolveConstValue(block, .unneeded, item_last_ref, undefined) catch unreachable; |
| 11201 | | 11226 | |
| 11202 | while (item.compareScalar(.lte, item_last, operand_ty, mod)) : ({ | 11227 | while (item.compareScalar(.lte, item_last, operand_ty, mod)) : ({ |
| ... | @@ -11235,10 +11260,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11235,10 +11260,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11235 | } | 11260 | } |
| 11236 | } | 11261 | } |
| 11237 | | 11262 | |
| 11238 | for (items, 0..) |item_ref, item_i| { | 11263 | for (items, 0..) |item, item_i| { |
| 11239 | cases_len += 1; | 11264 | cases_len += 1; |
| 11240 | | 11265 | |
| 11241 | const item = try sema.resolveInst(item_ref); | | |
| 11242 | case_block.inline_case_capture = item; | 11266 | case_block.inline_case_capture = item; |
| 11243 | | 11267 | |
| 11244 | case_block.instructions.shrinkRetainingCapacity(0); | 11268 | case_block.instructions.shrinkRetainingCapacity(0); |
| ... | @@ -11287,8 +11311,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11287,8 +11311,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11287 | cases_len += 1; | 11311 | cases_len += 1; |
| 11288 | | 11312 | |
| 11289 | const analyze_body = if (union_originally) | 11313 | const analyze_body = if (union_originally) |
| 11290 | for (items) |item_ref| { | 11314 | for (items) |item| { |
| 11291 | const item = try sema.resolveInst(item_ref); | | |
| 11292 | const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable; | 11315 | const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable; |
| 11293 | const field_ty = maybe_union_ty.unionFieldType(item_val, mod); | 11316 | const field_ty = maybe_union_ty.unionFieldType(item_val, mod); |
| 11294 | if (field_ty.zigTypeTag(mod) != .NoReturn) break true; | 11317 | if (field_ty.zigTypeTag(mod) != .NoReturn) break true; |
| ... | @@ -11312,15 +11335,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11312,15 +11335,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11312 | cases_extra.appendAssumeCapacity(@intCast(u32, items.len)); | 11335 | cases_extra.appendAssumeCapacity(@intCast(u32, items.len)); |
| 11313 | cases_extra.appendAssumeCapacity(@intCast(u32, case_block.instructions.items.len)); | 11336 | cases_extra.appendAssumeCapacity(@intCast(u32, case_block.instructions.items.len)); |
| 11314 | | 11337 | |
| 11315 | for (items) |item_ref| { | 11338 | for (items) |item| { |
| 11316 | const item = try sema.resolveInst(item_ref); | | |
| 11317 | cases_extra.appendAssumeCapacity(@enumToInt(item)); | 11339 | cases_extra.appendAssumeCapacity(@enumToInt(item)); |
| 11318 | } | 11340 | } |
| 11319 | | 11341 | |
| 11320 | cases_extra.appendSliceAssumeCapacity(case_block.instructions.items); | 11342 | cases_extra.appendSliceAssumeCapacity(case_block.instructions.items); |
| 11321 | } else { | 11343 | } else { |
| 11322 | for (items) |item_ref| { | 11344 | for (items) |item| { |
| 11323 | const item = try sema.resolveInst(item_ref); | | |
| 11324 | const cmp_ok = try case_block.addBinOp(if (case_block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, item); | 11345 | const cmp_ok = try case_block.addBinOp(if (case_block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, item); |
| 11325 | if (any_ok != .none) { | 11346 | if (any_ok != .none) { |
| 11326 | any_ok = try case_block.addBinOp(.bool_or, any_ok, cmp_ok); | 11347 | any_ok = try case_block.addBinOp(.bool_or, any_ok, cmp_ok); |
| ... | @@ -11331,13 +11352,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11331,13 +11352,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11331 | | 11352 | |
| 11332 | var range_i: usize = 0; | 11353 | var range_i: usize = 0; |
| 11333 | while (range_i < ranges_len) : (range_i += 1) { | 11354 | while (range_i < ranges_len) : (range_i += 1) { |
| 11334 | const first_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 11355 | const range_items = case_vals.items[case_val_idx..][0..2]; |
| 11335 | extra_index += 1; | 11356 | extra_index += 2; |
| 11336 | const last_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 11357 | case_val_idx += 2; |
| 11337 | extra_index += 1; | | |
| 11338 | | 11358 | |
| 11339 | const item_first = try sema.resolveInst(first_ref); | 11359 | const item_first = range_items[0]; |
| 11340 | const item_last = try sema.resolveInst(last_ref); | 11360 | const item_last = range_items[1]; |
| 11341 | | 11361 | |
| 11342 | // operand >= first and operand <= last | 11362 | // operand >= first and operand <= last |
| 11343 | const range_first_ok = try case_block.addBinOp( | 11363 | const range_first_ok = try case_block.addBinOp( |
| ... | @@ -11696,29 +11716,46 @@ const RangeSetUnhandledIterator = struct { | ... | @@ -11696,29 +11716,46 @@ const RangeSetUnhandledIterator = struct { |
| 11696 | } | 11716 | } |
| 11697 | }; | 11717 | }; |
| 11698 | | 11718 | |
| | 11719 | const ResolvedSwitchItem = struct { |
| | 11720 | ref: Air.Inst.Ref, |
| | 11721 | val: InternPool.Index, |
| | 11722 | }; |
| 11699 | fn resolveSwitchItemVal( | 11723 | fn resolveSwitchItemVal( |
| 11700 | sema: *Sema, | 11724 | sema: *Sema, |
| 11701 | block: *Block, | 11725 | block: *Block, |
| 11702 | item_ref: Zir.Inst.Ref, | 11726 | item_ref: Zir.Inst.Ref, |
| | 11727 | /// Coerce `item_ref` to this type. |
| | 11728 | coerce_ty: Type, |
| 11703 | switch_node_offset: i32, | 11729 | switch_node_offset: i32, |
| 11704 | switch_prong_src: Module.SwitchProngSrc, | 11730 | switch_prong_src: Module.SwitchProngSrc, |
| 11705 | range_expand: Module.SwitchProngSrc.RangeExpand, | 11731 | range_expand: Module.SwitchProngSrc.RangeExpand, |
| 11706 | ) CompileError!InternPool.Index { | 11732 | ) CompileError!ResolvedSwitchItem { |
| 11707 | const mod = sema.mod; | 11733 | const mod = sema.mod; |
| 11708 | const item = try sema.resolveInst(item_ref); | 11734 | const uncoerced_item = try sema.resolveInst(item_ref); |
| | 11735 | |
| 11709 | // Constructing a LazySrcLoc is costly because we only have the switch AST node. | 11736 | // Constructing a LazySrcLoc is costly because we only have the switch AST node. |
| 11710 | // Only if we know for sure we need to report a compile error do we resolve the | 11737 | // Only if we know for sure we need to report a compile error do we resolve the |
| 11711 | // full source locations. | 11738 | // full source locations. |
| 11712 | if (sema.resolveConstLazyValue(block, .unneeded, item, "")) |val| { | 11739 | |
| 11713 | return val.toIntern(); | 11740 | const item = sema.coerce(block, coerce_ty, uncoerced_item, .unneeded) catch |err| switch (err) { |
| 11714 | } else |err| switch (err) { | 11741 | error.NeededSourceLocation => { |
| | 11742 | const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, range_expand); |
| | 11743 | _ = try sema.coerce(block, coerce_ty, uncoerced_item, src); |
| | 11744 | unreachable; |
| | 11745 | }, |
| | 11746 | else => |e| return e, |
| | 11747 | }; |
| | 11748 | |
| | 11749 | const val = sema.resolveConstLazyValue(block, .unneeded, item, "") catch |err| switch (err) { |
| 11715 | error.NeededSourceLocation => { | 11750 | error.NeededSourceLocation => { |
| 11716 | const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, range_expand); | 11751 | const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, range_expand); |
| 11717 | _ = try sema.resolveConstValue(block, src, item, "switch prong values must be comptime-known"); | 11752 | _ = try sema.resolveConstValue(block, src, item, "switch prong values must be comptime-known"); |
| 11718 | unreachable; | 11753 | unreachable; |
| 11719 | }, | 11754 | }, |
| 11720 | else => |e| return e, | 11755 | else => |e| return e, |
| 11721 | } | 11756 | }; |
| | 11757 | |
| | 11758 | return .{ .ref = item, .val = val.toIntern() }; |
| 11722 | } | 11759 | } |
| 11723 | | 11760 | |
| 11724 | fn validateSwitchRange( | 11761 | fn validateSwitchRange( |
| ... | @@ -11727,31 +11764,35 @@ fn validateSwitchRange( | ... | @@ -11727,31 +11764,35 @@ fn validateSwitchRange( |
| 11727 | range_set: *RangeSet, | 11764 | range_set: *RangeSet, |
| 11728 | first_ref: Zir.Inst.Ref, | 11765 | first_ref: Zir.Inst.Ref, |
| 11729 | last_ref: Zir.Inst.Ref, | 11766 | last_ref: Zir.Inst.Ref, |
| | 11767 | operand_ty: Type, |
| 11730 | src_node_offset: i32, | 11768 | src_node_offset: i32, |
| 11731 | switch_prong_src: Module.SwitchProngSrc, | 11769 | switch_prong_src: Module.SwitchProngSrc, |
| 11732 | ) CompileError!void { | 11770 | ) CompileError![2]Air.Inst.Ref { |
| 11733 | const mod = sema.mod; | 11771 | const mod = sema.mod; |
| 11734 | const first = try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first); | 11772 | const first = try sema.resolveSwitchItemVal(block, first_ref, operand_ty, src_node_offset, switch_prong_src, .first); |
| 11735 | const last = try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last); | 11773 | const last = try sema.resolveSwitchItemVal(block, last_ref, operand_ty, src_node_offset, switch_prong_src, .last); |
| 11736 | if (first.toValue().compareScalar(.gt, last.toValue(), mod.intern_pool.typeOf(first).toType(), mod)) { | 11774 | if (try first.val.toValue().compareAll(.gt, last.val.toValue(), operand_ty, mod)) { |
| 11737 | const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), src_node_offset, .first); | 11775 | const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), src_node_offset, .first); |
| 11738 | return sema.fail(block, src, "range start value is greater than the end value", .{}); | 11776 | return sema.fail(block, src, "range start value is greater than the end value", .{}); |
| 11739 | } | 11777 | } |
| 11740 | const maybe_prev_src = try range_set.add(first, last, switch_prong_src); | 11778 | const maybe_prev_src = try range_set.add(first.val, last.val, switch_prong_src); |
| 11741 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); | 11779 | try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); |
| | 11780 | return .{ first.ref, last.ref }; |
| 11742 | } | 11781 | } |
| 11743 | | 11782 | |
| 11744 | fn validateSwitchItem( | 11783 | fn validateSwitchItemInt( |
| 11745 | sema: *Sema, | 11784 | sema: *Sema, |
| 11746 | block: *Block, | 11785 | block: *Block, |
| 11747 | range_set: *RangeSet, | 11786 | range_set: *RangeSet, |
| 11748 | item_ref: Zir.Inst.Ref, | 11787 | item_ref: Zir.Inst.Ref, |
| | 11788 | operand_ty: Type, |
| 11749 | src_node_offset: i32, | 11789 | src_node_offset: i32, |
| 11750 | switch_prong_src: Module.SwitchProngSrc, | 11790 | switch_prong_src: Module.SwitchProngSrc, |
| 11751 | ) CompileError!void { | 11791 | ) CompileError!Air.Inst.Ref { |
| 11752 | const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none); | 11792 | const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none); |
| 11753 | const maybe_prev_src = try range_set.add(item, item, switch_prong_src); | 11793 | const maybe_prev_src = try range_set.add(item.val, item.val, switch_prong_src); |
| 11754 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); | 11794 | try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); |
| | 11795 | return item.ref; |
| 11755 | } | 11796 | } |
| 11756 | | 11797 | |
| 11757 | fn validateSwitchItemEnum( | 11798 | fn validateSwitchItemEnum( |
| ... | @@ -11760,19 +11801,22 @@ fn validateSwitchItemEnum( | ... | @@ -11760,19 +11801,22 @@ fn validateSwitchItemEnum( |
| 11760 | seen_fields: []?Module.SwitchProngSrc, | 11801 | seen_fields: []?Module.SwitchProngSrc, |
| 11761 | range_set: *RangeSet, | 11802 | range_set: *RangeSet, |
| 11762 | item_ref: Zir.Inst.Ref, | 11803 | item_ref: Zir.Inst.Ref, |
| | 11804 | operand_ty: Type, |
| 11763 | src_node_offset: i32, | 11805 | src_node_offset: i32, |
| 11764 | switch_prong_src: Module.SwitchProngSrc, | 11806 | switch_prong_src: Module.SwitchProngSrc, |
| 11765 | ) CompileError!void { | 11807 | ) CompileError!Air.Inst.Ref { |
| 11766 | const ip = &sema.mod.intern_pool; | 11808 | const ip = &sema.mod.intern_pool; |
| 11767 | const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none); | 11809 | const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none); |
| 11768 | const int = ip.indexToKey(item).enum_tag.int; | 11810 | const int = ip.indexToKey(item.val).enum_tag.int; |
| 11769 | const field_index = ip.indexToKey(ip.typeOf(item)).enum_type.tagValueIndex(ip, int) orelse { | 11811 | const field_index = ip.indexToKey(ip.typeOf(item.val)).enum_type.tagValueIndex(ip, int) orelse { |
| 11770 | const maybe_prev_src = try range_set.add(int, int, switch_prong_src); | 11812 | const maybe_prev_src = try range_set.add(int, int, switch_prong_src); |
| 11771 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); | 11813 | try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); |
| | 11814 | return item.ref; |
| 11772 | }; | 11815 | }; |
| 11773 | const maybe_prev_src = seen_fields[field_index]; | 11816 | const maybe_prev_src = seen_fields[field_index]; |
| 11774 | seen_fields[field_index] = switch_prong_src; | 11817 | seen_fields[field_index] = switch_prong_src; |
| 11775 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); | 11818 | try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); |
| | 11819 | return item.ref; |
| 11776 | } | 11820 | } |
| 11777 | | 11821 | |
| 11778 | fn validateSwitchItemError( | 11822 | fn validateSwitchItemError( |
| ... | @@ -11780,18 +11824,19 @@ fn validateSwitchItemError( | ... | @@ -11780,18 +11824,19 @@ fn validateSwitchItemError( |
| 11780 | block: *Block, | 11824 | block: *Block, |
| 11781 | seen_errors: *SwitchErrorSet, | 11825 | seen_errors: *SwitchErrorSet, |
| 11782 | item_ref: Zir.Inst.Ref, | 11826 | item_ref: Zir.Inst.Ref, |
| | 11827 | operand_ty: Type, |
| 11783 | src_node_offset: i32, | 11828 | src_node_offset: i32, |
| 11784 | switch_prong_src: Module.SwitchProngSrc, | 11829 | switch_prong_src: Module.SwitchProngSrc, |
| 11785 | ) CompileError!void { | 11830 | ) CompileError!Air.Inst.Ref { |
| 11786 | const ip = &sema.mod.intern_pool; | 11831 | const ip = &sema.mod.intern_pool; |
| 11787 | const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none); | 11832 | const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none); |
| 11788 | // TODO: Do i need to typecheck here? | 11833 | const error_name = ip.indexToKey(item.val).err.name; |
| 11789 | const error_name = ip.indexToKey(item).err.name; | | |
| 11790 | const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev| | 11834 | const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev| |
| 11791 | prev.value | 11835 | prev.value |
| 11792 | else | 11836 | else |
| 11793 | null; | 11837 | null; |
| 11794 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); | 11838 | try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); |
| | 11839 | return item.ref; |
| 11795 | } | 11840 | } |
| 11796 | | 11841 | |
| 11797 | fn validateSwitchDupe( | 11842 | fn validateSwitchDupe( |
| ... | @@ -11834,19 +11879,20 @@ fn validateSwitchItemBool( | ... | @@ -11834,19 +11879,20 @@ fn validateSwitchItemBool( |
| 11834 | item_ref: Zir.Inst.Ref, | 11879 | item_ref: Zir.Inst.Ref, |
| 11835 | src_node_offset: i32, | 11880 | src_node_offset: i32, |
| 11836 | switch_prong_src: Module.SwitchProngSrc, | 11881 | switch_prong_src: Module.SwitchProngSrc, |
| 11837 | ) CompileError!void { | 11882 | ) CompileError!Air.Inst.Ref { |
| 11838 | const mod = sema.mod; | 11883 | const mod = sema.mod; |
| 11839 | const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none); | 11884 | const item = try sema.resolveSwitchItemVal(block, item_ref, Type.bool, src_node_offset, switch_prong_src, .none); |
| 11840 | if (item.toValue().toBool()) { | 11885 | if (item.val.toValue().toBool()) { |
| 11841 | true_count.* += 1; | 11886 | true_count.* += 1; |
| 11842 | } else { | 11887 | } else { |
| 11843 | false_count.* += 1; | 11888 | false_count.* += 1; |
| 11844 | } | 11889 | } |
| 11845 | if (true_count.* + false_count.* > 2) { | 11890 | if (true_count.* > 1 or false_count.* > 1) { |
| 11846 | const block_src_decl = mod.declPtr(block.src_decl); | 11891 | const block_src_decl = sema.mod.declPtr(block.src_decl); |
| 11847 | const src = switch_prong_src.resolve(mod, block_src_decl, src_node_offset, .none); | 11892 | const src = switch_prong_src.resolve(mod, block_src_decl, src_node_offset, .none); |
| 11848 | return sema.fail(block, src, "duplicate switch value", .{}); | 11893 | return sema.fail(block, src, "duplicate switch value", .{}); |
| 11849 | } | 11894 | } |
| | 11895 | return item.ref; |
| 11850 | } | 11896 | } |
| 11851 | | 11897 | |
| 11852 | const ValueSrcMap = std.AutoHashMapUnmanaged(InternPool.Index, Module.SwitchProngSrc); | 11898 | const ValueSrcMap = std.AutoHashMapUnmanaged(InternPool.Index, Module.SwitchProngSrc); |
| ... | @@ -11856,12 +11902,14 @@ fn validateSwitchItemSparse( | ... | @@ -11856,12 +11902,14 @@ fn validateSwitchItemSparse( |
| 11856 | block: *Block, | 11902 | block: *Block, |
| 11857 | seen_values: *ValueSrcMap, | 11903 | seen_values: *ValueSrcMap, |
| 11858 | item_ref: Zir.Inst.Ref, | 11904 | item_ref: Zir.Inst.Ref, |
| | 11905 | operand_ty: Type, |
| 11859 | src_node_offset: i32, | 11906 | src_node_offset: i32, |
| 11860 | switch_prong_src: Module.SwitchProngSrc, | 11907 | switch_prong_src: Module.SwitchProngSrc, |
| 11861 | ) CompileError!void { | 11908 | ) CompileError!Air.Inst.Ref { |
| 11862 | const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none); | 11909 | const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none); |
| 11863 | const kv = (try seen_values.fetchPut(sema.gpa, item, switch_prong_src)) orelse return; | 11910 | const kv = (try seen_values.fetchPut(sema.gpa, item.val, switch_prong_src)) orelse return item.ref; |
| 11864 | return sema.validateSwitchDupe(block, kv.value, switch_prong_src, src_node_offset); | 11911 | try sema.validateSwitchDupe(block, kv.value, switch_prong_src, src_node_offset); |
| | 11912 | unreachable; |
| 11865 | } | 11913 | } |
| 11866 | | 11914 | |
| 11867 | fn validateSwitchNoRange( | 11915 | fn validateSwitchNoRange( |