@@ -857,6 +857,7 @@ pub(super) enum ConstructorSet {
857
857
Variants {
858
858
visible_variants : Vec < VariantIdx > ,
859
859
hidden_variants : Vec < VariantIdx > ,
860
+ empty_variants : Vec < VariantIdx > ,
860
861
non_exhaustive : bool ,
861
862
} ,
862
863
/// 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 {
881
882
/// `present` is morally the set of constructors present in the column, and `missing` is the set of
882
883
/// constructors that exist in the type but are not present in the column.
883
884
///
884
- /// More formally, they respect the following constraints:
885
+ /// More formally, if we discard wildcards from the column, they respect the following constraints:
885
886
/// - 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`
891
890
/// - 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`.
894
897
#[ derive( Debug ) ]
895
898
pub ( super ) struct SplitConstructorSet < ' tcx > {
896
899
pub ( super ) present : SmallVec < [ Constructor < ' tcx > ; 1 ] > ,
@@ -904,12 +907,6 @@ impl ConstructorSet {
904
907
|start, end| IntRange :: from_range ( cx. tcx , start, end, ty, RangeEnd :: Included ) ;
905
908
// This determines the set of all possible constructors for the type `ty`. For numbers,
906
909
// 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()`).
913
910
match ty. kind ( ) {
914
911
ty:: Bool => {
915
912
Self :: Integers { range_1 : make_range ( 0 , 1 ) , range_2 : None , non_exhaustive : false }
@@ -958,56 +955,42 @@ impl ConstructorSet {
958
955
}
959
956
}
960
957
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.
977
958
let is_declared_nonexhaustive = cx. is_foreign_non_exhaustive_enum ( ty) ;
978
-
979
959
if def. variants ( ) . is_empty ( ) && !is_declared_nonexhaustive {
980
960
Self :: Uninhabited
981
961
} else {
982
962
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
+ }
1007
989
1008
990
Self :: Variants {
1009
991
visible_variants,
1010
992
hidden_variants,
993
+ empty_variants,
1011
994
non_exhaustive : is_declared_nonexhaustive,
1012
995
}
1013
996
}
@@ -1044,7 +1027,12 @@ impl ConstructorSet {
1044
1027
present. push ( Single ) ;
1045
1028
}
1046
1029
}
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
+ } => {
1048
1036
let seen_set: FxHashSet < _ > = seen. map ( |c| c. as_variant ( ) . unwrap ( ) ) . collect ( ) ;
1049
1037
let mut skipped_a_hidden_variant = false ;
1050
1038
@@ -1053,10 +1041,10 @@ impl ConstructorSet {
1053
1041
if seen_set. contains ( & variant) {
1054
1042
present. push ( ctor) ;
1055
1043
} else {
1044
+ // We only put visible variants directly into `missing`.
1056
1045
missing. push ( ctor) ;
1057
1046
}
1058
1047
}
1059
-
1060
1048
for variant in hidden_variants {
1061
1049
let ctor = Variant ( * variant) ;
1062
1050
if seen_set. contains ( & variant) {
@@ -1065,6 +1053,13 @@ impl ConstructorSet {
1065
1053
skipped_a_hidden_variant = true ;
1066
1054
}
1067
1055
}
1056
+ for variant in empty_variants {
1057
+ let ctor = Variant ( * variant) ;
1058
+ if seen_set. contains ( & variant) {
1059
+ present. push ( ctor) ;
1060
+ }
1061
+ }
1062
+
1068
1063
if skipped_a_hidden_variant {
1069
1064
missing. push ( Hidden ) ;
1070
1065
}
0 commit comments