Clean up MIR match lowering
* Adjust fake borrows to only be live over guards. * Remove unused `slice_len_checked` field. * Split the methods on builder into those for matches and those for all kinds of pattern bindings.
This commit is contained in:
parent
c15437c0c6
commit
d51b5cdd82
File diff suppressed because it is too large
Load Diff
@ -69,8 +69,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Slice { ref prefix, ref slice, ref suffix }
|
||||
if !match_pair.slice_len_checked => {
|
||||
PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
|
||||
let len = prefix.len() + suffix.len();
|
||||
let op = if slice.is_some() {
|
||||
BinOp::Ge
|
||||
@ -85,7 +84,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
PatternKind::AscribeUserType { .. } |
|
||||
PatternKind::Array { .. } |
|
||||
PatternKind::Slice { .. } |
|
||||
PatternKind::Wild |
|
||||
PatternKind::Binding { .. } |
|
||||
PatternKind::Leaf { .. } |
|
||||
@ -433,59 +431,49 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
target_block
|
||||
}
|
||||
|
||||
/// Given that we are performing `test` against `test_place`,
|
||||
/// this job sorts out what the status of `candidate` will be
|
||||
/// after the test. The `resulting_candidates` vector stores, for
|
||||
/// each possible outcome of `test`, a vector of the candidates
|
||||
/// that will result. This fn should add a (possibly modified)
|
||||
/// clone of candidate into `resulting_candidates` wherever
|
||||
/// appropriate.
|
||||
/// Given that we are performing `test` against `test_place`, this job
|
||||
/// sorts out what the status of `candidate` will be after the test. See
|
||||
/// `test_candidates` for the usage of this function. The returned index is
|
||||
/// the index that this candiate should be placed in the
|
||||
/// `target_candidates` vec. The candidate may be modified to update its
|
||||
/// `match_pairs`.
|
||||
///
|
||||
/// So, for example, if this candidate is `x @ Some(P0)` and the
|
||||
/// Tests is a variant test, then we would add `(x as Option).0 @
|
||||
/// P0` to the `resulting_candidates` entry corresponding to the
|
||||
/// variant `Some`.
|
||||
/// So, for example, if this candidate is `x @ Some(P0)` and the `Test` is
|
||||
/// a variant test, then we would modify the candidate to be `(x as
|
||||
/// Option).0 @ P0` and return the index corresponding to the variant
|
||||
/// `Some`.
|
||||
///
|
||||
/// However, in some cases, the test may just not be relevant to
|
||||
/// candidate. For example, suppose we are testing whether `foo.x == 22`,
|
||||
/// but in one match arm we have `Foo { x: _, ... }`... in that case,
|
||||
/// the test for what value `x` has has no particular relevance
|
||||
/// to this candidate. In such cases, this function just returns false
|
||||
/// without doing anything. This is used by the overall `match_candidates`
|
||||
/// algorithm to structure the match as a whole. See `match_candidates` for
|
||||
/// more details.
|
||||
/// However, in some cases, the test may just not be relevant to candidate.
|
||||
/// For example, suppose we are testing whether `foo.x == 22`, but in one
|
||||
/// match arm we have `Foo { x: _, ... }`... in that case, the test for
|
||||
/// what value `x` has has no particular relevance to this candidate. In
|
||||
/// such cases, this function just returns None without doing anything.
|
||||
/// This is used by the overall `match_candidates` algorithm to structure
|
||||
/// the match as a whole. See `match_candidates` for more details.
|
||||
///
|
||||
/// FIXME(#29623). In some cases, we have some tricky choices to
|
||||
/// make. for example, if we are testing that `x == 22`, but the
|
||||
/// candidate is `x @ 13..55`, what should we do? In the event
|
||||
/// that the test is true, we know that the candidate applies, but
|
||||
/// in the event of false, we don't know that it *doesn't*
|
||||
/// apply. For now, we return false, indicate that the test does
|
||||
/// not apply to this candidate, but it might be we can get
|
||||
/// FIXME(#29623). In some cases, we have some tricky choices to make. for
|
||||
/// example, if we are testing that `x == 22`, but the candidate is `x @
|
||||
/// 13..55`, what should we do? In the event that the test is true, we know
|
||||
/// that the candidate applies, but in the event of false, we don't know
|
||||
/// that it *doesn't* apply. For now, we return false, indicate that the
|
||||
/// test does not apply to this candidate, but it might be we can get
|
||||
/// tighter match code if we do something a bit different.
|
||||
pub fn sort_candidate<'pat>(&mut self,
|
||||
test_place: &Place<'tcx>,
|
||||
test: &Test<'tcx>,
|
||||
candidate: &Candidate<'pat, 'tcx>,
|
||||
resulting_candidates: &mut [Vec<Candidate<'pat, 'tcx>>])
|
||||
-> bool {
|
||||
pub fn sort_candidate<'pat, 'cand>(
|
||||
&mut self,
|
||||
test_place: &Place<'tcx>,
|
||||
test: &Test<'tcx>,
|
||||
candidate: &mut Candidate<'pat, 'tcx>,
|
||||
) -> Option<usize> {
|
||||
// Find the match_pair for this place (if any). At present,
|
||||
// afaik, there can be at most one. (In the future, if we
|
||||
// adopted a more general `@` operator, there might be more
|
||||
// than one, but it'd be very unusual to have two sides that
|
||||
// both require tests; you'd expect one side to be simplified
|
||||
// away.)
|
||||
let tested_match_pair = candidate.match_pairs.iter()
|
||||
.enumerate()
|
||||
.find(|&(_, mp)| mp.place == *test_place);
|
||||
let (match_pair_index, match_pair) = match tested_match_pair {
|
||||
Some(pair) => pair,
|
||||
None => {
|
||||
// We are not testing this place. Therefore, this
|
||||
// candidate applies to ALL outcomes.
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let (match_pair_index, match_pair) = candidate.match_pairs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|&(_, mp)| mp.place == *test_place)?;
|
||||
|
||||
match (&test.kind, &*match_pair.pattern.kind) {
|
||||
// If we are performing a variant switch, then this
|
||||
@ -493,17 +481,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
(&TestKind::Switch { adt_def: tested_adt_def, .. },
|
||||
&PatternKind::Variant { adt_def, variant_index, ref subpatterns, .. }) => {
|
||||
assert_eq!(adt_def, tested_adt_def);
|
||||
let new_candidate =
|
||||
self.candidate_after_variant_switch(match_pair_index,
|
||||
adt_def,
|
||||
variant_index,
|
||||
subpatterns,
|
||||
candidate);
|
||||
resulting_candidates[variant_index.as_usize()].push(new_candidate);
|
||||
true
|
||||
self.candidate_after_variant_switch(match_pair_index,
|
||||
adt_def,
|
||||
variant_index,
|
||||
subpatterns,
|
||||
candidate);
|
||||
Some(variant_index.as_usize())
|
||||
}
|
||||
|
||||
(&TestKind::Switch { .. }, _) => false,
|
||||
(&TestKind::Switch { .. }, _) => None,
|
||||
|
||||
// If we are performing a switch over integers, then this informs integer
|
||||
// equality, but nothing else.
|
||||
@ -514,10 +500,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
&PatternKind::Constant { ref value })
|
||||
if is_switch_ty(match_pair.pattern.ty) => {
|
||||
let index = indices[value];
|
||||
let new_candidate = self.candidate_without_match_pair(match_pair_index,
|
||||
candidate);
|
||||
resulting_candidates[index].push(new_candidate);
|
||||
true
|
||||
self.candidate_without_match_pair(match_pair_index, candidate);
|
||||
Some(index)
|
||||
}
|
||||
|
||||
(&TestKind::SwitchInt { switch_ty: _, ref options, ref indices },
|
||||
@ -530,14 +514,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
// No switch values are contained in the pattern range,
|
||||
// so the pattern can be matched only if this test fails.
|
||||
let otherwise = options.len();
|
||||
resulting_candidates[otherwise].push(candidate.clone());
|
||||
true
|
||||
Some(otherwise)
|
||||
} else {
|
||||
false
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
(&TestKind::SwitchInt { .. }, _) => false,
|
||||
(&TestKind::SwitchInt { .. }, _) => None,
|
||||
|
||||
(&TestKind::Len { len: test_len, op: BinOp::Eq },
|
||||
&PatternKind::Slice { ref prefix, ref slice, ref suffix }) => {
|
||||
@ -546,32 +529,28 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
(Ordering::Equal, &None) => {
|
||||
// on true, min_len = len = $actual_length,
|
||||
// on false, len != $actual_length
|
||||
resulting_candidates[0].push(
|
||||
self.candidate_after_slice_test(match_pair_index,
|
||||
candidate,
|
||||
prefix,
|
||||
slice.as_ref(),
|
||||
suffix)
|
||||
);
|
||||
true
|
||||
self.candidate_after_slice_test(match_pair_index,
|
||||
candidate,
|
||||
prefix,
|
||||
slice.as_ref(),
|
||||
suffix);
|
||||
Some(0)
|
||||
}
|
||||
(Ordering::Less, _) => {
|
||||
// test_len < pat_len. If $actual_len = test_len,
|
||||
// then $actual_len < pat_len and we don't have
|
||||
// enough elements.
|
||||
resulting_candidates[1].push(candidate.clone());
|
||||
true
|
||||
Some(1)
|
||||
}
|
||||
(Ordering::Equal, &Some(_)) | (Ordering::Greater, &Some(_)) => {
|
||||
// This can match both if $actual_len = test_len >= pat_len,
|
||||
// and if $actual_len > test_len. We can't advance.
|
||||
false
|
||||
None
|
||||
}
|
||||
(Ordering::Greater, &None) => {
|
||||
// test_len != pat_len, so if $actual_len = test_len, then
|
||||
// $actual_len != pat_len.
|
||||
resulting_candidates[1].push(candidate.clone());
|
||||
true
|
||||
Some(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -584,32 +563,28 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
(Ordering::Equal, &Some(_)) => {
|
||||
// $actual_len >= test_len = pat_len,
|
||||
// so we can match.
|
||||
resulting_candidates[0].push(
|
||||
self.candidate_after_slice_test(match_pair_index,
|
||||
candidate,
|
||||
prefix,
|
||||
slice.as_ref(),
|
||||
suffix)
|
||||
);
|
||||
true
|
||||
self.candidate_after_slice_test(match_pair_index,
|
||||
candidate,
|
||||
prefix,
|
||||
slice.as_ref(),
|
||||
suffix);
|
||||
Some(0)
|
||||
}
|
||||
(Ordering::Less, _) | (Ordering::Equal, &None) => {
|
||||
// test_len <= pat_len. If $actual_len < test_len,
|
||||
// then it is also < pat_len, so the test passing is
|
||||
// necessary (but insufficient).
|
||||
resulting_candidates[0].push(candidate.clone());
|
||||
true
|
||||
Some(0)
|
||||
}
|
||||
(Ordering::Greater, &None) => {
|
||||
// test_len > pat_len. If $actual_len >= test_len > pat_len,
|
||||
// then we know we won't have a match.
|
||||
resulting_candidates[1].push(candidate.clone());
|
||||
true
|
||||
Some(1)
|
||||
}
|
||||
(Ordering::Greater, &Some(_)) => {
|
||||
// test_len < pat_len, and is therefore less
|
||||
// strict. This can still go both ways.
|
||||
false
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -617,12 +592,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
(&TestKind::Range(test),
|
||||
&PatternKind::Range(pat)) => {
|
||||
if test == pat {
|
||||
resulting_candidates[0]
|
||||
.push(self.candidate_without_match_pair(
|
||||
match_pair_index,
|
||||
candidate,
|
||||
));
|
||||
return true;
|
||||
self.candidate_without_match_pair(
|
||||
match_pair_index,
|
||||
candidate,
|
||||
);
|
||||
return Some(0);
|
||||
}
|
||||
|
||||
let no_overlap = (|| {
|
||||
@ -649,10 +623,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
if no_overlap == Some(true) {
|
||||
// Testing range does not overlap with pattern range,
|
||||
// so the pattern can be matched only if this test fails.
|
||||
resulting_candidates[1].push(candidate.clone());
|
||||
true
|
||||
Some(1)
|
||||
} else {
|
||||
false
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@ -660,15 +633,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
if self.const_range_contains(range, value) == Some(false) {
|
||||
// `value` is not contained in the testing range,
|
||||
// so `value` can be matched only if this test fails.
|
||||
resulting_candidates[1].push(candidate.clone());
|
||||
true
|
||||
Some(1)
|
||||
} else {
|
||||
false
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
(&TestKind::Range { .. }, _) => false,
|
||||
|
||||
(&TestKind::Range { .. }, _) => None,
|
||||
|
||||
(&TestKind::Eq { .. }, _) |
|
||||
(&TestKind::Len { .. }, _) => {
|
||||
@ -677,73 +648,53 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
// FIXME(#29623) we can be more clever here
|
||||
let pattern_test = self.test(&match_pair);
|
||||
if pattern_test.kind == test.kind {
|
||||
let new_candidate = self.candidate_without_match_pair(match_pair_index,
|
||||
candidate);
|
||||
resulting_candidates[0].push(new_candidate);
|
||||
true
|
||||
self.candidate_without_match_pair(match_pair_index, candidate);
|
||||
Some(0)
|
||||
} else {
|
||||
false
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn candidate_without_match_pair<'pat>(&mut self,
|
||||
match_pair_index: usize,
|
||||
candidate: &Candidate<'pat, 'tcx>)
|
||||
-> Candidate<'pat, 'tcx> {
|
||||
let other_match_pairs =
|
||||
candidate.match_pairs.iter()
|
||||
.enumerate()
|
||||
.filter(|&(index, _)| index != match_pair_index)
|
||||
.map(|(_, mp)| mp.clone())
|
||||
.collect();
|
||||
Candidate {
|
||||
span: candidate.span,
|
||||
match_pairs: other_match_pairs,
|
||||
bindings: candidate.bindings.clone(),
|
||||
ascriptions: candidate.ascriptions.clone(),
|
||||
guard: candidate.guard.clone(),
|
||||
arm_index: candidate.arm_index,
|
||||
pat_index: candidate.pat_index,
|
||||
pre_binding_block: candidate.pre_binding_block,
|
||||
next_candidate_pre_binding_block: candidate.next_candidate_pre_binding_block,
|
||||
}
|
||||
fn candidate_without_match_pair(
|
||||
&mut self,
|
||||
match_pair_index: usize,
|
||||
candidate: &mut Candidate<'_, 'tcx>,
|
||||
) {
|
||||
candidate.match_pairs.remove(match_pair_index);
|
||||
}
|
||||
|
||||
fn candidate_after_slice_test<'pat>(&mut self,
|
||||
match_pair_index: usize,
|
||||
candidate: &Candidate<'pat, 'tcx>,
|
||||
candidate: &mut Candidate<'pat, 'tcx>,
|
||||
prefix: &'pat [Pattern<'tcx>],
|
||||
opt_slice: Option<&'pat Pattern<'tcx>>,
|
||||
suffix: &'pat [Pattern<'tcx>])
|
||||
-> Candidate<'pat, 'tcx> {
|
||||
let mut new_candidate =
|
||||
self.candidate_without_match_pair(match_pair_index, candidate);
|
||||
suffix: &'pat [Pattern<'tcx>]) {
|
||||
let removed_place = candidate.match_pairs.remove(match_pair_index).place;
|
||||
self.prefix_slice_suffix(
|
||||
&mut new_candidate.match_pairs,
|
||||
&candidate.match_pairs[match_pair_index].place,
|
||||
&mut candidate.match_pairs,
|
||||
&removed_place,
|
||||
prefix,
|
||||
opt_slice,
|
||||
suffix);
|
||||
|
||||
new_candidate
|
||||
}
|
||||
|
||||
fn candidate_after_variant_switch<'pat>(&mut self,
|
||||
match_pair_index: usize,
|
||||
adt_def: &'tcx ty::AdtDef,
|
||||
variant_index: VariantIdx,
|
||||
subpatterns: &'pat [FieldPattern<'tcx>],
|
||||
candidate: &Candidate<'pat, 'tcx>)
|
||||
-> Candidate<'pat, 'tcx> {
|
||||
let match_pair = &candidate.match_pairs[match_pair_index];
|
||||
fn candidate_after_variant_switch<'pat>(
|
||||
&mut self,
|
||||
match_pair_index: usize,
|
||||
adt_def: &'tcx ty::AdtDef,
|
||||
variant_index: VariantIdx,
|
||||
subpatterns: &'pat [FieldPattern<'tcx>],
|
||||
candidate: &mut Candidate<'pat, 'tcx>,
|
||||
) {
|
||||
let match_pair = candidate.match_pairs.remove(match_pair_index);
|
||||
|
||||
// So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
|
||||
// we want to create a set of derived match-patterns like
|
||||
// `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
|
||||
let elem = ProjectionElem::Downcast(adt_def, variant_index);
|
||||
let downcast_place = match_pair.place.clone().elem(elem); // `(x as Variant)`
|
||||
let downcast_place = match_pair.place.elem(elem); // `(x as Variant)`
|
||||
let consequent_match_pairs =
|
||||
subpatterns.iter()
|
||||
.map(|subpattern| {
|
||||
@ -754,26 +705,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
MatchPair::new(place, &subpattern.pattern)
|
||||
});
|
||||
|
||||
// In addition, we need all the other match pairs from the old candidate.
|
||||
let other_match_pairs =
|
||||
candidate.match_pairs.iter()
|
||||
.enumerate()
|
||||
.filter(|&(index, _)| index != match_pair_index)
|
||||
.map(|(_, mp)| mp.clone());
|
||||
|
||||
let all_match_pairs = consequent_match_pairs.chain(other_match_pairs).collect();
|
||||
|
||||
Candidate {
|
||||
span: candidate.span,
|
||||
match_pairs: all_match_pairs,
|
||||
bindings: candidate.bindings.clone(),
|
||||
ascriptions: candidate.ascriptions.clone(),
|
||||
guard: candidate.guard.clone(),
|
||||
arm_index: candidate.arm_index,
|
||||
pat_index: candidate.pat_index,
|
||||
pre_binding_block: candidate.pre_binding_block,
|
||||
next_candidate_pre_binding_block: candidate.next_candidate_pre_binding_block,
|
||||
}
|
||||
candidate.match_pairs.extend(consequent_match_pairs);
|
||||
}
|
||||
|
||||
fn error_simplifyable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> ! {
|
||||
|
@ -72,7 +72,6 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
||||
MatchPair {
|
||||
place,
|
||||
pattern,
|
||||
slice_len_checked: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,47 +41,47 @@ fn main() {
|
||||
// StorageLive(_3);
|
||||
// _3 = const true;
|
||||
// FakeRead(ForMatchedPlace, _3);
|
||||
// switchInt(_3) -> [false: bb11, otherwise: bb10];
|
||||
// switchInt(_3) -> [false: bb9, otherwise: bb8];
|
||||
// }
|
||||
// bb4: {
|
||||
// resume;
|
||||
// }
|
||||
// bb5: {
|
||||
// _2 = const 4i32;
|
||||
// goto -> bb14;
|
||||
// falseEdges -> [real: bb12, imaginary: bb6];
|
||||
// }
|
||||
// bb6: {
|
||||
// _0 = ();
|
||||
// goto -> bb15;
|
||||
// falseEdges -> [real: bb14, imaginary: bb7];
|
||||
// }
|
||||
// bb7: {
|
||||
// falseEdges -> [real: bb12, imaginary: bb8];
|
||||
// }
|
||||
// bb8: {
|
||||
// falseEdges -> [real: bb13, imaginary: bb9];
|
||||
// }
|
||||
// bb9: {
|
||||
// unreachable;
|
||||
// }
|
||||
// bb10: {
|
||||
// goto -> bb8;
|
||||
// }
|
||||
// bb11: {
|
||||
// goto -> bb7;
|
||||
// }
|
||||
// bb12: {
|
||||
// goto -> bb5;
|
||||
// }
|
||||
// bb13: {
|
||||
// bb8: {
|
||||
// goto -> bb6;
|
||||
// }
|
||||
// bb14: {
|
||||
// bb9: {
|
||||
// goto -> bb5;
|
||||
// }
|
||||
// bb10: {
|
||||
// FakeRead(ForLet, _2);
|
||||
// StorageDead(_3);
|
||||
// StorageLive(_6);
|
||||
// _6 = &_2;
|
||||
// _5 = const std::mem::drop(move _6) -> [return: bb19, unwind: bb4];
|
||||
// }
|
||||
// bb11: {
|
||||
// _2 = const 4i32;
|
||||
// goto -> bb10;
|
||||
// }
|
||||
// bb12: {
|
||||
// goto -> bb11;
|
||||
// }
|
||||
// bb13: {
|
||||
// _0 = ();
|
||||
// goto -> bb15;
|
||||
// }
|
||||
// bb14: {
|
||||
// goto -> bb13;
|
||||
// }
|
||||
// bb15: {
|
||||
// StorageDead(_3);
|
||||
// goto -> bb16;
|
||||
@ -96,7 +96,7 @@ fn main() {
|
||||
// }
|
||||
// bb18: {
|
||||
// StorageDead(_4);
|
||||
// goto -> bb14;
|
||||
// goto -> bb10;
|
||||
// }
|
||||
// bb19: {
|
||||
// StorageDead(_6);
|
||||
|
@ -44,73 +44,69 @@ fn main() {
|
||||
// ...
|
||||
// _2 = std::option::Option<i32>::Some(const 42i32,);
|
||||
// FakeRead(ForMatchedPlace, _2);
|
||||
// _7 = discriminant(_2);
|
||||
// _9 = &shallow (promoted[2]: std::option::Option<i32>);
|
||||
// _10 = &(((promoted[1]: std::option::Option<i32>) as Some).0: i32);
|
||||
// switchInt(move _7) -> [0isize: bb5, 1isize: bb3, otherwise: bb7];
|
||||
// _3 = discriminant(_2);
|
||||
// switchInt(move _3) -> [0isize: bb4, 1isize: bb2, otherwise: bb7];
|
||||
// }
|
||||
// bb1: {
|
||||
// resume;
|
||||
// }
|
||||
// bb2: { // arm1
|
||||
// _1 = (const 3i32, const 3i32);
|
||||
// goto -> bb13;
|
||||
// bb2: {
|
||||
// falseEdges -> [real: bb9, imaginary: bb3]; //pre_binding1
|
||||
// }
|
||||
// bb3: { // binding3(empty) and arm3
|
||||
// FakeRead(ForMatchGuard, _9);
|
||||
// FakeRead(ForMatchGuard, _10);
|
||||
// falseEdges -> [real: bb8, imaginary: bb4]; //pre_binding1
|
||||
// bb3: {
|
||||
// falseEdges -> [real: bb12, imaginary: bb4]; //pre_binding2
|
||||
// }
|
||||
// bb4: {
|
||||
// FakeRead(ForMatchGuard, _9);
|
||||
// FakeRead(ForMatchGuard, _10);
|
||||
// falseEdges -> [real: bb12, imaginary: bb5]; //pre_binding2
|
||||
// falseEdges -> [real: bb13, imaginary: bb5]; //pre_binding3
|
||||
// }
|
||||
// bb5: {
|
||||
// FakeRead(ForMatchGuard, _9);
|
||||
// FakeRead(ForMatchGuard, _10);
|
||||
// falseEdges -> [real: bb2, imaginary: bb6]; //pre_binding3
|
||||
// }
|
||||
// bb6: {
|
||||
// unreachable;
|
||||
// }
|
||||
// bb6: { // to pre_binding2
|
||||
// falseEdges -> [real: bb3, imaginary: bb3];
|
||||
// }
|
||||
// bb7: {
|
||||
// unreachable;
|
||||
// }
|
||||
// bb8: { // binding1 and guard
|
||||
// StorageLive(_5);
|
||||
// _5 = &(((promoted[0]: std::option::Option<i32>) as Some).0: i32);
|
||||
// StorageLive(_8);
|
||||
// _8 = const guard() -> [return: bb9, unwind: bb1];
|
||||
// }
|
||||
// bb9: {
|
||||
// switchInt(move _8) -> [false: bb10, otherwise: bb11];
|
||||
// }
|
||||
// bb10: { // to pre_binding2
|
||||
// falseEdges -> [real: bb4, imaginary: bb4];
|
||||
// }
|
||||
// bb11: { // bindingNoLandingPads.before.mir2 and arm2
|
||||
// StorageLive(_3);
|
||||
// _3 = ((_2 as Some).0: i32);
|
||||
// StorageLive(_11);
|
||||
// _11 = _3;
|
||||
// _1 = (const 1i32, move _11);
|
||||
// StorageDead(_11);
|
||||
// goto -> bb13;
|
||||
// }
|
||||
// bb12: {
|
||||
// StorageLive(_6);
|
||||
// _6 = ((_2 as Some).0: i32);
|
||||
// StorageLive(_12);
|
||||
// _12 = _6;
|
||||
// _1 = (const 2i32, move_12);
|
||||
// StorageDead(_12);
|
||||
// goto -> bb13;
|
||||
// }
|
||||
// bb13: {
|
||||
// bb8: {
|
||||
// ...
|
||||
// return;
|
||||
// }
|
||||
// bb9: { // binding1 and guard
|
||||
// StorageLive(_8);
|
||||
// _8 = &(((promoted[2]: std::option::Option<i32>) as Some).0: i32);
|
||||
// _4 = &shallow (promoted[1]: std::option::Option<i32>);
|
||||
// _5 = &(((promoted[0]: std::option::Option<i32>) as Some).0: i32);
|
||||
// StorageLive(_9);
|
||||
// _9 = const guard() -> [return: bb10, unwind: bb1];
|
||||
// }
|
||||
// bb10: {
|
||||
// FakeRead(ForMatchGuard, _4);
|
||||
// FakeRead(ForMatchGuard, _5);
|
||||
// switchInt(move _9) -> [false: bb6, otherwise: bb11];
|
||||
// }
|
||||
// bb11: {
|
||||
// StorageLive(_6);
|
||||
// _6 = ((_2 as Some).0: i32);
|
||||
// StorageLive(_10);
|
||||
// _10 = _6;
|
||||
// _1 = (const 1i32, move _10);
|
||||
// StorageDead(_10);
|
||||
// goto -> bb8;
|
||||
// }
|
||||
// bb12: {
|
||||
// StorageLive(_11);
|
||||
// _11 = ((_2 as Some).0: i32);
|
||||
// StorageLive(_12);
|
||||
// _12 = _11;
|
||||
// _1 = (const 2i32, move _12);
|
||||
// StorageDead(_12);
|
||||
// goto -> bb8;
|
||||
// }
|
||||
// bb13: {
|
||||
// _1 = (const 3i32, const 3i32);
|
||||
// goto -> bb8;
|
||||
// }
|
||||
// END rustc.full_tested_match.QualifyAndPromoteConstants.after.mir
|
||||
//
|
||||
// START rustc.full_tested_match2.QualifyAndPromoteConstants.before.mir
|
||||
@ -118,164 +114,158 @@ fn main() {
|
||||
// ...
|
||||
// _2 = std::option::Option<i32>::Some(const 42i32,);
|
||||
// FakeRead(ForMatchedPlace, _2);
|
||||
// _7 = discriminant(_2);
|
||||
// _9 = &shallow _2;
|
||||
// _10 = &((_2 as Some).0: i32);
|
||||
// switchInt(move _7) -> [0isize: bb4, 1isize: bb3, otherwise: bb7];
|
||||
// _3 = discriminant(_2);
|
||||
// switchInt(move _3) -> [0isize: bb3, 1isize: bb2, otherwise: bb7];
|
||||
// }
|
||||
// bb1: {
|
||||
// resume;
|
||||
// }
|
||||
// bb2: { // arm2
|
||||
// _1 = (const 3i32, const 3i32);
|
||||
// goto -> bb13;
|
||||
// bb2: {
|
||||
// falseEdges -> [real: bb9, imaginary: bb3];
|
||||
// }
|
||||
// bb3: {
|
||||
// FakeRead(ForMatchGuard, _9);
|
||||
// FakeRead(ForMatchGuard, _10);
|
||||
// falseEdges -> [real: bb8, imaginary: bb4]; //pre_binding1
|
||||
// falseEdges -> [real: bb12, imaginary: bb4];
|
||||
// }
|
||||
// bb4: {
|
||||
// FakeRead(ForMatchGuard, _9);
|
||||
// FakeRead(ForMatchGuard, _10);
|
||||
// falseEdges -> [real: bb2, imaginary: bb5]; //pre_binding2
|
||||
// falseEdges -> [real: bb13, imaginary: bb5];
|
||||
// }
|
||||
// bb5: {
|
||||
// FakeRead(ForMatchGuard, _9);
|
||||
// FakeRead(ForMatchGuard, _10);
|
||||
// falseEdges -> [real: bb12, imaginary: bb6]; //pre_binding3
|
||||
// }
|
||||
// bb6: {
|
||||
// unreachable;
|
||||
// }
|
||||
// bb6: { // to pre_binding3 (can skip 2 since this is `Some`)
|
||||
// falseEdges -> [real: bb4, imaginary: bb3];
|
||||
// }
|
||||
// bb7: {
|
||||
// unreachable;
|
||||
// }
|
||||
// bb8: { // binding1 and guard
|
||||
// StorageLive(_5);
|
||||
// _5 = &((_2 as Some).0: i32);
|
||||
// StorageLive(_8);
|
||||
// _8 = const guard() -> [return: bb9, unwind: bb1];
|
||||
// }
|
||||
// bb9: { // end of guard
|
||||
// switchInt(move _8) -> [false: bb10, otherwise: bb11];
|
||||
// }
|
||||
// bb10: { // to pre_binding3 (can skip 2 since this is `Some`)
|
||||
// falseEdges -> [real: bb5, imaginary: bb4];
|
||||
// }
|
||||
// bb11: { // arm1
|
||||
// StorageLive(_3);
|
||||
// _3 = ((_2 as Some).0: i32);
|
||||
// StorageLive(_11);
|
||||
// _11 = _3;
|
||||
// _1 = (const 1i32, move _11);
|
||||
// StorageDead(_11);
|
||||
// goto -> bb13;
|
||||
// }
|
||||
// bb12: { // binding3 and arm3
|
||||
// StorageLive(_6);
|
||||
// _6 = ((_2 as Some).0: i32);
|
||||
// StorageLive(_12);
|
||||
// _12 = _6;
|
||||
// _1 = (const 2i32, move _12);
|
||||
// StorageDead(_12);
|
||||
// goto -> bb13;
|
||||
// }
|
||||
// bb13: {
|
||||
// bb8: {
|
||||
// ...
|
||||
// return;
|
||||
// }
|
||||
// bb9: { // binding1 and guard
|
||||
// StorageLive(_8);
|
||||
// _8 = &((_2 as Some).0: i32);
|
||||
// _4 = &shallow _2;
|
||||
// _5 = &((_2 as Some).0: i32);
|
||||
// StorageLive(_9);
|
||||
// _9 = const guard() -> [return: bb10, unwind: bb1];
|
||||
// }
|
||||
// bb10: { // end of guard
|
||||
// FakeRead(ForMatchGuard, _4);
|
||||
// FakeRead(ForMatchGuard, _5);
|
||||
// switchInt(move _9) -> [false: bb6, otherwise: bb11];
|
||||
// }
|
||||
// bb11: { // arm1
|
||||
// StorageLive(_6);
|
||||
// _6 = ((_2 as Some).0: i32);
|
||||
// StorageLive(_10);
|
||||
// _10 = _6;
|
||||
// _1 = (const 1i32, move _10);
|
||||
// StorageDead(_10);
|
||||
// goto -> bb8;
|
||||
// }
|
||||
// bb12: { // arm2
|
||||
// _1 = (const 3i32, const 3i32);
|
||||
// goto -> bb8;
|
||||
// }
|
||||
// bb13: { // binding3 and arm3
|
||||
// StorageLive(_11);
|
||||
// _11 = ((_2 as Some).0: i32);
|
||||
// StorageLive(_12);
|
||||
// _12 = _11;
|
||||
// _1 = (const 2i32, move _12);
|
||||
// StorageDead(_12);
|
||||
// goto -> bb8;
|
||||
// }
|
||||
// END rustc.full_tested_match2.QualifyAndPromoteConstants.before.mir
|
||||
//
|
||||
// START rustc.main.QualifyAndPromoteConstants.before.mir
|
||||
// bb0: {
|
||||
// ...
|
||||
// _2 = std::option::Option<i32>::Some(const 1i32,);
|
||||
// FakeRead(ForMatchedPlace, _2);
|
||||
// _11 = discriminant(_2);
|
||||
// _16 = &shallow _2;
|
||||
// _17 = &((_2 as Some).0: i32);
|
||||
// switchInt(move _11) -> [1isize: bb2, otherwise: bb3];
|
||||
// }
|
||||
// bb1: {
|
||||
// resume;
|
||||
// }
|
||||
// bb2: {
|
||||
// FakeRead(ForMatchGuard, _16);
|
||||
// FakeRead(ForMatchGuard, _17);
|
||||
// falseEdges -> [real: bb7, imaginary: bb3]; //pre_binding1
|
||||
// }
|
||||
// bb3: {
|
||||
// FakeRead(ForMatchGuard, _16);
|
||||
// FakeRead(ForMatchGuard, _17);
|
||||
// falseEdges -> [real: bb11, imaginary: bb4]; //pre_binding2
|
||||
// }
|
||||
// bb4: {
|
||||
// FakeRead(ForMatchGuard, _16);
|
||||
// FakeRead(ForMatchGuard, _17);
|
||||
// falseEdges -> [real: bb12, imaginary: bb5]; //pre_binding3
|
||||
// }
|
||||
// bb5: {
|
||||
// FakeRead(ForMatchGuard, _16);
|
||||
// FakeRead(ForMatchGuard, _17);
|
||||
// falseEdges -> [real: bb16, imaginary: bb6]; //pre_binding4
|
||||
// }
|
||||
// bb6: {
|
||||
// unreachable;
|
||||
// }
|
||||
// bb7: { // binding1: Some(w) if guard()
|
||||
// StorageLive(_5);
|
||||
// _5 = &((_2 as Some).0: i32);
|
||||
// StorageLive(_12);
|
||||
// _12 = const guard() -> [return: bb8, unwind: bb1];
|
||||
// }
|
||||
// bb8: { //end of guard
|
||||
// switchInt(move _12) -> [false: bb9, otherwise: bb10];
|
||||
// }
|
||||
// bb9: { // to pre_binding2
|
||||
// falseEdges -> [real: bb3, imaginary: bb3];
|
||||
// }
|
||||
// bb10: { // set up bindings for arm1
|
||||
// StorageLive(_3);
|
||||
// _3 = ((_2 as Some).0: i32);
|
||||
// _1 = const 1i32;
|
||||
// goto -> bb17;
|
||||
// }
|
||||
// bb11: { // binding2 & arm2
|
||||
// StorageLive(_6);
|
||||
// _6 = _2;
|
||||
// _1 = const 2i32;
|
||||
// goto -> bb17;
|
||||
// }
|
||||
// bb12: { // binding3: Some(y) if guard2(y)
|
||||
// StorageLive(_9);
|
||||
// _9 = &((_2 as Some).0: i32);
|
||||
// StorageLive(_14);
|
||||
// StorageLive(_15);
|
||||
// _15 = (*_9);
|
||||
// _14 = const guard2(move _15) -> [return: bb13, unwind: bb1];
|
||||
// }
|
||||
// bb13: { // end of guard2
|
||||
// StorageDead(_15);
|
||||
// switchInt(move _14) -> [false: bb14, otherwise: bb15];
|
||||
// }
|
||||
// bb14: { // to pre_binding4
|
||||
// falseEdges -> [real: bb5, imaginary: bb5];
|
||||
// }
|
||||
// bb15: { // set up bindings for arm3
|
||||
// StorageLive(_7);
|
||||
// _7 = ((_2 as Some).0: i32);
|
||||
// _1 = const 3i32;
|
||||
// goto -> bb17;
|
||||
// }
|
||||
// bb16: { // binding4 & arm4
|
||||
// StorageLive(_10);
|
||||
// _10 = _2;
|
||||
// _1 = const 4i32;
|
||||
// goto -> bb17;
|
||||
// }
|
||||
// bb17: {
|
||||
// ...
|
||||
// return;
|
||||
// }
|
||||
// _2 = std::option::Option<i32>::Some(const 1i32,);
|
||||
// FakeRead(ForMatchedPlace, _2);
|
||||
// _3 = discriminant(_2);
|
||||
// switchInt(move _3) -> [1isize: bb2, otherwise: bb3];
|
||||
// }
|
||||
// bb1: {
|
||||
// resume;
|
||||
// }
|
||||
// bb2: {
|
||||
// falseEdges -> [real: bb10, imaginary: bb3]; //pre_binding1
|
||||
// }
|
||||
// bb3: {
|
||||
// falseEdges -> [real: bb13, imaginary: bb4]; //pre_binding2
|
||||
// }
|
||||
// bb4: {
|
||||
// falseEdges -> [real: bb14, imaginary: bb5]; //pre_binding3
|
||||
// }
|
||||
// bb5: {
|
||||
// falseEdges -> [real: bb17, imaginary: bb6]; //pre_binding4
|
||||
// }
|
||||
// bb6: {
|
||||
// unreachable;
|
||||
// }
|
||||
// bb7: { // to pre_binding2
|
||||
// falseEdges -> [real: bb3, imaginary: bb3];
|
||||
// }
|
||||
// bb8: { // to pre_binding4
|
||||
// falseEdges -> [real: bb5, imaginary: bb5];
|
||||
// }
|
||||
// bb9: {
|
||||
// ...
|
||||
// return;
|
||||
// }
|
||||
// bb10: { // binding1: Some(w) if guard()
|
||||
// StorageLive(_9);
|
||||
// _9 = &((_2 as Some).0: i32);
|
||||
// _5 = &shallow _2;
|
||||
// _6 = &((_2 as Some).0: i32);
|
||||
// StorageLive(_10);
|
||||
// _10 = const guard() -> [return: bb11, unwind: bb1];
|
||||
// }
|
||||
// bb11: { //end of guard
|
||||
// FakeRead(ForMatchGuard, _5);
|
||||
// FakeRead(ForMatchGuard, _6);
|
||||
// switchInt(move _10) -> [false: bb7, otherwise: bb12];
|
||||
// }
|
||||
// bb12: { // set up bindings for arm1
|
||||
// StorageLive(_7);
|
||||
// _7 = ((_2 as Some).0: i32);
|
||||
// _1 = const 1i32;
|
||||
// goto -> bb9;
|
||||
// }
|
||||
// bb13: { // binding2 & arm2
|
||||
// StorageLive(_11);
|
||||
// _11 = _2;
|
||||
// _1 = const 2i32;
|
||||
// goto -> bb9;
|
||||
// }
|
||||
// bb14: { // binding3: Some(y) if guard2(y)
|
||||
// StorageLive(_14);
|
||||
// _14 = &((_2 as Some).0: i32);
|
||||
// _5 = &shallow _2;
|
||||
// _6 = &((_2 as Some).0: i32);
|
||||
// StorageLive(_15);
|
||||
// StorageLive(_16);
|
||||
// _16 = (*_14);
|
||||
// _15 = const guard2(move _16) -> [return: bb15, unwind: bb1];
|
||||
// }
|
||||
// bb15: { // end of guard2
|
||||
// StorageDead(_16);
|
||||
// FakeRead(ForMatchGuard, _5);
|
||||
// FakeRead(ForMatchGuard, _6);
|
||||
// switchInt(move _15) -> [false: bb8, otherwise: bb16];
|
||||
// }
|
||||
// bb16: { // binding4 & arm4
|
||||
// StorageLive(_12);
|
||||
// _12 = ((_2 as Some).0: i32);
|
||||
// _1 = const 3i32;
|
||||
// goto -> bb9;
|
||||
// }
|
||||
// bb17: {
|
||||
// StorageLive(_17);
|
||||
// _17 = _2;
|
||||
// _1 = const 4i32;
|
||||
// goto -> bb9;
|
||||
// }
|
||||
// END rustc.main.QualifyAndPromoteConstants.before.mir
|
||||
|
@ -20,66 +20,67 @@ fn main() {
|
||||
// START rustc.main.SimplifyCfg-initial.after.mir
|
||||
// bb0: {
|
||||
// ...
|
||||
// _4 = Le(const 0i32, _1);
|
||||
// switchInt(move _4) -> [false: bb10, otherwise: bb11];
|
||||
// switchInt(move _4) -> [false: bb7, otherwise: bb8];
|
||||
// }
|
||||
// bb1: {
|
||||
// _3 = const 0i32;
|
||||
// goto -> bb16;
|
||||
// falseEdges -> [real: bb13, imaginary: bb2];
|
||||
// }
|
||||
// bb2: {
|
||||
// _3 = const 1i32;
|
||||
// goto -> bb16;
|
||||
// falseEdges -> [real: bb14, imaginary: bb3];
|
||||
// }
|
||||
// bb3: {
|
||||
// _3 = const 2i32;
|
||||
// goto -> bb16;
|
||||
// falseEdges -> [real: bb15, imaginary: bb4];
|
||||
// }
|
||||
// bb4: {
|
||||
// _3 = const 3i32;
|
||||
// goto -> bb16;
|
||||
// falseEdges -> [real: bb16, imaginary: bb5];
|
||||
// }
|
||||
// bb5: {
|
||||
// falseEdges -> [real: bb12, imaginary: bb6];
|
||||
// }
|
||||
// bb6: {
|
||||
// falseEdges -> [real: bb2, imaginary: bb7];
|
||||
// }
|
||||
// bb7: {
|
||||
// falseEdges -> [real: bb3, imaginary: bb8];
|
||||
// }
|
||||
// bb8: {
|
||||
// falseEdges -> [real: bb4, imaginary: bb9];
|
||||
// }
|
||||
// bb9: {
|
||||
// unreachable;
|
||||
// }
|
||||
// bb6: {
|
||||
// falseEdges -> [real: bb4, imaginary: bb2];
|
||||
// }
|
||||
// bb7: {
|
||||
// _6 = Le(const 10i32, _1);
|
||||
// switchInt(move _6) -> [false: bb9, otherwise: bb10];
|
||||
// }
|
||||
// bb8: {
|
||||
// _5 = Lt(_1, const 10i32);
|
||||
// switchInt(move _5) -> [false: bb7, otherwise: bb1];
|
||||
// }
|
||||
// bb9: {
|
||||
// switchInt(_1) -> [-1i32: bb3, otherwise: bb4];
|
||||
// }
|
||||
// bb10: {
|
||||
// _7 = Le(const 10i32, _1);
|
||||
// switchInt(move _7) -> [false: bb14, otherwise: bb15];
|
||||
// _7 = Le(_1, const 20i32);
|
||||
// switchInt(move _7) -> [false: bb9, otherwise: bb2];
|
||||
// }
|
||||
// bb11: {
|
||||
// _5 = Lt(_1, const 10i32);
|
||||
// switchInt(move _5) -> [false: bb10, otherwise: bb5];
|
||||
// }
|
||||
// bb12: {
|
||||
// StorageLive(_6);
|
||||
// _6 = _2;
|
||||
// switchInt(move _6) -> [false: bb13, otherwise: bb1];
|
||||
// }
|
||||
// bb13: {
|
||||
// falseEdges -> [real: bb8, imaginary: bb6];
|
||||
// }
|
||||
// bb14: {
|
||||
// switchInt(_1) -> [-1i32: bb7, otherwise: bb8];
|
||||
// }
|
||||
// bb15: {
|
||||
// _8 = Le(_1, const 20i32);
|
||||
// switchInt(move _8) -> [false: bb14, otherwise: bb6];
|
||||
// }
|
||||
// bb16: {
|
||||
// StorageDead(_6);
|
||||
// ...
|
||||
// StorageDead(_8);
|
||||
// _0 = ();
|
||||
// StorageDead(_2);
|
||||
// StorageDead(_1);
|
||||
// return;
|
||||
// }
|
||||
// bb12: {
|
||||
// _3 = const 0i32;
|
||||
// goto -> bb11;
|
||||
// }
|
||||
// bb13: {
|
||||
// StorageLive(_8);
|
||||
// _8 = _2;
|
||||
// switchInt(move _8) -> [false: bb6, otherwise: bb12];
|
||||
// }
|
||||
// bb14: {
|
||||
// _3 = const 1i32;
|
||||
// goto -> bb11;
|
||||
// }
|
||||
// bb15: {
|
||||
// _3 = const 2i32;
|
||||
// goto -> bb11;
|
||||
// }
|
||||
// bb16: {
|
||||
// _3 = const 3i32;
|
||||
// goto -> bb11;
|
||||
// }
|
||||
// END rustc.main.SimplifyCfg-initial.after.mir
|
||||
|
@ -4,15 +4,15 @@
|
||||
|
||||
#![feature(nll)]
|
||||
|
||||
fn match_guard(x: Option<&&i32>) -> i32 {
|
||||
fn match_guard(x: Option<&&i32>, c: bool) -> i32 {
|
||||
match x {
|
||||
Some(0) if true => 0,
|
||||
Some(0) if c => 0,
|
||||
_ => 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match_guard(None);
|
||||
match_guard(None, true);
|
||||
}
|
||||
|
||||
// END RUST SOURCE
|
||||
@ -20,49 +20,48 @@ fn main() {
|
||||
// START rustc.match_guard.CleanFakeReadsAndBorrows.before.mir
|
||||
// bb0: {
|
||||
// FakeRead(ForMatchedPlace, _1);
|
||||
// _2 = discriminant(_1);
|
||||
// _3 = &shallow _1;
|
||||
// _4 = &shallow ((_1 as Some).0: &'<empty> &'<empty> i32);
|
||||
// _5 = &shallow (*((_1 as Some).0: &'<empty> &'<empty> i32));
|
||||
// _6 = &shallow (*(*((_1 as Some).0: &'<empty> &'<empty> i32)));
|
||||
// switchInt(move _2) -> [1isize: bb6, otherwise: bb4];
|
||||
// _3 = discriminant(_1);
|
||||
// switchInt(move _3) -> [1isize: bb5, otherwise: bb2];
|
||||
// }
|
||||
// bb1: {
|
||||
// _0 = const 0i32;
|
||||
// goto -> bb9;
|
||||
// goto -> bb8;
|
||||
// }
|
||||
// bb2: {
|
||||
// _0 = const 1i32;
|
||||
// goto -> bb9;
|
||||
// }
|
||||
// bb3: {
|
||||
// FakeRead(ForMatchGuard, _3);
|
||||
// FakeRead(ForMatchGuard, _4);
|
||||
// FakeRead(ForMatchGuard, _5);
|
||||
// FakeRead(ForMatchGuard, _6);
|
||||
// goto -> bb7;
|
||||
// unreachable;
|
||||
// }
|
||||
// bb4: {
|
||||
// FakeRead(ForMatchGuard, _3);
|
||||
// FakeRead(ForMatchGuard, _4);
|
||||
// FakeRead(ForMatchGuard, _5);
|
||||
// FakeRead(ForMatchGuard, _6);
|
||||
// goto -> bb2;
|
||||
// }
|
||||
// bb5: {
|
||||
// unreachable;
|
||||
// switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb1, otherwise: bb2];
|
||||
// }
|
||||
// bb6: {
|
||||
// switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb3, otherwise: bb4];
|
||||
// StorageDead(_8);
|
||||
// return;
|
||||
// }
|
||||
// bb7: {
|
||||
// goto -> bb1;
|
||||
// _0 = const 0i32;
|
||||
// goto -> bb6;
|
||||
// }
|
||||
// bb8: {
|
||||
// goto -> bb4;
|
||||
// _4 = &shallow _1;
|
||||
// _5 = &shallow ((_1 as Some).0: &'<empty> &'<empty> i32);
|
||||
// _6 = &shallow (*((_1 as Some).0: &'<empty> &'<empty> i32));
|
||||
// _7 = &shallow (*(*((_1 as Some).0: &'<empty> &'<empty> i32)));
|
||||
// StorageLive(_8);
|
||||
// _8 = _2;
|
||||
// FakeRead(ForMatchGuard, _4);
|
||||
// FakeRead(ForMatchGuard, _5);
|
||||
// FakeRead(ForMatchGuard, _6);
|
||||
// FakeRead(ForMatchGuard, _7);
|
||||
// switchInt(move _8) -> [false: bb4, otherwise: bb7];
|
||||
// }
|
||||
// bb9: {
|
||||
// return;
|
||||
// _0 = const 1i32;
|
||||
// goto -> bb6;
|
||||
// }
|
||||
// bb10: {
|
||||
// resume;
|
||||
@ -72,51 +71,50 @@ fn main() {
|
||||
// START rustc.match_guard.CleanFakeReadsAndBorrows.after.mir
|
||||
// bb0: {
|
||||
// nop;
|
||||
// _2 = discriminant(_1);
|
||||
// nop;
|
||||
// nop;
|
||||
// nop;
|
||||
// nop;
|
||||
// switchInt(move _2) -> [1isize: bb6, otherwise: bb4];
|
||||
// _3 = discriminant(_1);
|
||||
// switchInt(move _3) -> [1isize: bb5, otherwise: bb2];
|
||||
// }
|
||||
// bb1: {
|
||||
// _0 = const 0i32;
|
||||
// goto -> bb9;
|
||||
// goto -> bb8;
|
||||
// }
|
||||
// bb2: {
|
||||
// _0 = const 1i32;
|
||||
// goto -> bb9;
|
||||
// }
|
||||
// bb3: {
|
||||
// nop;
|
||||
// nop;
|
||||
// nop;
|
||||
// nop;
|
||||
// goto -> bb7;
|
||||
// unreachable;
|
||||
// }
|
||||
// bb4: {
|
||||
// nop;
|
||||
// nop;
|
||||
// nop;
|
||||
// nop;
|
||||
// goto -> bb2;
|
||||
// }
|
||||
// bb5: {
|
||||
// unreachable;
|
||||
// switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb1, otherwise: bb2];
|
||||
// }
|
||||
// bb6: {
|
||||
// switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb3, otherwise: bb4];
|
||||
// StorageDead(_8);
|
||||
// return;
|
||||
// }
|
||||
// bb7: {
|
||||
// goto -> bb1;
|
||||
// _0 = const 0i32;
|
||||
// goto -> bb6;
|
||||
// }
|
||||
// bb8: {
|
||||
// goto -> bb4;
|
||||
// nop;
|
||||
// nop;
|
||||
// nop;
|
||||
// nop;
|
||||
// StorageLive(_8);
|
||||
// _8 = _2;
|
||||
// nop;
|
||||
// nop;
|
||||
// nop;
|
||||
// nop;
|
||||
// switchInt(move _8) -> [false: bb4, otherwise: bb7];
|
||||
// }
|
||||
// bb9: {
|
||||
// return;
|
||||
// _0 = const 1i32;
|
||||
// goto -> bb6;
|
||||
// }
|
||||
// bb10: {
|
||||
// resume;
|
||||
// }
|
||||
// }
|
||||
// END rustc.match_guard.CleanFakeReadsAndBorrows.after.mir
|
||||
|
Loading…
x
Reference in New Issue
Block a user