@@ -1279,43 +1279,76 @@ impl<'tcx> IntRange<'tcx> {
1279
1279
}
1280
1280
}
1281
1281
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 > {
1287
1284
tcx : TyCtxt < ' tcx > ,
1288
1285
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
+ }
1304
1299
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
+ }
1310
1336
}
1311
- }
1312
1337
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
+ }
1319
1352
}
1320
1353
1321
1354
/// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html.
@@ -1426,6 +1459,9 @@ pub fn is_useful<'p, 'a, 'tcx>(
1426
1459
let all_ctors = all_constructors ( cx, pcx) ;
1427
1460
debug ! ( "all_ctors = {:#?}" , all_ctors) ;
1428
1461
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
+
1429
1465
// `missing_ctors` is the set of constructors from the same type as the
1430
1466
// first column of `matrix` that are matched only by wildcard patterns
1431
1467
// from the first column.
@@ -1449,14 +1485,11 @@ pub fn is_useful<'p, 'a, 'tcx>(
1449
1485
// non-wildcard patterns in the current column. To determine if
1450
1486
// the set is empty, we can check that `.peek().is_none()`, so
1451
1487
// 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) ;
1454
1489
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 ) ;
1457
1490
debug ! (
1458
1491
"missing_ctors.empty()={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}" ,
1459
- missing_ctors. peek ( ) . is_none ( ) ,
1492
+ missing_ctors. is_empty ( ) ,
1460
1493
is_privately_empty,
1461
1494
is_declared_nonexhaustive
1462
1495
) ;
@@ -1467,8 +1500,8 @@ pub fn is_useful<'p, 'a, 'tcx>(
1467
1500
|| is_declared_nonexhaustive
1468
1501
|| ( pcx. ty . is_ptr_sized_integral ( ) && !cx. tcx . features ( ) . precise_pointer_size_matching ) ;
1469
1502
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 ( ) ;
1472
1505
split_grouped_constructors (
1473
1506
cx. tcx ,
1474
1507
cx. param_env ,
@@ -1532,7 +1565,8 @@ pub fn is_useful<'p, 'a, 'tcx>(
1532
1565
// `(<direction-1>, <direction-2>, true)` - we are
1533
1566
// satisfied with `(_, _, true)`. In this case,
1534
1567
// `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
+ {
1536
1570
// All constructors are unused. Add a wild pattern
1537
1571
// rather than each individual constructor.
1538
1572
vec ! [ Pat { ty: pcx. ty, span: DUMMY_SP , kind: box PatKind :: Wild } ]
@@ -1541,7 +1575,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
1541
1575
// constructor, that matches everything that can be built with
1542
1576
// it. For example, if `ctor` is a `Constructor::Variant` for
1543
1577
// `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 ( )
1545
1579
} ;
1546
1580
// Add the new patterns to each witness
1547
1581
let new_witnesses = witnesses
0 commit comments