@@ -1279,43 +1279,76 @@ impl<'tcx> IntRange<'tcx> {
12791279 }
12801280}
12811281
1282- type MissingConstructors < ' a , ' tcx , F > =
1283- std:: iter:: FlatMap < std:: slice:: Iter < ' a , Constructor < ' tcx > > , Vec < Constructor < ' tcx > > , F > ;
1284- // Compute a set of constructors equivalent to `all_ctors \ used_ctors`. This
1285- // returns an iterator, so that we only construct the whole set if needed.
1286- fn compute_missing_ctors < ' a , ' tcx > (
1282+ // A struct to compute a set of constructors equivalent to `all_ctors \ used_ctors`.
1283+ struct MissingConstructors < ' tcx > {
12871284 tcx : TyCtxt < ' tcx > ,
12881285 param_env : ty:: ParamEnv < ' tcx > ,
1289- all_ctors : & ' a Vec < Constructor < ' tcx > > ,
1290- used_ctors : & ' a Vec < Constructor < ' tcx > > ,
1291- ) -> MissingConstructors < ' a , ' tcx , impl FnMut ( & ' a Constructor < ' tcx > ) -> Vec < Constructor < ' tcx > > > {
1292- all_ctors. iter ( ) . flat_map ( move |req_ctor| {
1293- let mut refined_ctors = vec ! [ req_ctor. clone( ) ] ;
1294- for used_ctor in used_ctors {
1295- if used_ctor == req_ctor {
1296- // If a constructor appears in a `match` arm, we can
1297- // eliminate it straight away.
1298- refined_ctors = vec ! [ ]
1299- } else if let Some ( interval) = IntRange :: from_ctor ( tcx, param_env, used_ctor) {
1300- // Refine the required constructors for the type by subtracting
1301- // the range defined by the current constructor pattern.
1302- refined_ctors = interval. subtract_from ( tcx, param_env, refined_ctors) ;
1303- }
1286+ all_ctors : Vec < Constructor < ' tcx > > ,
1287+ used_ctors : Vec < Constructor < ' tcx > > ,
1288+ }
1289+
1290+ impl < ' tcx > MissingConstructors < ' tcx > {
1291+ fn new (
1292+ tcx : TyCtxt < ' tcx > ,
1293+ param_env : ty:: ParamEnv < ' tcx > ,
1294+ all_ctors : Vec < Constructor < ' tcx > > ,
1295+ used_ctors : Vec < Constructor < ' tcx > > ,
1296+ ) -> Self {
1297+ MissingConstructors { tcx, param_env, all_ctors, used_ctors }
1298+ }
13041299
1305- // If the constructor patterns that have been considered so far
1306- // already cover the entire range of values, then we know the
1307- // constructor is not missing, and we can move on to the next one.
1308- if refined_ctors. is_empty ( ) {
1309- break ;
1300+ fn into_inner ( self ) -> ( Vec < Constructor < ' tcx > > , Vec < Constructor < ' tcx > > ) {
1301+ ( self . all_ctors , self . used_ctors )
1302+ }
1303+
1304+ fn is_empty ( & self ) -> bool {
1305+ self . iter ( ) . next ( ) . is_none ( )
1306+ }
1307+ /// Whether this contains all the constructors for the given type or only a
1308+ /// subset.
1309+ fn all_ctors_are_missing ( & self ) -> bool {
1310+ self . used_ctors . is_empty ( )
1311+ }
1312+
1313+ /// Iterate over all_ctors \ used_ctors
1314+ fn iter < ' a > ( & ' a self ) -> impl Iterator < Item = Constructor < ' tcx > > + Captures < ' a > {
1315+ self . all_ctors . iter ( ) . flat_map ( move |req_ctor| {
1316+ let mut refined_ctors = vec ! [ req_ctor. clone( ) ] ;
1317+ for used_ctor in & self . used_ctors {
1318+ if used_ctor == req_ctor {
1319+ // If a constructor appears in a `match` arm, we can
1320+ // eliminate it straight away.
1321+ refined_ctors = vec ! [ ]
1322+ } else if let Some ( interval) =
1323+ IntRange :: from_ctor ( self . tcx , self . param_env , used_ctor)
1324+ {
1325+ // Refine the required constructors for the type by subtracting
1326+ // the range defined by the current constructor pattern.
1327+ refined_ctors = interval. subtract_from ( self . tcx , self . param_env , refined_ctors) ;
1328+ }
1329+
1330+ // If the constructor patterns that have been considered so far
1331+ // already cover the entire range of values, then we know the
1332+ // constructor is not missing, and we can move on to the next one.
1333+ if refined_ctors. is_empty ( ) {
1334+ break ;
1335+ }
13101336 }
1311- }
13121337
1313- // If a constructor has not been matched, then it is missing.
1314- // We add `refined_ctors` instead of `req_ctor`, because then we can
1315- // provide more detailed error information about precisely which
1316- // ranges have been omitted.
1317- refined_ctors
1318- } )
1338+ // If a constructor has not been matched, then it is missing.
1339+ // We add `refined_ctors` instead of `req_ctor`, because then we can
1340+ // provide more detailed error information about precisely which
1341+ // ranges have been omitted.
1342+ refined_ctors
1343+ } )
1344+ }
1345+ }
1346+
1347+ impl < ' tcx > fmt:: Debug for MissingConstructors < ' tcx > {
1348+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1349+ let ctors: Vec < _ > = self . iter ( ) . collect ( ) ;
1350+ write ! ( f, "{:?}" , ctors)
1351+ }
13191352}
13201353
13211354/// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html.
@@ -1426,6 +1459,9 @@ pub fn is_useful<'p, 'a, 'tcx>(
14261459 let all_ctors = all_constructors ( cx, pcx) ;
14271460 debug ! ( "all_ctors = {:#?}" , all_ctors) ;
14281461
1462+ let is_privately_empty = all_ctors. is_empty ( ) && !cx. is_uninhabited ( pcx. ty ) ;
1463+ let is_declared_nonexhaustive = cx. is_non_exhaustive_enum ( pcx. ty ) && !cx. is_local ( pcx. ty ) ;
1464+
14291465 // `missing_ctors` is the set of constructors from the same type as the
14301466 // first column of `matrix` that are matched only by wildcard patterns
14311467 // from the first column.
@@ -1449,14 +1485,11 @@ pub fn is_useful<'p, 'a, 'tcx>(
14491485 // non-wildcard patterns in the current column. To determine if
14501486 // the set is empty, we can check that `.peek().is_none()`, so
14511487 // we only fully construct them on-demand, because they're rarely used and can be big.
1452- let mut missing_ctors =
1453- compute_missing_ctors ( cx. tcx , cx. param_env , & all_ctors, & used_ctors) . peekable ( ) ;
1488+ let missing_ctors = MissingConstructors :: new ( cx. tcx , cx. param_env , all_ctors, used_ctors) ;
14541489
1455- let is_privately_empty = all_ctors. is_empty ( ) && !cx. is_uninhabited ( pcx. ty ) ;
1456- let is_declared_nonexhaustive = cx. is_non_exhaustive_enum ( pcx. ty ) && !cx. is_local ( pcx. ty ) ;
14571490 debug ! (
14581491 "missing_ctors.empty()={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}" ,
1459- missing_ctors. peek ( ) . is_none ( ) ,
1492+ missing_ctors. is_empty ( ) ,
14601493 is_privately_empty,
14611494 is_declared_nonexhaustive
14621495 ) ;
@@ -1467,8 +1500,8 @@ pub fn is_useful<'p, 'a, 'tcx>(
14671500 || is_declared_nonexhaustive
14681501 || ( pcx. ty . is_ptr_sized_integral ( ) && !cx. tcx . features ( ) . precise_pointer_size_matching ) ;
14691502
1470- if missing_ctors. peek ( ) . is_none ( ) && !is_non_exhaustive {
1471- drop ( missing_ctors ) ; // It was borrowing ` all_ctors`, which we want to move.
1503+ if missing_ctors. is_empty ( ) && !is_non_exhaustive {
1504+ let ( all_ctors, _ ) = missing_ctors . into_inner ( ) ;
14721505 split_grouped_constructors (
14731506 cx. tcx ,
14741507 cx. param_env ,
@@ -1532,7 +1565,8 @@ pub fn is_useful<'p, 'a, 'tcx>(
15321565 // `(<direction-1>, <direction-2>, true)` - we are
15331566 // satisfied with `(_, _, true)`. In this case,
15341567 // `used_ctors` is empty.
1535- let new_patterns = if is_non_exhaustive || used_ctors. is_empty ( ) {
1568+ let new_patterns = if is_non_exhaustive || missing_ctors. all_ctors_are_missing ( )
1569+ {
15361570 // All constructors are unused. Add a wild pattern
15371571 // rather than each individual constructor.
15381572 vec ! [ Pat { ty: pcx. ty, span: DUMMY_SP , kind: box PatKind :: Wild } ]
@@ -1541,7 +1575,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
15411575 // constructor, that matches everything that can be built with
15421576 // it. For example, if `ctor` is a `Constructor::Variant` for
15431577 // `Option::Some`, we get the pattern `Some(_)`.
1544- missing_ctors. map ( |ctor| ctor. apply_wildcards ( cx, pcx. ty ) ) . collect ( )
1578+ missing_ctors. iter ( ) . map ( |ctor| ctor. apply_wildcards ( cx, pcx. ty ) ) . collect ( )
15451579 } ;
15461580 // Add the new patterns to each witness
15471581 let new_witnesses = witnesses
0 commit comments