Skip to content

Commit cdc6633

Browse files
committed
Use a SmallVec within _match::Matrix.
This commit also fixes up lifetimes a bit: - Renames `'a` as `'p` when used with `Matrix` and `Pattern`, for consistency. - Removes some unnecessary `'p` lifetimes on some function arguments. - Adds some missing lifetime parameters.
1 parent ecf6cd4 commit cdc6633

File tree

2 files changed

+34
-28
lines changed

2 files changed

+34
-28
lines changed

src/librustc_mir/hair/pattern/_match.rs

+28-23
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ use syntax_pos::{Span, DUMMY_SP};
190190

191191
use arena::TypedArena;
192192

193+
use smallvec::{SmallVec, smallvec};
193194
use std::cmp::{self, Ordering, min, max};
194195
use std::fmt;
195196
use std::iter::{FromIterator, IntoIterator};
@@ -237,14 +238,16 @@ impl<'tcx> Pattern<'tcx> {
237238
}
238239
}
239240

240-
pub struct Matrix<'a, 'tcx: 'a>(Vec<Vec<&'a Pattern<'tcx>>>);
241+
/// A 2D matrix. Nx1 matrices are very common, which is why `SmallVec[_; 2]`
242+
/// works well for each row.
243+
pub struct Matrix<'p, 'tcx: 'p>(Vec<SmallVec<[&'p Pattern<'tcx>; 2]>>);
241244

