@@ -1255,41 +1255,17 @@ impl<'tcx> IntRange<'tcx> {
1255
1255
}
1256
1256
}
1257
1257
1258
- // A request for missing constructor data in terms of either:
1259
- // - whether or not there any missing constructors; or
1260
- // - the actual set of missing constructors.
1261
- #[ derive( PartialEq ) ]
1262
- enum MissingCtorsInfo {
1263
- Emptiness ,
1264
- Ctors ,
1265
- }
1266
-
1267
- // Used by `compute_missing_ctors`.
1268
- #[ derive( Debug , PartialEq ) ]
1269
- enum MissingCtors < ' tcx > {
1270
- Empty ,
1271
- NonEmpty ,
1272
-
1273
- // Note that the Vec can be empty.
1274
- Ctors ( Vec < Constructor < ' tcx > > ) ,
1275
- }
1276
-
1277
- // When `info` is `MissingCtorsInfo::Ctors`, compute a set of constructors
1278
- // equivalent to `all_ctors \ used_ctors`. When `info` is
1279
- // `MissingCtorsInfo::Emptiness`, just determines if that set is empty or not.
1280
- // (The split logic gives a performance win, because we always need to know if
1281
- // the set is empty, but we rarely need the full set, and it can be expensive
1282
- // to compute the full set.)
1283
- fn compute_missing_ctors < ' tcx > (
1284
- info : MissingCtorsInfo ,
1258
+ type MissingConstructors < ' a , ' tcx , F > =
1259
+ std:: iter:: FlatMap < std:: slice:: Iter < ' a , Constructor < ' tcx > > , Vec < Constructor < ' tcx > > , F > ;
1260
+ // Compute a set of constructors equivalent to `all_ctors \ used_ctors`. This
1261
+ // returns an iterator, so that we only construct the whole set if needed.
1262
+ fn compute_missing_ctors < ' a , ' tcx > (
1285
1263
tcx : TyCtxt < ' tcx > ,
1286
1264
param_env : ty:: ParamEnv < ' tcx > ,
1287
- all_ctors : & Vec < Constructor < ' tcx > > ,
1288
- used_ctors : & Vec < Constructor < ' tcx > > ,
1289
- ) -> MissingCtors < ' tcx > {
1290
- let mut missing_ctors = vec ! [ ] ;
1291
-
1292
- for req_ctor in all_ctors {
1265
+ all_ctors : & ' a Vec < Constructor < ' tcx > > ,
1266
+ used_ctors : & ' a Vec < Constructor < ' tcx > > ,
1267
+ ) -> MissingConstructors < ' a , ' tcx , impl FnMut ( & ' a Constructor < ' tcx > ) -> Vec < Constructor < ' tcx > > > {
1268
+ all_ctors. iter ( ) . flat_map ( move |req_ctor| {
1293
1269
let mut refined_ctors = vec ! [ req_ctor. clone( ) ] ;
1294
1270
for used_ctor in used_ctors {
1295
1271
if used_ctor == req_ctor {
@@ -1303,32 +1279,19 @@ fn compute_missing_ctors<'tcx>(
1303
1279
}
1304
1280
1305
1281
// If the constructor patterns that have been considered so far
1306
- // already cover the entire range of values, then we the
1282
+ // already cover the entire range of values, then we know the
1307
1283
// constructor is not missing, and we can move on to the next one.
1308
1284
if refined_ctors. is_empty ( ) {
1309
1285
break ;
1310
1286
}
1311
1287
}
1288
+
1312
1289
// If a constructor has not been matched, then it is missing.
1313
1290
// We add `refined_ctors` instead of `req_ctor`, because then we can
1314
1291
// provide more detailed error information about precisely which
1315
1292
// ranges have been omitted.
1316
- if info == MissingCtorsInfo :: Emptiness {
1317
- if !refined_ctors. is_empty ( ) {
1318
- // The set is non-empty; return early.
1319
- return MissingCtors :: NonEmpty ;
1320
- }
1321
- } else {
1322
- missing_ctors. extend ( refined_ctors) ;
1323
- }
1324
- }
1325
-
1326
- if info == MissingCtorsInfo :: Emptiness {
1327
- // If we reached here, the set is empty.
1328
- MissingCtors :: Empty
1329
- } else {
1330
- MissingCtors :: Ctors ( missing_ctors)
1331
- }
1293
+ refined_ctors
1294
+ } )
1332
1295
}
1333
1296
1334
1297
/// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html.
@@ -1459,22 +1422,19 @@ pub fn is_useful<'p, 'a, 'tcx>(
1459
1422
// needed for that case.
1460
1423
1461
1424
// Missing constructors are those that are not matched by any
1462
- // non-wildcard patterns in the current column. We always determine if
1463
- // the set is empty, but we only fully construct them on-demand,
1464
- // because they're rarely used and can be big.
1465
- let cheap_missing_ctors = compute_missing_ctors (
1466
- MissingCtorsInfo :: Emptiness ,
1467
- cx. tcx ,
1468
- cx. param_env ,
1469
- & all_ctors,
1470
- & used_ctors,
1471
- ) ;
1425
+ // non-wildcard patterns in the current column. To determine if
1426
+ // the set is empty, we can check that `.peek().is_none()`, so
1427
+ // we only fully construct them on-demand, because they're rarely used and can be big.
1428
+ let mut missing_ctors =
1429
+ compute_missing_ctors ( cx. tcx , cx. param_env , & all_ctors, & used_ctors) . peekable ( ) ;
1472
1430
1473
1431
let is_privately_empty = all_ctors. is_empty ( ) && !cx. is_uninhabited ( pcx. ty ) ;
1474
1432
let is_declared_nonexhaustive = cx. is_non_exhaustive_enum ( pcx. ty ) && !cx. is_local ( pcx. ty ) ;
1475
1433
debug ! (
1476
- "cheap_missing_ctors={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}" ,
1477
- cheap_missing_ctors, is_privately_empty, is_declared_nonexhaustive
1434
+ "missing_ctors.empty()={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}" ,
1435
+ missing_ctors. peek( ) . is_none( ) ,
1436
+ is_privately_empty,
1437
+ is_declared_nonexhaustive
1478
1438
) ;
1479
1439
1480
1440
// For privately empty and non-exhaustive enums, we work as if there were an "extra"
@@ -1483,7 +1443,8 @@ pub fn is_useful<'p, 'a, 'tcx>(
1483
1443
|| is_declared_nonexhaustive
1484
1444
|| ( pcx. ty . is_ptr_sized_integral ( ) && !cx. tcx . features ( ) . precise_pointer_size_matching ) ;
1485
1445
1486
- if cheap_missing_ctors == MissingCtors :: Empty && !is_non_exhaustive {
1446
+ if missing_ctors. peek ( ) . is_none ( ) && !is_non_exhaustive {
1447
+ drop ( missing_ctors) ; // It was borrowing `all_ctors`, which we want to move.
1487
1448
split_grouped_constructors (
1488
1449
cx. tcx ,
1489
1450
cx. param_env ,
@@ -1561,28 +1522,18 @@ pub fn is_useful<'p, 'a, 'tcx>(
1561
1522
} )
1562
1523
. collect ( )
1563
1524
} else {
1564
- let expensive_missing_ctors = compute_missing_ctors (
1565
- MissingCtorsInfo :: Ctors ,
1566
- cx. tcx ,
1567
- cx. param_env ,
1568
- & all_ctors,
1569
- & used_ctors,
1570
- ) ;
1571
- if let MissingCtors :: Ctors ( missing_ctors) = expensive_missing_ctors {
1572
- pats. into_iter ( )
1573
- . flat_map ( |witness| {
1574
- missing_ctors. iter ( ) . map ( move |ctor| {
1575
- // Extends the witness with a "wild" version of this
1576
- // constructor, that matches everything that can be built with
1577
- // it. For example, if `ctor` is a `Constructor::Variant` for
1578
- // `Option::Some`, this pushes the witness for `Some(_)`.
1579
- witness. clone ( ) . push_wild_constructor ( cx, ctor, pcx. ty )
1580
- } )
1525
+ let missing_ctors: Vec < _ > = missing_ctors. collect ( ) ;
1526
+ pats. into_iter ( )
1527
+ . flat_map ( |witness| {
1528
+ missing_ctors. iter ( ) . map ( move |ctor| {
1529
+ // Extends the witness with a "wild" version of this
1530
+ // constructor, that matches everything that can be built with
1531
+ // it. For example, if `ctor` is a `Constructor::Variant` for
1532
+ // `Option::Some`, this pushes the witness for `Some(_)`.
1533
+ witness. clone ( ) . push_wild_constructor ( cx, ctor, pcx. ty )
1581
1534
} )
1582
- . collect ( )
1583
- } else {
1584
- bug ! ( "cheap missing ctors" )
1585
- }
1535
+ } )
1536
+ . collect ( )
1586
1537
} ;
1587
1538
UsefulWithWitness ( new_witnesses)
1588
1539
}
0 commit comments