Avoid double-deref in Fields

This commit is contained in:
Nadrieril 2021-09-25 17:46:44 +01:00
parent 71abc9565f
commit b6062bda4c
2 changed files with 31 additions and 35 deletions

View 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(),
}
}
}

View 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)
}