@@ -394,9 +394,15 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
394
394
cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
395
395
constructor : & Constructor < ' tcx > ,
396
396
ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
397
+ is_my_head_ctor : bool ,
397
398
) -> Option < PatStack < ' p , ' tcx > > {
398
- let new_fields =
399
- specialize_one_pattern ( cx, self . head ( ) , constructor, ctor_wild_subpatterns) ?;
399
+ let new_fields = specialize_one_pattern (
400
+ cx,
401
+ self . head ( ) ,
402
+ constructor,
403
+ ctor_wild_subpatterns,
404
+ is_my_head_ctor,
405
+ ) ?;
400
406
Some ( new_fields. push_on_patstack ( & self . 0 [ 1 ..] ) )
401
407
}
402
408
}
@@ -574,6 +580,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
574
580
cx,
575
581
constructor,
576
582
ctor_wild_subpatterns,
583
+ false ,
577
584
)
578
585
} )
579
586
. collect ( )
@@ -599,7 +606,9 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
599
606
SpecializationCache :: Incompatible => self
600
607
. patterns
601
608
. iter ( )
602
- . filter_map ( |r| r. specialize_constructor ( cx, constructor, ctor_wild_subpatterns) )
609
+ . filter_map ( |r| {
610
+ r. specialize_constructor ( cx, constructor, ctor_wild_subpatterns, false )
611
+ } )
603
612
. collect ( ) ,
604
613
}
605
614
}
@@ -821,8 +830,6 @@ enum Constructor<'tcx> {
821
830
Single ,
822
831
/// Enum variants.
823
832
Variant ( DefId ) ,
824
- /// Literal values.
825
- ConstantValue ( & ' tcx ty:: Const < ' tcx > ) ,
826
833
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
827
834
IntRange ( IntRange < ' tcx > ) ,
828
835
/// Ranges of floating-point literal values (`2.0..=5.2`).
@@ -831,27 +838,22 @@ enum Constructor<'tcx> {
831
838
Str ( & ' tcx ty:: Const < ' tcx > ) ,
832
839
/// Array and slice patterns.
833
840
Slice ( Slice ) ,
841
+ /// Constants that must not be matched structurally. They are treated as black
842
+ /// boxes for the purposes of exhaustiveness: we must not inspect them, and they
843
+ /// don't count towards making a match exhaustive.
844
+ Opaque ,
834
845
/// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
835
846
NonExhaustive ,
836
847
}
837
848
838
849
impl < ' tcx > Constructor < ' tcx > {
839
- fn variant_index_for_adt < ' a > (
840
- & self ,
841
- cx : & MatchCheckCtxt < ' a , ' tcx > ,
842
- adt : & ' tcx ty:: AdtDef ,
843
- ) -> VariantIdx {
850
+ fn variant_index_for_adt ( & self , adt : & ' tcx ty:: AdtDef ) -> VariantIdx {
844
851
match * self {
845
852
Variant ( id) => adt. variant_index_with_id ( id) ,
846
853
Single => {
847
854
assert ! ( !adt. is_enum( ) ) ;
848
855
VariantIdx :: new ( 0 )
849
856
}
850
- ConstantValue ( c) => cx
851
- . tcx
852
- . destructure_const ( cx. param_env . and ( c) )
853
- . variant
854
- . expect ( "destructed const of adt without variant id" ) ,
855
857
_ => bug ! ( "bad constructor {:?} for adt {:?}" , self , adt) ,
856
858
}
857
859
}
@@ -865,7 +867,7 @@ impl<'tcx> Constructor<'tcx> {
865
867
866
868
match self {
867
869
// Those constructors can only match themselves.
868
- Single | Variant ( _) | ConstantValue ( .. ) | Str ( ..) | FloatRange ( ..) => {
870
+ Single | Variant ( _) | Str ( ..) | FloatRange ( ..) => {
869
871
if other_ctors. iter ( ) . any ( |c| c == self ) { vec ! [ ] } else { vec ! [ self . clone( ) ] }
870
872
}
871
873
& Slice ( slice) => {
@@ -936,6 +938,7 @@ impl<'tcx> Constructor<'tcx> {
936
938
}
937
939
// This constructor is never covered by anything else
938
940
NonExhaustive => vec ! [ NonExhaustive ] ,
941
+ Opaque => bug ! ( "unexpected opaque ctor {:?} found in all_ctors" , self ) ,
939
942
}
940
943
}
941
944
@@ -975,7 +978,7 @@ impl<'tcx> Constructor<'tcx> {
975
978
PatKind :: Variant {
976
979
adt_def : adt,
977
980
substs,
978
- variant_index : self . variant_index_for_adt ( cx , adt) ,
981
+ variant_index : self . variant_index_for_adt ( adt) ,
979
982
subpatterns,
980
983
}
981
984
} else {
@@ -1014,11 +1017,11 @@ impl<'tcx> Constructor<'tcx> {
1014
1017
PatKind :: Slice { prefix, slice : Some ( wild) , suffix }
1015
1018
}
1016
1019
} ,
1017
- & ConstantValue ( value) => PatKind :: Constant { value } ,
1018
1020
& Str ( value) => PatKind :: Constant { value } ,
1019
1021
& FloatRange ( lo, hi, end) => PatKind :: Range ( PatRange { lo, hi, end } ) ,
1020
1022
IntRange ( range) => return range. to_pat ( cx. tcx ) ,
1021
1023
NonExhaustive => PatKind :: Wild ,
1024
+ Opaque => bug ! ( "we should not try to apply an opaque constructor {:?}" , self ) ,
1022
1025
} ;
1023
1026
1024
1027
Pat { ty, span : DUMMY_SP , kind : Box :: new ( pat) }
@@ -1122,7 +1125,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1122
1125
// Use T as the sub pattern type of Box<T>.
1123
1126
Fields :: from_single_pattern ( wildcard_from_ty ( substs. type_at ( 0 ) ) )
1124
1127
} else {
1125
- let variant = & adt. variants [ constructor. variant_index_for_adt ( cx , adt) ] ;
1128
+ let variant = & adt. variants [ constructor. variant_index_for_adt ( adt) ] ;
1126
1129
// Whether we must not match the fields of this variant exhaustively.
1127
1130
let is_non_exhaustive =
1128
1131
variant. is_field_list_non_exhaustive ( ) && !adt. did . is_local ( ) ;
@@ -1170,9 +1173,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1170
1173
}
1171
1174
_ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, ty) ,
1172
1175
} ,
1173
- ConstantValue ( ..) | Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive => {
1174
- Fields :: empty ( )
1175
- }
1176
+ Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque => Fields :: empty ( ) ,
1176
1177
} ;
1177
1178
debug ! ( "Fields::wildcards({:?}, {:?}) = {:#?}" , constructor, ty, ret) ;
1178
1179
ret
@@ -2085,7 +2086,7 @@ fn is_useful_specialized<'p, 'tcx>(
2085
2086
// We cache the result of `Fields::wildcards` because it is used a lot.
2086
2087
let ctor_wild_subpatterns = Fields :: wildcards ( cx, & ctor, ty) ;
2087
2088
let matrix = matrix. specialize_constructor ( cx, & ctor, & ctor_wild_subpatterns) ;
2088
- v. specialize_constructor ( cx, & ctor, & ctor_wild_subpatterns)
2089
+ v. specialize_constructor ( cx, & ctor, & ctor_wild_subpatterns, true )
2089
2090
. map ( |v| is_useful ( cx, & matrix, & v, witness_preference, hir_id, is_under_guard, false ) )
2090
2091
. map ( |u| u. apply_constructor ( cx, & ctor, ty, & ctor_wild_subpatterns) )
2091
2092
. unwrap_or ( NotUseful )
@@ -2112,7 +2113,7 @@ fn pat_constructor<'tcx>(
2112
2113
match value. ty . kind ( ) {
2113
2114
ty:: Float ( _) => Some ( FloatRange ( value, value, RangeEnd :: Included ) ) ,
2114
2115
ty:: Ref ( _, t, _) if t. is_str ( ) => Some ( Str ( value) ) ,
2115
- _ => Some ( ConstantValue ( value ) ) ,
2116
+ _ => Some ( Opaque ) ,
2116
2117
}
2117
2118
}
2118
2119
}
@@ -2461,15 +2462,26 @@ fn specialize_one_pattern<'p, 'tcx>(
2461
2462
pat : & ' p Pat < ' tcx > ,
2462
2463
constructor : & Constructor < ' tcx > ,
2463
2464
ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
2465
+ is_its_own_ctor : bool , // Whether `ctor` is known to be derived from `pat`
2464
2466
) -> Option < Fields < ' p , ' tcx > > {
2465
2467
if let NonExhaustive = constructor {
2466
- // Only a wildcard pattern can match the special extra constructor
2468
+ // Only a wildcard pattern can match the special extra constructor.
2467
2469
if !pat. is_wildcard ( ) {
2468
2470
return None ;
2469
2471
}
2470
2472
return Some ( Fields :: empty ( ) ) ;
2471
2473
}
2472
2474
2475
+ if let Opaque = constructor {
2476
+ // Only a wildcard pattern can match an opaque constant, unless we're specializing the
2477
+ // value against its own constructor.
2478
+ if is_its_own_ctor || pat. is_wildcard ( ) {
2479
+ return Some ( Fields :: empty ( ) ) ;
2480
+ } else {
2481
+ return None ;
2482
+ }
2483
+ }
2484
+
2473
2485
let result = match * pat. kind {
2474
2486
PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled by `expand_pattern`
2475
2487
@@ -2491,7 +2503,6 @@ fn specialize_one_pattern<'p, 'tcx>(
2491
2503
2492
2504
PatKind :: Constant { .. } | PatKind :: Range { .. } => {
2493
2505
match constructor {
2494
- Single => { }
2495
2506
IntRange ( ctor) => {
2496
2507
let pat = IntRange :: from_pat ( cx. tcx , cx. param_env , pat) ?;
2497
2508
ctor. intersection ( cx. tcx , & pat) ?;
@@ -2514,7 +2525,7 @@ fn specialize_one_pattern<'p, 'tcx>(
2514
2525
return None ;
2515
2526
}
2516
2527
}
2517
- ConstantValue ( ctor_value ) | Str ( ctor_value) => {
2528
+ Str ( ctor_value) => {
2518
2529
let pat_value = match * pat. kind {
2519
2530
PatKind :: Constant { value } => value,
2520
2531
_ => span_bug ! (
@@ -2532,7 +2543,9 @@ fn specialize_one_pattern<'p, 'tcx>(
2532
2543
}
2533
2544
}
2534
2545
_ => {
2535
- span_bug ! ( pat. span, "unexpected pattern {:?} with ctor {:?}" , pat, constructor)
2546
+ // If we reach here, we must be trying to inspect an opaque constant. Thus we skip
2547
+ // the row.
2548
+ return None ;
2536
2549
}
2537
2550
}
2538
2551
Some ( Fields :: empty ( ) )
0 commit comments