Skip to content

Commit b052036

Browse files
committed
Don't use SmallVec when we could use Option
This reverts some of the or-patterns future-proofing, for the sake of performance.
1 parent 9c3682f commit b052036

File tree

1 file changed

+55
-61
lines changed

1 file changed

+55
-61
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 55 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ pub struct PatStack<'p, 'tcx> {
342342
// This caches the invocation of `pat_constructors` on the head of the stack. We avoid mutating
343343
// `self` to be sure we don't keep an invalid cache around. Must be non-empty unless `patterns`
344344
// is empty.
345-
head_ctors: SmallVec<[Constructor<'tcx>; 1]>,
345+
head_ctor: Option<Constructor<'tcx>>,
346346
}
347347

348348
impl<'p, 'tcx> PatStack<'p, 'tcx> {
@@ -351,15 +351,15 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
351351
}
352352

353353
fn empty() -> Self {
354-
PatStack { patterns: smallvec![], head_ctors: smallvec![] }
354+
PatStack { patterns: smallvec![], head_ctor: None }
355355
}
356356

357357
fn from_vec(cx: &MatchCheckCtxt<'_, 'tcx>, patterns: SmallVec<[&'p Pat<'tcx>; 2]>) -> Self {
358358
if patterns.is_empty() {
359359
return PatStack::empty();
360360
}
361-
let head_ctors = pat_constructors(cx.tcx, cx.param_env, patterns[0]);
362-
PatStack { patterns, head_ctors }
361+
let head_ctor = Some(pat_constructors(cx.tcx, cx.param_env, patterns[0]));
362+
PatStack { patterns, head_ctor }
363363
}
364364

365365
fn from_slice(cx: &MatchCheckCtxt<'_, 'tcx>, s: &[&'p Pat<'tcx>]) -> Self {
@@ -378,8 +378,8 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
378378
self.patterns[0]
379379
}
380380

381-
fn head_ctors(&self) -> &SmallVec<[Constructor<'tcx>; 1]> {
382-
&self.head_ctors
381+
fn head_ctors(&self) -> &Constructor<'tcx> {
382+
self.head_ctor.as_ref().unwrap()
383383
}
384384

385385
fn iter(&self) -> impl Iterator<Item = &Pat<'tcx>> {
@@ -392,20 +392,17 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
392392
cx: &MatchCheckCtxt<'a, 'tcx>,
393393
constructor: &Constructor<'tcx>,
394394
ctor_wild_subpatterns: &[&'q Pat<'tcx>],
395-
) -> SmallVec<[PatStack<'q, 'tcx>; 1]>
395+
) -> Option<PatStack<'q, 'tcx>>
396396
where
397397
'a: 'q,
398398
'p: 'q,
399399
{
400-
let new_heads = specialize_one_pattern(cx, self.head(), constructor, ctor_wild_subpatterns);
401-
let result = new_heads
402-
.into_iter()
403-
.map(|new_head| {
404-
let mut pats = new_head.patterns;
405-
pats.extend_from_slice(&self.patterns[1..]);
406-
PatStack::from_vec(cx, pats)
407-
})
408-
.collect();
400+
let new_head = specialize_one_pattern(cx, self.head(), constructor, ctor_wild_subpatterns);
401+
let result = new_head.map(|new_head| {
402+
let mut pats = new_head.patterns;
403+
pats.extend_from_slice(&self.patterns[1..]);
404+
PatStack::from_vec(cx, pats)
405+
});
409406
debug!("specialize({:#?}, {:#?}) = {:#?}", self, constructor, result);
410407
result
411408
}
@@ -435,7 +432,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
435432
}
436433

437434
fn head_ctors(&self) -> Vec<&Constructor<'tcx>> {
438-
self.0.iter().flat_map(|r| r.head_ctors()).filter(|ctor| !ctor.is_wildcard()).collect()
435+
self.0.iter().map(|r| r.head_ctors()).filter(|ctor| !ctor.is_wildcard()).collect()
439436
}
440437

