@@ -609,19 +609,23 @@ pub(super) enum Constructor<'tcx> {
609
609
/// boxes for the purposes of exhaustiveness: we must not inspect them, and they
610
610
/// don't count towards making a match exhaustive.
611
611
Opaque ,
612
+ /// Or-pattern.
613
+ Or ,
614
+ /// Wildcard pattern.
615
+ Wildcard ,
612
616
/// Fake extra constructor for enums that aren't allowed to be matched exhaustively. Also used
613
617
/// for those types for which we cannot list constructors explicitly, like `f64` and `str`.
614
618
NonExhaustive ,
615
- /// Stands for constructors that are not seen in the matrix, as explained in the code for
616
- /// [`Constructor::split`]. The carried `bool` is used for the `non_exhaustive_omitted_patterns`
617
- /// lint.
619
+ /// Fake extra constructor for variants that should not be mentioned in diagnostics.
620
+ /// We use this for variants behind an unstable gate as well as
621
+ /// `#[doc(hidden)]` ones.
622
+ Hidden ,
623
+ /// Fake extra constructor for constructors that are not seen in the matrix, as explained in the
624
+ /// code for [`Constructor::split`]. The carried `bool` is used for the
625
+ /// `non_exhaustive_omitted_patterns` lint.
618
626
Missing {
619
- nonexhaustive_enum_missing_real_variants : bool ,
627
+ nonexhaustive_enum_missing_visible_variants : bool ,
620
628
} ,
621
- /// Wildcard pattern.
622
- Wildcard ,
623
- /// Or-pattern.
624
- Or ,
625
629
}
626
630
627
631
impl < ' tcx > Constructor < ' tcx > {
@@ -652,32 +656,6 @@ impl<'tcx> Constructor<'tcx> {
652
656
}
653
657
}
654
658
655
- /// Checks if the `Constructor` is a variant and `TyCtxt::eval_stability` returns
656
- /// `EvalResult::Deny { .. }`.
657
- ///
658
- /// This means that the variant has a stdlib unstable feature marking it.
659
- pub ( super ) fn is_unstable_variant ( & self , pcx : & PatCtxt < ' _ , ' _ , ' tcx > ) -> bool {
660
- if let Constructor :: Variant ( idx) = self && let ty:: Adt ( adt, _) = pcx. ty . kind ( ) {
661
- let variant_def_id = adt. variant ( * idx) . def_id ;
662
- // Filter variants that depend on a disabled unstable feature.
663
- return matches ! (
664
- pcx. cx. tcx. eval_stability( variant_def_id, None , DUMMY_SP , None ) ,
665
- EvalResult :: Deny { .. }
666
- ) ;
667
- }
668
- false
669
- }
670
-
671
- /// Checks if the `Constructor` is a `Constructor::Variant` with a `#[doc(hidden)]`
672
- /// attribute from a type not local to the current crate.
673
- pub ( super ) fn is_doc_hidden_variant ( & self , pcx : & PatCtxt < ' _ , ' _ , ' tcx > ) -> bool {
674
- if let Constructor :: Variant ( idx) = self && let ty:: Adt ( adt, _) = pcx. ty . kind ( ) {
675
- let variant_def_id = adt. variants ( ) [ * idx] . def_id ;
676
- return pcx. cx . tcx . is_doc_hidden ( variant_def_id) && !variant_def_id. is_local ( ) ;
677
- }
678
- false
679
- }
680
-
681
659
fn variant_index_for_adt ( & self , adt : ty:: AdtDef < ' tcx > ) -> VariantIdx {
682
660
match * self {
683
661
Variant ( idx) => idx,
@@ -713,8 +691,9 @@ impl<'tcx> Constructor<'tcx> {
713
691
| F32Range ( ..)
714
692
| F64Range ( ..)
715
693
| IntRange ( ..)
716
- | NonExhaustive
717
694
| Opaque
695
+ | NonExhaustive
696
+ | Hidden
718
697
| Missing { .. }
719
698
| Wildcard => 0 ,
720
699
Or => bug ! ( "The `Or` constructor doesn't have a fixed arity" ) ,
@@ -795,8 +774,8 @@ impl<'tcx> Constructor<'tcx> {
795
774
Wildcard
796
775
} else {
797
776
Missing {
798
- nonexhaustive_enum_missing_real_variants : split_set
799
- . nonexhaustive_enum_missing_real_variants ,
777
+ nonexhaustive_enum_missing_visible_variants : split_set
778
+ . nonexhaustive_enum_missing_visible_variants ,
800
779
}
801
780
} ;
802
781
smallvec ! [ ctor]
@@ -828,8 +807,8 @@ impl<'tcx> Constructor<'tcx> {
828
807
match ( self , other) {
829
808
// Wildcards cover anything
830
809
( _, Wildcard ) => true ,
831
- // The missing ctors are not covered by anything in the matrix except wildcards .
832
- ( Missing { .. } | Wildcard , _) => false ,
810
+ // Only a wildcard pattern can match these special constructors .
811
+ ( Wildcard | Missing { .. } | NonExhaustive | Hidden , _) => false ,
833
812
834
813
( Single , Single ) => true ,
835
814
( Variant ( self_id) , Variant ( other_id) ) => self_id == other_id,
@@ -860,8 +839,6 @@ impl<'tcx> Constructor<'tcx> {
860
839
861
840
// We are trying to inspect an opaque constant. Thus we skip the row.
862
841
( Opaque , _) | ( _, Opaque ) => false ,
863
- // Only a wildcard pattern can match the special extra constructor.
864
- ( NonExhaustive , _) => false ,
865
842
866
843
_ => span_bug ! (
867
844
pcx. span,
@@ -878,7 +855,14 @@ pub(super) enum ConstructorSet {
878
855
/// The type has a single constructor, e.g. `&T` or a struct.
879
856
Single ,
880
857
/// This type has the following list of constructors.
881
- Variants { variants : Vec < VariantIdx > , non_exhaustive : bool } ,
858
+ /// Some variants are hidden, which means they won't be mentioned in diagnostics unless the user
859
+ /// mentioned them first. We use this for variants behind an unstable gate as well as
860
+ /// `#[doc(hidden)]` ones.
861
+ Variants {
862
+ visible_variants : Vec < VariantIdx > ,
863
+ hidden_variants : Vec < VariantIdx > ,
864
+ non_exhaustive : bool ,
865
+ } ,
882
866
/// The type is spanned by integer values. The range or ranges give the set of allowed values.
883
867
/// The second range is only useful for `char`.
884
868
/// This is reused for bool. FIXME: don't.
@@ -915,7 +899,7 @@ struct SplitConstructorSet<'tcx> {
915
899
present : SmallVec < [ Constructor < ' tcx > ; 1 ] > ,
916
900
missing : Vec < Constructor < ' tcx > > ,
917
901
/// For the `non_exhaustive_omitted_patterns` lint.
918
- nonexhaustive_enum_missing_real_variants : bool ,
902
+ nonexhaustive_enum_missing_visible_variants : bool ,
919
903
}
920
904
921
905
impl ConstructorSet {
@@ -1001,7 +985,7 @@ impl ConstructorSet {
1001
985
Self :: Uninhabited
1002
986
} else {
1003
987
let is_exhaustive_pat_feature = cx. tcx . features ( ) . exhaustive_patterns ;
1004
- let variants : Vec < _ > = def
988
+ let ( hidden_variants , visible_variants ) = def
1005
989
. variants ( )
1006
990
. iter_enumerated ( )
1007
991
. filter ( |( _, v) | {
@@ -1013,9 +997,24 @@ impl ConstructorSet {
1013
997
. apply ( cx. tcx , cx. param_env , cx. module )
1014
998
} )
1015
999
. map ( |( idx, _) | idx)
1016
- . collect ( ) ;
1017
-
1018
- Self :: Variants { variants, non_exhaustive : is_declared_nonexhaustive }
1000
+ . partition ( |idx| {
1001
+ let variant_def_id = def. variant ( * idx) . def_id ;
1002
+ // Filter variants that depend on a disabled unstable feature.
1003
+ let is_unstable = matches ! (
1004
+ cx. tcx. eval_stability( variant_def_id, None , DUMMY_SP , None ) ,
1005
+ EvalResult :: Deny { .. }
1006
+ ) ;
1007
+ // Filter foreign `#[doc(hidden)]` variants.
1008
+ let is_doc_hidden =
1009
+ cx. tcx . is_doc_hidden ( variant_def_id) && !variant_def_id. is_local ( ) ;
1010
+ is_unstable || is_doc_hidden
1011
+ } ) ;
1012
+
1013
+ Self :: Variants {
1014
+ visible_variants,
1015
+ hidden_variants,
1016
+ non_exhaustive : is_declared_nonexhaustive,
1017
+ }
1019
1018
}
1020
1019
}
1021
1020
ty:: Never => Self :: Uninhabited ,
@@ -1050,7 +1049,7 @@ impl ConstructorSet {
1050
1049
}
1051
1050
}
1052
1051
}
1053
- let mut nonexhaustive_enum_missing_real_variants = false ;
1052
+ let mut nonexhaustive_enum_missing_visible_variants = false ;
1054
1053
match self {
1055
1054
ConstructorSet :: Single => {
1056
1055
if seen. is_empty ( ) {
@@ -1059,29 +1058,34 @@ impl ConstructorSet {
1059
1058
present. push ( Single ) ;
1060
1059
}
1061
1060
}
1062
- ConstructorSet :: Variants { variants , non_exhaustive } => {
1061
+ ConstructorSet :: Variants { visible_variants , hidden_variants , non_exhaustive } => {
1063
1062
let seen_set: FxHashSet < _ > = seen. iter ( ) . map ( |c| c. as_variant ( ) . unwrap ( ) ) . collect ( ) ;
1064
1063
let mut skipped_a_hidden_variant = false ;
1065
- for variant in variants {
1064
+ for variant in visible_variants {
1066
1065
let ctor = Variant ( * variant) ;
1067
1066
if seen_set. contains ( & variant) {
1068
1067
present. push ( ctor) ;
1069
- } else if ctor. is_doc_hidden_variant ( pcx) || ctor. is_unstable_variant ( pcx) {
1070
- // We don't want to mention any variants that are `doc(hidden)` or behind an
1071
- // unstable feature gate if they aren't present in the match.
1072
- skipped_a_hidden_variant = true ;
1073
1068
} else {
1074
1069
missing. push ( ctor) ;
1075
1070
}
1076
1071
}
1072
+ nonexhaustive_enum_missing_visible_variants =
1073
+ * non_exhaustive && !missing. is_empty ( ) ;
1074
+
1075
+ for variant in hidden_variants {
1076
+ let ctor = Variant ( * variant) ;
1077
+ if seen_set. contains ( & variant) {
1078
+ present. push ( ctor) ;
1079
+ } else {
1080
+ skipped_a_hidden_variant = true ;
1081
+ }
1082
+ }
1083
+ if skipped_a_hidden_variant {
1084
+ missing. push ( Hidden ) ;
1085
+ }
1077
1086
1078
1087
if * non_exhaustive {
1079
- nonexhaustive_enum_missing_real_variants = !missing. is_empty ( ) ;
1080
1088
missing. push ( NonExhaustive ) ;
1081
- } else if skipped_a_hidden_variant {
1082
- // FIXME(Nadrieril): This represents the skipped variants, but isn't super
1083
- // clean. Using `NonExhaustive` breaks things elsewhere.
1084
- missing. push ( Wildcard ) ;
1085
1089
}
1086
1090
}
1087
1091
ConstructorSet :: Integers { range_1, range_2, non_exhaustive } => {
@@ -1142,7 +1146,7 @@ impl ConstructorSet {
1142
1146
ConstructorSet :: Uninhabited => { }
1143
1147
}
1144
1148
1145
- SplitConstructorSet { present, missing, nonexhaustive_enum_missing_real_variants }
1149
+ SplitConstructorSet { present, missing, nonexhaustive_enum_missing_visible_variants }
1146
1150
}
1147
1151
1148
1152
/// Compute the set of constructors missing from this column.
@@ -1272,8 +1276,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1272
1276
| F32Range ( ..)
1273
1277
| F64Range ( ..)
1274
1278
| IntRange ( ..)
1275
- | NonExhaustive
1276
1279
| Opaque
1280
+ | NonExhaustive
1281
+ | Hidden
1277
1282
| Missing { .. }
1278
1283
| Wildcard => Fields :: empty ( ) ,
1279
1284
Or => {
@@ -1587,7 +1592,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
1587
1592
}
1588
1593
& Str ( value) => PatKind :: Constant { value } ,
1589
1594
IntRange ( range) => return range. to_pat ( cx. tcx , self . ty ) ,
1590
- Wildcard | NonExhaustive => PatKind :: Wild ,
1595
+ Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
1591
1596
Missing { .. } => bug ! (
1592
1597
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
1593
1598
`Missing` should have been processed in `apply_constructors`"
@@ -1770,15 +1775,15 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> {
1770
1775
F32Range ( lo, hi, end) => write ! ( f, "{lo}{end}{hi}" ) ,
1771
1776
F64Range ( lo, hi, end) => write ! ( f, "{lo}{end}{hi}" ) ,
1772
1777
IntRange ( range) => write ! ( f, "{range:?}" ) , // Best-effort, will render e.g. `false` as `0..=0`
1773
- Wildcard | Missing { .. } | NonExhaustive => write ! ( f, "_ : {:?}" , self . ty) ,
1778
+ Str ( value) => write ! ( f, "{value}" ) ,
1779
+ Opaque => write ! ( f, "<constant pattern>" ) ,
1774
1780
Or => {
1775
1781
for pat in self . iter_fields ( ) {
1776
1782
write ! ( f, "{}{:?}" , start_or_continue( " | " ) , pat) ?;
1777
1783
}
1778
1784
Ok ( ( ) )
1779
1785
}
1780
- Str ( value) => write ! ( f, "{value}" ) ,
1781
- Opaque => write ! ( f, "<constant pattern>" ) ,
1786
+ Wildcard | Missing { .. } | NonExhaustive | Hidden => write ! ( f, "_ : {:?}" , self . ty) ,
1782
1787
}
1783
1788
}
1784
1789
}
0 commit comments