@@ -394,9 +394,15 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
394394 cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
395395 constructor : & Constructor < ' tcx > ,
396396 ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
397+ is_my_head_ctor : bool ,
397398 ) -> 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+ ) ?;
400406 Some ( new_fields. push_on_patstack ( & self . 0 [ 1 ..] ) )
401407 }
402408}
@@ -574,6 +580,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
574580 cx,
575581 constructor,
576582 ctor_wild_subpatterns,
583+ false ,
577584 )
578585 } )
579586 . collect ( )
@@ -599,7 +606,9 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
599606 SpecializationCache :: Incompatible => self
600607 . patterns
601608 . 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+ } )
603612 . collect ( ) ,
604613 }
605614 }
@@ -821,8 +830,6 @@ enum Constructor<'tcx> {
821830 Single ,
822831 /// Enum variants.
823832 Variant ( DefId ) ,
824- /// Literal values.
825- ConstantValue ( & ' tcx ty:: Const < ' tcx > ) ,
826833 /// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
827834 IntRange ( IntRange < ' tcx > ) ,
828835 /// Ranges of floating-point literal values (`2.0..=5.2`).
@@ -831,27 +838,22 @@ enum Constructor<'tcx> {
831838 Str ( & ' tcx ty:: Const < ' tcx > ) ,
832839 /// Array and slice patterns.
833840 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 ,
834845 /// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
835846 NonExhaustive ,
836847}
837848
838849impl < ' 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 {
844851 match * self {
845852 Variant ( id) => adt. variant_index_with_id ( id) ,
846853 Single => {
847854 assert ! ( !adt. is_enum( ) ) ;
848855 VariantIdx :: new ( 0 )
849856 }
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" ) ,
855857 _ => bug ! ( "bad constructor {:?} for adt {:?}" , self , adt) ,
856858 }
857859 }
@@ -865,7 +867,7 @@ impl<'tcx> Constructor<'tcx> {
865867
866868 match self {
867869 // Those constructors can only match themselves.
868- Single | Variant ( _) | ConstantValue ( .. ) | Str ( ..) | FloatRange ( ..) => {
870+ Single | Variant ( _) | Str ( ..) | FloatRange ( ..) => {
869871 if other_ctors. iter ( ) . any ( |c| c == self ) { vec ! [ ] } else { vec ! [ self . clone( ) ] }
870872 }
871873 & Slice ( slice) => {
@@ -936,6 +938,7 @@ impl<'tcx> Constructor<'tcx> {
936938 }
937939 // This constructor is never covered by anything else
938940 NonExhaustive => vec ! [ NonExhaustive ] ,
941+ Opaque => bug ! ( "unexpected opaque ctor {:?} found in all_ctors" , self ) ,
939942 }
940943 }
941944
@@ -975,7 +978,7 @@ impl<'tcx> Constructor<'tcx> {
975978 PatKind :: Variant {
976979 adt_def : adt,
977980 substs,
978- variant_index : self . variant_index_for_adt ( cx , adt) ,
981+ variant_index : self . variant_index_for_adt ( adt) ,
979982 subpatterns,
980983 }
981984 } else {
@@ -1014,11 +1017,11 @@ impl<'tcx> Constructor<'tcx> {
10141017 PatKind :: Slice { prefix, slice : Some ( wild) , suffix }
10151018 }
10161019 } ,
1017- & ConstantValue ( value) => PatKind :: Constant { value } ,
10181020 & Str ( value) => PatKind :: Constant { value } ,
10191021 & FloatRange ( lo, hi, end) => PatKind :: Range ( PatRange { lo, hi, end } ) ,
10201022 IntRange ( range) => return range. to_pat ( cx. tcx ) ,
10211023 NonExhaustive => PatKind :: Wild ,
1024+ Opaque => bug ! ( "we should not try to apply an opaque constructor {:?}" , self ) ,
10221025 } ;
10231026
10241027 Pat { ty, span : DUMMY_SP , kind : Box :: new ( pat) }
@@ -1122,7 +1125,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11221125 // Use T as the sub pattern type of Box<T>.
11231126 Fields :: from_single_pattern ( wildcard_from_ty ( substs. type_at ( 0 ) ) )
11241127 } else {
1125- let variant = & adt. variants [ constructor. variant_index_for_adt ( cx , adt) ] ;
1128+ let variant = & adt. variants [ constructor. variant_index_for_adt ( adt) ] ;
11261129 // Whether we must not match the fields of this variant exhaustively.
11271130 let is_non_exhaustive =
11281131 variant. is_field_list_non_exhaustive ( ) && !adt. did . is_local ( ) ;
@@ -1170,9 +1173,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11701173 }
11711174 _ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, ty) ,
11721175 } ,
1173- ConstantValue ( ..) | Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive => {
1174- Fields :: empty ( )
1175- }
1176+ Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque => Fields :: empty ( ) ,
11761177 } ;
11771178 debug ! ( "Fields::wildcards({:?}, {:?}) = {:#?}" , constructor, ty, ret) ;
11781179 ret
@@ -2085,7 +2086,7 @@ fn is_useful_specialized<'p, 'tcx>(
20852086 // We cache the result of `Fields::wildcards` because it is used a lot.
20862087 let ctor_wild_subpatterns = Fields :: wildcards ( cx, & ctor, ty) ;
20872088 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 )
20892090 . map ( |v| is_useful ( cx, & matrix, & v, witness_preference, hir_id, is_under_guard, false ) )
20902091 . map ( |u| u. apply_constructor ( cx, & ctor, ty, & ctor_wild_subpatterns) )
20912092 . unwrap_or ( NotUseful )
@@ -2112,7 +2113,7 @@ fn pat_constructor<'tcx>(
21122113 match value. ty . kind ( ) {
21132114 ty:: Float ( _) => Some ( FloatRange ( value, value, RangeEnd :: Included ) ) ,
21142115 ty:: Ref ( _, t, _) if t. is_str ( ) => Some ( Str ( value) ) ,
2115- _ => Some ( ConstantValue ( value ) ) ,
2116+ _ => Some ( Opaque ) ,
21162117 }
21172118 }
21182119 }
@@ -2461,15 +2462,26 @@ fn specialize_one_pattern<'p, 'tcx>(
24612462 pat : & ' p Pat < ' tcx > ,
24622463 constructor : & Constructor < ' tcx > ,
24632464 ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
2465+ is_its_own_ctor : bool , // Whether `ctor` is known to be derived from `pat`
24642466) -> Option < Fields < ' p , ' tcx > > {
24652467 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.
24672469 if !pat. is_wildcard ( ) {
24682470 return None ;
24692471 }
24702472 return Some ( Fields :: empty ( ) ) ;
24712473 }
24722474
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+
24732485 let result = match * pat. kind {
24742486 PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled by `expand_pattern`
24752487
@@ -2491,7 +2503,6 @@ fn specialize_one_pattern<'p, 'tcx>(
24912503
24922504 PatKind :: Constant { .. } | PatKind :: Range { .. } => {
24932505 match constructor {
2494- Single => { }
24952506 IntRange ( ctor) => {
24962507 let pat = IntRange :: from_pat ( cx. tcx , cx. param_env , pat) ?;
24972508 ctor. intersection ( cx. tcx , & pat) ?;
@@ -2514,7 +2525,7 @@ fn specialize_one_pattern<'p, 'tcx>(
25142525 return None ;
25152526 }
25162527 }
2517- ConstantValue ( ctor_value ) | Str ( ctor_value) => {
2528+ Str ( ctor_value) => {
25182529 let pat_value = match * pat. kind {
25192530 PatKind :: Constant { value } => value,
25202531 _ => span_bug ! (
@@ -2532,7 +2543,9 @@ fn specialize_one_pattern<'p, 'tcx>(
25322543 }
25332544 }
25342545 _ => {
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 ;
25362549 }
25372550 }
25382551 Some ( Fields :: empty ( ) )
0 commit comments