diff options
Diffstat (limited to 'compiler/rustc_mir_build/src/build/matches/simplify.rs')
| -rw-r--r-- | compiler/rustc_mir_build/src/build/matches/simplify.rs | 70 | 
1 files changed, 20 insertions, 50 deletions
| diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 53a5056cc3f..b5f0a97b28a 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -43,60 +43,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // let y = x; // } // - // We can't just reverse the binding order, because we must preserve pattern-order - // otherwise, e.g. in `let (Some(a), Some(b)) = (x, y)`. Our rule then is: deepest-first, - // and bindings at the same depth stay in source order. - // - // To do this, every time around the loop we prepend the newly found bindings to the - // bindings we already had. - // - // example: - // candidate.bindings = [1, 2, 3] - // bindings in iter 1: [4, 5] - // bindings in iter 2: [6, 7] - // - // final bindings: [6, 7, 4, 5, 1, 2, 3] - let mut accumulated_bindings = mem::take(candidate_bindings); - let mut simplified_match_pairs = Vec::new(); - // Repeatedly simplify match pairs until we're left with only unsimplifiable ones. - loop { - for mut match_pair in mem::take(match_pairs) { - if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case { - if let Some(binding) = binding { - candidate_bindings.push(binding); - } - if let Some(ascription) = ascription { - candidate_ascriptions.push(ascription); - } - // Simplifiable pattern; we replace it with its subpairs and simplify further. - match_pairs.append(&mut match_pair.subpairs); - } else { - // Unsimplifiable pattern; we recursively simplify its subpairs and don't - // process it further. - self.simplify_match_pairs( - &mut match_pair.subpairs, - candidate_bindings, - candidate_ascriptions, - ); - simplified_match_pairs.push(match_pair); + // We therefore lower bindings from left-to-right, except we lower the `x` in `x @ pat` + // after any bindings in `pat`. This doesn't work for or-patterns: the current structure of + // match lowering forces us to lower bindings inside or-patterns last. + for mut match_pair in mem::take(match_pairs) { + self.simplify_match_pairs( + &mut match_pair.subpairs, + candidate_bindings, + candidate_ascriptions, + ); + if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case { + if let Some(binding) = binding { + candidate_bindings.push(binding); } - } - - // This does: accumulated_bindings = candidate.bindings.take() ++ accumulated_bindings - candidate_bindings.extend_from_slice(&accumulated_bindings); - mem::swap(candidate_bindings, &mut accumulated_bindings); - candidate_bindings.clear(); - - if match_pairs.is_empty() { - break; + if let Some(ascription) = ascription { + candidate_ascriptions.push(ascription); + } + // Simplifiable pattern; we replace it with its already simplified subpairs. + match_pairs.append(&mut match_pair.subpairs); + } else { + // Unsimplifiable pattern; we keep it. + match_pairs.push(match_pair); } } - // Store computed bindings back in `candidate_bindings`. - mem::swap(candidate_bindings, &mut accumulated_bindings); - // Store simplified match pairs back in `match_pairs`. - mem::swap(match_pairs, &mut simplified_match_pairs); - // Move or-patterns to the end, because they can result in us // creating additional candidates, so we want to test them as // late as possible. | 
