authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-05-05 23:04:34+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-06-13 12:50:49+01:00
logcebd80032a2dcc9f516f8183d1bfade5d1f12e45
treef4c669061d753840d12d8dbb4b232e5f2d4bafb0
parenta377bf87ce6f021f958087bcf080425845a7bae6
signaturelock-open Commit is signed but in an unrecognized format.

Move switch case value coercion from AstGen to Sema

This is in preparation for #2473. Also fixes a bug where switching on bools allows invalid case combinations.

2 files changed, 150 insertions(+), 104 deletions(-)

src/AstGen.zig+1-3
...@@ -6837,9 +6837,7 @@ fn switchExpr(...@@ -6837,9 +6837,7 @@ fn switchExpr(
6837 const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node);6837 const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node);
6838 // Sema expects a dbg_stmt immediately after switch_cond(_ref)6838 // Sema expects a dbg_stmt immediately after switch_cond(_ref)
6839 try emitDbgStmt(parent_gz, operand_lc);6839 try emitDbgStmt(parent_gz, operand_lc);
6840 // We need the type of the operand to use as the result location for all the prong items.6840 const item_ri: ResultInfo = .{ .rl = .none };
6841 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);
6842 const item_ri: ResultInfo = .{ .rl = .{ .ty = cond_ty_inst } };
68436841
6844 // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti,6842 // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti,
6845 // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with6843 // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with
src/Sema.zig+149-101
...@@ -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 }
1017710179
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;
1017910183
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 succeed10188 // 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;
1018610191
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 succeed10197 // 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;
1019410200
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;
1040810414
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;
1049310502
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;
1051510525
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 }
1052610538
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;
1059010602
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;
1061110624
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 }
1062110636
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;
1073010745
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;
1075110767
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 }
1076110779
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;
1076810787
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 }
1077810800
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;
1081910841
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;
1084110863
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 }
1085210875
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;
1090110924
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;
1092210946
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 }
1093210958
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;
1100711032
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];
1103211055
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
1104411069
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;
1105111075
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)) and11079 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
1111511139
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;
1113211155
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.
1113611159
...@@ -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);
1116611189
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;
1117911204
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
1118911214
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];
1119611223
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;
1120111226
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 }
1123711262
11238 for (items, 0..) |item_ref, item_i| {11263 for (items, 0..) |item, item_i| {
11239 cases_len += 1;11264 cases_len += 1;
1124011265
11241 const item = try sema.resolveInst(item_ref);
11242 case_block.inline_case_capture = item;11266 case_block.inline_case_capture = item;
1124311267
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;
1128811312
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));
1131411337
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 }
1131911341
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
1133111352
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;
1133811358
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];
1134111361
11342 // operand >= first and operand <= last11362 // 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};
1169811718
11719const ResolvedSwitchItem = struct {
11720 ref: Air.Inst.Ref,
11721 val: InternPool.Index,
11722};
11699fn resolveSwitchItemVal(11723fn 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 the11737 // 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}
1172311760
11724fn validateSwitchRange(11761fn 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}
1174311782
11744fn validateSwitchItem(11783fn 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}
1175611797
11757fn validateSwitchItemEnum(11798fn 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}
1177711821
11778fn validateSwitchItemError(11822fn 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.value11835 prev.value
11792 else11836 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}
1179611841
11797fn validateSwitchDupe(11842fn 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}
1185111897
11852const ValueSrcMap = std.AutoHashMapUnmanaged(InternPool.Index, Module.SwitchProngSrc);11898const 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}
1186611914
11867fn validateSwitchNoRange(11915fn validateSwitchNoRange(