@@ -609,19 +609,23 @@ pub(super) enum Constructor<'tcx> {
609609 /// boxes for the purposes of exhaustiveness: we must not inspect them, and they
610610 /// don't count towards making a match exhaustive.
611611 Opaque ,
612+ /// Or-pattern.
613+ Or ,
614+ /// Wildcard pattern.
615+ Wildcard ,
612616 /// Fake extra constructor for enums that aren't allowed to be matched exhaustively. Also used
613617 /// for those types for which we cannot list constructors explicitly, like `f64` and `str`.
614618 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.
618626 Missing {
619- nonexhaustive_enum_missing_real_variants : bool ,
627+ nonexhaustive_enum_missing_visible_variants : bool ,
620628 } ,
621- /// Wildcard pattern.
622- Wildcard ,
623- /// Or-pattern.
624- Or ,
625629}
626630
627631impl < ' tcx > Constructor < ' tcx > {
@@ -652,32 +656,6 @@ impl<'tcx> Constructor<'tcx> {
652656 }
653657 }
654658
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-
681659 fn variant_index_for_adt ( & self , adt : ty:: AdtDef < ' tcx > ) -> VariantIdx {
682660 match * self {
683661 Variant ( idx) => idx,
@@ -713,8 +691,9 @@ impl<'tcx> Constructor<'tcx> {
713691 | F32Range ( ..)
714692 | F64Range ( ..)
715693 | IntRange ( ..)
716- | NonExhaustive
717694 | Opaque
695+ | NonExhaustive
696+ | Hidden
718697 | Missing { .. }
719698 | Wildcard => 0 ,
720699 Or => bug ! ( "The `Or` constructor doesn't have a fixed arity" ) ,
@@ -795,8 +774,8 @@ impl<'tcx> Constructor<'tcx> {
795774 Wildcard
796775 } else {
797776 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 ,
800779 }
801780 } ;
802781 smallvec ! [ ctor]
@@ -828,8 +807,8 @@ impl<'tcx> Constructor<'tcx> {
828807 match ( self , other) {
829808 // Wildcards cover anything
830809 ( _, 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 ,
833812
834813 ( Single , Single ) => true ,
835814 ( Variant ( self_id) , Variant ( other_id) ) => self_id == other_id,
@@ -860,8 +839,6 @@ impl<'tcx> Constructor<'tcx> {
860839
861840 // We are trying to inspect an opaque constant. Thus we skip the row.
862841 ( Opaque , _) | ( _, Opaque ) => false ,
863- // Only a wildcard pattern can match the special extra constructor.
864- ( NonExhaustive , _) => false ,
865842
866843 _ => span_bug ! (
867844 pcx. span,
@@ -878,7 +855,14 @@ pub(super) enum ConstructorSet {
878855 /// The type has a single constructor, e.g. `&T` or a struct.
879856 Single ,
880857 /// 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+ } ,
882866 /// The type is spanned by integer values. The range or ranges give the set of allowed values.
883867 /// The second range is only useful for `char`.
884868 /// This is reused for bool. FIXME: don't.
@@ -915,7 +899,7 @@ struct SplitConstructorSet<'tcx> {
915899 present : SmallVec < [ Constructor < ' tcx > ; 1 ] > ,
916900 missing : Vec < Constructor < ' tcx > > ,
917901 /// For the `non_exhaustive_omitted_patterns` lint.
918- nonexhaustive_enum_missing_real_variants : bool ,
902+ nonexhaustive_enum_missing_visible_variants : bool ,
919903}
920904
921905impl ConstructorSet {
@@ -1001,7 +985,7 @@ impl ConstructorSet {
1001985 Self :: Uninhabited
1002986 } else {
1003987 let is_exhaustive_pat_feature = cx. tcx . features ( ) . exhaustive_patterns ;
1004- let variants : Vec < _ > = def
988+ let ( hidden_variants , visible_variants ) = def
1005989 . variants ( )
1006990 . iter_enumerated ( )
1007991 . filter ( |( _, v) | {
@@ -1013,9 +997,24 @@ impl ConstructorSet {
1013997 . apply ( cx. tcx , cx. param_env , cx. module )
1014998 } )
1015999 . 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+ }
10191018 }
10201019 }
10211020 ty:: Never => Self :: Uninhabited ,
@@ -1050,7 +1049,7 @@ impl ConstructorSet {
10501049 }
10511050 }
10521051 }
1053- let mut nonexhaustive_enum_missing_real_variants = false ;
1052+ let mut nonexhaustive_enum_missing_visible_variants = false ;
10541053 match self {
10551054 ConstructorSet :: Single => {
10561055 if seen. is_empty ( ) {
@@ -1059,29 +1058,34 @@ impl ConstructorSet {
10591058 present. push ( Single ) ;
10601059 }
10611060 }
1062- ConstructorSet :: Variants { variants , non_exhaustive } => {
1061+ ConstructorSet :: Variants { visible_variants , hidden_variants , non_exhaustive } => {
10631062 let seen_set: FxHashSet < _ > = seen. iter ( ) . map ( |c| c. as_variant ( ) . unwrap ( ) ) . collect ( ) ;
10641063 let mut skipped_a_hidden_variant = false ;
1065- for variant in variants {
1064+ for variant in visible_variants {
10661065 let ctor = Variant ( * variant) ;
10671066 if seen_set. contains ( & variant) {
10681067 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 ;
10731068 } else {
10741069 missing. push ( ctor) ;
10751070 }
10761071 }
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+ }
10771086
10781087 if * non_exhaustive {
1079- nonexhaustive_enum_missing_real_variants = !missing. is_empty ( ) ;
10801088 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 ) ;
10851089 }
10861090 }
10871091 ConstructorSet :: Integers { range_1, range_2, non_exhaustive } => {
@@ -1142,7 +1146,7 @@ impl ConstructorSet {
11421146 ConstructorSet :: Uninhabited => { }
11431147 }
11441148
1145- SplitConstructorSet { present, missing, nonexhaustive_enum_missing_real_variants }
1149+ SplitConstructorSet { present, missing, nonexhaustive_enum_missing_visible_variants }
11461150 }
11471151
11481152 /// Compute the set of constructors missing from this column.
@@ -1272,8 +1276,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12721276 | F32Range ( ..)
12731277 | F64Range ( ..)
12741278 | IntRange ( ..)
1275- | NonExhaustive
12761279 | Opaque
1280+ | NonExhaustive
1281+ | Hidden
12771282 | Missing { .. }
12781283 | Wildcard => Fields :: empty ( ) ,
12791284 Or => {
@@ -1587,7 +1592,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
15871592 }
15881593 & Str ( value) => PatKind :: Constant { value } ,
15891594 IntRange ( range) => return range. to_pat ( cx. tcx , self . ty ) ,
1590- Wildcard | NonExhaustive => PatKind :: Wild ,
1595+ Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
15911596 Missing { .. } => bug ! (
15921597 "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
15931598 `Missing` should have been processed in `apply_constructors`"
@@ -1770,15 +1775,15 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> {
17701775 F32Range ( lo, hi, end) => write ! ( f, "{lo}{end}{hi}" ) ,
17711776 F64Range ( lo, hi, end) => write ! ( f, "{lo}{end}{hi}" ) ,
17721777 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>" ) ,
17741780 Or => {
17751781 for pat in self . iter_fields ( ) {
17761782 write ! ( f, "{}{:?}" , start_or_continue( " | " ) , pat) ?;
17771783 }
17781784 Ok ( ( ) )
17791785 }
1780- Str ( value) => write ! ( f, "{value}" ) ,
1781- Opaque => write ! ( f, "<constant pattern>" ) ,
1786+ Wildcard | Missing { .. } | NonExhaustive | Hidden => write ! ( f, "_ : {:?}" , self . ty) ,
17821787 }
17831788 }
17841789}
0 commit comments