]> git.lizzy.rs Git - rust.git/commitdiff
Avoid double-deref in `Fields`
authorNadrieril <nadrieril+git@gmail.com>
Sat, 25 Sep 2021 16:46:44 +0000 (17:46 +0100)
committerNadrieril <nadrieril+git@gmail.com>
Sat, 25 Sep 2021 23:30:39 +0000 (00:30 +0100)
compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

index b217aa7cc3f39533650f171f3799c54fb843cd1a..a69f5de372759cebef14e8f888079db9331db925 100644 (file)
@@ -62,7 +62,6 @@
 use rustc_target::abi::{Integer, Size, VariantIdx};
 
 use smallvec::{smallvec, SmallVec};
-use std::borrow::Cow;
 use std::cmp::{self, max, min, Ordering};
 use std::fmt;
 use std::iter::{once, IntoIterator};
@@ -1107,33 +1106,27 @@ pub(super) fn iter_missing<'a, 'p>(
 /// because the code mustn't observe that it is uninhabited. In that case that field is not
 /// included in `fields`. For that reason, when you have a `mir::Field` you must use
 /// `index_with_declared_idx`.
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Copy)]
 pub(super) struct Fields<'p, 'tcx> {
-    fields: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
+    fields: &'p [DeconstructedPat<'p, 'tcx>],
 }
 
 impl<'p, 'tcx> Fields<'p, 'tcx> {
     fn empty() -> Self {
-        Fields { fields: SmallVec::new() }
+        Fields { fields: &[] }
     }
 
     fn singleton(cx: &MatchCheckCtxt<'p, 'tcx>, field: DeconstructedPat<'p, 'tcx>) -> Self {
         let field: &_ = cx.pattern_arena.alloc(field);
-        Fields { fields: smallvec![field] }
+        Fields { fields: std::slice::from_ref(field) }
     }
 
     pub(super) fn from_iter(
         cx: &MatchCheckCtxt<'p, 'tcx>,
         fields: impl IntoIterator<Item = DeconstructedPat<'p, 'tcx>>,
     ) -> Self {
-        let fields: &_ = cx.pattern_arena.alloc_from_iter(fields);
-        Fields { fields: fields.into_iter().collect() }
-    }
-
-    pub(super) fn from_ref_iter(
-        fields: impl IntoIterator<Item = &'p DeconstructedPat<'p, 'tcx>>,
-    ) -> Self {
-        Fields { fields: fields.into_iter().collect() }
+        let fields: &[_] = cx.pattern_arena.alloc_from_iter(fields);
+        Fields { fields }
     }
 
     fn wildcards_from_tys(
@@ -1222,7 +1215,7 @@ pub(super) fn wildcards(
     pub(super) fn iter_patterns<'a>(
         &'a self,
     ) -> impl Iterator<Item = &'p DeconstructedPat<'p, 'tcx>> + Captures<'a> {
-        self.fields.iter().copied()
+        self.fields.iter()
     }
 }
 
@@ -1245,9 +1238,8 @@ pub(super) fn new(ctor: Constructor<'tcx>, fields: Fields<'p, 'tcx>, ty: Ty<'tcx
 
     pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self {
         let mkpat = |pat| DeconstructedPat::from_pat(cx, pat);
-        let allocpat = |pat| &*cx.pattern_arena.alloc(mkpat(pat));
         let ctor;
-        let mut fields;
+        let fields;
         match pat.kind.as_ref() {
             PatKind::AscribeUserType { subpattern, .. } => return mkpat(subpattern),
             PatKind::Binding { subpattern: Some(subpat), .. } => return mkpat(subpat),
@@ -1263,10 +1255,15 @@ pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self {
                 match pat.ty.kind() {
                     ty::Tuple(fs) => {
                         ctor = Single;
-                        fields = Fields::wildcards_from_tys(cx, fs.iter().map(|ty| ty.expect_ty()));
+                        let mut wilds: SmallVec<[_; 2]> = fs
+                            .iter()
+                            .map(|ty| ty.expect_ty())
+                            .map(DeconstructedPat::wildcard)
+                            .collect();
                         for pat in subpatterns {
-                            fields.fields[pat.field.index()] = allocpat(&pat.pattern);
+                            wilds[pat.field.index()] = mkpat(&pat.pattern);
                         }
+                        fields = Fields::from_iter(cx, wilds);
                     }
                     ty::Adt(adt, substs) if adt.is_box() => {
                         // The only legal patterns of type `Box` (outside `std`) are `_` and box
@@ -1306,12 +1303,14 @@ pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self {
                                 field_id_to_id[field.index()] = Some(i);
                                 ty
                             });
-                        fields = Fields::wildcards_from_tys(cx, tys);
+                        let mut wilds: SmallVec<[_; 2]> =
+                            tys.map(DeconstructedPat::wildcard).collect();
                         for pat in subpatterns {
                             if let Some(i) = field_id_to_id[pat.field.index()] {
-                                fields.fields[i] = allocpat(&pat.pattern);
+                                wilds[i] = mkpat(&pat.pattern);
                             }
                         }
+                        fields = Fields::from_iter(cx, wilds);
                     }
                     _ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, pat.ty),
                 }
@@ -1510,11 +1509,11 @@ pub(super) fn specialize<'a>(
         &'a self,
         cx: &MatchCheckCtxt<'p, 'tcx>,
         other_ctor: &Constructor<'tcx>,
-    ) -> Cow<'a, Fields<'p, 'tcx>> {
+    ) -> SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]> {
         match (&self.ctor, other_ctor) {
             (Wildcard, _) => {
                 // We return a wildcard for each field of `other_ctor`.
-                Cow::Owned(Fields::wildcards(cx, self.ty, other_ctor))
+                Fields::wildcards(cx, self.ty, other_ctor).iter_patterns().collect()
             }
             (Slice(self_slice), Slice(other_slice))
                 if self_slice.arity() != other_slice.arity() =>
@@ -1522,8 +1521,8 @@ pub(super) fn specialize<'a>(
                 // The only tricky case: two slices of different arity. Since `self_slice` covers
                 // `other_slice`, `self_slice` must be `VarLen`, i.e. of the form
                 // `[prefix, .., suffix]`. Moreover `other_slice` is guaranteed to have a larger
-                // arity. We fill the middle part with enough wildcards to reach the length of the
-                // new, larger slice.
+                // arity. So we fill the middle part with enough wildcards to reach the length of
+                // the new, larger slice.
                 match self_slice.kind {
                     FixedLen(_) => bug!("{:?} doesn't cover {:?}", self_slice, other_slice),
                     VarLen(prefix, suffix) => {
@@ -1531,19 +1530,17 @@ pub(super) fn specialize<'a>(
                             ty::Slice(ty) | ty::Array(ty, _) => ty,
                             _ => bug!("bad slice pattern {:?} {:?}", self.ctor, self.ty),
                         };
-                        let prefix = self.fields.fields[..prefix].iter().copied();
-                        let suffix =
-                            self.fields.fields[self_slice.arity() - suffix..].iter().copied();
+                        let prefix = &self.fields.fields[..prefix];
+                        let suffix = &self.fields.fields[self_slice.arity() - suffix..];
+                        let wildcard: &_ =
+                            cx.pattern_arena.alloc(DeconstructedPat::wildcard(inner_ty));
                         let extra_wildcards = other_slice.arity() - self_slice.arity();
-                        let extra_wildcards: &[_] = cx.pattern_arena.alloc_from_iter(
-                            (0..extra_wildcards).map(|_| DeconstructedPat::wildcard(inner_ty)),
-                        );
-                        let fields = prefix.chain(extra_wildcards).chain(suffix);
-                        Cow::Owned(Fields::from_ref_iter(fields))
+                        let extra_wildcards = (0..extra_wildcards).map(|_| wildcard);
+                        prefix.iter().chain(extra_wildcards).chain(suffix).collect()
                     }
                 }
             }
-            _ => Cow::Borrowed(&self.fields),
+            _ => self.fields.iter_patterns().collect(),
         }
     }
 }
index 1cadc4a0ba65eef803509a3aa2fcce5a47f2fb75..9ab0e906eb7cf4a92ef28146242d1db7f6fd10c9 100644 (file)
@@ -407,8 +407,7 @@ fn pop_head_constructor(
     ) -> PatStack<'p, 'tcx> {
         // We pop the head pattern and push the new fields extracted from the arguments of
         // `self.head()`.
-        let mut new_fields: SmallVec<[_; 2]> =
-            self.head().specialize(cx, ctor).iter_patterns().collect();
+        let mut new_fields: SmallVec<[_; 2]> = self.head().specialize(cx, ctor);
         new_fields.extend_from_slice(&self.pats[1..]);
         PatStack::from_vec(new_fields)
     }