@@ -52,11 +52,11 @@ use rustc_data_structures::captures::Captures;
5252use rustc_index:: vec:: Idx ;
5353
5454use rustc_hir:: { HirId , RangeEnd } ;
55- use rustc_middle:: mir:: interpret:: ConstValue ;
5655use rustc_middle:: mir:: Field ;
5756use rustc_middle:: thir:: { FieldPat , Pat , PatKind , PatRange } ;
5857use rustc_middle:: ty:: layout:: IntegerExt ;
5958use rustc_middle:: ty:: { self , Const , Ty , TyCtxt , VariantDef } ;
59+ use rustc_middle:: { middle:: stability:: EvalResult , mir:: interpret:: ConstValue } ;
6060use rustc_session:: lint;
6161use rustc_span:: { Span , DUMMY_SP } ;
6262use rustc_target:: abi:: { Integer , Size , VariantIdx } ;
@@ -675,6 +675,36 @@ impl<'tcx> Constructor<'tcx> {
675675 }
676676 }
677677
678+ /// Checks if the `Constructor` is a variant and `TyCtxt::eval_stability` returns
679+ /// `EvalResult::Deny { .. }`.
680+ ///
681+ /// This means that the variant has a stdlib unstable feature marking it.
682+ pub ( super ) fn is_unstable_variant ( & self , pcx : PatCtxt < ' _ , ' _ , ' tcx > ) -> bool {
683+ if let Constructor :: Variant ( idx) = self {
684+ if let ty:: Adt ( adt, _) = pcx. ty . kind ( ) {
685+ let variant_def_id = adt. variants [ * idx] . def_id ;
686+ // Filter variants that depend on a disabled unstable feature.
687+ return matches ! (
688+ pcx. cx. tcx. eval_stability( variant_def_id, None , DUMMY_SP , None ) ,
689+ EvalResult :: Deny { .. }
690+ ) ;
691+ }
692+ }
693+ false
694+ }
695+
696+ /// Checks if the `Constructor` is a `Constructor::Variant` with a `#[doc(hidden)]`
697+ /// attribute.
698+ pub ( super ) fn is_doc_hidden_variant ( & self , pcx : PatCtxt < ' _ , ' _ , ' tcx > ) -> bool {
699+ if let Constructor :: Variant ( idx) = self {
700+ if let ty:: Adt ( adt, _) = pcx. ty . kind ( ) {
701+ let variant_def_id = adt. variants [ * idx] . def_id ;
702+ return pcx. cx . tcx . is_doc_hidden ( variant_def_id) ;
703+ }
704+ }
705+ false
706+ }
707+
678708 fn variant_index_for_adt ( & self , adt : & ' tcx ty:: AdtDef ) -> VariantIdx {
679709 match * self {
680710 Variant ( idx) => idx,
@@ -929,36 +959,33 @@ impl<'tcx> SplitWildcard<'tcx> {
929959 // witness.
930960 let is_declared_nonexhaustive = cx. is_foreign_non_exhaustive_enum ( pcx. ty ) ;
931961
962+ let is_exhaustive_pat_feature = cx. tcx . features ( ) . exhaustive_patterns ;
963+
932964 // If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
933965 // as though it had an "unknown" constructor to avoid exposing its emptiness. The
934966 // exception is if the pattern is at the top level, because we want empty matches to be
935967 // considered exhaustive.
936- let is_secretly_empty = def. variants . is_empty ( )
937- && !cx. tcx . features ( ) . exhaustive_patterns
938- && !pcx. is_top_level ;
939-
940- if is_secretly_empty {
941- smallvec ! [ NonExhaustive ]
942- } else if is_declared_nonexhaustive {
943- def. variants
944- . indices ( )
945- . map ( |idx| Variant ( idx) )
946- . chain ( Some ( NonExhaustive ) )
947- . collect ( )
948- } else if cx. tcx . features ( ) . exhaustive_patterns {
949- // If `exhaustive_patterns` is enabled, we exclude variants known to be
950- // uninhabited.
951- def. variants
952- . iter_enumerated ( )
953- . filter ( |( _, v) | {
954- !v. uninhabited_from ( cx. tcx , substs, def. adt_kind ( ) , cx. param_env )
955- . contains ( cx. tcx , cx. module )
956- } )
957- . map ( |( idx, _) | Variant ( idx) )
958- . collect ( )
959- } else {
960- def. variants . indices ( ) . map ( |idx| Variant ( idx) ) . collect ( )
968+ let is_secretly_empty =
969+ def. variants . is_empty ( ) && !is_exhaustive_pat_feature && !pcx. is_top_level ;
970+
971+ let mut ctors: SmallVec < [ _ ; 1 ] > = def
972+ . variants
973+ . iter_enumerated ( )
974+ . filter ( |( _, v) | {
975+ // If `exhaustive_patterns` is enabled, we exclude variants known to be
976+ // uninhabited.
977+ let is_uninhabited = is_exhaustive_pat_feature
978+ && v. uninhabited_from ( cx. tcx , substs, def. adt_kind ( ) , cx. param_env )
979+ . contains ( cx. tcx , cx. module ) ;
980+ !is_uninhabited
981+ } )
982+ . map ( |( idx, _) | Variant ( idx) )
983+ . collect ( ) ;
984+
985+ if is_secretly_empty || is_declared_nonexhaustive {
986+ ctors. push ( NonExhaustive ) ;
961987 }
988+ ctors
962989 }
963990 ty:: Char => {
964991 smallvec ! [
@@ -1068,7 +1095,7 @@ impl<'tcx> SplitWildcard<'tcx> {
10681095 Missing {
10691096 nonexhaustive_enum_missing_real_variants : self
10701097 . iter_missing ( pcx)
1071- . any ( |c| !c. is_non_exhaustive ( ) ) ,
1098+ . any ( |c| !( c. is_non_exhaustive ( ) || c . is_unstable_variant ( pcx ) ) ) ,
10721099 }
10731100 } else {
10741101 Missing { nonexhaustive_enum_missing_real_variants : false }
@@ -1222,9 +1249,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12221249
12231250/// Values and patterns can be represented as a constructor applied to some fields. This represents
12241251/// a pattern in this form.
1225- /// This also keeps track of whether the pattern has been foundreachable during analysis. For this
1252+ /// This also keeps track of whether the pattern has been found reachable during analysis. For this
12261253/// reason we should be careful not to clone patterns for which we care about that. Use
1227- /// `clone_and_forget_reachability` is you're sure.
1254+ /// `clone_and_forget_reachability` if you're sure.
12281255pub ( crate ) struct DeconstructedPat < ' p , ' tcx > {
12291256 ctor : Constructor < ' tcx > ,
12301257 fields : Fields < ' p , ' tcx > ,
0 commit comments