@@ -2529,17 +2529,69 @@ fn specialize_one_pattern<'p, 'tcx>(
25292529 pat : & ' p Pat < ' tcx > ,
25302530 constructor : & Constructor < ' tcx > ,
25312531 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`
25332533) -> 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 ( ) ) ;
25402536 }
25412537
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+
25432595 // Only a wildcard pattern can match an opaque constant, unless we're specializing the
25442596 // value against its own constructor. That happens when we call
25452597 // `v.specialize_constructor(ctor)` with `ctor` obtained from `pat_constructor(v.head())`.
@@ -2559,109 +2611,23 @@ fn specialize_one_pattern<'p, 'tcx>(
25592611 // (FOO, false) => {}
25602612 // }
25612613 // ```
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 ,
26582619
2659- PatKind :: Or { .. } => bug ! ( "Or-pattern should have been expanded earlier on." ) ,
2620+ _ => bug ! ( "trying to specialize pattern {:?} with constructor {:?}" , pat , constructor ) ,
26602621 } ;
2622+
26612623 debug ! (
26622624 "specialize({:#?}, {:#?}, {:#?}) = {:#?}" ,
26632625 pat, constructor, ctor_wild_subpatterns, result
26642626 ) ;
26652627
2628+ if let Some ( fields) = & result {
2629+ debug_assert_eq ! ( fields. len( ) , ctor_wild_subpatterns. len( ) ) ;
2630+ }
2631+
26662632 result
26672633}
0 commit comments