about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNadrieril <nadrieril+git@gmail.com>2024-01-21 21:38:24 +0100
committerNadrieril <nadrieril+git@gmail.com>2024-02-19 21:28:26 +0100
commite86c82296f26454d7451d64586062b59c9b62d22 (patch)
tree30172dc5418b1fcbab19114c9f3d49cd799c5e34
parentbafad5a737a2afac7926cc0ead6c9f76baf089cb (diff)
downloadrust-e86c82296f26454d7451d64586062b59c9b62d22.tar.gz
rust-e86c82296f26454d7451d64586062b59c9b62d22.zip
Make `simplify_candidate` more general
Because we will soon need to apply it to match pairs that aren't
directly in a candidate.
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs9
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs95
2 files changed, 56 insertions, 48 deletions
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index b35a0c3c671..bb307089f1c 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -1168,7 +1168,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // be a switch or pattern comparison.
         let mut split_or_candidate = false;
         for candidate in &mut *candidates {
-            self.simplify_candidate(candidate);
+            self.simplify_match_pairs(
+                &mut candidate.match_pairs,
+                &mut candidate.bindings,
+                &mut candidate.ascriptions,
+            );
             if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place, .. }] =
                 &*candidate.match_pairs
             {
@@ -1181,7 +1185,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // }
                 //
                 // only generates a single switch.
-                candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats);
+                candidate.subcandidates =
+                    self.create_or_subcandidates(place, pats, candidate.has_guard);
                 candidate.match_pairs.pop();
                 split_or_candidate = true;
             }
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index a74b664441a..040d38c109b 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -6,7 +6,7 @@
 //! - `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_candidate` routine just repeatedly applies these
+//! 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
@@ -22,10 +22,15 @@ use rustc_middle::ty;
 use std::mem;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    /// Simplify a candidate so that all match pairs require a test.
-    #[instrument(skip(self, candidate), level = "debug")]
-    pub(super) fn simplify_candidate<'pat>(&mut self, candidate: &mut Candidate<'pat, 'tcx>) {
-        debug!("{candidate:#?}");
+    /// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
+    /// ascriptions in the provided `Vec`s.
+    #[instrument(skip(self), level = "debug")]
+    pub(super) fn simplify_match_pairs<'pat>(
+        &mut self,
+        match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
+        candidate_bindings: &mut Vec<Binding<'tcx>>,
+        candidate_ascriptions: &mut Vec<Ascription<'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):
         //
@@ -53,25 +58,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // bindings in iter 2: [6, 7]
         //
         // final bindings: [6, 7, 4, 5, 1, 2, 3]
-        let mut accumulated_bindings = mem::take(&mut candidate.bindings);
+        let mut accumulated_bindings = mem::take(candidate_bindings);
         // Repeatedly simplify match pairs until fixed point is reached
         loop {
             let mut changed = false;
-            for match_pair in mem::take(&mut candidate.match_pairs) {
-                match self.simplify_match_pair(match_pair, candidate) {
+            for match_pair in mem::take(match_pairs) {
+                match self.simplify_match_pair(
+                    match_pair,
+                    candidate_bindings,
+                    candidate_ascriptions,
+                    match_pairs,
+                ) {
                     Ok(()) => {
                         changed = true;
                     }
                     Err(match_pair) => {
-                        candidate.match_pairs.push(match_pair);
+                        match_pairs.push(match_pair);
                     }
                 }
             }
 
             // This does: accumulated_bindings = candidate.bindings.take() ++ accumulated_bindings
-            candidate.bindings.extend_from_slice(&accumulated_bindings);
-            mem::swap(&mut candidate.bindings, &mut accumulated_bindings);
-            candidate.bindings.clear();
+            candidate_bindings.extend_from_slice(&accumulated_bindings);
+            mem::swap(candidate_bindings, &mut accumulated_bindings);
+            candidate_bindings.clear();
 
             if !changed {
                 // If we were not able to simplify anymore, done.
@@ -79,14 +89,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         }
 
-        // Store computed bindings back in `candidate`.
-        mem::swap(&mut candidate.bindings, &mut accumulated_bindings);
+        // Store computed bindings back in `candidate_bindings`.
+        mem::swap(candidate_bindings, &mut accumulated_bindings);
 
         // 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.
-        candidate.match_pairs.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
-        debug!(simplified = ?candidate, "simplify_candidate");
+        match_pairs.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
+        debug!(simplified = ?match_pairs, "simplify_match_pairs");
     }
 
     /// Given `candidate` that has a single or-pattern for its match-pairs,
@@ -94,19 +104,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// `pats`.
     pub(super) fn create_or_subcandidates<'pat>(
         &mut self,
-        candidate: &Candidate<'pat, 'tcx>,
         place: &PlaceBuilder<'tcx>,
         pats: &'pat [Box<Pat<'tcx>>],
+        has_guard: bool,
     ) -> Vec<Candidate<'pat, 'tcx>> {
         pats.iter()
             .map(|box pat| {
-                let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard, self);
-                self.simplify_candidate(&mut candidate);
+                let mut candidate = Candidate::new(place.clone(), pat, has_guard, self);
+                self.simplify_match_pairs(
+                    &mut candidate.match_pairs,
+                    &mut candidate.bindings,
+                    &mut candidate.ascriptions,
+                );
 
                 if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place, .. }] =
                     &*candidate.match_pairs
                 {
-                    candidate.subcandidates = self.create_or_subcandidates(&candidate, place, pats);
+                    candidate.subcandidates =
+                        self.create_or_subcandidates(place, pats, candidate.has_guard);
                     candidate.match_pairs.pop();
                 }
                 candidate
