@@ -443,11 +443,9 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
443443 constructor : & Constructor < ' tcx > ,
444444 ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
445445 ) -> Option < PatStack < ' p , ' tcx > > {
446- let new_heads = specialize_one_pattern ( cx, self . head ( ) , constructor, ctor_wild_subpatterns) ;
447- new_heads. map ( |mut new_head| {
448- new_head. 0 . extend_from_slice ( & self . 0 [ 1 ..] ) ;
449- new_head
450- } )
446+ let new_fields =
447+ specialize_one_pattern ( cx, self . head ( ) , constructor, ctor_wild_subpatterns) ?;
448+ Some ( new_fields. push_on_patstack ( & self . 0 [ 1 ..] ) )
451449 }
452450}
453451
@@ -1034,9 +1032,24 @@ impl<'tcx> Constructor<'tcx> {
10341032#[ derive( Debug , Clone ) ]
10351033enum Fields < ' p , ' tcx > {
10361034 Slice ( & ' p [ Pat < ' tcx > ] ) ,
1035+ Vec ( SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) ,
10371036}
10381037
10391038impl < ' p , ' tcx > Fields < ' p , ' tcx > {
1039+ fn empty ( ) -> Self {
1040+ Fields :: Slice ( & [ ] )
1041+ }
1042+
1043+ /// Construct a new `Fields` from the given pattern. Must not be used if the pattern is a field
1044+ /// of a struct/tuple/variant.
1045+ fn from_single_pattern ( pat : & ' p Pat < ' tcx > ) -> Self {
1046+ Fields :: Slice ( std:: slice:: from_ref ( pat) )
1047+ }
1048+
1049+ fn from_vec ( pats : SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) -> Self {
1050+ Fields :: Vec ( pats)
1051+ }
1052+
10401053 /// Creates a new list of wildcard fields for a given constructor.
10411054 fn wildcards (
10421055 cx : & MatchCheckCtxt < ' p , ' tcx > ,
@@ -1051,13 +1064,27 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
10511064 fn len ( & self ) -> usize {
10521065 match self {
10531066 Fields :: Slice ( pats) => pats. len ( ) ,
1067+ Fields :: Vec ( pats) => pats. len ( ) ,
10541068 }
10551069 }
10561070
1057- fn iter < ' a > ( & ' a self ) -> impl Iterator < Item = & ' p Pat < ' tcx > > + Captures < ' a > {
1058- match self {
1059- Fields :: Slice ( pats) => pats. iter ( ) ,
1060- }
1071+ fn iter ( & self ) -> impl Iterator < Item = & ' p Pat < ' tcx > > {
1072+ let pats: SmallVec < _ > = match self {
1073+ Fields :: Slice ( pats) => pats. iter ( ) . collect ( ) ,
1074+ Fields :: Vec ( pats) => pats. clone ( ) ,
1075+ } ;
1076+ pats. into_iter ( )
1077+ }
1078+
1079+ fn push_on_patstack ( self , stack : & [ & ' p Pat < ' tcx > ] ) -> PatStack < ' p , ' tcx > {
1080+ let pats: SmallVec < _ > = match self {
1081+ Fields :: Slice ( pats) => pats. iter ( ) . chain ( stack. iter ( ) . copied ( ) ) . collect ( ) ,
1082+ Fields :: Vec ( mut pats) => {
1083+ pats. extend_from_slice ( stack) ;
1084+ pats
1085+ }
1086+ } ;
1087+ PatStack :: from_vec ( pats)
10611088 }
10621089}
10631090
@@ -2330,7 +2357,7 @@ fn patterns_for_variant<'p, 'tcx>(
23302357 subpatterns : & ' p [ FieldPat < ' tcx > ] ,
23312358 ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
23322359 is_non_exhaustive : bool ,
2333- ) -> PatStack < ' p , ' tcx > {
2360+ ) -> Fields < ' p , ' tcx > {
23342361 let mut result: SmallVec < _ > = ctor_wild_subpatterns. iter ( ) . collect ( ) ;
23352362
23362363 for subpat in subpatterns {
@@ -2343,7 +2370,7 @@ fn patterns_for_variant<'p, 'tcx>(
23432370 "patterns_for_variant({:#?}, {:#?}) = {:#?}" ,
23442371 subpatterns, ctor_wild_subpatterns, result
23452372 ) ;
2346- PatStack :: from_vec ( result)
2373+ Fields :: from_vec ( result)
23472374}
23482375
23492376/// This is the main specialization step. It expands the pattern
@@ -2360,16 +2387,16 @@ fn specialize_one_pattern<'p, 'tcx>(
23602387 pat : & ' p Pat < ' tcx > ,
23612388 constructor : & Constructor < ' tcx > ,
23622389 ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
2363- ) -> Option < PatStack < ' p , ' tcx > > {
2390+ ) -> Option < Fields < ' p , ' tcx > > {
23642391 if let NonExhaustive = constructor {
23652392 // Only a wildcard pattern can match the special extra constructor
2366- return if pat. is_wildcard ( ) { Some ( PatStack :: default ( ) ) } else { None } ;
2393+ return if pat. is_wildcard ( ) { Some ( Fields :: empty ( ) ) } else { None } ;
23672394 }
23682395
23692396 let result = match * pat. kind {
23702397 PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled by `expand_pattern`
23712398
2372- PatKind :: Binding { .. } | PatKind :: Wild => Some ( ctor_wild_subpatterns. iter ( ) . collect ( ) ) ,
2399+ PatKind :: Binding { .. } | PatKind :: Wild => Some ( ctor_wild_subpatterns. clone ( ) ) ,
23732400
23742401 PatKind :: Variant { adt_def, variant_index, ref subpatterns, .. } => {
23752402 let variant = & adt_def. variants [ variant_index] ;
@@ -2385,7 +2412,7 @@ fn specialize_one_pattern<'p, 'tcx>(
23852412 Some ( patterns_for_variant ( cx, subpatterns, ctor_wild_subpatterns, false ) )
23862413 }
23872414
2388- PatKind :: Deref { ref subpattern } => Some ( PatStack :: from_pattern ( subpattern) ) ,
2415+ PatKind :: Deref { ref subpattern } => Some ( Fields :: from_single_pattern ( subpattern) ) ,
23892416
23902417 PatKind :: Constant { value } if constructor. is_slice ( ) => {
23912418 // We extract an `Option` for the pointer because slices of zero
@@ -2399,7 +2426,7 @@ fn specialize_one_pattern<'p, 'tcx>(
23992426 // the result would be exactly what we early return here.
24002427 if n == 0 {
24012428 if ctor_wild_subpatterns. len ( ) as u64 == 0 {
2402- return Some ( PatStack :: from_slice ( & [ ] ) ) ;
2429+ return Some ( Fields :: empty ( ) ) ;
24032430 } else {
24042431 return None ;
24052432 }
@@ -2440,7 +2467,7 @@ fn specialize_one_pattern<'p, 'tcx>(
24402467 // convert a constant slice/array pattern to a list of patterns.
24412468 let layout = cx. tcx . layout_of ( cx. param_env . and ( ty) ) . ok ( ) ?;
24422469 let ptr = Pointer :: new ( AllocId ( 0 ) , offset) ;
2443- ( 0 ..n)
2470+ let pats = ( 0 ..n)
24442471 . map ( |i| {
24452472 let ptr = ptr. offset ( layout. size * i, & cx. tcx ) . ok ( ) ?;
24462473 let scalar = alloc. read_scalar ( & cx. tcx , ptr, layout. size ) . ok ( ) ?;
@@ -2450,7 +2477,8 @@ fn specialize_one_pattern<'p, 'tcx>(
24502477 Pat { ty, span : pat. span , kind : box PatKind :: Constant { value } } ;
24512478 Some ( & * cx. pattern_arena . alloc ( pattern) )
24522479 } )
2453- . collect ( )
2480+ . collect :: < Option < _ > > ( ) ?;
2481+ Some ( Fields :: from_vec ( pats) )
24542482 } else {
24552483 None
24562484 }
@@ -2466,7 +2494,7 @@ fn specialize_one_pattern<'p, 'tcx>(
24662494 // Constructor splitting should ensure that all intersections we encounter
24672495 // are actually inclusions.
24682496 assert ! ( ctor. is_subrange( & pat) ) ;
2469- PatStack :: default ( )
2497+ Fields :: empty ( )
24702498 } ) ,
24712499 _ => None ,
24722500 }
@@ -2477,7 +2505,7 @@ fn specialize_one_pattern<'p, 'tcx>(
24772505 // range so intersection actually devolves into being covered
24782506 // by the pattern.
24792507 constructor_covered_by_range ( cx. tcx , cx. param_env , constructor, pat)
2480- . map ( |( ) | PatStack :: default ( ) )
2508+ . map ( |( ) | Fields :: empty ( ) )
24812509 }
24822510 }
24832511
@@ -2487,7 +2515,7 @@ fn specialize_one_pattern<'p, 'tcx>(
24872515 let pat_len = prefix. len ( ) + suffix. len ( ) ;
24882516 if let Some ( slice_count) = ctor_wild_subpatterns. len ( ) . checked_sub ( pat_len) {
24892517 if slice_count == 0 || slice. is_some ( ) {
2490- Some (
2518+ Some ( Fields :: from_vec (
24912519 prefix
24922520 . iter ( )
24932521 . chain (
@@ -2498,7 +2526,7 @@ fn specialize_one_pattern<'p, 'tcx>(
24982526 . chain ( suffix. iter ( ) ) ,
24992527 )
25002528 . collect ( ) ,
2501- )
2529+ ) )
25022530 } else {
25032531 None
25042532 }
@@ -2516,7 +2544,7 @@ fn specialize_one_pattern<'p, 'tcx>(
25162544 suffix,
25172545 cx. param_env ,
25182546 ) {
2519- Ok ( true ) => Some ( PatStack :: default ( ) ) ,
2547+ Ok ( true ) => Some ( Fields :: empty ( ) ) ,
25202548 Ok ( false ) => None ,
25212549 Err ( ErrorReported ) => None ,
25222550 }
0 commit comments