@@ -2527,9 +2527,9 @@ fn pat_constructor<'tcx>(
2527
2527
fn specialize_one_pattern < ' p , ' tcx > (
2528
2528
cx : & MatchCheckCtxt < ' p , ' tcx > ,
2529
2529
pat : & ' p Pat < ' tcx > ,
2530
- constructor : & Constructor < ' tcx > ,
2530
+ ctor : & Constructor < ' tcx > ,
2531
2531
ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
2532
- is_its_own_ctor : bool , // Whether `constructor ` is known to be derived from `pat`
2532
+ is_its_own_ctor : bool , // Whether `ctor ` is known to be derived from `pat`
2533
2533
) -> Option < Fields < ' p , ' tcx > > {
2534
2534
if pat. is_wildcard ( ) {
2535
2535
return Some ( ctor_wild_subpatterns. clone ( ) ) ;
@@ -2539,57 +2539,34 @@ fn specialize_one_pattern<'p, 'tcx>(
2539
2539
// `unwrap` is safe because `pat` is not a wildcard.
2540
2540
let pat_ctor = pat_constructor ( cx. tcx , cx. param_env , pat) . unwrap ( ) ;
2541
2541
2542
- let result = match ( constructor, & pat_ctor, pat. kind . as_ref ( ) ) {
2543
- ( Single , Single , PatKind :: Leaf { subpatterns } ) => {
2544
- Some ( ctor_wild_subpatterns. replace_with_fieldpats ( subpatterns) )
2545
- }
2546
- ( Single , Single , PatKind :: Deref { subpattern } ) => {
2547
- Some ( Fields :: from_single_pattern ( subpattern) )
2548
- }
2549
- ( Variant ( _) , Variant ( _) , _) if constructor != & pat_ctor => None ,
2550
- ( Variant ( _) , Variant ( _) , PatKind :: Variant { subpatterns, .. } ) => {
2551
- Some ( ctor_wild_subpatterns. replace_with_fieldpats ( subpatterns) )
2552
- }
2542
+ let ctor_covered_by_pat = match ( ctor, & pat_ctor) {
2543
+ ( Single , Single ) => true ,
2544
+ ( Variant ( ctor_id) , Variant ( pat_id) ) => ctor_id == pat_id,
2553
2545
2554
- ( IntRange ( ctor_range) , IntRange ( pat_range) , _) => {
2555
- ctor_range. intersection ( cx. tcx , & pat_range) ?;
2556
- // Constructor splitting should ensure that all intersections we encounter
2557
- // are actually inclusions.
2558
- assert ! ( ctor_range. is_subrange( & pat_range) ) ;
2559
- Some ( Fields :: empty ( ) )
2546
+ ( IntRange ( ctor_range) , IntRange ( pat_range) ) => {
2547
+ if ctor_range. intersection ( cx. tcx , pat_range) . is_some ( ) {
2548
+ // Constructor splitting should ensure that all intersections we encounter
2549
+ // are actually inclusions.
2550
+ assert ! ( ctor_range. is_subrange( pat_range) ) ;
2551
+ true
2552
+ } else {
2553
+ false
2554
+ }
2560
2555
}
2561
- ( FloatRange ( ctor_from, ctor_to, ctor_end) , FloatRange ( pat_from, pat_to, pat_end) , _ ) => {
2556
+ ( FloatRange ( ctor_from, ctor_to, ctor_end) , FloatRange ( pat_from, pat_to, pat_end) ) => {
2562
2557
let to = compare_const_vals ( cx. tcx , ctor_to, pat_to, cx. param_env , ty) ?;
2563
2558
let from = compare_const_vals ( cx. tcx , ctor_from, pat_from, cx. param_env , ty) ?;
2564
- let intersects = ( from == Ordering :: Greater || from == Ordering :: Equal )
2565
- && ( to == Ordering :: Less || ( pat_end == ctor_end && to == Ordering :: Equal ) ) ;
2566
- if intersects { Some ( Fields :: empty ( ) ) } else { None }
2559
+ ( from == Ordering :: Greater || from == Ordering :: Equal )
2560
+ && ( to == Ordering :: Less || ( pat_end == ctor_end && to == Ordering :: Equal ) )
2567
2561
}
2568
- ( Str ( ctor_val) , Str ( pat_val) , _ ) => {
2562
+ ( Str ( ctor_val) , Str ( pat_val) ) => {
2569
2563
// FIXME: there's probably a more direct way of comparing for equality
2570
2564
let comparison = compare_const_vals ( cx. tcx , ctor_val, pat_val, cx. param_env , ty) ?;
2571
- if comparison == Ordering :: Equal { Some ( Fields :: empty ( ) ) } else { None }
2572
- }
2573
-
2574
- ( Slice ( ctor_slice) , Slice ( pat_slice) , _)
2575
- if !pat_slice. pattern_kind ( ) . covers_length ( ctor_slice. arity ( ) ) =>
2576
- {
2577
- None
2565
+ comparison == Ordering :: Equal
2578
2566
}
2579
- (
2580
- Slice ( ctor_slice) ,
2581
- Slice ( _) ,
2582
- PatKind :: Array { prefix, suffix, .. } | PatKind :: Slice { prefix, suffix, .. } ,
2583
- ) => {
2584
- // Number of subpatterns for the constructor
2585
- let ctor_arity = ctor_slice. arity ( ) ;
2586
2567
2587
- // Replace the prefix and the suffix with the given patterns, leaving wildcards in
2588
- // the middle if there was a subslice pattern `..`.
2589
- let prefix = prefix. iter ( ) . enumerate ( ) ;
2590
- let suffix =
2591
- suffix. iter ( ) . enumerate ( ) . map ( |( i, p) | ( ctor_arity as usize - suffix. len ( ) + i, p) ) ;
2592
- Some ( ctor_wild_subpatterns. replace_fields_indexed ( prefix. chain ( suffix) ) )
2568
+ ( Slice ( ctor_slice) , Slice ( pat_slice) ) => {
2569
+ pat_slice. pattern_kind ( ) . covers_length ( ctor_slice. arity ( ) )
2593
2570
}
2594
2571
2595
2572
// Only a wildcard pattern can match an opaque constant, unless we're specializing the
@@ -2611,23 +2588,38 @@ fn specialize_one_pattern<'p, 'tcx>(
2611
2588
// (FOO, false) => {}
2612
2589
// }
2613
2590
// ```
2614
- ( Opaque , Opaque , _ ) if is_its_own_ctor => Some ( Fields :: empty ( ) ) ,
2591
+ ( Opaque , Opaque ) if is_its_own_ctor => true ,
2615
2592
// We are trying to inspect an opaque constant. Thus we skip the row.
2616
- ( Opaque , _, _ ) | ( _, Opaque , _ ) => None ,
2593
+ ( Opaque , _) | ( _, Opaque ) => false ,
2617
2594
// Only a wildcard pattern can match the special extra constructor.
2618
- ( NonExhaustive , _, _ ) => None ,
2595
+ ( NonExhaustive , _) => false ,
2619
2596
2620
- _ => bug ! ( "trying to specialize pattern {:?} with constructor {:?}" , pat, constructor ) ,
2597
+ _ => bug ! ( "trying to specialize pattern {:?} with constructor {:?}" , pat, ctor ) ,
2621
2598
} ;
2622
2599
2623
- debug ! (
2624
- "specialize({:#?}, {:#?}, {:#?}) = {:#?}" ,
2625
- pat, constructor, ctor_wild_subpatterns, result
2626
- ) ;
2627
-
2628
- if let Some ( fields) = & result {
2629
- debug_assert_eq ! ( fields. len( ) , ctor_wild_subpatterns. len( ) ) ;
2600
+ if !ctor_covered_by_pat {
2601
+ return None ;
2630
2602
}
2631
2603
2632
- result
2604
+ let fields = match pat. kind . as_ref ( ) {
2605
+ PatKind :: Deref { subpattern } => Fields :: from_single_pattern ( subpattern) ,
2606
+ PatKind :: Leaf { subpatterns } | PatKind :: Variant { subpatterns, .. } => {
2607
+ ctor_wild_subpatterns. replace_with_fieldpats ( subpatterns)
2608
+ }
2609
+ PatKind :: Array { prefix, suffix, .. } | PatKind :: Slice { prefix, suffix, .. } => {
2610
+ // Number of subpatterns for the constructor
2611
+ let ctor_arity = ctor_wild_subpatterns. len ( ) ;
2612
+
2613
+ // Replace the prefix and the suffix with the given patterns, leaving wildcards in
2614
+ // the middle if there was a subslice pattern `..`.
2615
+ let prefix = prefix. iter ( ) . enumerate ( ) ;
2616
+ let suffix = suffix. iter ( ) . enumerate ( ) . map ( |( i, p) | ( ctor_arity - suffix. len ( ) + i, p) ) ;
2617
+ ctor_wild_subpatterns. replace_fields_indexed ( prefix. chain ( suffix) )
2618
+ }
2619
+ _ => ctor_wild_subpatterns. clone ( ) ,
2620
+ } ;
2621
+
2622
+ debug ! ( "specialize({:#?}, {:#?}, {:#?}) = {:#?}" , pat, ctor, ctor_wild_subpatterns, fields) ;
2623
+
2624
+ Some ( fields)
2633
2625
}
0 commit comments