@@ -1255,41 +1255,17 @@ impl<'tcx> IntRange<'tcx> {
12551255 }
12561256}
12571257
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 > (
12851263 tcx : TyCtxt < ' tcx > ,
12861264 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| {
12931269 let mut refined_ctors = vec ! [ req_ctor. clone( ) ] ;
12941270 for used_ctor in used_ctors {
12951271 if used_ctor == req_ctor {
@@ -1303,32 +1279,19 @@ fn compute_missing_ctors<'tcx>(
13031279 }
13041280
13051281 // 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
13071283 // constructor is not missing, and we can move on to the next one.
13081284 if refined_ctors. is_empty ( ) {
13091285 break ;
13101286 }
13111287 }
1288+
13121289 // If a constructor has not been matched, then it is missing.
13131290 // We add `refined_ctors` instead of `req_ctor`, because then we can
13141291 // provide more detailed error information about precisely which
13151292 // 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+ } )
13321295}
13331296
13341297/// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html.
@@ -1459,22 +1422,19 @@ pub fn is_useful<'p, 'a, 'tcx>(
14591422 // needed for that case.
14601423
14611424 // 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 ( ) ;
14721430
14731431 let is_privately_empty = all_ctors. is_empty ( ) && !cx. is_uninhabited ( pcx. ty ) ;
14741432 let is_declared_nonexhaustive = cx. is_non_exhaustive_enum ( pcx. ty ) && !cx. is_local ( pcx. ty ) ;
14751433 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
14781438 ) ;
14791439
14801440 // 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>(
14831443 || is_declared_nonexhaustive
14841444 || ( pcx. ty . is_ptr_sized_integral ( ) && !cx. tcx . features ( ) . precise_pointer_size_matching ) ;
14851445
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.
14871448 split_grouped_constructors (
14881449 cx. tcx ,
14891450 cx. param_env ,
@@ -1561,28 +1522,18 @@ pub fn is_useful<'p, 'a, 'tcx>(
15611522 } )
15621523 . collect ( )
15631524 } 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 )
15811534 } )
1582- . collect ( )
1583- } else {
1584- bug ! ( "cheap missing ctors" )
1585- }
1535+ } )
1536+ . collect ( )
15861537 } ;
15871538 UsefulWithWitness ( new_witnesses)
15881539 }
0 commit comments