Auto merge of #121172 - Nadrieril:simplify-empty-selection, r=matthewjasper

match lowering: simplify empty candidate selection

In match lowering, `match_simplified_candidates` is tasked with removing candidates that are fully matched and linking them up properly. The code that does that was needlessly complicated; this PR simplifies it.

The overall change isn't big but I split it up into tiny commits to convince myself that I was correctly preserving behavior. The test changes are all due to the first commit. Let me know if you'd prefer me to split up the PR to make reviewing easier.

r? `@matthewjasper`
This commit is contained in:
bors 2024-02-21 03:11:24 +00:00
commit 096598dc79
16 changed files with 487 additions and 412 deletions

View File

@ -1235,53 +1235,43 @@ fn match_simplified_candidates(
&mut self,
span: Span,
scrutinee_span: Span,
start_block: BasicBlock,
mut start_block: BasicBlock,
otherwise_block: BasicBlock,
candidates: &mut [&mut Candidate<'_, 'tcx>],
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) {
// The candidates are sorted by priority. Check to see whether the
// higher priority candidates (and hence at the front of the slice)
// have satisfied all their match pairs.
let fully_matched = candidates.iter().take_while(|c| c.match_pairs.is_empty()).count();
debug!("match_candidates: {:?} candidates fully matched", fully_matched);
let (matched_candidates, unmatched_candidates) = candidates.split_at_mut(fully_matched);
let block = if !matched_candidates.is_empty() {
let otherwise_block =
self.select_matched_candidates(matched_candidates, start_block, fake_borrows);
if let Some(last_otherwise_block) = otherwise_block {
last_otherwise_block
} else {
// Any remaining candidates are unreachable.
if unmatched_candidates.is_empty() {
return;
}
self.cfg.start_new_block()
match candidates {
[] => {
// If there are no candidates that still need testing, we're done. Since all matches are
// exhaustive, execution should never reach this point.
let source_info = self.source_info(span);
self.cfg.goto(start_block, source_info, otherwise_block);
}
[first, remaining @ ..] if first.match_pairs.is_empty() => {
// The first candidate has satisfied all its match pairs; we link it up and continue
// with the remaining candidates.
start_block = self.select_matched_candidate(first, start_block, fake_borrows);
self.match_simplified_candidates(
span,
scrutinee_span,
start_block,
otherwise_block,
remaining,
fake_borrows,
)
}
candidates => {
// The first candidate has some unsatisfied match pairs; we proceed to do more tests.
self.test_candidates_with_or(
span,
scrutinee_span,
candidates,
start_block,
otherwise_block,
fake_borrows,
);
}
} else {
start_block
};
// If there are no candidates that still need testing, we're
// done. Since all matches are exhaustive, execution should
// never reach this point.
if unmatched_candidates.is_empty() {
let source_info = self.source_info(span);
self.cfg.goto(block, source_info, otherwise_block);
return;
}
// Test for the remaining candidates.
self.test_candidates_with_or(
span,
scrutinee_span,
unmatched_candidates,
block,
otherwise_block,
fake_borrows,
);
}
/// Link up matched candidates.
@ -1303,47 +1293,40 @@ fn match_simplified_candidates(
/// * the [otherwise block] of the third pattern to a block with an
/// [`Unreachable` terminator](TerminatorKind::Unreachable).
///
/// In addition, we add fake edges from the otherwise blocks to the
/// In addition, we later add fake edges from the otherwise blocks to the
/// pre-binding block of the next candidate in the original set of
/// candidates.
///
/// [pre-binding block]: Candidate::pre_binding_block
/// [otherwise block]: Candidate::otherwise_block
fn select_matched_candidates(
fn select_matched_candidate(
&mut self,
matched_candidates: &mut [&mut Candidate<'_, 'tcx>],
candidate: &mut Candidate<'_, 'tcx>,
start_block: BasicBlock,
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) -> Option<BasicBlock> {
debug_assert!(
!matched_candidates.is_empty(),
"select_matched_candidates called with no candidates",
);
debug_assert!(
matched_candidates.iter().all(|c| c.subcandidates.is_empty()),
"subcandidates should be empty in select_matched_candidates",
);
) -> BasicBlock {
assert!(candidate.otherwise_block.is_none());
assert!(candidate.pre_binding_block.is_none());
assert!(candidate.subcandidates.is_empty());
// Insert a borrows of prefixes of places that are bound and are
// behind a dereference projection.
//
// These borrows are taken to avoid situations like the following:
//
// match x[10] {
// _ if { x = &[0]; false } => (),
// y => (), // Out of bounds array access!
// }
//
// match *x {
// // y is bound by reference in the guard and then by copy in the
// // arm, so y is 2 in the arm!
// y if { y == 1 && (x = &2) == () } => y,
// _ => 3,
// }
if let Some(fake_borrows) = fake_borrows {
for Binding { source, .. } in
matched_candidates.iter().flat_map(|candidate| &candidate.bindings)
{
// Insert a borrows of prefixes of places that are bound and are
// behind a dereference projection.
//
// These borrows are taken to avoid situations like the following:
//
// match x[10] {
// _ if { x = &[0]; false } => (),
// y => (), // Out of bounds array access!
// }
//
// match *x {
// // y is bound by reference in the guard and then by copy in the
// // arm, so y is 2 in the arm!
// y if { y == 1 && (x = &2) == () } => y,
// _ => 3,
// }
for Binding { source, .. } in &candidate.bindings {
if let Some(i) =
source.projection.iter().rposition(|elem| elem == ProjectionElem::Deref)
{
@ -1357,38 +1340,14 @@ fn select_matched_candidates(
}
}
let fully_matched_with_guard = matched_candidates
.iter()
.position(|c| !c.has_guard)
.unwrap_or(matched_candidates.len() - 1);
let (reachable_candidates, unreachable_candidates) =
matched_candidates.split_at_mut(fully_matched_with_guard + 1);
let mut next_prebinding = start_block;
for candidate in reachable_candidates.iter_mut() {
assert!(candidate.otherwise_block.is_none());
assert!(candidate.pre_binding_block.is_none());
candidate.pre_binding_block = Some(next_prebinding);
if candidate.has_guard {
// Create the otherwise block for this candidate, which is the
// pre-binding block for the next candidate.
next_prebinding = self.cfg.start_new_block();
candidate.otherwise_block = Some(next_prebinding);
}
candidate.pre_binding_block = Some(start_block);
let otherwise_block = self.cfg.start_new_block();
if candidate.has_guard {
// Create the otherwise block for this candidate, which is the
// pre-binding block for the next candidate.
candidate.otherwise_block = Some(otherwise_block);
}
debug!(
"match_candidates: add pre_binding_blocks for unreachable {:?}",
unreachable_candidates,
);
for candidate in unreachable_candidates {
assert!(candidate.pre_binding_block.is_none());
candidate.pre_binding_block = Some(self.cfg.start_new_block());
}
reachable_candidates.last_mut().unwrap().otherwise_block
otherwise_block
}
/// Tests a candidate where there are only or-patterns left to test, or

View File

@ -27,13 +27,13 @@ fn main() -> () {
StorageLive(_5);
PlaceMention(_1);
_6 = discriminant(_1);
switchInt(move _6) -> [1: bb5, otherwise: bb4];
switchInt(move _6) -> [1: bb6, otherwise: bb4];
}
bb1: {
StorageLive(_3);
StorageLive(_4);
_4 = begin_panic::<&str>(const "explicit panic") -> bb8;
_4 = begin_panic::<&str>(const "explicit panic") -> bb10;
}
bb2: {
@ -48,14 +48,22 @@ fn main() -> () {
}
bb4: {
goto -> bb7;
goto -> bb9;
}
bb5: {
falseEdge -> [real: bb6, imaginary: bb4];
goto -> bb3;
}
bb6: {
falseEdge -> [real: bb8, imaginary: bb4];
}
bb7: {
goto -> bb4;
}
bb8: {
_5 = ((_1 as Some).0: u8);
_0 = const ();
StorageDead(_5);
@ -63,12 +71,12 @@ fn main() -> () {
return;
}
bb7: {
bb9: {
StorageDead(_5);
goto -> bb1;
}
bb8 (cleanup): {
bb10 (cleanup): {
resume;
}
}

View File

@ -17,7 +17,7 @@ fn main() -> () {
}
bb1: {
falseUnwind -> [real: bb2, unwind: bb12];
falseUnwind -> [real: bb2, unwind: bb14];
}
bb2: {
@ -25,7 +25,7 @@ fn main() -> () {
StorageLive(_3);
_3 = const true;
PlaceMention(_3);
switchInt(_3) -> [0: bb4, otherwise: bb5];
switchInt(_3) -> [0: bb4, otherwise: bb6];
}
bb3: {
@ -34,37 +34,45 @@ fn main() -> () {
}
bb4: {
falseEdge -> [real: bb6, imaginary: bb5];
falseEdge -> [real: bb8, imaginary: bb6];
}
bb5: {
_0 = const ();
goto -> bb11;
goto -> bb3;
}
bb6: {
_2 = const 4_i32;
goto -> bb9;
_0 = const ();
goto -> bb13;
}
bb7: {
unreachable;
goto -> bb3;
}
bb8: {
goto -> bb9;
_2 = const 4_i32;
goto -> bb11;
}
bb9: {
unreachable;
}
bb10: {
goto -> bb11;
}
bb11: {
FakeRead(ForLet(None), _2);
StorageDead(_3);
StorageLive(_5);
StorageLive(_6);
_6 = &_2;
_5 = std::mem::drop::<&i32>(move _6) -> [return: bb10, unwind: bb12];
_5 = std::mem::drop::<&i32>(move _6) -> [return: bb12, unwind: bb14];
}
bb10: {
bb12: {
StorageDead(_6);
StorageDead(_5);
_1 = const ();
@ -72,13 +80,13 @@ fn main() -> () {
goto -> bb1;
}
bb11: {
bb13: {
StorageDead(_3);
StorageDead(_2);
return;
}
bb12 (cleanup): {
bb14 (cleanup): {
resume;
}
}

View File

@ -19,13 +19,13 @@ fn test_complex() -> () {
bb0: {
StorageLive(_1);
StorageLive(_2);
_2 = E::f() -> [return: bb1, unwind: bb33];
_2 = E::f() -> [return: bb1, unwind: bb37];
}
bb1: {
PlaceMention(_2);
_3 = discriminant(_2);
switchInt(move _3) -> [0: bb4, otherwise: bb3];
switchInt(move _3) -> [0: bb5, otherwise: bb3];
}
bb2: {
@ -34,163 +34,179 @@ fn test_complex() -> () {
}
bb3: {
goto -> bb20;
goto -> bb22;
}
bb4: {
falseEdge -> [real: bb5, imaginary: bb3];
goto -> bb2;
}
bb5: {
StorageLive(_4);
_4 = always_true() -> [return: bb6, unwind: bb33];
falseEdge -> [real: bb7, imaginary: bb3];
}
bb6: {
switchInt(move _4) -> [0: bb8, otherwise: bb7];
goto -> bb3;
}
bb7: {
StorageLive(_4);
_4 = always_true() -> [return: bb8, unwind: bb37];
}
bb8: {
switchInt(move _4) -> [0: bb10, otherwise: bb9];
}
bb9: {
StorageLive(_5);
StorageLive(_6);
StorageLive(_7);
_7 = Droppy(const 0_u8);
_6 = (_7.0: u8);
_5 = Gt(move _6, const 0_u8);
switchInt(move _5) -> [0: bb10, otherwise: bb9];
}
bb8: {
goto -> bb14;
}
bb9: {
drop(_7) -> [return: bb11, unwind: bb33];
switchInt(move _5) -> [0: bb12, otherwise: bb11];
}
bb10: {
goto -> bb12;
goto -> bb16;
}
bb11: {
StorageDead(_7);
StorageDead(_6);
goto -> bb17;
drop(_7) -> [return: bb13, unwind: bb37];
}
bb12: {
drop(_7) -> [return: bb13, unwind: bb33];
goto -> bb14;
}
bb13: {
StorageDead(_7);
StorageDead(_6);
goto -> bb14;
goto -> bb19;
}
bb14: {
drop(_7) -> [return: bb15, unwind: bb37];
}
bb15: {
StorageDead(_7);
StorageDead(_6);
goto -> bb16;
}
bb16: {
StorageLive(_8);
StorageLive(_9);
StorageLive(_10);
_10 = Droppy(const 1_u8);
_9 = (_10.0: u8);
_8 = Gt(move _9, const 1_u8);
switchInt(move _8) -> [0: bb16, otherwise: bb15];
}
bb15: {
drop(_10) -> [return: bb17, unwind: bb33];
}
bb16: {
goto -> bb18;
switchInt(move _8) -> [0: bb18, otherwise: bb17];
}
bb17: {
StorageDead(_10);
StorageDead(_9);
_1 = const ();
goto -> bb21;
drop(_10) -> [return: bb19, unwind: bb37];
}
bb18: {
drop(_10) -> [return: bb19, unwind: bb33];
goto -> bb20;
}
bb19: {
StorageDead(_10);
StorageDead(_9);
goto -> bb20;
_1 = const ();
goto -> bb23;
}
bb20: {
_1 = const ();
goto -> bb21;
drop(_10) -> [return: bb21, unwind: bb37];
}
bb21: {
StorageDead(_10);
StorageDead(_9);
goto -> bb22;
}
bb22: {
_1 = const ();
goto -> bb23;
}
bb23: {
StorageDead(_8);
StorageDead(_5);
StorageDead(_4);
StorageDead(_2);
StorageDead(_1);
StorageLive(_11);
_11 = always_true() -> [return: bb22, unwind: bb33];
}
bb22: {
switchInt(move _11) -> [0: bb24, otherwise: bb23];
}
bb23: {
goto -> bb31;
_11 = always_true() -> [return: bb24, unwind: bb37];
}
bb24: {
goto -> bb25;
switchInt(move _11) -> [0: bb26, otherwise: bb25];
}
bb25: {
StorageLive(_12);
_12 = E::f() -> [return: bb26, unwind: bb33];
goto -> bb35;
}
bb26: {
PlaceMention(_12);
_13 = discriminant(_12);
switchInt(move _13) -> [1: bb29, otherwise: bb28];
goto -> bb27;
}
bb27: {
StorageLive(_12);
_12 = E::f() -> [return: bb28, unwind: bb37];
}
bb28: {
PlaceMention(_12);
_13 = discriminant(_12);
switchInt(move _13) -> [1: bb32, otherwise: bb30];
}
bb29: {
FakeRead(ForMatchedPlace(None), _12);
unreachable;
}
bb28: {
goto -> bb31;
}
bb29: {
falseEdge -> [real: bb30, imaginary: bb28];
}
bb30: {
_0 = const ();
goto -> bb32;
goto -> bb35;
}
bb31: {
_0 = const ();
goto -> bb32;
goto -> bb29;
}
bb32: {
falseEdge -> [real: bb34, imaginary: bb30];
}
bb33: {
goto -> bb30;
}
bb34: {
_0 = const ();
goto -> bb36;
}
bb35: {
_0 = const ();
goto -> bb36;
}
bb36: {
StorageDead(_11);
StorageDead(_12);
return;
}
bb33 (cleanup): {
bb37 (cleanup): {
resume;
}
}

View File

@ -28,7 +28,7 @@ fn full_tested_match() -> () {
_2 = Option::<i32>::Some(const 42_i32);
PlaceMention(_2);
_3 = discriminant(_2);
switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
switchInt(move _3) -> [0: bb2, 1: bb4, otherwise: bb1];
}
bb1: {
@ -38,30 +38,38 @@ fn full_tested_match() -> () {
bb2: {
_1 = (const 3_i32, const 3_i32);
goto -> bb11;
goto -> bb13;
}
bb3: {
falseEdge -> [real: bb5, imaginary: bb4];
goto -> bb1;
}
bb4: {
falseEdge -> [real: bb10, imaginary: bb2];
falseEdge -> [real: bb7, imaginary: bb5];
}
bb5: {
falseEdge -> [real: bb12, imaginary: bb2];
}
bb6: {
goto -> bb1;
}
bb7: {
StorageLive(_6);
_6 = &((_2 as Some).0: i32);
_4 = &fake _2;
StorageLive(_7);
_7 = guard() -> [return: bb6, unwind: bb13];
_7 = guard() -> [return: bb8, unwind: bb16];
}
bb6: {
switchInt(move _7) -> [0: bb8, otherwise: bb7];
bb8: {
switchInt(move _7) -> [0: bb10, otherwise: bb9];
}
bb7: {
bb9: {
StorageDead(_7);
FakeRead(ForMatchGuard, _4);
FakeRead(ForGuardBinding, _6);
@ -73,20 +81,20 @@ fn full_tested_match() -> () {
StorageDead(_8);
StorageDead(_5);
StorageDead(_6);
goto -> bb11;
}
bb8: {
goto -> bb9;
}
bb9: {
StorageDead(_7);
StorageDead(_6);
goto -> bb4;
goto -> bb13;
}
bb10: {
goto -> bb11;
}
bb11: {
StorageDead(_7);
StorageDead(_6);
goto -> bb5;
}
bb12: {
StorageLive(_9);
_9 = ((_2 as Some).0: i32);
StorageLive(_10);
@ -94,10 +102,10 @@ fn full_tested_match() -> () {
_1 = (const 2_i32, move _10);
StorageDead(_10);
StorageDead(_9);
goto -> bb11;
goto -> bb13;
}
bb11: {
bb13: {
PlaceMention(_1);
StorageDead(_2);
StorageDead(_1);
@ -105,12 +113,16 @@ fn full_tested_match() -> () {
return;
}
bb12: {
bb14: {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}
bb13 (cleanup): {
bb15: {
goto -> bb14;
}
bb16 (cleanup): {
resume;
}
}

View File

@ -28,7 +28,7 @@ fn full_tested_match2() -> () {
_2 = Option::<i32>::Some(const 42_i32);
PlaceMention(_2);
_3 = discriminant(_2);
switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
switchInt(move _3) -> [0: bb2, 1: bb4, otherwise: bb1];
}
bb1: {
@ -37,14 +37,18 @@ fn full_tested_match2() -> () {
}
bb2: {
falseEdge -> [real: bb10, imaginary: bb4];
falseEdge -> [real: bb12, imaginary: bb5];
}
bb3: {
falseEdge -> [real: bb5, imaginary: bb2];
goto -> bb1;
}
bb4: {
falseEdge -> [real: bb7, imaginary: bb2];
}
bb5: {
StorageLive(_9);
_9 = ((_2 as Some).0: i32);
StorageLive(_10);
@ -52,22 +56,26 @@ fn full_tested_match2() -> () {
_1 = (const 2_i32, move _10);
StorageDead(_10);
StorageDead(_9);
goto -> bb11;
goto -> bb13;
}
bb5: {
bb6: {
goto -> bb1;
}
bb7: {
StorageLive(_6);
_6 = &((_2 as Some).0: i32);
_4 = &fake _2;
StorageLive(_7);
_7 = guard() -> [return: bb6, unwind: bb13];
_7 = guard() -> [return: bb8, unwind: bb16];
}
bb6: {
switchInt(move _7) -> [0: bb8, otherwise: bb7];
bb8: {
switchInt(move _7) -> [0: bb10, otherwise: bb9];
}
bb7: {
bb9: {
StorageDead(_7);
FakeRead(ForMatchGuard, _4);
FakeRead(ForGuardBinding, _6);
@ -79,25 +87,25 @@ fn full_tested_match2() -> () {
StorageDead(_8);
StorageDead(_5);
StorageDead(_6);
goto -> bb11;
}
bb8: {
goto -> bb9;
}
bb9: {
StorageDead(_7);
StorageDead(_6);
falseEdge -> [real: bb4, imaginary: bb2];
goto -> bb13;
}
bb10: {
_1 = (const 3_i32, const 3_i32);
goto -> bb11;
}
bb11: {
StorageDead(_7);
StorageDead(_6);
falseEdge -> [real: bb5, imaginary: bb2];
}
bb12: {
_1 = (const 3_i32, const 3_i32);
goto -> bb13;
}
bb13: {
PlaceMention(_1);
StorageDead(_2);
StorageDead(_1);
@ -105,12 +113,16 @@ fn full_tested_match2() -> () {
return;
}
bb12: {
bb14: {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}
bb13 (cleanup): {
bb15: {
goto -> bb14;
}
bb16 (cleanup): {
resume;
}
}

View File

@ -39,7 +39,7 @@ fn main() -> () {
_2 = Option::<i32>::Some(const 1_i32);
PlaceMention(_2);
_4 = discriminant(_2);
switchInt(move _4) -> [1: bb7, otherwise: bb2];
switchInt(move _4) -> [1: bb8, otherwise: bb2];
}
bb1: {
@ -48,12 +48,12 @@ fn main() -> () {
}
bb2: {
falseEdge -> [real: bb14, imaginary: bb5];
falseEdge -> [real: bb15, imaginary: bb6];
}
bb3: {
_3 = discriminant(_2);
switchInt(move _3) -> [1: bb5, otherwise: bb4];
switchInt(move _3) -> [1: bb6, otherwise: bb4];
}
bb4: {
@ -61,38 +61,42 @@ fn main() -> () {
_14 = _2;
_1 = const 4_i32;
StorageDead(_14);
goto -> bb20;
goto -> bb21;
}
bb5: {
falseEdge -> [real: bb15, imaginary: bb4];
goto -> bb1;
}
bb6: {
goto -> bb4;
falseEdge -> [real: bb16, imaginary: bb4];
}
bb7: {
falseEdge -> [real: bb9, imaginary: bb2];
goto -> bb4;
}
bb8: {
goto -> bb2;
falseEdge -> [real: bb10, imaginary: bb2];
}
bb9: {
goto -> bb2;
}
bb10: {
StorageLive(_7);
_7 = &((_2 as Some).0: i32);
_5 = &fake _2;
StorageLive(_8);
_8 = guard() -> [return: bb10, unwind: bb22];
}
bb10: {
switchInt(move _8) -> [0: bb12, otherwise: bb11];
_8 = guard() -> [return: bb11, unwind: bb24];
}
bb11: {
switchInt(move _8) -> [0: bb13, otherwise: bb12];
}
bb12: {
StorageDead(_8);
FakeRead(ForMatchGuard, _5);
FakeRead(ForGuardBinding, _7);
@ -101,42 +105,42 @@ fn main() -> () {
_1 = const 1_i32;
StorageDead(_6);
StorageDead(_7);
goto -> bb20;
}
bb12: {
goto -> bb13;
goto -> bb21;
}
bb13: {
StorageDead(_8);
StorageDead(_7);
falseEdge -> [real: bb8, imaginary: bb2];
goto -> bb14;
}
bb14: {
StorageDead(_8);
StorageDead(_7);
falseEdge -> [real: bb9, imaginary: bb2];
}
bb15: {
StorageLive(_9);
_9 = _2;
_1 = const 2_i32;
StorageDead(_9);
goto -> bb20;
goto -> bb21;
}
bb15: {
bb16: {
StorageLive(_11);
_11 = &((_2 as Some).0: i32);
_5 = &fake _2;
StorageLive(_12);
StorageLive(_13);
_13 = (*_11);
_12 = guard2(move _13) -> [return: bb16, unwind: bb22];
}
bb16: {
switchInt(move _12) -> [0: bb18, otherwise: bb17];
_12 = guard2(move _13) -> [return: bb17, unwind: bb24];
}
bb17: {
switchInt(move _12) -> [0: bb19, otherwise: bb18];
}
bb18: {
StorageDead(_13);
StorageDead(_12);
FakeRead(ForMatchGuard, _5);
@ -146,21 +150,21 @@ fn main() -> () {
_1 = const 3_i32;
StorageDead(_10);
StorageDead(_11);
goto -> bb20;
}
bb18: {
goto -> bb19;
goto -> bb21;
}
bb19: {
StorageDead(_13);
StorageDead(_12);
StorageDead(_11);
falseEdge -> [real: bb6, imaginary: bb4];
goto -> bb20;
}
bb20: {
StorageDead(_13);
StorageDead(_12);
StorageDead(_11);
falseEdge -> [real: bb7, imaginary: bb4];
}
bb21: {
PlaceMention(_1);
StorageDead(_2);
StorageDead(_1);
@ -168,12 +172,16 @@ fn main() -> () {
return;
}
bb21: {
bb22: {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}
bb22 (cleanup): {
bb23: {
goto -> bb22;
}
bb24 (cleanup): {
resume;
}
}

View File

@ -6,7 +6,7 @@ fn match_bool(_1: bool) -> usize {
bb0: {
PlaceMention(_1);
switchInt(_1) -> [0: bb2, otherwise: bb3];
switchInt(_1) -> [0: bb2, otherwise: bb4];
}
bb1: {
@ -16,19 +16,27 @@ fn match_bool(_1: bool) -> usize {
bb2: {
_0 = const 20_usize;
goto -> bb5;
goto -> bb7;
}
bb3: {
falseEdge -> [real: bb4, imaginary: bb2];
goto -> bb1;
}
bb4: {
_0 = const 10_usize;
goto -> bb5;
falseEdge -> [real: bb6, imaginary: bb2];
}
bb5: {
goto -> bb2;
}
bb6: {
_0 = const 10_usize;
goto -> bb7;
}
bb7: {
return;
}
}

View File

@ -30,7 +30,7 @@ fn move_out_by_subslice() -> () {
StorageLive(_2);
_3 = SizeOf(i32);
_4 = AlignOf(i32);
_5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb13];
_5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb14];
}
bb1: {
@ -38,7 +38,7 @@ fn move_out_by_subslice() -> () {
_6 = ShallowInitBox(move _5, i32);
(*_6) = const 1_i32;
_2 = move _6;
drop(_6) -> [return: bb2, unwind: bb12];
drop(_6) -> [return: bb2, unwind: bb13];
}
bb2: {
@ -46,7 +46,7 @@ fn move_out_by_subslice() -> () {
StorageLive(_7);
_8 = SizeOf(i32);
_9 = AlignOf(i32);
_10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb12];
_10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb13];
}
bb3: {
@ -54,18 +54,18 @@ fn move_out_by_subslice() -> () {
_11 = ShallowInitBox(move _10, i32);
(*_11) = const 2_i32;
_7 = move _11;
drop(_11) -> [return: bb4, unwind: bb11];
drop(_11) -> [return: bb4, unwind: bb12];
}
bb4: {
StorageDead(_11);
_1 = [move _2, move _7];
drop(_7) -> [return: bb5, unwind: bb12];
drop(_7) -> [return: bb5, unwind: bb13];
}
bb5: {
StorageDead(_7);
drop(_2) -> [return: bb6, unwind: bb13];
drop(_2) -> [return: bb6, unwind: bb14];
}
bb6: {
@ -75,7 +75,7 @@ fn move_out_by_subslice() -> () {
StorageLive(_12);
_12 = move _1[0..2];
_0 = const ();
drop(_12) -> [return: bb8, unwind: bb10];
drop(_12) -> [return: bb9, unwind: bb11];
}
bb7: {
@ -84,28 +84,32 @@ fn move_out_by_subslice() -> () {
}
bb8: {
StorageDead(_12);
drop(_1) -> [return: bb9, unwind: bb13];
goto -> bb7;
}
bb9: {
StorageDead(_12);
drop(_1) -> [return: bb10, unwind: bb14];
}
bb10: {
StorageDead(_1);
return;
}
bb10 (cleanup): {
drop(_1) -> [return: bb13, unwind terminate(cleanup)];
}
bb11 (cleanup): {
drop(_7) -> [return: bb12, unwind terminate(cleanup)];
drop(_1) -> [return: bb14, unwind terminate(cleanup)];
}
bb12 (cleanup): {
drop(_2) -> [return: bb13, unwind terminate(cleanup)];
drop(_7) -> [return: bb13, unwind terminate(cleanup)];
}
bb13 (cleanup): {
drop(_2) -> [return: bb14, unwind terminate(cleanup)];
}
bb14 (cleanup): {
resume;
}
}

View File

@ -30,7 +30,7 @@ fn move_out_from_end() -> () {
StorageLive(_2);
_3 = SizeOf(i32);
_4 = AlignOf(i32);
_5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb13];
_5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb14];
}
bb1: {
@ -38,7 +38,7 @@ fn move_out_from_end() -> () {
_6 = ShallowInitBox(move _5, i32);
(*_6) = const 1_i32;
_2 = move _6;
drop(_6) -> [return: bb2, unwind: bb12];
drop(_6) -> [return: bb2, unwind: bb13];
}
bb2: {
@ -46,7 +46,7 @@ fn move_out_from_end() -> () {
StorageLive(_7);
_8 = SizeOf(i32);
_9 = AlignOf(i32);
_10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb12];
_10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb13];
}
bb3: {
@ -54,18 +54,18 @@ fn move_out_from_end() -> () {
_11 = ShallowInitBox(move _10, i32);
(*_11) = const 2_i32;
_7 = move _11;
drop(_11) -> [return: bb4, unwind: bb11];
drop(_11) -> [return: bb4, unwind: bb12];
}
bb4: {
StorageDead(_11);
_1 = [move _2, move _7];
drop(_7) -> [return: bb5, unwind: bb12];
drop(_7) -> [return: bb5, unwind: bb13];
}
bb5: {
StorageDead(_7);
drop(_2) -> [return: bb6, unwind: bb13];
drop(_2) -> [return: bb6, unwind: bb14];
}
bb6: {
@ -75,7 +75,7 @@ fn move_out_from_end() -> () {
StorageLive(_12);
_12 = move _1[1 of 2];
_0 = const ();
drop(_12) -> [return: bb8, unwind: bb10];
drop(_12) -> [return: bb9, unwind: bb11];
}
bb7: {
@ -84,28 +84,32 @@ fn move_out_from_end() -> () {
}
bb8: {
StorageDead(_12);
drop(_1) -> [return: bb9, unwind: bb13];
goto -> bb7;
}
bb9: {
StorageDead(_12);
drop(_1) -> [return: bb10, unwind: bb14];
}
bb10: {
StorageDead(_1);
return;
}
bb10 (cleanup): {
drop(_1) -> [return: bb13, unwind terminate(cleanup)];
}
bb11 (cleanup): {
drop(_7) -> [return: bb12, unwind terminate(cleanup)];
drop(_1) -> [return: bb14, unwind terminate(cleanup)];
}
bb12 (cleanup): {
drop(_2) -> [return: bb13, unwind terminate(cleanup)];
drop(_7) -> [return: bb13, unwind terminate(cleanup)];
}
bb13 (cleanup): {
drop(_2) -> [return: bb14, unwind terminate(cleanup)];
}
bb14 (cleanup): {
resume;
}
}

View File

@ -19,4 +19,8 @@ fn bar(_1: [(Never, u32); 1]) -> u32 {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}
bb2: {
goto -> bb1;
}
}

View File

@ -22,7 +22,7 @@ fn main() -> () {
bb0: {
StorageLive(_1);
_1 = std::mem::size_of::<Foo>() -> [return: bb1, unwind: bb5];
_1 = std::mem::size_of::<Foo>() -> [return: bb1, unwind: bb7];
}
bb1: {
@ -42,7 +42,7 @@ fn main() -> () {
_6 = const 0_usize;
_7 = Len(_2);
_8 = Lt(_6, _7);
assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb5];
assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb4, unwind: bb7];
}
bb2: {
@ -51,6 +51,10 @@ fn main() -> () {
}
bb3: {
goto -> bb2;
}
bb4: {
_5 = (_2[_6].0: u64);
PlaceMention(_5);
StorageDead(_6);
@ -60,12 +64,16 @@ fn main() -> () {
return;
}
bb4: {
bb5: {
FakeRead(ForMatchedPlace(None), _5);
unreachable;
}
bb5 (cleanup): {
bb6: {
goto -> bb5;
}
bb7 (cleanup): {
resume;
}
}

View File

@ -12,7 +12,7 @@ fn bar(_1: Box<[T]>) -> () {
StorageLive(_2);
StorageLive(_3);
_3 = &(*_1);
_2 = <[T] as Index<usize>>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb4];
_2 = <[T] as Index<usize>>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb5];
}
bb1: {
@ -20,7 +20,7 @@ fn bar(_1: Box<[T]>) -> () {
PlaceMention((*_2));
StorageDead(_2);
_0 = const ();
drop(_1) -> [return: bb3, unwind: bb5];
drop(_1) -> [return: bb4, unwind: bb6];
}
bb2: {
@ -29,14 +29,18 @@ fn bar(_1: Box<[T]>) -> () {
}
bb3: {
goto -> bb2;
}
bb4: {
return;
}
bb4 (cleanup): {
drop(_1) -> [return: bb5, unwind terminate(cleanup)];
bb5 (cleanup): {
drop(_1) -> [return: bb6, unwind terminate(cleanup)];
}
bb5 (cleanup): {
bb6 (cleanup): {
resume;
}
}

View File

@ -14,7 +14,7 @@ fn hey(_1: &[T]) -> () {
StorageLive(_3);
StorageLive(_4);
_4 = &(*_1);
_3 = <[T] as Index<usize>>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb3];
_3 = <[T] as Index<usize>>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb4];
}
bb1: {
@ -32,7 +32,11 @@ fn hey(_1: &[T]) -> () {
unreachable;
}
bb3 (cleanup): {
bb3: {
goto -> bb2;
}
bb4 (cleanup): {
resume;
}
}

View File

@ -67,7 +67,7 @@ fn main() -> () {
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
_4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb23];
_4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb25];
}
bb1: {
@ -91,7 +91,7 @@ fn main() -> () {
_11 = &(*_8);
StorageLive(_12);
_12 = &(*_9);
_10 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _11, move _12) -> [return: bb3, unwind: bb23];
_10 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _11, move _12) -> [return: bb4, unwind: bb25];
}
bb2: {
@ -100,20 +100,24 @@ fn main() -> () {
}
bb3: {
switchInt(move _10) -> [0: bb5, otherwise: bb4];
goto -> bb2;
}
bb4: {
StorageDead(_12);
StorageDead(_11);
goto -> bb9;
switchInt(move _10) -> [0: bb6, otherwise: bb5];
}
bb5: {
goto -> bb6;
StorageDead(_12);
StorageDead(_11);
goto -> bb10;
}
bb6: {
goto -> bb7;
}
bb7: {
StorageDead(_12);
StorageDead(_11);
StorageLive(_14);
@ -132,10 +136,10 @@ fn main() -> () {
_19 = &(*_20);
StorageLive(_21);
_21 = Option::<Arguments<'_>>::None;
_15 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _16, move _17, move _19, move _21) -> bb23;
_15 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _16, move _17, move _19, move _21) -> bb25;
}
bb7: {
bb8: {
StorageDead(_21);
StorageDead(_19);
StorageDead(_17);
@ -147,23 +151,23 @@ fn main() -> () {
unreachable;
}
bb8: {
goto -> bb10;
}
bb9: {
_1 = const ();
goto -> bb10;
goto -> bb11;
}
bb10: {
StorageDead(_10);
StorageDead(_9);
StorageDead(_8);
_1 = const ();
goto -> bb11;
}
bb11: {
StorageDead(_10);
StorageDead(_9);
StorageDead(_8);
goto -> bb12;
}
bb12: {
StorageDead(_7);
StorageDead(_6);
StorageDead(_4);
@ -173,10 +177,10 @@ fn main() -> () {
StorageLive(_23);
StorageLive(_24);
StorageLive(_25);
_25 = function_with_bytes::<&*b"AAAA">() -> [return: bb12, unwind: bb23];
_25 = function_with_bytes::<&*b"AAAA">() -> [return: bb13, unwind: bb25];
}
bb12: {
bb13: {
_24 = &_25;
StorageLive(_26);
StorageLive(_27);
@ -195,29 +199,33 @@ fn main() -> () {
_31 = &(*_28);
StorageLive(_32);
_32 = &(*_29);
_30 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _31, move _32) -> [return: bb14, unwind: bb23];
_30 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _31, move _32) -> [return: bb16, unwind: bb25];
}
bb13: {
bb14: {
FakeRead(ForMatchedPlace(None), _23);
unreachable;
}
bb14: {
switchInt(move _30) -> [0: bb16, otherwise: bb15];
}
bb15: {
StorageDead(_32);
StorageDead(_31);
goto -> bb20;
goto -> bb14;
}
bb16: {
goto -> bb17;
switchInt(move _30) -> [0: bb18, otherwise: bb17];
}
bb17: {
StorageDead(_32);
StorageDead(_31);
goto -> bb22;
}
bb18: {
goto -> bb19;
}
bb19: {
StorageDead(_32);
StorageDead(_31);
StorageLive(_34);
@ -236,10 +244,10 @@ fn main() -> () {
_39 = &(*_40);
StorageLive(_41);
_41 = Option::<Arguments<'_>>::None;
_35 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _36, move _37, move _39, move _41) -> bb23;
_35 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _36, move _37, move _39, move _41) -> bb25;
}
bb18: {
bb20: {
StorageDead(_41);
StorageDead(_39);
StorageDead(_37);
@ -251,23 +259,23 @@ fn main() -> () {
unreachable;
}
bb19: {
goto -> bb21;
}
bb20: {
_22 = const ();
goto -> bb21;
}
bb21: {
StorageDead(_30);
StorageDead(_29);
StorageDead(_28);
goto -> bb22;
goto -> bb23;
}
bb22: {
_22 = const ();
goto -> bb23;
}
bb23: {
StorageDead(_30);
StorageDead(_29);
StorageDead(_28);
goto -> bb24;
}
bb24: {
StorageDead(_27);
StorageDead(_25);
StorageDead(_23);
@ -276,7 +284,7 @@ fn main() -> () {
return;
}
bb23 (cleanup): {
bb25 (cleanup): {
resume;
}
}

View File

@ -67,7 +67,7 @@ fn main() -> () {
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
_4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb23];
_4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb25];
}
bb1: {
@ -91,7 +91,7 @@ fn main() -> () {
_11 = &(*_8);
StorageLive(_12);
_12 = &(*_9);
_10 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _11, move _12) -> [return: bb3, unwind: bb23];
_10 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _11, move _12) -> [return: bb4, unwind: bb25];
}
bb2: {
@ -100,20 +100,24 @@ fn main() -> () {
}
bb3: {
switchInt(move _10) -> [0: bb5, otherwise: bb4];
goto -> bb2;
}
bb4: {
StorageDead(_12);
StorageDead(_11);
goto -> bb9;
switchInt(move _10) -> [0: bb6, otherwise: bb5];
}
bb5: {
goto -> bb6;
StorageDead(_12);
StorageDead(_11);
goto -> bb10;
}
bb6: {
goto -> bb7;
}
bb7: {
StorageDead(_12);
StorageDead(_11);
StorageLive(_14);
@ -132,10 +136,10 @@ fn main() -> () {
_19 = &(*_20);
StorageLive(_21);
_21 = Option::<Arguments<'_>>::None;
_15 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _16, move _17, move _19, move _21) -> bb23;
_15 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _16, move _17, move _19, move _21) -> bb25;
}
bb7: {
bb8: {
StorageDead(_21);
StorageDead(_19);
StorageDead(_17);
@ -147,23 +151,23 @@ fn main() -> () {
unreachable;
}
bb8: {
goto -> bb10;
}
bb9: {
_1 = const ();
goto -> bb10;
goto -> bb11;
}
bb10: {
StorageDead(_10);
StorageDead(_9);
StorageDead(_8);
_1 = const ();
goto -> bb11;
}
bb11: {
StorageDead(_10);
StorageDead(_9);
StorageDead(_8);
goto -> bb12;
}
bb12: {
StorageDead(_7);
StorageDead(_6);
StorageDead(_4);
@ -173,10 +177,10 @@ fn main() -> () {
StorageLive(_23);
StorageLive(_24);
StorageLive(_25);
_25 = function_with_bytes::<&*b"AAAA">() -> [return: bb12, unwind: bb23];
_25 = function_with_bytes::<&*b"AAAA">() -> [return: bb13, unwind: bb25];
}
bb12: {
bb13: {
_24 = &_25;
StorageLive(_26);
StorageLive(_27);
@ -195,29 +199,33 @@ fn main() -> () {
_31 = &(*_28);
StorageLive(_32);
_32 = &(*_29);
_30 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _31, move _32) -> [return: bb14, unwind: bb23];
_30 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _31, move _32) -> [return: bb16, unwind: bb25];
}
bb13: {
bb14: {
FakeRead(ForMatchedPlace(None), _23);
unreachable;
}
bb14: {
switchInt(move _30) -> [0: bb16, otherwise: bb15];
}
bb15: {
StorageDead(_32);
StorageDead(_31);
goto -> bb20;
goto -> bb14;
}
bb16: {
goto -> bb17;
switchInt(move _30) -> [0: bb18, otherwise: bb17];
}
bb17: {
StorageDead(_32);
StorageDead(_31);
goto -> bb22;
}
bb18: {
goto -> bb19;
}
bb19: {
StorageDead(_32);
StorageDead(_31);
StorageLive(_34);
@ -236,10 +244,10 @@ fn main() -> () {
_39 = &(*_40);
StorageLive(_41);
_41 = Option::<Arguments<'_>>::None;
_35 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _36, move _37, move _39, move _41) -> bb23;
_35 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _36, move _37, move _39, move _41) -> bb25;
}
bb18: {
bb20: {
StorageDead(_41);
StorageDead(_39);
StorageDead(_37);
@ -251,23 +259,23 @@ fn main() -> () {
unreachable;
}
bb19: {
goto -> bb21;
}
bb20: {
_22 = const ();
goto -> bb21;
}
bb21: {
StorageDead(_30);
StorageDead(_29);
StorageDead(_28);
goto -> bb22;
goto -> bb23;
}
bb22: {
_22 = const ();
goto -> bb23;
}
bb23: {
StorageDead(_30);
StorageDead(_29);
StorageDead(_28);
goto -> bb24;
}
bb24: {
StorageDead(_27);
StorageDead(_25);
StorageDead(_23);
@ -276,7 +284,7 @@ fn main() -> () {
return;
}
bb23 (cleanup): {
bb25 (cleanup): {
resume;
}
}