@@ -2390,7 +2390,10 @@ fn specialize_one_pattern<'p, 'tcx>(
2390
2390
) -> Option < Fields < ' p , ' tcx > > {
2391
2391
if let NonExhaustive = constructor {
2392
2392
// Only a wildcard pattern can match the special extra constructor
2393
- return if pat. is_wildcard ( ) { Some ( Fields :: empty ( ) ) } else { None } ;
2393
+ if !pat. is_wildcard ( ) {
2394
+ return None ;
2395
+ }
2396
+ return Some ( Fields :: empty ( ) ) ;
2394
2397
}
2395
2398
2396
2399
let result = match * pat. kind {
@@ -2400,12 +2403,11 @@ fn specialize_one_pattern<'p, 'tcx>(
2400
2403
2401
2404
PatKind :: Variant { adt_def, variant_index, ref subpatterns, .. } => {
2402
2405
let variant = & adt_def. variants [ variant_index] ;
2406
+ if constructor != & Variant ( variant. def_id ) {
2407
+ return None ;
2408
+ }
2403
2409
let is_non_exhaustive = cx. is_foreign_non_exhaustive_variant ( pat. ty , variant) ;
2404
- Some ( Variant ( variant. def_id ) )
2405
- . filter ( |variant_constructor| variant_constructor == constructor)
2406
- . map ( |_| {
2407
- patterns_for_variant ( cx, subpatterns, ctor_wild_subpatterns, is_non_exhaustive)
2408
- } )
2410
+ Some ( patterns_for_variant ( cx, subpatterns, ctor_wild_subpatterns, is_non_exhaustive) )
2409
2411
}
2410
2412
2411
2413
PatKind :: Leaf { ref subpatterns } => {
@@ -2425,11 +2427,10 @@ fn specialize_one_pattern<'p, 'tcx>(
2425
2427
// Shortcut for `n == 0` where no matter what `alloc` and `offset` we produce,
2426
2428
// the result would be exactly what we early return here.
2427
2429
if n == 0 {
2428
- if ctor_wild_subpatterns. len ( ) as u64 == 0 {
2429
- return Some ( Fields :: empty ( ) ) ;
2430
- } else {
2430
+ if ctor_wild_subpatterns. len ( ) as u64 != n {
2431
2431
return None ;
2432
2432
}
2433
+ return Some ( Fields :: empty ( ) ) ;
2433
2434
}
2434
2435
match value. val {
2435
2436
ty:: ConstKind :: Value ( ConstValue :: ByRef { offset, alloc, .. } ) => {
@@ -2463,76 +2464,66 @@ fn specialize_one_pattern<'p, 'tcx>(
2463
2464
constructor,
2464
2465
) ,
2465
2466
} ;
2466
- if ctor_wild_subpatterns. len ( ) as u64 == n {
2467
- // convert a constant slice/array pattern to a list of patterns.
2468
- let layout = cx. tcx . layout_of ( cx. param_env . and ( ty) ) . ok ( ) ?;
2469
- let ptr = Pointer :: new ( AllocId ( 0 ) , offset) ;
2470
- let pats = ( 0 ..n)
2471
- . map ( |i| {
2472
- let ptr = ptr. offset ( layout. size * i, & cx. tcx ) . ok ( ) ?;
2473
- let scalar = alloc. read_scalar ( & cx. tcx , ptr, layout. size ) . ok ( ) ?;
2474
- let scalar = scalar. not_undef ( ) . ok ( ) ?;
2475
- let value = ty:: Const :: from_scalar ( cx. tcx , scalar, ty) ;
2476
- let pattern =
2477
- Pat { ty, span : pat. span , kind : box PatKind :: Constant { value } } ;
2478
- Some ( & * cx. pattern_arena . alloc ( pattern) )
2479
- } )
2480
- . collect :: < Option < _ > > ( ) ?;
2481
- Some ( Fields :: from_vec ( pats) )
2482
- } else {
2483
- None
2467
+ if ctor_wild_subpatterns. len ( ) as u64 != n {
2468
+ return None ;
2484
2469
}
2470
+ // Convert a constant slice/array pattern to a list of patterns.
2471
+ let layout = cx. tcx . layout_of ( cx. param_env . and ( ty) ) . ok ( ) ?;
2472
+ let ptr = Pointer :: new ( AllocId ( 0 ) , offset) ;
2473
+ let pats = ( 0 ..n)
2474
+ . map ( |i| {
2475
+ let ptr = ptr. offset ( layout. size * i, & cx. tcx ) . ok ( ) ?;
2476
+ let scalar = alloc. read_scalar ( & cx. tcx , ptr, layout. size ) . ok ( ) ?;
2477
+ let scalar = scalar. not_undef ( ) . ok ( ) ?;
2478
+ let value = ty:: Const :: from_scalar ( cx. tcx , scalar, ty) ;
2479
+ let pattern = Pat { ty, span : pat. span , kind : box PatKind :: Constant { value } } ;
2480
+ Some ( & * cx. pattern_arena . alloc ( pattern) )
2481
+ } )
2482
+ . collect :: < Option < _ > > ( ) ?;
2483
+ Some ( Fields :: from_vec ( pats) )
2485
2484
}
2486
2485
2487
2486
PatKind :: Constant { .. } | PatKind :: Range { .. } => {
2488
2487
// If the constructor is a:
2489
2488
// - Single value: add a row if the pattern contains the constructor.
2490
2489
// - Range: add a row if the constructor intersects the pattern.
2491
2490
if let IntRange ( ctor) = constructor {
2492
- match IntRange :: from_pat ( cx. tcx , cx. param_env , pat) {
2493
- Some ( pat) => ctor. intersection ( cx. tcx , & pat) . map ( |_| {
2494
- // Constructor splitting should ensure that all intersections we encounter
2495
- // are actually inclusions.
2496
- assert ! ( ctor. is_subrange( & pat) ) ;
2497
- Fields :: empty ( )
2498
- } ) ,
2499
- _ => None ,
2500
- }
2491
+ let pat = IntRange :: from_pat ( cx. tcx , cx. param_env , pat) ?;
2492
+ ctor. intersection ( cx. tcx , & pat) ?;
2493
+ // Constructor splitting should ensure that all intersections we encounter
2494
+ // are actually inclusions.
2495
+ assert ! ( ctor. is_subrange( & pat) ) ;
2501
2496
} else {
2502
2497
// Fallback for non-ranges and ranges that involve
2503
2498
// floating-point numbers, which are not conveniently handled
2504
2499
// by `IntRange`. For these cases, the constructor may not be a
2505
2500
// range so intersection actually devolves into being covered
2506
2501
// by the pattern.
2507
- constructor_covered_by_range ( cx. tcx , cx. param_env , constructor, pat)
2508
- . map ( |( ) | Fields :: empty ( ) )
2502
+ constructor_covered_by_range ( cx. tcx , cx. param_env , constructor, pat) ?;
2509
2503
}
2504
+ Some ( Fields :: empty ( ) )
2510
2505
}
2511
2506
2512
2507
PatKind :: Array { ref prefix, ref slice, ref suffix }
2513
2508
| PatKind :: Slice { ref prefix, ref slice, ref suffix } => match * constructor {
2514
2509
Slice ( _) => {
2510
+ // Number of subpatterns for this pattern
2515
2511
let pat_len = prefix. len ( ) + suffix. len ( ) ;
2516
- if let Some ( slice_count) = ctor_wild_subpatterns. len ( ) . checked_sub ( pat_len) {
2517
- if slice_count == 0 || slice. is_some ( ) {
2518
- Some ( Fields :: from_vec (
2519
- prefix
2520
- . iter ( )
2521
- . chain (
2522
- ctor_wild_subpatterns
2523
- . iter ( )
2524
- . skip ( prefix. len ( ) )
2525
- . take ( slice_count)
2526
- . chain ( suffix. iter ( ) ) ,
2527
- )
2528
- . collect ( ) ,
2529
- ) )
2530
- } else {
2531
- None
2532
- }
2533
- } else {
2534
- None
2512
+ // Number of subpatterns for this constructor
2513
+ let arity = ctor_wild_subpatterns. len ( ) ;
2514
+
2515
+ if slice. is_none ( ) && arity != pat_len {
2516
+ return None ;
2535
2517
}
2518
+
2519
+ // Number of subpatterns matched by the `..` subslice pattern (is 0 for a slice
2520
+ // pattern of fixed length).
2521
+ let subslice_count = arity. checked_sub ( pat_len) ?;
2522
+ let subslice_pats =
2523
+ ctor_wild_subpatterns. iter ( ) . skip ( prefix. len ( ) ) . take ( subslice_count) ;
2524
+ Some ( Fields :: from_vec (
2525
+ prefix. iter ( ) . chain ( subslice_pats) . chain ( suffix. iter ( ) ) . collect ( ) ,
2526
+ ) )
2536
2527
}
2537
2528
ConstantValue ( cv) => {
2538
2529
match slice_pat_covered_by_const (
0 commit comments