6262/// The specialisation of a row vector is computed by `specialize`.
6363///
6464/// 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:
6666/// r_1, .., r_a, p_(i,2), .., p_(i,n)
6767/// 1.2. `p_(i,1) = c'(r_1, .., r_a')` where `c ≠ c'`. Then `S(c, P)` has no
6868/// corresponding row.
8585/// D((r_1, p_(i,2), .., p_(i,n)))
8686/// D((r_2, p_(i,2), .., p_(i,n)))
8787///
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+ ///
8891/// The algorithm for computing `U`
8992/// -------------------------------
9093/// The algorithm is inductive (on the number of columns: i.e. components of tuple patterns).
97100/// then `U(P, p_{m + 1})` is false.
98101/// - Otherwise, `P` must be empty, so `U(P, p_{m + 1})` is true.
99102///
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])
101105/// We're going to match on the new pattern, `p_{m + 1}`.
102106/// - If `p_{m + 1} == c(r_1, .., r_a)`, then we have a constructor pattern.
103107/// Thus, the usefulness of `p_{m + 1}` can be reduced to whether it is useful when
@@ -926,6 +930,46 @@ impl<'tcx> IntRange<'tcx> {
926930 }
927931}
928932
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+
929973/// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html
930974/// The algorithm from the paper has been modified to correctly handle empty
931975/// types. The changes are:
@@ -1017,38 +1061,6 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
10171061 let all_ctors = all_constructors ( cx, pcx) ;
10181062 debug ! ( "all_ctors = {:#?}" , all_ctors) ;
10191063
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-
10521064 // `missing_ctors` is the set of constructors from the same type as the
10531065 // first column of `matrix` that are matched only by wildcard patterns
10541066 // from the first column.
@@ -1067,11 +1079,10 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
10671079 // be a privately-empty enum is when the exhaustive_patterns
10681080 // feature flag is not present, so this is only
10691081 // needed for that case.
1082+ let missing_ctors = compute_missing_ctors ( cx. tcx , & all_ctors, & used_ctors) ;
10701083
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 ) ;
10751086 debug ! ( "missing_ctors={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}" ,
10761087 missing_ctors, is_privately_empty, is_declared_nonexhaustive) ;
10771088
0 commit comments