@@ -342,16 +342,69 @@ impl<'tcx> Pat<'tcx> {
342342 }
343343}
344344
345- /// A 2D matrix. Nx1 matrices are very common, which is why `SmallVec[_; 2]`
346- /// works well for each row.
347- pub struct Matrix < ' p , ' tcx > ( Vec < SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > > ) ;
345+ /// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
346+ /// works well.
347+ #[ derive( Debug , Clone ) ]
348+ pub struct PatStack < ' p , ' tcx > ( SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) ;
349+
350+ impl < ' p , ' tcx > PatStack < ' p , ' tcx > {
351+ pub fn from_pattern ( pat : & ' p Pat < ' tcx > ) -> Self {
352+ PatStack ( smallvec ! [ pat] )
353+ }
354+
355+ fn from_vec ( vec : SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) -> Self {
356+ PatStack ( vec)
357+ }
358+
359+ fn from_slice ( s : & [ & ' p Pat < ' tcx > ] ) -> Self {
360+ PatStack ( SmallVec :: from_slice ( s) )
361+ }
362+
363+ fn is_empty ( & self ) -> bool {
364+ self . 0 . is_empty ( )
365+ }
366+
367+ fn len ( & self ) -> usize {
368+ self . 0 . len ( )
369+ }
370+
371+ fn head ( & self ) -> & ' p Pat < ' tcx > {
372+ self . 0 [ 0 ]
373+ }
374+
375+ fn to_tail ( & self ) -> Self {
376+ PatStack :: from_slice ( & self . 0 [ 1 ..] )
377+ }
378+
379+ fn iter ( & self ) -> impl Iterator < Item = & Pat < ' tcx > > {
380+ self . 0 . iter ( ) . map ( |p| * p)
381+ }
382+ }
383+
384+ impl < ' p , ' tcx > Default for PatStack < ' p , ' tcx > {
385+ fn default ( ) -> Self {
386+ PatStack ( smallvec ! [ ] )
387+ }
388+ }
389+
390+ impl < ' p , ' tcx > FromIterator < & ' p Pat < ' tcx > > for PatStack < ' p , ' tcx > {
391+ fn from_iter < T > ( iter : T ) -> Self
392+ where
393+ T : IntoIterator < Item = & ' p Pat < ' tcx > > ,
394+ {
395+ PatStack ( iter. into_iter ( ) . collect ( ) )
396+ }
397+ }
398+
399+ /// A 2D matrix.
400+ pub struct Matrix < ' p , ' tcx > ( Vec < PatStack < ' p , ' tcx > > ) ;
348401
349402impl < ' p , ' tcx > Matrix < ' p , ' tcx > {
350403 pub fn empty ( ) -> Self {
351404 Matrix ( vec ! [ ] )
352405 }
353406
354- pub fn push ( & mut self , row : SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) {
407+ pub fn push ( & mut self , row : PatStack < ' p , ' tcx > ) {
355408 self . 0 . push ( row)
356409 }
357410}
@@ -399,10 +452,10 @@ impl<'p, 'tcx> fmt::Debug for Matrix<'p, 'tcx> {
399452 }
400453}
401454
402- impl < ' p , ' tcx > FromIterator < SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > > for Matrix < ' p , ' tcx > {
455+ impl < ' p , ' tcx > FromIterator < PatStack < ' p , ' tcx > > for Matrix < ' p , ' tcx > {
403456 fn from_iter < T > ( iter : T ) -> Self
404457 where
405- T : IntoIterator < Item = SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > > ,
458+ T : IntoIterator < Item = PatStack < ' p , ' tcx > > ,
406459 {
407460 Matrix ( iter. into_iter ( ) . collect ( ) )
408461 }
@@ -1226,7 +1279,7 @@ fn compute_missing_ctors<'tcx>(
12261279pub fn is_useful < ' p , ' a , ' tcx > (
12271280 cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
12281281 matrix : & Matrix < ' p , ' tcx > ,
1229- v : & [ & Pat < ' tcx > ] ,
1282+ v : & PatStack < ' _ , ' tcx > ,
12301283 witness : WitnessPreference ,
12311284 hir_id : HirId ,
12321285) -> Usefulness < ' tcx > {
@@ -1253,9 +1306,9 @@ pub fn is_useful<'p, 'a, 'tcx>(
12531306
12541307 let ( ty, span) = rows
12551308 . iter ( )
1256- . map ( |r| ( r[ 0 ] . ty , r[ 0 ] . span ) )
1309+ . map ( |r| ( r. head ( ) . ty , r. head ( ) . span ) )
12571310 . find ( |( ty, _) | !ty. references_error ( ) )
1258- . unwrap_or ( ( v[ 0 ] . ty , v[ 0 ] . span ) ) ;
1311+ . unwrap_or ( ( v. head ( ) . ty , v. head ( ) . span ) ) ;
12591312 let pcx = PatCtxt {
12601313 // TyErr is used to represent the type of wildcard patterns matching
12611314 // against inaccessible (private) fields of structs, so that we won't
@@ -1277,13 +1330,13 @@ pub fn is_useful<'p, 'a, 'tcx>(
12771330 // introducing uninhabited patterns for inaccessible fields. We
12781331 // need to figure out how to model that.
12791332 ty,
1280- max_slice_length : max_slice_length ( cx, rows. iter ( ) . map ( |r| r[ 0 ] ) . chain ( Some ( v[ 0 ] ) ) ) ,
1333+ max_slice_length : max_slice_length ( cx, rows. iter ( ) . map ( |r| r. head ( ) ) . chain ( Some ( v. head ( ) ) ) ) ,
12811334 span,
12821335 } ;
12831336
1284- debug ! ( "is_useful_expand_first_col: pcx={:#?}, expanding {:#?}" , pcx, v[ 0 ] ) ;
1337+ debug ! ( "is_useful_expand_first_col: pcx={:#?}, expanding {:#?}" , pcx, v. head ( ) ) ;
12851338
1286- if let Some ( constructors) = pat_constructors ( cx, v[ 0 ] , pcx) {
1339+ if let Some ( constructors) = pat_constructors ( cx, v. head ( ) , pcx) {
12871340 debug ! ( "is_useful - expanding constructors: {:#?}" , constructors) ;
12881341 split_grouped_constructors (
12891342 cx. tcx ,
@@ -1303,7 +1356,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
13031356
13041357 let used_ctors: Vec < Constructor < ' _ > > = rows
13051358 . iter ( )
1306- . flat_map ( |row| pat_constructors ( cx, row[ 0 ] , pcx) . unwrap_or ( vec ! [ ] ) )
1359+ . flat_map ( |row| pat_constructors ( cx, row. head ( ) , pcx) . unwrap_or ( vec ! [ ] ) )
13071360 . collect ( ) ;
13081361 debug ! ( "used_ctors = {:#?}" , used_ctors) ;
13091362 // `all_ctors` are all the constructors for the given type, which
@@ -1372,11 +1425,9 @@ pub fn is_useful<'p, 'a, 'tcx>(
13721425 } else {
13731426 let matrix = rows
13741427 . iter ( )
1375- . filter_map ( |r| {
1376- if r[ 0 ] . is_wildcard ( ) { Some ( SmallVec :: from_slice ( & r[ 1 ..] ) ) } else { None }
1377- } )
1428+ . filter_map ( |r| if r. head ( ) . is_wildcard ( ) { Some ( r. to_tail ( ) ) } else { None } )
13781429 . collect ( ) ;
1379- match is_useful ( cx, & matrix, & v[ 1 .. ] , witness, hir_id) {
1430+ match is_useful ( cx, & matrix, & v. to_tail ( ) , witness, hir_id) {
13801431 UsefulWithWitness ( pats) => {
13811432 let cx = & * cx;
13821433 // In this case, there's at least one "free"
@@ -1473,7 +1524,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
14731524fn is_useful_specialized < ' p , ' a , ' tcx > (
14741525 cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
14751526 & Matrix ( ref m) : & Matrix < ' p , ' tcx > ,
1476- v : & [ & Pat < ' tcx > ] ,
1527+ v : & PatStack < ' _ , ' tcx > ,
14771528 ctor : Constructor < ' tcx > ,
14781529 lty : Ty < ' tcx > ,
14791530 witness : WitnessPreference ,
@@ -1787,7 +1838,7 @@ fn split_grouped_constructors<'p, 'tcx>(
17871838 let row_borders = m
17881839 . iter ( )
17891840 . flat_map ( |row| {
1790- IntRange :: from_pat ( tcx, param_env, row[ 0 ] ) . map ( |r| ( r, row. len ( ) ) )
1841+ IntRange :: from_pat ( tcx, param_env, row. head ( ) ) . map ( |r| ( r, row. len ( ) ) )
17911842 } )
17921843 . flat_map ( |( range, row_len) | {
17931844 let intersection = ctor_range. intersection ( & range) ;
@@ -1933,7 +1984,7 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
19331984 subpatterns : & ' p [ FieldPat < ' tcx > ] ,
19341985 wild_patterns : & [ & ' p Pat < ' tcx > ] ,
19351986 is_non_exhaustive : bool ,
1936- ) -> SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > {
1987+ ) -> PatStack < ' p , ' tcx > {
19371988 let mut result = SmallVec :: from_slice ( wild_patterns) ;
19381989
19391990 for subpat in subpatterns {
@@ -1943,7 +1994,7 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
19431994 }
19441995
19451996 debug ! ( "patterns_for_variant({:#?}, {:#?}) = {:#?}" , subpatterns, wild_patterns, result) ;
1946- result
1997+ PatStack :: from_vec ( result)
19471998}
19481999
19492000/// This is the main specialization step. It expands the first pattern in the given row
@@ -1954,20 +2005,20 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
19542005/// different patterns.
19552006/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
19562007/// fields filled with wild patterns.
1957- fn specialize < ' p , ' a : ' p , ' tcx > (
2008+ fn specialize < ' p , ' a : ' p , ' q : ' p , ' tcx > (
19582009 cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
1959- r : & [ & ' p Pat < ' tcx > ] ,
2010+ r : & PatStack < ' q , ' tcx > ,
19602011 constructor : & Constructor < ' tcx > ,
19612012 wild_patterns : & [ & ' p Pat < ' tcx > ] ,
1962- ) -> Option < SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > > {
1963- let pat = & r [ 0 ] ;
2013+ ) -> Option < PatStack < ' p , ' tcx > > {
2014+ let pat = r . head ( ) ;
19642015
19652016 let head = match * pat. kind {
19662017 PatKind :: AscribeUserType { ref subpattern, .. } => {
1967- specialize ( cx, :: std :: slice :: from_ref ( & subpattern) , constructor, wild_patterns)
2018+ specialize ( cx, & PatStack :: from_pattern ( subpattern) , constructor, wild_patterns)
19682019 }
19692020
1970- PatKind :: Binding { .. } | PatKind :: Wild => Some ( SmallVec :: from_slice ( wild_patterns) ) ,
2021+ PatKind :: Binding { .. } | PatKind :: Wild => Some ( PatStack :: from_slice ( wild_patterns) ) ,
19712022
19722023 PatKind :: Variant { adt_def, variant_index, ref subpatterns, .. } => {
19732024 let ref variant = adt_def. variants [ variant_index] ;
@@ -1981,7 +2032,7 @@ fn specialize<'p, 'a: 'p, 'tcx>(
19812032 Some ( patterns_for_variant ( cx, subpatterns, wild_patterns, false ) )
19822033 }
19832034
1984- PatKind :: Deref { ref subpattern } => Some ( smallvec ! [ subpattern] ) ,
2035+ PatKind :: Deref { ref subpattern } => Some ( PatStack :: from_pattern ( subpattern) ) ,
19852036
19862037 PatKind :: Constant { value } if constructor. is_slice ( ) => {
19872038 // We extract an `Option` for the pointer because slices of zero
@@ -2051,7 +2102,7 @@ fn specialize<'p, 'a: 'p, 'tcx>(
20512102 let ( pat_lo, pat_hi) = pat. range . into_inner ( ) ;
20522103 let ( ctor_lo, ctor_hi) = ctor. range . into_inner ( ) ;
20532104 assert ! ( pat_lo <= ctor_lo && ctor_hi <= pat_hi) ;
2054- smallvec ! [ ]
2105+ PatStack :: default ( )
20552106 } ) ,
20562107 _ => None ,
20572108 }
@@ -2062,7 +2113,7 @@ fn specialize<'p, 'a: 'p, 'tcx>(
20622113 // range so intersection actually devolves into being covered
20632114 // by the pattern.
20642115 match constructor_covered_by_range ( cx. tcx , cx. param_env , constructor, pat) {
2065- Ok ( true ) => Some ( smallvec ! [ ] ) ,
2116+ Ok ( true ) => Some ( PatStack :: default ( ) ) ,
20662117 Ok ( false ) | Err ( ErrorReported ) => None ,
20672118 }
20682119 }
@@ -2104,7 +2155,7 @@ fn specialize<'p, 'a: 'p, 'tcx>(
21042155 suffix,
21052156 cx. param_env ,
21062157 ) {
2107- Ok ( true ) => Some ( smallvec ! [ ] ) ,
2158+ Ok ( true ) => Some ( PatStack :: default ( ) ) ,
21082159 Ok ( false ) => None ,
21092160 Err ( ErrorReported ) => None ,
21102161 }
@@ -2116,10 +2167,11 @@ fn specialize<'p, 'a: 'p, 'tcx>(
21162167 bug ! ( "support for or-patterns has not been fully implemented yet." ) ;
21172168 }
21182169 } ;
2119- debug ! ( "specialize({:#?}, {:#?}) = {:#?}" , r[ 0 ] , wild_patterns, head) ;
2170+ debug ! ( "specialize({:#?}, {:#?}) = {:#?}" , r. head ( ) , wild_patterns, head) ;
21202171
2121- head. map ( |mut head| {
2122- head. extend_from_slice ( & r[ 1 ..] ) ;
2123- head
2172+ head. map ( |head| {
2173+ let mut head = head. 0 ;
2174+ head. extend_from_slice ( & r. 0 [ 1 ..] ) ;
2175+ PatStack :: from_vec ( head)
21242176 } )
21252177}
0 commit comments