@@ -122,7 +137,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn simplify_match_pair<'pat>(
         &mut self,
         match_pair: MatchPair<'pat, 'tcx>,
-        candidate: &mut Candidate<'pat, 'tcx>,
+        bindings: &mut Vec<Binding<'tcx>>,
+        ascriptions: &mut Vec<Ascription<'tcx>>,
+        match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
     ) -> Result<(), MatchPair<'pat, 'tcx>> {
         match match_pair.pattern.kind {
             PatKind::AscribeUserType {
@@ -131,14 +148,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             } => {
                 // Apply the type ascription to the value at `match_pair.place`
                 if let Some(source) = match_pair.place.try_to_place(self) {
-                    candidate.ascriptions.push(Ascription {
+                    ascriptions.push(Ascription {
                         annotation: annotation.clone(),
                         source,
                         variance,
                     });
                 }
 
-                candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
+                match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
 
                 Ok(())
             }
@@ -158,7 +175,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 is_primary: _,
             } => {
                 if let Some(source) = match_pair.place.try_to_place(self) {
-                    candidate.bindings.push(Binding {
+                    bindings.push(Binding {
                         span: match_pair.pattern.span,
                         source,
                         var_id: var,
@@ -168,7 +185,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 if let Some(subpattern) = subpattern.as_ref() {
                     // this is the `x @ P` case; have to keep matching against `P` now
-                    candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
+                    match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
                 }
 
                 Ok(())
@@ -211,13 +228,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         span,
                         user_ty: Box::new(user_ty),
                     };
-                    candidate.ascriptions.push(Ascription {
+                    ascriptions.push(Ascription {
                         annotation,
                         source,
                         variance: ty::Contravariant,
                     });
                 }
-                candidate.match_pairs.push(MatchPair::new(match_pair.place, pattern, self));
+                match_pairs.push(MatchPair::new(match_pair.place, pattern, self));
 
                 Ok(())
             }
@@ -233,13 +250,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             PatKind::Slice { ref prefix, ref slice, ref suffix } => {
                 if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
                     // irrefutable
-                    self.prefix_slice_suffix(
-                        &mut candidate.match_pairs,
-                        &match_pair.place,
-                        prefix,
-                        slice,
-                        suffix,
-                    );
+                    self.prefix_slice_suffix(match_pairs, &match_pair.place, prefix, slice, suffix);
                     Ok(())
                 } else {
                     Err(match_pair)
@@ -260,9 +271,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     || !adt_def.is_variant_list_non_exhaustive());
                 if irrefutable {
                     let place_builder = match_pair.place.downcast(adt_def, variant_index);
-                    candidate
-                        .match_pairs
-                        .extend(self.field_match_pairs(place_builder, subpatterns));
+                    match_pairs.extend(self.field_match_pairs(place_builder, subpatterns));
                     Ok(())
                 } else {
                     Err(match_pair)
@@ -270,25 +279,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
 
             PatKind::Array { ref prefix, ref slice, ref suffix } => {
-                self.prefix_slice_suffix(
-                    &mut candidate.match_pairs,
-                    &match_pair.place,
-                    prefix,
-                    slice,
-                    suffix,
-                );
+                self.prefix_slice_suffix(match_pairs, &match_pair.place, prefix, slice, suffix);
                 Ok(())
             }
 
             PatKind::Leaf { ref subpatterns } => {
                 // tuple struct, match subpats (if any)
-                candidate.match_pairs.extend(self.field_match_pairs(match_pair.place, subpatterns));
+                match_pairs.extend(self.field_match_pairs(match_pair.place, subpatterns));
                 Ok(())
             }
 
             PatKind::Deref { ref subpattern } => {
                 let place_builder = match_pair.place.deref();
-                candidate.match_pairs.push(MatchPair::new(place_builder, subpattern, self));
+                match_pairs.push(MatchPair::new(place_builder, subpattern, self));
                 Ok(())
             }