@@ -52,11 +52,11 @@ use rustc_data_structures::captures::Captures;
52
52
use rustc_index:: vec:: Idx ;
53
53
54
54
use rustc_hir:: { HirId , RangeEnd } ;
55
- use rustc_middle:: mir:: interpret:: ConstValue ;
56
55
use rustc_middle:: mir:: Field ;
57
56
use rustc_middle:: thir:: { FieldPat , Pat , PatKind , PatRange } ;
58
57
use rustc_middle:: ty:: layout:: IntegerExt ;
59
58
use rustc_middle:: ty:: { self , Const , Ty , TyCtxt , VariantDef } ;
59
+ use rustc_middle:: { middle:: stability:: EvalResult , mir:: interpret:: ConstValue } ;
60
60
use rustc_session:: lint;
61
61
use rustc_span:: { Span , DUMMY_SP } ;
62
62
use rustc_target:: abi:: { Integer , Size , VariantIdx } ;
@@ -675,6 +675,36 @@ impl<'tcx> Constructor<'tcx> {
675
675
}
676
676
}
677
677
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
+
678
708
fn variant_index_for_adt ( & self , adt : & ' tcx ty:: AdtDef ) -> VariantIdx {
679
709
match * self {
680
710
Variant ( idx) => idx,
@@ -929,36 +959,33 @@ impl<'tcx> SplitWildcard<'tcx> {
929
959
// witness.
930
960
let is_declared_nonexhaustive = cx. is_foreign_non_exhaustive_enum ( pcx. ty ) ;
931
961
962
+ let is_exhaustive_pat_feature = cx. tcx . features ( ) . exhaustive_patterns ;
963
+
932
964
// If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
933
965
// as though it had an "unknown" constructor to avoid exposing its emptiness. The
934
966
// exception is if the pattern is at the top level, because we want empty matches to be
935
967
// 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 ) ;
961
987
}
988
+ ctors
962
989
}
963
990
ty:: Char => {
964
991
smallvec ! [
@@ -1068,7 +1095,7 @@ impl<'tcx> SplitWildcard<'tcx> {
1068
1095
Missing {
1069
1096
nonexhaustive_enum_missing_real_variants : self
1070
1097
. iter_missing ( pcx)
1071
- . any ( |c| !c. is_non_exhaustive ( ) ) ,
1098
+ . any ( |c| !( c. is_non_exhaustive ( ) || c . is_unstable_variant ( pcx ) ) ) ,
1072
1099
}
1073
1100
} else {
1074
1101
Missing { nonexhaustive_enum_missing_real_variants : false }
@@ -1222,9 +1249,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1222
1249
1223
1250
/// Values and patterns can be represented as a constructor applied to some fields. This represents
1224
1251
/// 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
1226
1253
/// 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.
1228
1255
pub ( crate ) struct DeconstructedPat < ' p , ' tcx > {
1229
1256
ctor : Constructor < ' tcx > ,
1230
1257
fields : Fields < ' p , ' tcx > ,
0 commit comments