diff options
| author | 许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com> | 2025-03-05 21:46:45 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-05 21:46:45 +0800 |
| commit | 9d1b2f7fda9845360c190b931a79acba495634e1 (patch) | |
| tree | 5b27a79b2d82485ec5848c8009330aa275fdb7c0 | |
| parent | 927c11fcb7fb5a4e0e7f97fb59e2bbed5ab77280 (diff) | |
| parent | e3e74bc89a958e36c658fa809d98b4dd66d53cf8 (diff) | |
| download | rust-9d1b2f7fda9845360c190b931a79acba495634e1.tar.gz rust-9d1b2f7fda9845360c190b931a79acba495634e1.zip | |
Rollup merge of #137875 - Zalathar:irrefutable, r=Nadrieril
mir_build: Integrate "simplification" steps into match-pair-tree creation The “simplification” step helps to prepare THIR patterns for lowering into MIR, and originally dates back to the earliest days of MIR in the compiler. Over time, various intermediate data structures have been introduced (e.g. `MatchPair`, later renamed to `MatchPairTree`) that reduce the need for a separate simplification step, because some of the necessary simplifications can be built into the construction of those intermediate structures instead. This PR continues that process to its logical conclusion and removes the simplification step entirely, by integrating its remaining responsibilities into match-pair-tree creation: flattening “irrefutable” nodes, collecting bindings/ascriptions in flat lists, and sorting or-patterns after other subpatterns. This has a few immediate benefits: - We can remove `TestCase::Irrefutable`, which was not allowed to exist after simplification, and was much larger than other test-case variants. - We can make `MatchPairTree::place` non-optional, because only irrefutable nodes could fail to have a place. In the future, this should also help with some ideas I have for simplifying how `AscribeUserType` and `ExpandedConstant` nodes are handled, by representing them as side-data keyed by THIR pattern ID, so that they are no longer their own kinds of THIR pattern node.
5 files changed, 168 insertions, 204 deletions
diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 10b43390eb2..c6f3e22e95f 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -6,27 +6,25 @@ use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use crate::builder::Builder; use crate::builder::expr::as_place::{PlaceBase, PlaceBuilder}; -use crate::builder::matches::{FlatPat, MatchPairTree, TestCase}; +use crate::builder::matches::{FlatPat, MatchPairTree, PatternExtraData, TestCase}; impl<'a, 'tcx> Builder<'a, 'tcx> { - /// Builds and returns [`MatchPairTree`] subtrees, one for each pattern in + /// Builds and pushes [`MatchPairTree`] subtrees, one for each pattern in /// `subpatterns`, representing the fields of a [`PatKind::Variant`] or /// [`PatKind::Leaf`]. /// /// Used internally by [`MatchPairTree::for_pattern`]. fn field_match_pairs( &mut self, + match_pairs: &mut Vec<MatchPairTree<'tcx>>, + extra_data: &mut PatternExtraData<'tcx>, place: PlaceBuilder<'tcx>, subpatterns: &[FieldPat<'tcx>], - ) -> Vec<MatchPairTree<'tcx>> { - subpatterns - .iter() - .map(|fieldpat| { - let place = - place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty)); - MatchPairTree::for_pattern(place, &fieldpat.pattern, self) - }) - .collect() + ) { + for fieldpat in subpatterns { + let place = place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty)); + MatchPairTree::for_pattern(place, &fieldpat.pattern, self, match_pairs, extra_data); + } } /// Builds [`MatchPairTree`] subtrees for the prefix/middle/suffix parts of an @@ -36,6 +34,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn prefix_slice_suffix( &mut self, match_pairs: &mut Vec<MatchPairTree<'tcx>>, + extra_data: &mut PatternExtraData<'tcx>, place: &PlaceBuilder<'tcx>, prefix: &[Pat<'tcx>], opt_slice: &Option<Box<Pat<'tcx>>>, @@ -56,11 +55,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ((prefix.len() + suffix.len()).try_into().unwrap(), false) }; - match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| { + for (idx, subpattern) in prefix.iter().enumerate() { let elem = ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false }; - MatchPairTree::for_pattern(place.clone_project(elem), subpattern, self) - })); + let place = place.clone_project(elem); + MatchPairTree::for_pattern(place, subpattern, self, match_pairs, extra_data) + } if let Some(subslice_pat) = opt_slice { let suffix_len = suffix.len() as u64; @@ -69,10 +69,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { to: if exact_size { min_length - suffix_len } else { suffix_len }, from_end: !exact_size, }); - match_pairs.push(MatchPairTree::for_pattern(subslice, subslice_pat, self)); + MatchPairTree::for_pattern(subslice, subslice_pat, self, match_pairs, extra_data); } - match_pairs.extend(suffix.iter().rev().enumerate().map(|(idx, subpattern)| { + for (idx, subpattern) in suffix.iter().rev().enumerate() { let end_offset = (idx + 1) as u64; let elem = ProjectionElem::ConstantIndex { offset: if exact_size { min_length - end_offset } else { end_offset }, @@ -80,19 +80,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { from_end: !exact_size, }; let place = place.clone_project(elem); - MatchPairTree::for_pattern(place, subpattern, self) - })); + MatchPairTree::for_pattern(place, subpattern, self, match_pairs, extra_data) + } } } impl<'tcx> MatchPairTree<'tcx> { /// Recursively builds a match pair tree for the given pattern and its /// subpatterns. - pub(in crate::builder) fn for_pattern( + pub(super) fn for_pattern( mut place_builder: PlaceBuilder<'tcx>, pattern: &Pat<'tcx>, cx: &mut Builder<'_, 'tcx>, - ) -> MatchPairTree<'tcx> { + match_pairs: &mut Vec<Self>, // Newly-created nodes are added to this vector + extra_data: &mut PatternExtraData<'tcx>, // Bindings/ascriptions are added here + ) { // Force the place type to the pattern's type. // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks? if let Some(resolved) = place_builder.resolve_upvar(cx) { @@ -113,64 +115,102 @@ impl<'tcx> MatchPairTree<'tcx> { place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty)); } + // Place can be none if the pattern refers to a non-captured place in a closure. let place = place_builder.try_to_place(cx); - let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None }; let mut subpairs = Vec::new(); let test_case = match pattern.kind { - PatKind::Wild | PatKind::Error(_) => default_irrefutable(), + PatKind::Wild | PatKind::Error(_) => None, - PatKind::Or { ref pats } => TestCase::Or { + PatKind::Or { ref pats } => Some(TestCase::Or { pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(), - }, + }), PatKind::Range(ref range) => { if range.is_full_range(cx.tcx) == Some(true) { - default_irrefutable() + None } else { - TestCase::Range(Arc::clone(range)) + Some(TestCase::Range(Arc::clone(range))) } } - PatKind::Constant { value } => TestCase::Constant { value }, + PatKind::Constant { value } => Some(TestCase::Constant { value }), PatKind::AscribeUserType { ascription: Ascription { ref annotation, variance }, ref subpattern, .. } => { + MatchPairTree::for_pattern( + place_builder, + subpattern, + cx, + &mut subpairs, + extra_data, + ); + // Apply the type ascription to the value at `match_pair.place` - let ascription = place.map(|source| super::Ascription { - annotation: annotation.clone(), - source, - variance, - }); - - subpairs.push(MatchPairTree::for_pattern(place_builder, subpattern, cx)); - TestCase::Irrefutable { ascription, binding: None } + if let Some(source) = place { + let annotation = annotation.clone(); + extra_data.ascriptions.push(super::Ascription { source, annotation, variance }); + } + + None } PatKind::Binding { mode, var, ref subpattern, .. } => { - let binding = place.map(|source| super::Binding { - span: pattern.span, - source, - var_id: var, - binding_mode: mode, - }); + // In order to please the borrow checker, when lowering a pattern + // like `x @ subpat` we must establish any bindings in `subpat` + // before establishing the binding for `x`. + // + // For example (from #69971): + // + // ```ignore (illustrative) + // struct NonCopyStruct { + // copy_field: u32, + // } + // + // fn foo1(x: NonCopyStruct) { + // let y @ NonCopyStruct { copy_field: z } = x; + // // the above should turn into + // let z = x.copy_field; + // let y = x; + // } + // ``` + // First, recurse into the subpattern, if any. if let Some(subpattern) = subpattern.as_ref() { // this is the `x @ P` case; have to keep matching against `P` now - subpairs.push(MatchPairTree::for_pattern(place_builder, subpattern, cx)); + MatchPairTree::for_pattern( + place_builder, + subpattern, + cx, + &mut subpairs, + extra_data, + ); } - TestCase::Irrefutable { ascription: None, binding } + + // Then push this binding, after any bindings in the subpattern. + if let Some(source) = place { + extra_data.bindings.push(super::Binding { + span: pattern.span, + source, + var_id: var, + binding_mode: mode, + }); + } + + None } PatKind::ExpandedConstant { subpattern: ref pattern, def_id: _, is_inline: false } => { - subpairs.push(MatchPairTree::for_pattern(place_builder, pattern, cx)); - default_irrefutable() + MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data); + None } PatKind::ExpandedConstant { subpattern: ref pattern, def_id, is_inline: true } => { + MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data); + // Apply a type ascription for the inline constant to the value at `match_pair.place` - let ascription = place.map(|source| { + if let Some(source) = place { let span = pattern.span; let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id()); let args = ty::InlineConstArgs::new( @@ -189,33 +229,47 @@ impl<'tcx> MatchPairTree<'tcx> { span, user_ty: Box::new(user_ty), }; - super::Ascription { annotation, source, variance: ty::Contravariant } - }); + let variance = ty::Contravariant; + extra_data.ascriptions.push(super::Ascription { annotation, source, variance }); + } - subpairs.push(MatchPairTree::for_pattern(place_builder, pattern, cx)); - TestCase::Irrefutable { ascription, binding: None } + None } PatKind::Array { ref prefix, ref slice, ref suffix } => { - cx.prefix_slice_suffix(&mut subpairs, &place_builder, prefix, slice, suffix); - default_irrefutable() + cx.prefix_slice_suffix( + &mut subpairs, + extra_data, + &place_builder, + prefix, + slice, + suffix, + ); + None } PatKind::Slice { ref prefix, ref slice, ref suffix } => { - cx.prefix_slice_suffix(&mut subpairs, &place_builder, prefix, slice, suffix); + cx.prefix_slice_suffix( + &mut subpairs, + extra_data, + &place_builder, + prefix, + slice, + suffix, + ); if prefix.is_empty() && slice.is_some() && suffix.is_empty() { - default_irrefutable() + None } else { - TestCase::Slice { + Some(TestCase::Slice { len: prefix.len() + suffix.len(), variable_length: slice.is_some(), - } + }) } } PatKind::Variant { adt_def, variant_index, args, ref subpatterns } => { let downcast_place = place_builder.downcast(adt_def, variant_index); // `(x as Variant)` - subpairs = cx.field_match_pairs(downcast_place, subpatterns); + cx.field_match_pairs(&mut subpairs, extra_data, downcast_place, subpatterns); let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| { i == variant_index @@ -225,21 +279,23 @@ impl<'tcx> MatchPairTree<'tcx> { .apply_ignore_module(cx.tcx, cx.infcx.typing_env(cx.param_env)) }) && (adt_def.did().is_local() || !adt_def.is_variant_list_non_exhaustive()); - if irrefutable { - default_irrefutable() - } else { - TestCase::Variant { adt_def, variant_index } - } + if irrefutable { None } else { Some(TestCase::Variant { adt_def, variant_index }) } } PatKind::Leaf { ref subpatterns } => { - subpairs = cx.field_match_pairs(place_builder, subpatterns); - default_irrefutable() + cx.field_match_pairs(&mut subpairs, extra_data, place_builder, subpatterns); + None } PatKind::Deref { ref subpattern } => { - subpairs.push(MatchPairTree::for_pattern(place_builder.deref(), subpattern, cx)); - default_irrefutable() + MatchPairTree::for_pattern( + place_builder.deref(), + subpattern, + cx, + &mut subpairs, + extra_data, + ); + None } PatKind::DerefPattern { ref subpattern, mutability } => { @@ -249,23 +305,32 @@ impl<'tcx> MatchPairTree<'tcx> { Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, subpattern.ty, mutability), pattern.span, ); - subpairs.push(MatchPairTree::for_pattern( + MatchPairTree::for_pattern( PlaceBuilder::from(temp).deref(), subpattern, cx, - )); - TestCase::Deref { temp, mutability } + &mut subpairs, + extra_data, + ); + Some(TestCase::Deref { temp, mutability }) } - PatKind::Never => TestCase::Never, + PatKind::Never => Some(TestCase::Never), }; - MatchPairTree { - place, - test_case, - subpairs, - pattern_ty: pattern.ty, - pattern_span: pattern.span, + if let Some(test_case) = test_case { + // This pattern is refutable, so push a new match-pair node. + match_pairs.push(MatchPairTree { + place: place.expect("refutable patterns should always have a place to inspect"), + test_case, + subpairs, + pattern_ty: pattern.ty, + pattern_span: pattern.span, + }) + } else { + // This pattern is irrefutable, so it doesn't need its own match-pair node. + // Just push its refutable subpatterns instead, if any. + match_pairs.extend(subpairs); } } } diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index d05d5b151ff..b05052a3455 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -26,7 +26,6 @@ use crate::builder::{ // helper functions, broken out by category: mod match_pair; -mod simplify; mod test; mod util; @@ -987,18 +986,16 @@ impl<'tcx> PatternExtraData<'tcx> { } /// A pattern in a form suitable for lowering the match tree, with all irrefutable -/// patterns simplified away, and or-patterns sorted to the end. +/// patterns simplified away. /// -/// Here, "flat" indicates that the pattern's match pairs have been recursively -/// simplified by [`Builder::simplify_match_pairs`]. They are not necessarily -/// flat in an absolute sense. +/// Here, "flat" indicates that irrefutable nodes in the pattern tree have been +/// recursively replaced with their refutable subpatterns. They are not +/// necessarily flat in an absolute sense. /// /// Will typically be incorporated into a [`Candidate`]. #[derive(Debug, Clone)] struct FlatPat<'tcx> { /// To match the pattern, all of these must be satisfied... - // Invariant: all the match pairs are recursively simplified. - // Invariant: or-patterns must be sorted to the end. match_pairs: Vec<MatchPairTree<'tcx>>, extra_data: PatternExtraData<'tcx>, @@ -1008,17 +1005,15 @@ impl<'tcx> FlatPat<'tcx> { /// Creates a `FlatPat` containing a simplified [`MatchPairTree`] list/forest /// for the given pattern. fn new(place: PlaceBuilder<'tcx>, pattern: &Pat<'tcx>, cx: &mut Builder<'_, 'tcx>) -> Self { - // First, recursively build a tree of match pairs for the given pattern. - let mut match_pairs = vec![MatchPairTree::for_pattern(place, pattern, cx)]; + // Recursively build a tree of match pairs for the given pattern. + let mut match_pairs = vec![]; let mut extra_data = PatternExtraData { span: pattern.span, bindings: Vec::new(), ascriptions: Vec::new(), is_never: pattern.is_never_pattern(), }; - // Recursively remove irrefutable match pairs, while recording their - // bindings/ascriptions, and sort or-patterns after other match pairs. - cx.simplify_match_pairs(&mut match_pairs, &mut extra_data); + MatchPairTree::for_pattern(place, pattern, cx, &mut match_pairs, &mut extra_data); Self { match_pairs, extra_data } } @@ -1055,7 +1050,6 @@ struct Candidate<'tcx> { /// (see [`Builder::test_remaining_match_pairs_after_or`]). /// /// Invariants: - /// - All [`TestCase::Irrefutable`] patterns have been removed by simplification. /// - All or-patterns ([`TestCase::Or`]) have been sorted to the end. match_pairs: Vec<MatchPairTree<'tcx>>, @@ -1126,7 +1120,7 @@ impl<'tcx> Candidate<'tcx> { /// Incorporates an already-simplified [`FlatPat`] into a new candidate. fn from_flat_pat(flat_pat: FlatPat<'tcx>, has_guard: bool) -> Self { - Candidate { + let mut this = Candidate { match_pairs: flat_pat.match_pairs, extra_data: flat_pat.extra_data, has_guard, @@ -1135,7 +1129,14 @@ impl<'tcx> Candidate<'tcx> { otherwise_block: None, pre_binding_block: None, false_edge_start_block: None, - } + }; + this.sort_match_pairs(); + this + } + + /// Restores the invariant that or-patterns must be sorted to the end. + fn sort_match_pairs(&mut self) { + self.match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. })); } /// Returns whether the first match pair of this candidate is an or-pattern. @@ -1227,17 +1228,11 @@ struct Ascription<'tcx> { /// - [`Builder::pick_test_for_match_pair`] (to choose a test) /// - [`Builder::sort_candidate`] (to see how the test interacts with a match pair) /// -/// Two variants are unlike the others and deserve special mention: -/// -/// - [`Self::Irrefutable`] is only used temporarily when building a [`MatchPairTree`]. -/// They are then flattened away by [`Builder::simplify_match_pairs`], with any -/// bindings/ascriptions incorporated into the enclosing [`FlatPat`]. -/// - [`Self::Or`] are not tested directly like the other variants. Instead they -/// participate in or-pattern expansion, where they are transformed into subcandidates. -/// - See [`Builder::expand_and_match_or_candidates`]. +/// Note that or-patterns are not tested directly like the other variants. +/// Instead they participate in or-pattern expansion, where they are transformed into +/// subcandidates. See [`Builder::expand_and_match_or_candidates`]. #[derive(Debug, Clone)] enum TestCase<'tcx> { - Irrefutable { binding: Option<Binding<'tcx>>, ascription: Option<Ascription<'tcx>> }, Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx }, Constant { value: mir::Const<'tcx> }, Range(Arc<PatRange<'tcx>>), @@ -1261,19 +1256,9 @@ impl<'tcx> TestCase<'tcx> { #[derive(Debug, Clone)] pub(crate) struct MatchPairTree<'tcx> { /// This place... - /// - /// --- - /// This can be `None` if it referred to a non-captured place in a closure. - /// - /// Invariant: Can only be `None` when `test_case` is `Irrefutable`. - /// Therefore this must be `Some(_)` after simplification. - place: Option<Place<'tcx>>, + place: Place<'tcx>, /// ... must pass this test... - /// - /// --- - /// Invariant: after creation and simplification in [`FlatPat::new`], - /// this must not be [`TestCase::Irrefutable`]. test_case: TestCase<'tcx>, /// ... and these subpairs must match. @@ -2091,11 +2076,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Extract the match-pair from the highest priority candidate let match_pair = &candidates[0].match_pairs[0]; let test = self.pick_test_for_match_pair(match_pair); - // Unwrap is ok after simplification. - let match_place = match_pair.place.unwrap(); debug!(?test, ?match_pair); - (match_place, test) + (match_pair.place, test) } /// Given a test, we partition the input candidates into several buckets. diff --git a/compiler/rustc_mir_build/src/builder/matches/simplify.rs b/compiler/rustc_mir_build/src/builder/matches/simplify.rs deleted file mode 100644 index 15c860151dc..00000000000 --- a/compiler/rustc_mir_build/src/builder/matches/simplify.rs +++ /dev/null @@ -1,71 +0,0 @@ -//! Simplifying Candidates -//! -//! *Simplifying* a match pair `place @ pattern` means breaking it down -//! into bindings or other, simpler match pairs. For example: -//! -//! - `place @ (P1, P2)` can be simplified to `[place.0 @ P1, place.1 @ P2]` -//! - `place @ x` can be simplified to `[]` by binding `x` to `place` -//! -//! The `simplify_match_pairs` routine just repeatedly applies these -//! sort of simplifications until there is nothing left to -//! simplify. Match pairs cannot be simplified if they require some -//! sort of test: for example, testing which variant an enum is, or -//! testing a value against a constant. - -use std::mem; - -use tracing::{debug, instrument}; - -use crate::builder::Builder; -use crate::builder::matches::{MatchPairTree, PatternExtraData, TestCase}; - -impl<'a, 'tcx> Builder<'a, 'tcx> { - /// Simplify a list of match pairs so they all require a test. Stores relevant bindings and - /// ascriptions in `extra_data`. - #[instrument(skip(self), level = "debug")] - pub(super) fn simplify_match_pairs( - &mut self, - match_pairs: &mut Vec<MatchPairTree<'tcx>>, - extra_data: &mut PatternExtraData<'tcx>, - ) { - // In order to please the borrow checker, in a pattern like `x @ pat` we must lower the - // bindings in `pat` before `x`. E.g. (#69971): - // - // struct NonCopyStruct { - // copy_field: u32, - // } - // - // fn foo1(x: NonCopyStruct) { - // let y @ NonCopyStruct { copy_field: z } = x; - // // the above should turn into - // let z = x.copy_field; - // let y = x; - // } - // - // 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, extra_data); - if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case { - if let Some(binding) = binding { - extra_data.bindings.push(binding); - } - if let Some(ascription) = ascription { - extra_data.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); - } - } - - // 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. - match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. })); - debug!(simplified = ?match_pairs, "simplify_match_pairs"); - } -} diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index a7a028bff97..e5d61bc9e55 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -55,12 +55,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Or-patterns are not tested directly; instead they are expanded into subcandidates, // which are then distinguished by testing whatever non-or patterns they contain. TestCase::Or { .. } => bug!("or-patterns should have already been handled"), - - TestCase::Irrefutable { .. } => span_bug!( - match_pair.pattern_span, - "simplifiable pattern found: {:?}", - match_pair.pattern_span - ), }; Test { span: match_pair.pattern_span, kind } @@ -546,11 +540,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // 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 (match_pair_index, match_pair) = candidate - .match_pairs - .iter() - .enumerate() - .find(|&(_, mp)| mp.place == Some(test_place))?; + let (match_pair_index, match_pair) = + candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == test_place)?; // If true, the match pair is completely entailed by its corresponding test // branch, so it can be removed. If false, the match pair is _compatible_ @@ -593,7 +584,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate .match_pairs .iter() - .any(|mp| mp.place == Some(test_place) && is_covering_range(&mp.test_case)) + .any(|mp| mp.place == test_place && is_covering_range(&mp.test_case)) }; if sorted_candidates .get(&TestBranch::Failure) @@ -769,7 +760,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let match_pair = candidate.match_pairs.remove(match_pair_index); candidate.match_pairs.extend(match_pair.subpairs); // Move or-patterns to the end. - candidate.match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. })); + candidate.sort_match_pairs(); } ret diff --git a/compiler/rustc_mir_build/src/builder/matches/util.rs b/compiler/rustc_mir_build/src/builder/matches/util.rs index 589e350a03f..ed3b652e4ef 100644 --- a/compiler/rustc_mir_build/src/builder/matches/util.rs +++ b/compiler/rustc_mir_build/src/builder/matches/util.rs @@ -173,14 +173,10 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { // } // ``` // Hence we fake borrow using a deep borrow. - if let Some(place) = match_pair.place { - self.fake_borrow(place, FakeBorrowKind::Deep); - } + self.fake_borrow(match_pair.place, FakeBorrowKind::Deep); } else { // Insert a Shallow borrow of any place that is switched on. - if let Some(place) = match_pair.place { - self.fake_borrow(place, FakeBorrowKind::Shallow); - } + self.fake_borrow(match_pair.place, FakeBorrowKind::Shallow); for subpair in &match_pair.subpairs { self.visit_match_pair(subpair); |
