62
62
/// The specialisation of a row vector is computed by `specialize`.
63
63
///
64
64
/// It is computed as follows. For each row `p_i` of P, we have four cases:
65
- /// 1.1. `p_(i,1)= c(r_1, .., r_a)`. Then `S(c, P)` has a corresponding row:
65
+ /// 1.1. `p_(i,1) = c(r_1, .., r_a)`. Then `S(c, P)` has a corresponding row:
66
66
/// r_1, .., r_a, p_(i,2), .., p_(i,n)
67
67
/// 1.2. `p_(i,1) = c'(r_1, .., r_a')` where `c ≠ c'`. Then `S(c, P)` has no
68
68
/// corresponding row.
85
85
/// D((r_1, p_(i,2), .., p_(i,n)))
86
86
/// D((r_2, p_(i,2), .., p_(i,n)))
87
87
///
88
+ /// Note that the OR-patterns are not always used directly in Rust, but are used to derive
89
+ /// the exhaustive integer matching rules, so they're written here for posterity.
90
+ ///
88
91
/// The algorithm for computing `U`
89
92
/// -------------------------------
90
93
/// The algorithm is inductive (on the number of columns: i.e. components of tuple patterns).
97
100
/// then `U(P, p_{m + 1})` is false.
98
101
/// - Otherwise, `P` must be empty, so `U(P, p_{m + 1})` is true.
99
102
///
100
- /// Inductive step. (`n > 0`, i.e. 1 or more tuple pattern components)
103
+ /// Inductive step. (`n > 0`, i.e. whether there's at least one column
104
+ /// [which may then be expanded into further columns later])
101
105
/// We're going to match on the new pattern, `p_{m + 1}`.
102
106
/// - If `p_{m + 1} == c(r_1, .., r_a)`, then we have a constructor pattern.
103
107
/// Thus, the usefulness of `p_{m + 1}` can be reduced to whether it is useful when
@@ -926,6 +930,46 @@ impl<'tcx> IntRange<'tcx> {
926
930
}
927
931
}
928
932
933
+ // Find those constructors that are not matched by any non-wildcard patterns in the current column.
934
+ fn compute_missing_ctors < ' a , ' tcx : ' a > (
935
+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
936
+ all_ctors : & Vec < Constructor < ' tcx > > ,
937
+ used_ctors : & Vec < Constructor < ' tcx > > ,
938
+ ) -> Vec < Constructor < ' tcx > > {
939
+ let mut missing_ctors = vec ! [ ] ;
940
+
941
+ for req_ctor in all_ctors {
942
+ let mut refined_ctors = vec ! [ req_ctor. clone( ) ] ;
943
+ for used_ctor in used_ctors {
944
+ if used_ctor == req_ctor {
945
+ // If a constructor appears in a `match` arm, we can
946
+ // eliminate it straight away.
947
+ refined_ctors = vec ! [ ]
948
+ } else if tcx. features ( ) . exhaustive_integer_patterns {
949
+ if let Some ( interval) = IntRange :: from_ctor ( tcx, used_ctor) {
950
+ // Refine the required constructors for the type by subtracting
951
+ // the range defined by the current constructor pattern.
952
+ refined_ctors = interval. subtract_from ( tcx, refined_ctors) ;
953
+ }
954
+ }
955
+
956
+ // If the constructor patterns that have been considered so far
957
+ // already cover the entire range of values, then we the
958
+ // constructor is not missing, and we can move on to the next one.
959
+ if refined_ctors. is_empty ( ) {
960
+ break ;
961
+ }
962
+ }
963
+ // If a constructor has not been matched, then it is missing.
964
+ // We add `refined_ctors` instead of `req_ctor`, because then we can
965
+ // provide more detailed error information about precisely which
966
+ // ranges have been omitted.
967
+ missing_ctors. extend ( refined_ctors) ;
968
+ }
969
+
970
+ missing_ctors
971
+ }
972
+
929
973
/// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html
930
974
/// The algorithm from the paper has been modified to correctly handle empty
931
975
/// types. The changes are:
@@ -1017,38 +1061,6 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
1017
1061
let all_ctors = all_constructors ( cx, pcx) ;
1018
1062
debug ! ( "all_ctors = {:#?}" , all_ctors) ;
1019
1063
1020
- // `missing_ctors` are those that should have appeared
1021
- // as patterns in the `match` expression, but did not.
1022
- let mut missing_ctors = vec ! [ ] ;
1023
- for req_ctor in & all_ctors {
1024
- let mut refined_ctors = vec ! [ req_ctor. clone( ) ] ;
1025
- for used_ctor in & used_ctors {
1026
- if used_ctor == req_ctor {
1027
- // If a constructor appears in a `match` arm, we can
1028
- // eliminate it straight away.
1029
- refined_ctors = vec ! [ ]
1030
- } else if cx. tcx . features ( ) . exhaustive_integer_patterns {
1031
- if let Some ( interval) = IntRange :: from_ctor ( cx. tcx , used_ctor) {
1032
- // Refine the required constructors for the type by subtracting
1033
- // the range defined by the current constructor pattern.
1034
- refined_ctors = interval. subtract_from ( cx. tcx , refined_ctors) ;
1035
- }
1036
- }
1037
-
1038
- // If the constructor patterns that have been considered so far
1039
- // already cover the entire range of values, then we the
1040
- // constructor is not missing, and we can move on to the next one.
1041
- if refined_ctors. is_empty ( ) {
1042
- break ;
1043
- }
1044
- }
1045
- // If a constructor has not been matched, then it is missing.
1046
- // We add `refined_ctors` instead of `req_ctor`, because then we can
1047
- // provide more detailed error information about precisely which
1048
- // ranges have been omitted.
1049
- missing_ctors. extend ( refined_ctors) ;
1050
- }
1051
-
1052
1064
// `missing_ctors` is the set of constructors from the same type as the
1053
1065
// first column of `matrix` that are matched only by wildcard patterns
1054
1066
// from the first column.
@@ -1067,11 +1079,10 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
1067
1079
// be a privately-empty enum is when the exhaustive_patterns
1068
1080
// feature flag is not present, so this is only
1069
1081
// needed for that case.
1082
+ let missing_ctors = compute_missing_ctors ( cx. tcx , & all_ctors, & used_ctors) ;
1070
1083
1071
- let is_privately_empty =
1072
- all_ctors. is_empty ( ) && !cx. is_uninhabited ( pcx. ty ) ;
1073
- let is_declared_nonexhaustive =
1074
- cx. is_non_exhaustive_enum ( pcx. ty ) && !cx. is_local ( pcx. ty ) ;
1084
+ let is_privately_empty = all_ctors. is_empty ( ) && !cx. is_uninhabited ( pcx. ty ) ;
1085
+ let is_declared_nonexhaustive = cx. is_non_exhaustive_enum ( pcx. ty ) && !cx. is_local ( pcx. ty ) ;
1075
1086
debug ! ( "missing_ctors={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}" ,
1076
1087
missing_ctors, is_privately_empty, is_declared_nonexhaustive) ;
1077
1088
0 commit comments