@@ -857,6 +857,7 @@ pub(super) enum ConstructorSet {
857857 Variants {
858858 visible_variants : Vec < VariantIdx > ,
859859 hidden_variants : Vec < VariantIdx > ,
860+ empty_variants : Vec < VariantIdx > ,
860861 non_exhaustive : bool ,
861862 } ,
862863 /// The type is spanned by integer values. The range or ranges give the set of allowed values.
@@ -881,16 +882,18 @@ pub(super) enum ConstructorSet {
881882/// `present` is morally the set of constructors present in the column, and `missing` is the set of
882883/// constructors that exist in the type but are not present in the column.
883884///
884- /// More formally, they respect the following constraints:
885+ /// More formally, if we discard wildcards from the column, they respect the following constraints:
885886/// - the union of `present` and `missing` covers the whole type
886- /// - `present` and `missing` are disjoint
887- /// - neither contains wildcards
888- /// - each constructor in `present` is covered by some non-wildcard constructor in the column
889- /// - together, the constructors in `present` cover all the non-wildcard constructor in the column
890- /// - non-wildcards in the column do no cover anything in `missing`
887+ /// - each constructor in `present` is covered by something in the column
888+ /// - no constructor in `missing` is covered by anything in the column
889+ /// - each constructor in the column is equal to the union of one or more constructors in `present`
891890/// - constructors in `present` and `missing` are split for the column; in other words, they are
892- /// either fully included in or disjoint from each constructor in the column. This avoids
893- /// non-trivial intersections like between `0..10` and `5..15`.
891+ /// either fully included in or disjoint from each constructor in the column. In other words,
892+ /// there are no non-trivial intersections like between `0..10` and `5..15`.
893+ ///
894+ /// When the `exhaustive_patterns` feature is enabled, all ctors in `missing` must match at least
895+ /// one value of the corresponding type. E.g. if the type is `Option<!>`, `missing` will never
896+ /// contain `Some`. This restriction does not apply to `present`.
894897#[ derive( Debug ) ]
895898pub ( super ) struct SplitConstructorSet < ' tcx > {
896899 pub ( super ) present : SmallVec < [ Constructor < ' tcx > ; 1 ] > ,
@@ -904,12 +907,6 @@ impl ConstructorSet {
904907 |start, end| IntRange :: from_range ( cx. tcx , start, end, ty, RangeEnd :: Included ) ;
905908 // This determines the set of all possible constructors for the type `ty`. For numbers,
906909 // arrays and slices we use ranges and variable-length slices when appropriate.
907- //
908- // If the `exhaustive_patterns` feature is enabled, we make sure to omit constructors that
909- // are statically impossible. E.g., for `Option<!>`, we do not include `Some(_)` in the
910- // returned list of constructors.
911- // Invariant: this is `Uninhabited` if and only if the type is uninhabited (as determined by
912- // `cx.is_uninhabited()`).
913910 match ty. kind ( ) {
914911 ty:: Bool => {
915912 Self :: Integers { range_1 : make_range ( 0 , 1 ) , range_2 : None , non_exhaustive : false }
@@ -958,56 +955,42 @@ impl ConstructorSet {
958955 }
959956 }
960957 ty:: Adt ( def, args) if def. is_enum ( ) => {
961- // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
962- // additional "unknown" constructor.
963- // There is no point in enumerating all possible variants, because the user can't
964- // actually match against them all themselves. So we always return only the fictitious
965- // constructor.
966- // E.g., in an example like:
967- //
968- // ```
969- // let err: io::ErrorKind = ...;
970- // match err {
971- // io::ErrorKind::NotFound => {},
972- // }
973- // ```
974- //
975- // we don't want to show every possible IO error, but instead have only `_` as the
976- // witness.
977958 let is_declared_nonexhaustive = cx. is_foreign_non_exhaustive_enum ( ty) ;
978-
979959 if def. variants ( ) . is_empty ( ) && !is_declared_nonexhaustive {
980960 Self :: Uninhabited
981961 } else {
982962 let is_exhaustive_pat_feature = cx. tcx . features ( ) . exhaustive_patterns ;
983- let ( hidden_variants, visible_variants) = def
984- . variants ( )
985- . iter_enumerated ( )
986- . filter ( |( _, v) | {
987- // If `exhaustive_patterns` is enabled, we exclude variants known to be
988- // uninhabited.
989- !is_exhaustive_pat_feature
990- || v. inhabited_predicate ( cx. tcx , * def)
991- . instantiate ( cx. tcx , args)
992- . apply ( cx. tcx , cx. param_env , cx. module )
993- } )
994- . map ( |( idx, _) | idx)
995- . partition ( |idx| {
996- let variant_def_id = def. variant ( * idx) . def_id ;
997- // Filter variants that depend on a disabled unstable feature.
998- let is_unstable = matches ! (
999- cx. tcx. eval_stability( variant_def_id, None , DUMMY_SP , None ) ,
1000- EvalResult :: Deny { .. }
1001- ) ;
1002- // Filter foreign `#[doc(hidden)]` variants.
1003- let is_doc_hidden =
1004- cx. tcx . is_doc_hidden ( variant_def_id) && !variant_def_id. is_local ( ) ;
1005- is_unstable || is_doc_hidden
1006- } ) ;
963+ let mut visible_variants = Vec :: new ( ) ;
964+ let mut hidden_variants = Vec :: new ( ) ;
965+ let mut empty_variants = Vec :: new ( ) ;
966+ for ( idx, v) in def. variants ( ) . iter_enumerated ( ) {
967+ let variant_def_id = def. variant ( idx) . def_id ;
968+ // Visibly uninhabited variants.
969+ let is_inhabited = v
970+ . inhabited_predicate ( cx. tcx , * def)
971+ . instantiate ( cx. tcx , args)
972+ . apply ( cx. tcx , cx. param_env , cx. module ) ;
973+ // Variants that depend on a disabled unstable feature.
974+ let is_unstable = matches ! (
975+ cx. tcx. eval_stability( variant_def_id, None , DUMMY_SP , None ) ,
976+ EvalResult :: Deny { .. }
977+ ) ;
978+ // Foreign `#[doc(hidden)]` variants.
979+ let is_doc_hidden =
980+ cx. tcx . is_doc_hidden ( variant_def_id) && !variant_def_id. is_local ( ) ;
981+ if is_exhaustive_pat_feature && !is_inhabited {
982+ empty_variants. push ( idx) ;
983+ } else if is_unstable || is_doc_hidden {
984+ hidden_variants. push ( idx) ;
985+ } else {
986+ visible_variants. push ( idx) ;
987+ }
988+ }
1007989
1008990 Self :: Variants {
1009991 visible_variants,
1010992 hidden_variants,
993+ empty_variants,
1011994 non_exhaustive : is_declared_nonexhaustive,
1012995 }
1013996 }
@@ -1044,7 +1027,12 @@ impl ConstructorSet {
10441027 present. push ( Single ) ;
10451028 }
10461029 }
1047- ConstructorSet :: Variants { visible_variants, hidden_variants, non_exhaustive } => {
1030+ ConstructorSet :: Variants {
1031+ visible_variants,
1032+ hidden_variants,
1033+ empty_variants,
1034+ non_exhaustive,
1035+ } => {
10481036 let seen_set: FxHashSet < _ > = seen. map ( |c| c. as_variant ( ) . unwrap ( ) ) . collect ( ) ;
10491037 let mut skipped_a_hidden_variant = false ;
10501038
@@ -1053,10 +1041,10 @@ impl ConstructorSet {
10531041 if seen_set. contains ( & variant) {
10541042 present. push ( ctor) ;
10551043 } else {
1044+ // We only put visible variants directly into `missing`.
10561045 missing. push ( ctor) ;
10571046 }
10581047 }
1059-
10601048 for variant in hidden_variants {
10611049 let ctor = Variant ( * variant) ;
10621050 if seen_set. contains ( & variant) {
@@ -1065,6 +1053,13 @@ impl ConstructorSet {
10651053 skipped_a_hidden_variant = true ;
10661054 }
10671055 }
1056+ for variant in empty_variants {
1057+ let ctor = Variant ( * variant) ;
1058+ if seen_set. contains ( & variant) {
1059+ present. push ( ctor) ;
1060+ }
1061+ }
1062+
10681063 if skipped_a_hidden_variant {
10691064 missing. push ( Hidden ) ;
10701065 }
0 commit comments