242-
impl<'a, 'tcx> Matrix<'a, 'tcx> {
245+
impl<'p, 'tcx> Matrix<'p, 'tcx> {
243246
pub fn empty() -> Self {
244247
Matrix(vec![])
245248
}
246249

247-
pub fn push(&mut self, row: Vec<&'a Pattern<'tcx>>) {
250+
pub fn push(&mut self, row: SmallVec<[&'p Pattern<'tcx>; 2]>) {
248251
self.0.push(row)
249252
}
250253
}
@@ -261,7 +264,7 @@ impl<'a, 'tcx> Matrix<'a, 'tcx> {
261264
/// ++++++++++++++++++++++++++
262265
/// + _ + [_, _, ..tail] +
263266
/// ++++++++++++++++++++++++++
264-
impl<'a, 'tcx> fmt::Debug for Matrix<'a, 'tcx> {
267+
impl<'p, 'tcx> fmt::Debug for Matrix<'p, 'tcx> {
265268
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
266269
write!(f, "\n")?;
267270

@@ -293,8 +296,9 @@ impl<'a, 'tcx> fmt::Debug for Matrix<'a, 'tcx> {
293296
}
294297
}
295298

296-
impl<'a, 'tcx> FromIterator<Vec<&'a Pattern<'tcx>>> for Matrix<'a, 'tcx> {
297-
fn from_iter<T: IntoIterator<Item=Vec<&'a Pattern<'tcx>>>>(iter: T) -> Self
299+
impl<'p, 'tcx> FromIterator<SmallVec<[&'p Pattern<'tcx>; 2]>> for Matrix<'p, 'tcx> {
300+
fn from_iter<T>(iter: T) -> Self
301+
where T: IntoIterator<Item=SmallVec<[&'p Pattern<'tcx>; 2]>>
298302
{
299303
Matrix(iter.into_iter().collect())
300304
}
@@ -998,7 +1002,7 @@ fn compute_missing_ctors<'a, 'tcx: 'a>(
9981002
/// matrix isn't exhaustive).
9991003
pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
10001004
matrix: &Matrix<'p, 'tcx>,
1001-
v: &[&'p Pattern<'tcx>],
1005+
v: &[&Pattern<'tcx>],
10021006
witness: WitnessPreference)
10031007
-> Usefulness<'tcx> {
10041008
let &Matrix(ref rows) = matrix;
@@ -1108,7 +1112,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
11081112
} else {
11091113
let matrix = rows.iter().filter_map(|r| {
11101114
if r[0].is_wildcard() {
1111-
Some(r[1..].to_vec())
1115+
Some(SmallVec::from_slice(&r[1..]))
11121116
} else {
11131117
None
11141118
}
@@ -1199,10 +1203,10 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
11991203

12001204
/// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e., `is_useful` applied
12011205
/// to the specialised version of both the pattern matrix `P` and the new pattern `q`.
1202-
fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>(
1206+
fn is_useful_specialized<'p, 'a: 'p, 'tcx: 'a>(
12031207
cx: &mut MatchCheckCtxt<'a, 'tcx>,
12041208
&Matrix(ref m): &Matrix<'p, 'tcx>,
1205-
v: &[&'p Pattern<'tcx>],
1209+
v: &[&Pattern<'tcx>],
12061210
ctor: Constructor<'tcx>,
12071211
lty: Ty<'tcx>,
12081212
witness: WitnessPreference,
@@ -1521,15 +1525,15 @@ fn constructor_intersects_pattern<'p, 'a: 'p, 'tcx: 'a>(
15211525
tcx: TyCtxt<'a, 'tcx, 'tcx>,
15221526
ctor: &Constructor<'tcx>,
15231527
pat: &'p Pattern<'tcx>,
1524-
) -> Option<Vec<&'p Pattern<'tcx>>> {
1528+
) -> Option<SmallVec<[&'p Pattern<'tcx>; 2]>> {
15251529
if should_treat_range_exhaustively(tcx, ctor) {
15261530
match (IntRange::from_ctor(tcx, ctor), IntRange::from_pat(tcx, pat)) {
15271531
(Some(ctor), Some(pat)) => {
15281532
ctor.intersection(&pat).map(|_| {
15291533
let (pat_lo, pat_hi) = pat.range.into_inner();
15301534
let (ctor_lo, ctor_hi) = ctor.range.into_inner();
15311535
assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi);
1532-
vec![]
1536+
smallvec![]
15331537
})
15341538
}
15351539
_ => None,
@@ -1539,7 +1543,7 @@ fn constructor_intersects_pattern<'p, 'a: 'p, 'tcx: 'a>(
15391543
// conveniently handled by `IntRange`. For these cases, the constructor may not be a range
15401544
// so intersection actually devolves into being covered by the pattern.
15411545
match constructor_covered_by_range(tcx, ctor, pat) {
1542-
Ok(true) => Some(vec![]),
1546+
Ok(true) => Some(smallvec![]),
15431547
Ok(false) | Err(ErrorReported) => None,
15441548
}
15451549
}
@@ -1610,9 +1614,9 @@ fn constructor_covered_by_range<'a, 'tcx>(
16101614
fn patterns_for_variant<'p, 'a: 'p, 'tcx: 'a>(
16111615
subpatterns: &'p [FieldPattern<'tcx>],
16121616
wild_patterns: &[&'p Pattern<'tcx>])
1613-
-> Vec<&'p Pattern<'tcx>>
1617+
-> SmallVec<[&'p Pattern<'tcx>; 2]>
16141618
{
1615-
let mut result = wild_patterns.to_owned();
1619+
let mut result = SmallVec::from_slice(wild_patterns);
16161620

16171621
for subpat in subpatterns {
16181622
result[subpat.field.index()] = &subpat.pattern;
@@ -1635,15 +1639,16 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
16351639
r: &[&'p Pattern<'tcx>],
16361640
constructor: &Constructor<'tcx>,
16371641
wild_patterns: &[&'p Pattern<'tcx>],
1638-
) -> Option<Vec<&'p Pattern<'tcx>>> {
1642+
) -> Option<SmallVec<[&'p Pattern<'tcx>; 2]>> {
16391643
let pat = &r[0];
16401644

1641-
let head: Option<Vec<&Pattern>> = match *pat.kind {
1642-
PatternKind::AscribeUserType { ref subpattern, .. } =>
1643-
specialize(cx, ::std::slice::from_ref(&subpattern), constructor, wild_patterns),
1645+
let head = match *pat.kind {
1646+
PatternKind::AscribeUserType { ref subpattern, .. } => {
1647+
specialize(cx, ::std::slice::from_ref(&subpattern), constructor, wild_patterns)
1648+
}
16441649

16451650
PatternKind::Binding { .. } | PatternKind::Wild => {
1646-
Some(wild_patterns.to_owned())
1651+
Some(SmallVec::from_slice(wild_patterns))
16471652
}
16481653

16491654
PatternKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
@@ -1660,7 +1665,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
16601665
}
16611666

16621667
PatternKind::Deref { ref subpattern } => {
1663-
Some(vec![subpattern])
1668+
Some(smallvec![subpattern])
16641669
}
16651670

16661671
PatternKind::Constant { value } => {
@@ -1696,7 +1701,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
16961701
if wild_patterns.len() as u64 == n {
16971702
// convert a constant slice/array pattern to a list of patterns.
16981703
match (n, opt_ptr) {
1699-
(0, _) => Some(Vec::new()),
1704+
(0, _) => Some(SmallVec::new()),
17001705
(_, Some(ptr)) => {
17011706
let alloc = cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
17021707
let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?;
@@ -1765,7 +1770,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
17651770
match slice_pat_covered_by_constructor(
17661771
cx.tcx, pat.span, constructor, prefix, slice, suffix
17671772
) {
1768-
Ok(true) => Some(vec![]),
1773+
Ok(true) => Some(smallvec![]),
17691774
Ok(false) => None,
17701775
Err(ErrorReported) => None
17711776
}

src/librustc_mir/hair/pattern/check_match.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use rustc::hir::def_id::DefId;
3131
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
3232
use rustc::hir::{self, Pat, PatKind};
3333

34+
use smallvec::smallvec;
3435
use std::slice;
3536

3637
use syntax::ast;
@@ -250,7 +251,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
250251
.iter()
251252
.filter(|&&(_, guard)| guard.is_none())
252253
.flat_map(|arm| &arm.0)
253-
.map(|pat| vec![pat.0])
254+
.map(|pat| smallvec![pat.0])
254255
.collect();
255256
let scrut_ty = self.tables.node_id_to_type(scrut.hir_id);
256257
check_exhaustive(cx, scrut_ty, scrut.span, &matrix);
@@ -274,7 +275,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
274275
self.tables);
275276
let pattern = patcx.lower_pattern(pat);
276277
let pattern_ty = pattern.ty;
277-
let pats: Matrix = vec![vec![
278+
let pats: Matrix = vec![smallvec![
278279
expand_pattern(cx, pattern)
279280
]].into_iter().collect();
280281

@@ -367,7 +368,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
367368
let mut printed_if_let_err = false;
368369
for (arm_index, &(ref pats, guard)) in arms.iter().enumerate() {
369370
for &(pat, hir_pat) in pats {
370-
let v = vec![pat];
371+
let v = smallvec![pat];
371372

372373
match is_useful(cx, &seen, &v, LeaveOutWitness) {
373374
NotUseful => {
@@ -462,10 +463,10 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
462463
}
463464
}
464465

465-
fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
466+
fn check_exhaustive<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
466467
scrut_ty: Ty<'tcx>,
467468
sp: Span,
468-
matrix: &Matrix<'a, 'tcx>) {
469+
matrix: &Matrix<'p, 'tcx>) {
469470
let wild_pattern = Pattern {
470471
ty: scrut_ty,
471472
span: DUMMY_SP,

0 commit comments

Comments
 (0)