@@ -793,6 +793,7 @@ pub(super) enum ConstructorSet {
793
793
Variants {
794
794
visible_variants : Vec < VariantIdx > ,
795
795
hidden_variants : Vec < VariantIdx > ,
796
+ empty_variants : Vec < VariantIdx > ,
796
797
non_exhaustive : bool ,
797
798
} ,
798
799
/// The type is spanned by integer values. The range or ranges give the set of allowed values.
@@ -817,16 +818,18 @@ pub(super) enum ConstructorSet {
817
818
/// `present` is morally the set of constructors present in the column, and `missing` is the set of
818
819
/// constructors that exist in the type but are not present in the column.
819
820
///
820
- /// More formally, they respect the following constraints:
821
+ /// More formally, if we discard wildcards from the column, they respect the following constraints:
821
822
/// - the union of `present` and `missing` covers the whole type
822
- /// - `present` and `missing` are disjoint
823
- /// - neither contains wildcards
824
- /// - each constructor in `present` is covered by some non-wildcard constructor in the column
825
- /// - together, the constructors in `present` cover all the non-wildcard constructor in the column
826
- /// - non-wildcards in the column do no cover anything in `missing`
823
+ /// - each constructor in `present` is covered by something in the column
824
+ /// - no constructor in `missing` is covered by anything in the column
825
+ /// - each constructor in the column is equal to the union of one or more constructors in `present`
827
826
/// - constructors in `present` and `missing` are split for the column; in other words, they are
828
- /// either fully included in or disjoint from each constructor in the column. This avoids
829
- /// non-trivial intersections like between `0..10` and `5..15`.
827
+ /// either fully included in or disjoint from each constructor in the column. In other words,
828
+ /// there are no non-trivial intersections like between `0..10` and `5..15`.
829
+ ///
830
+ /// When the `exhaustive_patterns` feature is enabled, all ctors in `missing` must match at least
831
+ /// one value of the corresponding type. E.g. if the type is `Option<!>`, `missing` will never
832
+ /// contain `Some`. This restriction does not apply to `present`.
830
833
#[ derive( Debug ) ]
831
834
pub ( super ) struct SplitConstructorSet < ' tcx > {
832
835
pub ( super ) present : SmallVec < [ Constructor < ' tcx > ; 1 ] > ,
@@ -840,12 +843,6 @@ impl ConstructorSet {
840
843
|start, end| IntRange :: from_range ( cx. tcx , start, end, ty, RangeEnd :: Included ) ;
841
844
// This determines the set of all possible constructors for the type `ty`. For numbers,
842
845
// arrays and slices we use ranges and variable-length slices when appropriate.
843
- //
844
- // If the `exhaustive_patterns` feature is enabled, we make sure to omit constructors that
845
- // are statically impossible. E.g., for `Option<!>`, we do not include `Some(_)` in the
846
- // returned list of constructors.
847
- // Invariant: this is `Uninhabited` if and only if the type is uninhabited (as determined by
848
- // `cx.is_uninhabited()`).
849
846
match ty. kind ( ) {
850
847
ty:: Bool => {
851
848
Self :: Integers { range_1 : make_range ( 0 , 1 ) , range_2 : None , non_exhaustive : false }
@@ -894,56 +891,42 @@ impl ConstructorSet {
894
891
}
895
892
}
896
893
ty:: Adt ( def, args) if def. is_enum ( ) => {
897
- // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
898
- // additional "unknown" constructor.
899
- // There is no point in enumerating all possible variants, because the user can't
900
- // actually match against them all themselves. So we always return only the fictitious
901
- // constructor.
902
- // E.g., in an example like:
903
- //
904
- // ```
905
- // let err: io::ErrorKind = ...;
906
- // match err {
907
- // io::ErrorKind::NotFound => {},
908
- // }
909
- // ```
910
- //
911
- // we don't want to show every possible IO error, but instead have only `_` as the
912
- // witness.
913
894
let is_declared_nonexhaustive = cx. is_foreign_non_exhaustive_enum ( ty) ;
914
-
915
895
if def. variants ( ) . is_empty ( ) && !is_declared_nonexhaustive {
916
896
Self :: Uninhabited
917
897
} else {
918
898
let is_exhaustive_pat_feature = cx. tcx . features ( ) . exhaustive_patterns ;
919
- let ( hidden_variants, visible_variants) = def
920
- . variants ( )
921
- . iter_enumerated ( )
922
- . filter ( |( _, v) | {
923
- // If `exhaustive_patterns` is enabled, we exclude variants known to be
924
- // uninhabited.
925
- !is_exhaustive_pat_feature
926
- || v. inhabited_predicate ( cx. tcx , * def)
927
- . instantiate ( cx. tcx , args)
928
- . apply ( cx. tcx , cx. param_env , cx. module )
929
- } )
930
- . map ( |( idx, _) | idx)
931
- . partition ( |idx| {
932
- let variant_def_id = def. variant ( * idx) . def_id ;
933
- // Filter variants that depend on a disabled unstable feature.
934
- let is_unstable = matches ! (
935
- cx. tcx. eval_stability( variant_def_id, None , DUMMY_SP , None ) ,
936
- EvalResult :: Deny { .. }
937
- ) ;
938
- // Filter foreign `#[doc(hidden)]` variants.
939
- let is_doc_hidden =
940
- cx. tcx . is_doc_hidden ( variant_def_id) && !variant_def_id. is_local ( ) ;
941
- is_unstable || is_doc_hidden
942
- } ) ;
899
+ let mut visible_variants = Vec :: new ( ) ;
900
+ let mut hidden_variants = Vec :: new ( ) ;
901
+ let mut empty_variants = Vec :: new ( ) ;
902
+ for ( idx, v) in def. variants ( ) . iter_enumerated ( ) {
903
+ let variant_def_id = def. variant ( idx) . def_id ;
904
+ // Visibly uninhabited variants.
905
+ let is_inhabited = v
906
+ . inhabited_predicate ( cx. tcx , * def)
907
+ . instantiate ( cx. tcx , args)
908
+ . apply ( cx. tcx , cx. param_env , cx. module ) ;
909
+ // Variants that depend on a disabled unstable feature.
910
+ let is_unstable = matches ! (
911
+ cx. tcx. eval_stability( variant_def_id, None , DUMMY_SP , None ) ,
912
+ EvalResult :: Deny { .. }
913
+ ) ;
914
+ // Foreign `#[doc(hidden)]` variants.
915
+ let is_doc_hidden =
916
+ cx. tcx . is_doc_hidden ( variant_def_id) && !variant_def_id. is_local ( ) ;
917
+ if is_exhaustive_pat_feature && !is_inhabited {
918
+ empty_variants. push ( idx) ;
919
+ } else if is_unstable || is_doc_hidden {
920
+ hidden_variants. push ( idx) ;
921
+ } else {
922
+ visible_variants. push ( idx) ;
923
+ }
924
+ }
943
925
944
926
Self :: Variants {
945
927
visible_variants,
946
928
hidden_variants,
929
+ empty_variants,
947
930
non_exhaustive : is_declared_nonexhaustive,
948
931
}
949
932
}
@@ -980,7 +963,12 @@ impl ConstructorSet {
980
963
present. push ( Single ) ;
981
964
}
982
965
}
983
- ConstructorSet :: Variants { visible_variants, hidden_variants, non_exhaustive } => {
966
+ ConstructorSet :: Variants {
967
+ visible_variants,
968
+ hidden_variants,
969
+ empty_variants,
970
+ non_exhaustive,
971
+ } => {
984
972
let seen_set: FxHashSet < _ > = seen. map ( |c| c. as_variant ( ) . unwrap ( ) ) . collect ( ) ;
985
973
let mut skipped_a_hidden_variant = false ;
986
974
@@ -992,7 +980,6 @@ impl ConstructorSet {
992
980
missing. push ( ctor) ;
993
981
}
994
982
}
995
-
996
983
for variant in hidden_variants {
997
984
let ctor = Variant ( * variant) ;
998
985
if seen_set. contains ( & variant) {
@@ -1001,6 +988,13 @@ impl ConstructorSet {
1001
988
skipped_a_hidden_variant = true ;
1002
989
}
1003
990
}
991
+ for variant in empty_variants {
992
+ let ctor = Variant ( * variant) ;
993
+ if seen_set. contains ( & variant) {
994
+ present. push ( ctor) ;
995
+ }
996
+ }
997
+
1004
998
if skipped_a_hidden_variant {
1005
999
missing. push ( Hidden ) ;
1006
1000
}
0 commit comments