@@ -276,6 +276,7 @@ use self::Usefulness::*;
276
276
use self :: WitnessPreference :: * ;
277
277
278
278
use rustc_data_structures:: captures:: Captures ;
279
+ use rustc_data_structures:: fx:: FxHashSet ;
279
280
use rustc_index:: vec:: Idx ;
280
281
281
282
use super :: { compare_const_vals, PatternFoldable , PatternFolder } ;
@@ -1246,15 +1247,15 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1246
1247
}
1247
1248
1248
1249
#[ derive( Clone , Debug ) ]
1249
- crate enum Usefulness < ' tcx , ' p > {
1250
+ crate enum Usefulness < ' tcx > {
1250
1251
/// Carries a list of unreachable subpatterns. Used only in the presence of or-patterns.
1251
- Useful ( Vec < & ' p Pat < ' tcx > > ) ,
1252
+ Useful ( Vec < Span > ) ,
1252
1253
/// Carries a list of witnesses of non-exhaustiveness.
1253
1254
UsefulWithWitness ( Vec < Witness < ' tcx > > ) ,
1254
1255
NotUseful ,
1255
1256
}
1256
1257
1257
- impl < ' tcx , ' p > Usefulness < ' tcx , ' p > {
1258
+ impl < ' tcx > Usefulness < ' tcx > {
1258
1259
fn new_useful ( preference : WitnessPreference ) -> Self {
1259
1260
match preference {
1260
1261
ConstructWitness => UsefulWithWitness ( vec ! [ Witness ( vec![ ] ) ] ) ,
@@ -1269,7 +1270,7 @@ impl<'tcx, 'p> Usefulness<'tcx, 'p> {
1269
1270
}
1270
1271
}
1271
1272
1272
- fn apply_constructor (
1273
+ fn apply_constructor < ' p > (
1273
1274
self ,
1274
1275
cx : & MatchCheckCtxt < ' p , ' tcx > ,
1275
1276
ctor : & Constructor < ' tcx > ,
@@ -1828,7 +1829,7 @@ crate fn is_useful<'p, 'tcx>(
1828
1829
hir_id : HirId ,
1829
1830
is_under_guard : bool ,
1830
1831
is_top_level : bool ,
1831
- ) -> Usefulness < ' tcx , ' p > {
1832
+ ) -> Usefulness < ' tcx > {
1832
1833
let & Matrix ( ref rows) = matrix;
1833
1834
debug ! ( "is_useful({:#?}, {:#?})" , matrix, v) ;
1834
1835
@@ -1852,16 +1853,35 @@ crate fn is_useful<'p, 'tcx>(
1852
1853
// We need to push the already-seen patterns into the matrix in order to detect redundant
1853
1854
// branches like `Some(_) | Some(0)`. We also keep track of the unreachable subpatterns.
1854
1855
let mut matrix = matrix. clone ( ) ;
1855
- let mut unreachable_pats = Vec :: new ( ) ;
1856
+ // `Vec` of all the unreachable branches of the current or-pattern.
1857
+ let mut unreachable_branches = Vec :: new ( ) ;
1858
+ // Subpatterns that are unreachable from all branches. E.g. in the following case, the last
1859
+ // `true` is unreachable only from one branch, so it is overall reachable.
1860
+ // ```
1861
+ // match (true, true) {
1862
+ // (true, true) => {}
1863
+ // (false | true, false | true) => {}
1864
+ // }
1865
+ // ```
1866
+ let mut unreachable_subpats = FxHashSet :: default ( ) ;
1867
+ // Whether any branch at all is useful.
1856
1868
let mut any_is_useful = false ;
1869
+
1857
1870
for v in vs {
1858
1871
let res = is_useful ( cx, & matrix, & v, witness_preference, hir_id, is_under_guard, false ) ;
1859
1872
match res {
1860
1873
Useful ( pats) => {
1861
- any_is_useful = true ;
1862
- unreachable_pats. extend ( pats) ;
1874
+ if !any_is_useful {
1875
+ any_is_useful = true ;
1876
+ // Initialize with the first set of unreachable subpatterns encountered.
1877
+ unreachable_subpats = pats. into_iter ( ) . collect ( ) ;
1878
+ } else {
1879
+ // Keep the patterns unreachable from both this and previous branches.
1880
+ unreachable_subpats =
1881
+ pats. into_iter ( ) . filter ( |p| unreachable_subpats. contains ( p) ) . collect ( ) ;
1882
+ }
1863
1883
}
1864
- NotUseful => unreachable_pats . push ( v. head ( ) ) ,
1884
+ NotUseful => unreachable_branches . push ( v. head ( ) . span ) ,
1865
1885
UsefulWithWitness ( _) => {
1866
1886
bug ! ( "Encountered or-pat in `v` during exhaustiveness checking" )
1867
1887
}
@@ -1871,7 +1891,13 @@ crate fn is_useful<'p, 'tcx>(
1871
1891
matrix. push ( v) ;
1872
1892
}
1873
1893
}
1874
- return if any_is_useful { Useful ( unreachable_pats) } else { NotUseful } ;
1894
+ if any_is_useful {
1895
+ // Collect all the unreachable patterns.
1896
+ unreachable_branches. extend ( unreachable_subpats) ;
1897
+ return Useful ( unreachable_branches) ;
1898
+ } else {
1899
+ return NotUseful ;
1900
+ }
1875
1901
}
1876
1902
1877
1903
// FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
@@ -2014,7 +2040,7 @@ fn is_useful_specialized<'p, 'tcx>(
2014
2040
witness_preference : WitnessPreference ,
2015
2041
hir_id : HirId ,
2016
2042
is_under_guard : bool ,
2017
- ) -> Usefulness < ' tcx , ' p > {
2043
+ ) -> Usefulness < ' tcx > {
2018
2044
debug ! ( "is_useful_specialized({:#?}, {:#?}, {:?})" , v, ctor, ty) ;
2019
2045
2020
2046
// We cache the result of `Fields::wildcards` because it is used a lot.
0 commit comments