441438
/// This computes `S(constructor, self)`. See top of the file for explanations.
@@ -452,7 +449,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
452449
Matrix(
453450
self.0
454451
.iter()
455-
.flat_map(|r| r.specialize(cx, constructor, ctor_wild_subpatterns))
452+
.filter_map(|r| r.specialize(cx, constructor, ctor_wild_subpatterns))
456453
.collect(),
457454
)
458455
}
@@ -707,8 +704,8 @@ impl<'tcx> Constructor<'tcx> {
707704
let row_borders = head_ctors
708705
.iter()
709706
.map(|c| *c)
710-
.flat_map(IntRange::from_ctor)
711-
.flat_map(|range| ctor_range.intersection(cx.tcx, &range))
707+
.filter_map(IntRange::from_ctor)
708+
.filter_map(|range| ctor_range.intersection(cx.tcx, &range))
712709
.flat_map(|range| range_borders(range));
713710
let ctor_borders = range_borders(ctor_range.clone());
714711
let mut borders: Vec<_> = row_borders.chain(ctor_borders).collect();
@@ -1024,7 +1021,7 @@ impl<'tcx> Constructor<'tcx> {
10241021
}
10251022
}
10261023
IntRange(range) => {
1027-
let used_ranges = used_ctors.iter().flat_map(IntRange::from_ctor);
1024+
let used_ranges = used_ctors.iter().filter_map(IntRange::from_ctor);
10281025
let mut remaining_ranges: SmallVec<[IntRange<'tcx>; 1]> = smallvec![range];
10291026

10301027
// For each used ctor, subtract from the current set of constructors.
@@ -1763,12 +1760,9 @@ pub fn is_useful<'p, 'a, 'tcx>(
17631760

17641761
debug!("is_useful_expand_first_col: ty={:#?}, expanding {:#?}", ty, v.head());
17651762

1766-
let v_constructors = v.head_ctors();
1763+
let v_constructor = v.head_ctors();
17671764

1768-
if cx.is_non_exhaustive_variant(v.head())
1769-
&& !cx.is_local(ty)
1770-
&& !v_constructors.iter().any(|ctor| ctor.is_wildcard())
1771-
{
1765+
if cx.is_non_exhaustive_variant(v.head()) && !cx.is_local(ty) && !v_constructor.is_wildcard() {
17721766
debug!("is_useful - shortcut because declared non-exhaustive");
17731767
// FIXME(#65157)
17741768
return Useful;
@@ -1777,9 +1771,9 @@ pub fn is_useful<'p, 'a, 'tcx>(
17771771
let matrix_head_ctors = matrix.head_ctors();
17781772
debug!("matrix_head_ctors = {:#?}", matrix_head_ctors);
17791773

1780-
v_constructors
1781-
.iter()
1782-
.flat_map(|ctor| ctor.split_meta_constructor(cx, ty, &matrix_head_ctors))
1774+
v_constructor
1775+
.split_meta_constructor(cx, ty, &matrix_head_ctors)
1776+
.into_iter()
17831777
.map(|c| is_useful_specialized(cx, matrix, v, c, ty, witness_preference))
17841778
.find(|result| result.is_useful())
17851779
.unwrap_or(NotUseful)
@@ -1816,41 +1810,41 @@ fn pat_constructors<'tcx>(
18161810
tcx: TyCtxt<'tcx>,
18171811
param_env: ty::ParamEnv<'tcx>,
18181812
pat: &Pat<'tcx>,
1819-
) -> SmallVec<[Constructor<'tcx>; 1]> {
1813+
) -> Constructor<'tcx> {
18201814
match *pat.kind {
18211815
PatKind::AscribeUserType { ref subpattern, .. } => {
18221816
pat_constructors(tcx, param_env, subpattern)
18231817
}
1824-
PatKind::Binding { .. } | PatKind::Wild => smallvec![Wildcard],
1825-
PatKind::Leaf { .. } | PatKind::Deref { .. } => smallvec![Single],
1818+
PatKind::Binding { .. } | PatKind::Wild => Wildcard,
1819+
PatKind::Leaf { .. } | PatKind::Deref { .. } => Single,
18261820
PatKind::Variant { adt_def, variant_index, .. } => {
1827-
smallvec![Variant(adt_def.variants[variant_index].def_id)]
1821+
Variant(adt_def.variants[variant_index].def_id)
18281822
}
18291823
PatKind::Constant { value } => {
18301824
if let Some(range) = IntRange::from_const(tcx, param_env, value) {
1831-
smallvec![IntRange(range)]
1825+
IntRange(range)
18321826
} else {
1833-
smallvec![ConstantValue(value)]
1827+
ConstantValue(value)
18341828
}
18351829
}
18361830
PatKind::Range(PatRange { lo, hi, end }) => {
18371831
if let Some(range) = IntRange::from_const_range(tcx, param_env, &lo, &hi, &end) {
1838-
smallvec![IntRange(range)]
1832+
IntRange(range)
18391833
} else {
1840-
smallvec![ConstantRange(lo, hi, end)]
1834+
ConstantRange(lo, hi, end)
18411835
}
18421836
}
18431837
PatKind::Array { .. } => match pat.ty.kind {
1844-
ty::Array(_, length) => smallvec![FixedLenSlice(length.eval_usize(tcx, param_env))],
1838+
ty::Array(_, length) => FixedLenSlice(length.eval_usize(tcx, param_env)),
18451839
_ => span_bug!(pat.span, "bad ty {:?} for array pattern", pat.ty),
18461840
},
18471841
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
18481842
let prefix = prefix.len() as u64;
18491843
let suffix = suffix.len() as u64;
18501844
if slice.is_some() {
1851-
smallvec![VarLenSlice(prefix, suffix)]
1845+
VarLenSlice(prefix, suffix)
18521846
} else {
1853-
smallvec![FixedLenSlice(prefix + suffix)]
1847+
FixedLenSlice(prefix + suffix)
18541848
}
18551849
}
18561850
PatKind::Or { .. } => {
@@ -2005,7 +1999,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
20051999
mut pat: &'q Pat<'tcx>,
20062000
constructor: &Constructor<'tcx>,
20072001
ctor_wild_subpatterns: &[&'p Pat<'tcx>],
2008-
) -> SmallVec<[PatStack<'p, 'tcx>; 1]> {
2002+
) -> Option<PatStack<'p, 'tcx>> {
20092003
while let PatKind::AscribeUserType { ref subpattern, .. } = *pat.kind {
20102004
pat = subpattern;
20112005
}
@@ -2018,32 +2012,32 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
20182012
// If `constructor` is `MissingConstructors(_)`: by the invariant of MissingConstructors,
20192013
// we know that all non-wildcard constructors should be discarded.
20202014
return match *pat.kind {
2021-
PatKind::Binding { .. } | PatKind::Wild => smallvec![PatStack::empty()],
2022-
_ => smallvec![],
2015+
PatKind::Binding { .. } | PatKind::Wild => Some(PatStack::empty()),
2016+
_ => None,
20232017
};
20242018
}
20252019

20262020
match *pat.kind {
20272021
PatKind::AscribeUserType { .. } => unreachable!(), // Handled above
20282022

20292023
PatKind::Binding { .. } | PatKind::Wild => {
2030-
smallvec![PatStack::from_slice(cx, ctor_wild_subpatterns)]
2024+
Some(PatStack::from_slice(cx, ctor_wild_subpatterns))
20312025
}
20322026

20332027
PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
20342028
let ref variant = adt_def.variants[variant_index];
20352029
if Variant(variant.def_id) == *constructor {
2036-
smallvec![patterns_for_variant(cx, subpatterns, ctor_wild_subpatterns)]
2030+
Some(patterns_for_variant(cx, subpatterns, ctor_wild_subpatterns))
20372031
} else {
2038-
smallvec![]
2032+
None
20392033
}
20402034
}
20412035

20422036
PatKind::Leaf { ref subpatterns } => {
2043-
smallvec![patterns_for_variant(cx, subpatterns, ctor_wild_subpatterns)]
2037+
Some(patterns_for_variant(cx, subpatterns, ctor_wild_subpatterns))
20442038
}
20452039

2046-
PatKind::Deref { ref subpattern } => smallvec![PatStack::from_pattern(cx, subpattern)],
2040+
PatKind::Deref { ref subpattern } => Some(PatStack::from_pattern(cx, subpattern)),
20472041

20482042
PatKind::Constant { value } if constructor.is_slice() => {
20492043
// We extract an `Option` for the pointer because slices of zero
@@ -2064,7 +2058,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
20642058
}
20652059
ConstValue::ByRef { .. } => {
20662060
// FIXME(oli-obk): implement `deref` for `ConstValue`
2067-
return smallvec![];
2061+
return None;
20682062
}
20692063
_ => span_bug!(
20702064
pat.span,
@@ -2085,7 +2079,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
20852079
let layout = if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) {
20862080
layout
20872081
} else {
2088-
return smallvec![];
2082+
return None;
20892083
};
20902084
let ptr = Pointer::new(AllocId(0), offset);
20912085
let stack: Option<SmallVec<_>> = (0..n)
@@ -2100,11 +2094,11 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
21002094
})
21012095
.collect();
21022096
match stack {
2103-
Some(v) => smallvec![PatStack::from_vec(cx, v)],
2104-
None => smallvec![],
2097+
Some(v) => Some(PatStack::from_vec(cx, v)),
2098+
None => None,
21052099
}
21062100
} else {
2107-
smallvec![]
2101+
None
21082102
}
21092103
}
21102104

