@@ -2529,17 +2529,69 @@ fn specialize_one_pattern<'p, 'tcx>(
2529
2529
pat : & ' p Pat < ' tcx > ,
2530
2530
constructor : & Constructor < ' tcx > ,
2531
2531
ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
2532
- is_its_own_ctor : bool , // Whether `ctor ` is known to be derived from `pat`
2532
+ is_its_own_ctor : bool , // Whether `constructor ` is known to be derived from `pat`
2533
2533
) -> Option < Fields < ' p , ' tcx > > {
2534
- if let NonExhaustive = constructor {
2535
- // Only a wildcard pattern can match the special extra constructor.
2536
- if !pat. is_wildcard ( ) {
2537
- return None ;
2538
- }
2539
- return Some ( Fields :: empty ( ) ) ;
2534
+ if pat. is_wildcard ( ) {
2535
+ return Some ( ctor_wild_subpatterns. clone ( ) ) ;
2540
2536
}
2541
2537
2542
- if let Opaque = constructor {
2538
+ let ty = pat. ty ;
2539
+ // `unwrap` is safe because `pat` is not a wildcard.
2540
+ let pat_ctor = pat_constructor ( cx. tcx , cx. param_env , pat) . unwrap ( ) ;
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
+ }
2553
+
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 ( ) )
2560
+ }
2561
+ ( FloatRange ( ctor_from, ctor_to, ctor_end) , FloatRange ( pat_from, pat_to, pat_end) , _) => {
2562
+ let to = compare_const_vals ( cx. tcx , ctor_to, pat_to, cx. param_env , ty) ?;
2563
+ 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 }
2567
+ }
2568
+ ( Str ( ctor_val) , Str ( pat_val) , _) => {
2569
+ // FIXME: there's probably a more direct way of comparing for equality
2570
+ 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
2578
+ }
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
+
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) ) )
2593
+ }
2594
+
2543
2595
// Only a wildcard pattern can match an opaque constant, unless we're specializing the
2544
2596
// value against its own constructor. That happens when we call
2545
2597
// `v.specialize_constructor(ctor)` with `ctor` obtained from `pat_constructor(v.head())`.
@@ -2559,109 +2611,23 @@ fn specialize_one_pattern<'p, 'tcx>(
2559
2611
// (FOO, false) => {}
2560
2612
// }
2561
2613
// ```
2562
- if is_its_own_ctor || pat. is_wildcard ( ) {
2563
- return Some ( Fields :: empty ( ) ) ;
2564
- } else {
2565
- return None ;
2566
- }
2567
- }
2568
-
2569
- let result = match * pat. kind {
2570
- PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled by `expand_pattern`
2571
-
2572
- PatKind :: Binding { .. } | PatKind :: Wild => Some ( ctor_wild_subpatterns. clone ( ) ) ,
2573
-
2574
- PatKind :: Variant { adt_def, variant_index, ref subpatterns, .. } => {
2575
- let variant = & adt_def. variants [ variant_index] ;
2576
- if constructor != & Variant ( variant. def_id ) {
2577
- return None ;
2578
- }
2579
- Some ( ctor_wild_subpatterns. replace_with_fieldpats ( subpatterns) )
2580
- }
2581
-
2582
- PatKind :: Leaf { ref subpatterns } => {
2583
- Some ( ctor_wild_subpatterns. replace_with_fieldpats ( subpatterns) )
2584
- }
2585
-
2586
- PatKind :: Deref { ref subpattern } => Some ( Fields :: from_single_pattern ( subpattern) ) ,
2587
-
2588
- PatKind :: Constant { .. } | PatKind :: Range { .. } => {
2589
- match constructor {
2590
- IntRange ( ctor) => {
2591
- let pat = IntRange :: from_pat ( cx. tcx , cx. param_env , pat) ?;
2592
- ctor. intersection ( cx. tcx , & pat) ?;
2593
- // Constructor splitting should ensure that all intersections we encounter
2594
- // are actually inclusions.
2595
- assert ! ( ctor. is_subrange( & pat) ) ;
2596
- }
2597
- FloatRange ( ctor_from, ctor_to, ctor_end) => {
2598
- let ( pat_from, pat_to, pat_end, ty) = match * pat. kind {
2599
- PatKind :: Constant { value } => ( value, value, RangeEnd :: Included , value. ty ) ,
2600
- PatKind :: Range ( PatRange { lo, hi, end } ) => ( lo, hi, end, lo. ty ) ,
2601
- _ => unreachable ! ( ) , // This is ensured by the branch we're in
2602
- } ;
2603
- let to = compare_const_vals ( cx. tcx , ctor_to, pat_to, cx. param_env , ty) ?;
2604
- let from = compare_const_vals ( cx. tcx , ctor_from, pat_from, cx. param_env , ty) ?;
2605
- let intersects = ( from == Ordering :: Greater || from == Ordering :: Equal )
2606
- && ( to == Ordering :: Less
2607
- || ( pat_end == * ctor_end && to == Ordering :: Equal ) ) ;
2608
- if !intersects {
2609
- return None ;
2610
- }
2611
- }
2612
- Str ( ctor_value) => {
2613
- let pat_value = match * pat. kind {
2614
- PatKind :: Constant { value } => value,
2615
- _ => span_bug ! (
2616
- pat. span,
2617
- "unexpected range pattern {:?} for constant value ctor" ,
2618
- pat
2619
- ) ,
2620
- } ;
2621
-
2622
- // FIXME: there's probably a more direct way of comparing for equality
2623
- if compare_const_vals ( cx. tcx , ctor_value, pat_value, cx. param_env , pat. ty ) ?
2624
- != Ordering :: Equal
2625
- {
2626
- return None ;
2627
- }
2628
- }
2629
- _ => {
2630
- // If we reach here, we must be trying to inspect an opaque constant. Thus we skip
2631
- // the row.
2632
- return None ;
2633
- }
2634
- }
2635
- Some ( Fields :: empty ( ) )
2636
- }
2637
-
2638
- PatKind :: Array { ref prefix, ref slice, ref suffix }
2639
- | PatKind :: Slice { ref prefix, ref slice, ref suffix } => match * constructor {
2640
- Slice ( _) => {
2641
- // Number of subpatterns for this pattern
2642
- let pat_len = prefix. len ( ) + suffix. len ( ) ;
2643
- // Number of subpatterns for this constructor
2644
- let arity = ctor_wild_subpatterns. len ( ) ;
2645
-
2646
- if ( slice. is_none ( ) && arity != pat_len) || pat_len > arity {
2647
- return None ;
2648
- }
2649
-
2650
- // Replace the prefix and the suffix with the given patterns, leaving wildcards in
2651
- // the middle if there was a subslice pattern `..`.
2652
- let prefix = prefix. iter ( ) . enumerate ( ) ;
2653
- let suffix = suffix. iter ( ) . enumerate ( ) . map ( |( i, p) | ( arity - suffix. len ( ) + i, p) ) ;
2654
- Some ( ctor_wild_subpatterns. replace_fields_indexed ( prefix. chain ( suffix) ) )
2655
- }
2656
- _ => span_bug ! ( pat. span, "unexpected ctor {:?} for slice pat" , constructor) ,
2657
- } ,
2614
+ ( Opaque , Opaque , _) if is_its_own_ctor => Some ( Fields :: empty ( ) ) ,
2615
+ // We are trying to inspect an opaque constant. Thus we skip the row.
2616
+ ( Opaque , _, _) | ( _, Opaque , _) => None ,
2617
+ // Only a wildcard pattern can match the special extra constructor.
2618
+ ( NonExhaustive , _, _) => None ,
2658
2619
2659
- PatKind :: Or { .. } => bug ! ( "Or-pattern should have been expanded earlier on." ) ,
2620
+ _ => bug ! ( "trying to specialize pattern {:?} with constructor {:?}" , pat , constructor ) ,
2660
2621
} ;
2622
+
2661
2623
debug ! (
2662
2624
"specialize({:#?}, {:#?}, {:#?}) = {:#?}" ,
2663
2625
pat, constructor, ctor_wild_subpatterns, result
2664
2626
) ;
2665
2627
2628
+ if let Some ( fields) = & result {
2629
+ debug_assert_eq ! ( fields. len( ) , ctor_wild_subpatterns. len( ) ) ;
2630
+ }
2631
+
2666
2632
result
2667
2633
}
0 commit comments