@@ -443,11 +443,9 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
443
443
constructor : & Constructor < ' tcx > ,
444
444
ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
445
445
) -> 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 ..] ) )
451
449
}
452
450
}
453
451
@@ -1034,9 +1032,24 @@ impl<'tcx> Constructor<'tcx> {
1034
1032
#[ derive( Debug , Clone ) ]
1035
1033
enum Fields < ' p , ' tcx > {
1036
1034
Slice ( & ' p [ Pat < ' tcx > ] ) ,
1035
+ Vec ( SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) ,
1037
1036
}
1038
1037
1039
1038
impl < ' 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
+
1040
1053
/// Creates a new list of wildcard fields for a given constructor.
1041
1054
fn wildcards (
1042
1055
cx : & MatchCheckCtxt < ' p , ' tcx > ,
@@ -1051,13 +1064,27 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1051
1064
fn len ( & self ) -> usize {
1052
1065
match self {
1053
1066
Fields :: Slice ( pats) => pats. len ( ) ,
1067
+ Fields :: Vec ( pats) => pats. len ( ) ,
1054
1068
}
1055
1069
}
1056
1070
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)
1061
1088
}
1062
1089
}
1063
1090
@@ -2330,7 +2357,7 @@ fn patterns_for_variant<'p, 'tcx>(
2330
2357
subpatterns : & ' p [ FieldPat < ' tcx > ] ,
2331
2358
ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
2332
2359
is_non_exhaustive : bool ,
2333
- ) -> PatStack < ' p , ' tcx > {
2360
+ ) -> Fields < ' p , ' tcx > {
2334
2361
let mut result: SmallVec < _ > = ctor_wild_subpatterns. iter ( ) . collect ( ) ;
2335
2362
2336
2363
for subpat in subpatterns {
@@ -2343,7 +2370,7 @@ fn patterns_for_variant<'p, 'tcx>(
2343
2370
"patterns_for_variant({:#?}, {:#?}) = {:#?}" ,
2344
2371
subpatterns, ctor_wild_subpatterns, result
2345
2372
) ;
2346
- PatStack :: from_vec ( result)
2373
+ Fields :: from_vec ( result)
2347
2374
}
2348
2375
2349
2376
/// This is the main specialization step. It expands the pattern
@@ -2360,16 +2387,16 @@ fn specialize_one_pattern<'p, 'tcx>(
2360
2387
pat : & ' p Pat < ' tcx > ,
2361
2388
constructor : & Constructor < ' tcx > ,
2362
2389
ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
2363
- ) -> Option < PatStack < ' p , ' tcx > > {
2390
+ ) -> Option < Fields < ' p , ' tcx > > {
2364
2391
if let NonExhaustive = constructor {
2365
2392
// 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 } ;
2367
2394
}
2368
2395
2369
2396
let result = match * pat. kind {
2370
2397
PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled by `expand_pattern`
2371
2398
2372
- PatKind :: Binding { .. } | PatKind :: Wild => Some ( ctor_wild_subpatterns. iter ( ) . collect ( ) ) ,
2399
+ PatKind :: Binding { .. } | PatKind :: Wild => Some ( ctor_wild_subpatterns. clone ( ) ) ,
2373
2400
2374
2401
PatKind :: Variant { adt_def, variant_index, ref subpatterns, .. } => {
2375
2402
let variant = & adt_def. variants [ variant_index] ;
@@ -2385,7 +2412,7 @@ fn specialize_one_pattern<'p, 'tcx>(
2385
2412
Some ( patterns_for_variant ( cx, subpatterns, ctor_wild_subpatterns, false ) )
2386
2413
}
2387
2414
2388
- PatKind :: Deref { ref subpattern } => Some ( PatStack :: from_pattern ( subpattern) ) ,
2415
+ PatKind :: Deref { ref subpattern } => Some ( Fields :: from_single_pattern ( subpattern) ) ,
2389
2416
2390
2417
PatKind :: Constant { value } if constructor. is_slice ( ) => {
2391
2418
// We extract an `Option` for the pointer because slices of zero
@@ -2399,7 +2426,7 @@ fn specialize_one_pattern<'p, 'tcx>(
2399
2426
// the result would be exactly what we early return here.
2400
2427
if n == 0 {
2401
2428
if ctor_wild_subpatterns. len ( ) as u64 == 0 {
2402
- return Some ( PatStack :: from_slice ( & [ ] ) ) ;
2429
+ return Some ( Fields :: empty ( ) ) ;
2403
2430
} else {
2404
2431
return None ;
2405
2432
}
@@ -2440,7 +2467,7 @@ fn specialize_one_pattern<'p, 'tcx>(
2440
2467
// convert a constant slice/array pattern to a list of patterns.
2441
2468
let layout = cx. tcx . layout_of ( cx. param_env . and ( ty) ) . ok ( ) ?;
2442
2469
let ptr = Pointer :: new ( AllocId ( 0 ) , offset) ;
2443
- ( 0 ..n)
2470
+ let pats = ( 0 ..n)
2444
2471
. map ( |i| {
2445
2472
let ptr = ptr. offset ( layout. size * i, & cx. tcx ) . ok ( ) ?;
2446
2473
let scalar = alloc. read_scalar ( & cx. tcx , ptr, layout. size ) . ok ( ) ?;
@@ -2450,7 +2477,8 @@ fn specialize_one_pattern<'p, 'tcx>(
2450
2477
Pat { ty, span : pat. span , kind : box PatKind :: Constant { value } } ;
2451
2478
Some ( & * cx. pattern_arena . alloc ( pattern) )
2452
2479
} )
2453
- . collect ( )
2480
+ . collect :: < Option < _ > > ( ) ?;
2481
+ Some ( Fields :: from_vec ( pats) )
2454
2482
} else {
2455
2483
None
2456
2484
}
@@ -2466,7 +2494,7 @@ fn specialize_one_pattern<'p, 'tcx>(
2466
2494
// Constructor splitting should ensure that all intersections we encounter
2467
2495
// are actually inclusions.
2468
2496
assert ! ( ctor. is_subrange( & pat) ) ;
2469
- PatStack :: default ( )
2497
+ Fields :: empty ( )
2470
2498
} ) ,
2471
2499
_ => None ,
2472
2500
}
@@ -2477,7 +2505,7 @@ fn specialize_one_pattern<'p, 'tcx>(
2477
2505
// range so intersection actually devolves into being covered
2478
2506
// by the pattern.
2479
2507
constructor_covered_by_range ( cx. tcx , cx. param_env , constructor, pat)
2480
- . map ( |( ) | PatStack :: default ( ) )
2508
+ . map ( |( ) | Fields :: empty ( ) )
2481
2509
}
2482
2510
}
2483
2511
@@ -2487,7 +2515,7 @@ fn specialize_one_pattern<'p, 'tcx>(
2487
2515
let pat_len = prefix. len ( ) + suffix. len ( ) ;
2488
2516
if let Some ( slice_count) = ctor_wild_subpatterns. len ( ) . checked_sub ( pat_len) {
2489
2517
if slice_count == 0 || slice. is_some ( ) {
2490
- Some (
2518
+ Some ( Fields :: from_vec (
2491
2519
prefix
2492
2520
. iter ( )
2493
2521
. chain (
@@ -2498,7 +2526,7 @@ fn specialize_one_pattern<'p, 'tcx>(
2498
2526
. chain ( suffix. iter ( ) ) ,
2499
2527
)
2500
2528
. collect ( ) ,
2501
- )
2529
+ ) )
2502
2530
} else {
2503
2531
None
2504
2532
}
@@ -2516,7 +2544,7 @@ fn specialize_one_pattern<'p, 'tcx>(
2516
2544
suffix,
2517
2545
cx. param_env ,
2518
2546
) {
2519
- Ok ( true ) => Some ( PatStack :: default ( ) ) ,
2547
+ Ok ( true ) => Some ( Fields :: empty ( ) ) ,
2520
2548
Ok ( false ) => None ,
2521
2549
Err ( ErrorReported ) => None ,
2522
2550
}
0 commit comments