@@ -2113,9 +2107,9 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
21132107
// - Single value: add a row if the pattern contains the constructor.
21142108
// - Range: add a row if the constructor intersects the pattern.
21152109
if let Some(ps) = constructor_intersects_pattern(cx, constructor, pat) {
2116-
smallvec![ps]
2110+
Some(ps)
21172111
} else {
2118-
smallvec![]
2112+
None
21192113
}
21202114
}
21212115

@@ -2125,7 +2119,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
21252119
let pat_len = prefix.len() + suffix.len();
21262120
if let Some(slice_count) = ctor_wild_subpatterns.len().checked_sub(pat_len) {
21272121
if slice_count == 0 || slice.is_some() {
2128-
smallvec![PatStack::from_vec(
2122+
Some(PatStack::from_vec(
21292123
cx,
21302124
prefix
21312125
.iter()
@@ -2138,12 +2132,12 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
21382132
.chain(suffix.iter()),
21392133
)
21402134
.collect(),
2141-
)]
2135+
))
21422136
} else {
2143-
smallvec![]
2137+
None
21442138
}
21452139
} else {
2146-
smallvec![]
2140+
None
21472141
}
21482142
}
21492143
ConstantValue(cv) => {
@@ -2156,8 +2150,8 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
21562150
suffix,
21572151
cx.param_env,
21582152
) {
2159-
Ok(true) => smallvec![PatStack::default()],
2160-
Ok(false) | Err(ErrorReported) => smallvec![],
2153+
Ok(true) => Some(PatStack::default()),
2154+
Ok(false) | Err(ErrorReported) => None,
21612155
}
21622156
}
21632157
_ => span_bug!(pat.span, "unexpected ctor {:?} for slice pat", constructor),

0 commit comments

Comments
 (0)