@@ -1309,11 +1309,6 @@ impl<'tcx> Constructor<'tcx> {
1309
1309
1310
1310
Pat { ty, span : DUMMY_SP , kind : Box :: new ( pat) }
1311
1311
}
1312
-
1313
- /// Like `apply`, but where all the subpatterns are wildcards `_`.
1314
- fn apply_wildcards < ' a > ( & self , cx : & MatchCheckCtxt < ' a , ' tcx > , ty : Ty < ' tcx > ) -> Pat < ' tcx > {
1315
- self . apply ( cx, ty, Fields :: wildcards ( cx, self , ty) )
1316
- }
1317
1312
}
1318
1313
1319
1314
/// Some fields need to be explicitly hidden away in certain cases; see the comment above the
@@ -1649,35 +1644,15 @@ impl<'tcx> Usefulness<'tcx> {
1649
1644
}
1650
1645
}
1651
1646
1652
- fn apply_wildcard ( self , ty : Ty < ' tcx > ) -> Self {
1653
- match self {
1654
- UsefulWithWitness ( witnesses) => {
1655
- let wild = Pat :: wildcard_from_ty ( ty) ;
1656
- UsefulWithWitness (
1657
- witnesses
1658
- . into_iter ( )
1659
- . map ( |mut witness| {
1660
- witness. 0 . push ( wild. clone ( ) ) ;
1661
- witness
1662
- } )
1663
- . collect ( ) ,
1664
- )
1665
- }
1666
- x => x,
1667
- }
1668
- }
1669
-
1670
- fn apply_missing_ctors (
1647
+ fn apply_wildcard < ' p > (
1671
1648
self ,
1672
- cx : & MatchCheckCtxt < ' _ , ' tcx > ,
1673
- ty : Ty < ' tcx > ,
1674
- missing_ctors : & MissingConstructors < ' tcx > ,
1649
+ cx : & MatchCheckCtxt < ' p , ' tcx > ,
1650
+ pcx : PatCtxt < ' tcx > ,
1651
+ missing_ctors : MissingConstructors < ' tcx > ,
1675
1652
) -> Self {
1676
1653
match self {
1677
1654
UsefulWithWitness ( witnesses) => {
1678
- let new_patterns: Vec < _ > =
1679
- missing_ctors. iter ( ) . map ( |ctor| ctor. apply_wildcards ( cx, ty) ) . collect ( ) ;
1680
- // Add the new patterns to each witness
1655
+ let new_patterns = missing_ctors. report_patterns ( cx, pcx) ;
1681
1656
UsefulWithWitness (
1682
1657
witnesses
1683
1658
. into_iter ( )
@@ -2270,11 +2245,21 @@ impl<'tcx> std::cmp::PartialEq for IntRange<'tcx> {
2270
2245
struct MissingConstructors < ' tcx > {
2271
2246
all_ctors : Vec < Constructor < ' tcx > > ,
2272
2247
used_ctors : Vec < Constructor < ' tcx > > ,
2248
+ is_top_level : bool ,
2273
2249
}
2274
2250
2275
2251
impl < ' tcx > MissingConstructors < ' tcx > {
2276
- fn new ( all_ctors : Vec < Constructor < ' tcx > > , used_ctors : Vec < Constructor < ' tcx > > ) -> Self {
2277
- MissingConstructors { all_ctors, used_ctors }
2252
+ fn new < ' p > (
2253
+ cx : & MatchCheckCtxt < ' p , ' tcx > ,
2254
+ pcx : PatCtxt < ' tcx > ,
2255
+ matrix : & Matrix < ' p , ' tcx > ,
2256
+ is_top_level : bool ,
2257
+ ) -> Self {
2258
+ let used_ctors: Vec < Constructor < ' _ > > =
2259
+ matrix. head_ctors ( cx) . cloned ( ) . filter ( |c| !c. is_wildcard ( ) ) . collect ( ) ;
2260
+ let all_ctors = all_constructors ( cx, pcx) ;
2261
+
2262
+ MissingConstructors { all_ctors, used_ctors, is_top_level }
2278
2263
}
2279
2264
2280
2265
fn into_inner ( self ) -> ( Vec < Constructor < ' tcx > > , Vec < Constructor < ' tcx > > ) {
@@ -2284,16 +2269,64 @@ impl<'tcx> MissingConstructors<'tcx> {
2284
2269
fn is_empty ( & self ) -> bool {
2285
2270
self . iter ( ) . next ( ) . is_none ( )
2286
2271
}
2287
- /// Whether this contains all the constructors for the given type or only a
2288
- /// subset.
2289
- fn all_ctors_are_missing ( & self ) -> bool {
2290
- self . used_ctors . is_empty ( )
2291
- }
2292
2272
2293
2273
/// Iterate over all_ctors \ used_ctors
2294
2274
fn iter < ' a > ( & ' a self ) -> impl Iterator < Item = Constructor < ' tcx > > + Captures < ' a > {
2295
2275
self . all_ctors . iter ( ) . flat_map ( move |req_ctor| req_ctor. subtract_ctors ( & self . used_ctors ) )
2296
2276
}
2277
+
2278
+ /// List the patterns corresponding to the missing constructors. In some cases, instead of
2279
+ /// listing all constructors of a given type, we prefer to simply report a wildcard.
2280
+ fn report_patterns < ' p > (
2281
+ & self ,
2282
+ cx : & MatchCheckCtxt < ' p , ' tcx > ,
2283
+ pcx : PatCtxt < ' tcx > ,
2284
+ ) -> SmallVec < [ Pat < ' tcx > ; 1 ] > {
2285
+ // There are 2 ways we can report a witness here.
2286
+ // Commonly, we can report all the "free"
2287
+ // constructors as witnesses, e.g., if we have:
2288
+ //
2289
+ // ```
2290
+ // enum Direction { N, S, E, W }
2291
+ // let Direction::N = ...;
2292
+ // ```
2293
+ //
2294
+ // we can report 3 witnesses: `S`, `E`, and `W`.
2295
+ //
2296
+ // However, there is a case where we don't want
2297
+ // to do this and instead report a single `_` witness:
2298
+ // if the user didn't actually specify a constructor
2299
+ // in this arm, e.g., in
2300
+ //
2301
+ // ```
2302
+ // let x: (Direction, Direction, bool) = ...;
2303
+ // let (_, _, false) = x;
2304
+ // ```
2305
+ //
2306
+ // we don't want to show all 16 possible witnesses
2307
+ // `(<direction-1>, <direction-2>, true)` - we are
2308
+ // satisfied with `(_, _, true)`. In this case,
2309
+ // `used_ctors` is empty.
2310
+ // The exception is: if we are at the top-level, for example in an empty match, we
2311
+ // sometimes prefer reporting the list of constructors instead of just `_`.
2312
+ let report_when_all_missing = self . is_top_level && !IntRange :: is_integral ( pcx. ty ) ;
2313
+ if self . used_ctors . is_empty ( ) && !report_when_all_missing {
2314
+ // All constructors are unused. Report only a wildcard
2315
+ // rather than each individual constructor.
2316
+ smallvec ! [ Pat :: wildcard_from_ty( pcx. ty) ]
2317
+ } else {
2318
+ // Construct for each missing constructor a "wild" version of this
2319
+ // constructor, that matches everything that can be built with
2320
+ // it. For example, if `ctor` is a `Constructor::Variant` for
2321
+ // `Option::Some`, we get the pattern `Some(_)`.
2322
+ self . iter ( )
2323
+ . map ( |missing_ctor| {
2324
+ let fields = Fields :: wildcards ( cx, & missing_ctor, pcx. ty ) ;
2325
+ missing_ctor. apply ( cx, pcx. ty , fields)
2326
+ } )
2327
+ . collect ( )
2328
+ }
2329
+ }
2297
2330
}
2298
2331
2299
2332
impl < ' tcx > fmt:: Debug for MissingConstructors < ' tcx > {
@@ -2434,14 +2467,6 @@ crate fn is_useful<'p, 'tcx>(
2434
2467
} else {
2435
2468
debug ! ( "is_useful - expanding wildcard" ) ;
2436
2469
2437
- let used_ctors: Vec < Constructor < ' _ > > =
2438
- matrix. head_ctors ( cx) . cloned ( ) . filter ( |c| !c. is_wildcard ( ) ) . collect ( ) ;
2439
- debug ! ( "is_useful_used_ctors = {:#?}" , used_ctors) ;
2440
- // `all_ctors` are all the constructors for the given type, which
2441
- // should all be represented (or caught with the wild pattern `_`).
2442
- let all_ctors = all_constructors ( cx, pcx) ;
2443
- debug ! ( "is_useful_all_ctors = {:#?}" , all_ctors) ;
2444
-
2445
2470
// `missing_ctors` is the set of constructors from the same type as the
2446
2471
// first column of `matrix` that are matched only by wildcard patterns
2447
2472
// from the first column.
@@ -2453,7 +2478,7 @@ crate fn is_useful<'p, 'tcx>(
2453
2478
// Missing constructors are those that are not matched by any non-wildcard patterns in the
2454
2479
// current column. We only fully construct them on-demand, because they're rarely used and
2455
2480
// can be big.
2456
- let missing_ctors = MissingConstructors :: new ( all_ctors , used_ctors ) ;
2481
+ let missing_ctors = MissingConstructors :: new ( cx , pcx , matrix , is_top_level ) ;
2457
2482
2458
2483
debug ! ( "is_useful_missing_ctors.empty()={:#?}" , missing_ctors. is_empty( ) , ) ;
2459
2484
@@ -2485,49 +2510,7 @@ crate fn is_useful<'p, 'tcx>(
2485
2510
let usefulness =
2486
2511
is_useful ( cx, & matrix, & v, witness_preference, hir_id, is_under_guard, false ) ;
2487
2512
2488
- // In this case, there's at least one "free"
2489
- // constructor that is only matched against by
2490
- // wildcard patterns.
2491
- //
2492
- // There are 2 ways we can report a witness here.
2493
- // Commonly, we can report all the "free"
2494
- // constructors as witnesses, e.g., if we have:
2495
- //
2496
- // ```
2497
- // enum Direction { N, S, E, W }
2498
- // let Direction::N = ...;
2499
- // ```
2500
- //
2501
- // we can report 3 witnesses: `S`, `E`, and `W`.
2502
- //
2503
- // However, there is a case where we don't want
2504
- // to do this and instead report a single `_` witness:
2505
- // if the user didn't actually specify a constructor
2506
- // in this arm, e.g., in
2507
- //
2508
- // ```
2509
- // let x: (Direction, Direction, bool) = ...;
2510
- // let (_, _, false) = x;
2511
- // ```
2512
- //
2513
- // we don't want to show all 16 possible witnesses
2514
- // `(<direction-1>, <direction-2>, true)` - we are
2515
- // satisfied with `(_, _, true)`. In this case,
2516
- // `used_ctors` is empty.
2517
- // The exception is: if we are at the top-level, for example in an empty match, we
2518
- // sometimes prefer reporting the list of constructors instead of just `_`.
2519
- let report_ctors_rather_than_wildcard = is_top_level && !IntRange :: is_integral ( pcx. ty ) ;
2520
- if missing_ctors. all_ctors_are_missing ( ) && !report_ctors_rather_than_wildcard {
2521
- // All constructors are unused. Add a wild pattern
2522
- // rather than each individual constructor.
2523
- usefulness. apply_wildcard ( pcx. ty )
2524
- } else {
2525
- // Construct for each missing constructor a "wild" version of this
2526
- // constructor, that matches everything that can be built with
2527
- // it. For example, if `ctor` is a `Constructor::Variant` for
2528
- // `Option::Some`, we get the pattern `Some(_)`.
2529
- usefulness. apply_missing_ctors ( cx, pcx. ty , & missing_ctors)
2530
- }
2513
+ usefulness. apply_wildcard ( cx, pcx, missing_ctors)
2531
2514
}
2532
2515
} ;
2533
2516
debug ! ( "is_useful::returns({:#?}, {:#?}) = {:?}" , matrix, v, ret) ;
0 commit comments