@@ -2527,9 +2527,9 @@ fn pat_constructor<'tcx>(
25272527fn specialize_one_pattern < ' p , ' tcx > (
25282528 cx : & MatchCheckCtxt < ' p , ' tcx > ,
25292529 pat : & ' p Pat < ' tcx > ,
2530- constructor : & Constructor < ' tcx > ,
2530+ ctor : & Constructor < ' tcx > ,
25312531 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`
25332533) -> Option < Fields < ' p , ' tcx > > {
25342534 if pat. is_wildcard ( ) {
25352535 return Some ( ctor_wild_subpatterns. clone ( ) ) ;
@@ -2539,57 +2539,34 @@ fn specialize_one_pattern<'p, 'tcx>(
25392539 // `unwrap` is safe because `pat` is not a wildcard.
25402540 let pat_ctor = pat_constructor ( cx. tcx , cx. param_env , pat) . unwrap ( ) ;
25412541
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,
25532545
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+ }
25602555 }
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) ) => {
25622557 let to = compare_const_vals ( cx. tcx , ctor_to, pat_to, cx. param_env , ty) ?;
25632558 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 ) )
25672561 }
2568- ( Str ( ctor_val) , Str ( pat_val) , _ ) => {
2562+ ( Str ( ctor_val) , Str ( pat_val) ) => {
25692563 // FIXME: there's probably a more direct way of comparing for equality
25702564 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
25782566 }
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 ( ) ;
25862567
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 ( ) )
25932570 }
25942571
25952572 // Only a wildcard pattern can match an opaque constant, unless we're specializing the
@@ -2611,23 +2588,38 @@ fn specialize_one_pattern<'p, 'tcx>(
26112588 // (FOO, false) => {}
26122589 // }
26132590 // ```
2614- ( Opaque , Opaque , _ ) if is_its_own_ctor => Some ( Fields :: empty ( ) ) ,
2591+ ( Opaque , Opaque ) if is_its_own_ctor => true ,
26152592 // We are trying to inspect an opaque constant. Thus we skip the row.
2616- ( Opaque , _, _ ) | ( _, Opaque , _ ) => None ,
2593+ ( Opaque , _) | ( _, Opaque ) => false ,
26172594 // Only a wildcard pattern can match the special extra constructor.
2618- ( NonExhaustive , _, _ ) => None ,
2595+ ( NonExhaustive , _) => false ,
26192596
2620- _ => bug ! ( "trying to specialize pattern {:?} with constructor {:?}" , pat, constructor ) ,
2597+ _ => bug ! ( "trying to specialize pattern {:?} with constructor {:?}" , pat, ctor ) ,
26212598 } ;
26222599
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 ;
26302602 }
26312603
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)
26332625}
0 commit comments