Skip to content

Commit c640b95

Browse files
authored
Rollup merge of #70413 - AminArria:match-pattern-incorrect-warning, r=Centril,Nadrieril,varkor
Fix incorrect pattern warning "unreachable pattern" Fixes #70372 Added `is_under_guard` parameter to `_match::is_useful` and only add it to the matrix if `false` Tested with: ```rust #![feature(or_patterns)] fn main() { match (3,42) { (a,_) | (_,a) if a > 10 => {println!("{}", a)} _ => () } match Some((3,42)) { Some((a, _)) | Some((_, a)) if a > 10 => {println!("{}", a)} _ => () } match Some((3,42)) { Some((a, _) | (_, a)) if a > 10 => {println!("{}", a)} _ => () } } ```
2 parents de3d1e9 + ae7fa30 commit c640b95

File tree

3 files changed

+63
-8
lines changed

3 files changed

+63
-8
lines changed

src/librustc_mir_build/hair/pattern/_match.rs

+36-6
Original file line numberDiff line numberDiff line change
@@ -1619,12 +1619,17 @@ impl<'tcx> fmt::Debug for MissingConstructors<'tcx> {
16191619
/// relation to preceding patterns, it is not reachable) and exhaustiveness
16201620
/// checking (if a wildcard pattern is useful in relation to a matrix, the
16211621
/// matrix isn't exhaustive).
1622+
///
1623+
/// `is_under_guard` is used to inform if the pattern has a guard. If it
1624+
/// has one it must not be inserted into the matrix. This shouldn't be
1625+
/// relied on for soundness.
16221626
crate fn is_useful<'p, 'tcx>(
16231627
cx: &mut MatchCheckCtxt<'p, 'tcx>,
16241628
matrix: &Matrix<'p, 'tcx>,
16251629
v: &PatStack<'p, 'tcx>,
16261630
witness_preference: WitnessPreference,
16271631
hir_id: HirId,
1632+
is_under_guard: bool,
16281633
is_top_level: bool,
16291634
) -> Usefulness<'tcx, 'p> {
16301635
let &Matrix(ref rows) = matrix;
@@ -1653,7 +1658,7 @@ crate fn is_useful<'p, 'tcx>(
16531658
let mut unreachable_pats = Vec::new();
16541659
let mut any_is_useful = false;
16551660
for v in vs {
1656-
let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, false);
1661+
let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
16571662
match res {
16581663
Useful(pats) => {
16591664
any_is_useful = true;
@@ -1664,7 +1669,10 @@ crate fn is_useful<'p, 'tcx>(
16641669
bug!("Encountered or-pat in `v` during exhaustiveness checking")
16651670
}
16661671
}
1667-
matrix.push(v);
1672+
// If pattern has a guard don't add it to the matrix
1673+
if !is_under_guard {
1674+
matrix.push(v);
1675+
}
16681676
}
16691677
return if any_is_useful { Useful(unreachable_pats) } else { NotUseful };
16701678
}
@@ -1712,7 +1720,18 @@ crate fn is_useful<'p, 'tcx>(
17121720
Some(hir_id),
17131721
)
17141722
.into_iter()
1715-
.map(|c| is_useful_specialized(cx, matrix, v, c, pcx.ty, witness_preference, hir_id))
1723+
.map(|c| {
1724+
is_useful_specialized(
1725+
cx,
1726+
matrix,
1727+
v,
1728+
c,
1729+
pcx.ty,
1730+
witness_preference,
1731+
hir_id,
1732+
is_under_guard,
1733+
)
1734+
})
17161735
.find(|result| result.is_useful())
17171736
.unwrap_or(NotUseful)
17181737
} else {
@@ -1746,14 +1765,24 @@ crate fn is_useful<'p, 'tcx>(
17461765
split_grouped_constructors(cx.tcx, cx.param_env, pcx, all_ctors, matrix, DUMMY_SP, None)
17471766
.into_iter()
17481767
.map(|c| {
1749-
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness_preference, hir_id)
1768+
is_useful_specialized(
1769+
cx,
1770+
matrix,
1771+
v,
1772+
c,
1773+
pcx.ty,
1774+
witness_preference,
1775+
hir_id,
1776+
is_under_guard,
1777+
)
17501778
})
17511779
.find(|result| result.is_useful())
17521780
.unwrap_or(NotUseful)
17531781
} else {
17541782
let matrix = matrix.specialize_wildcard();
17551783
let v = v.to_tail();
1756-
let usefulness = is_useful(cx, &matrix, &v, witness_preference, hir_id, false);
1784+
let usefulness =
1785+
is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
17571786

17581787
// In this case, there's at least one "free"
17591788
// constructor that is only matched against by
@@ -1810,14 +1839,15 @@ fn is_useful_specialized<'p, 'tcx>(
18101839
lty: Ty<'tcx>,
18111840
witness_preference: WitnessPreference,
18121841
hir_id: HirId,
1842+
is_under_guard: bool,
18131843
) -> Usefulness<'tcx, 'p> {
18141844
debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty);
18151845

18161846
let ctor_wild_subpatterns =
18171847
cx.pattern_arena.alloc_from_iter(ctor.wildcard_subpatterns(cx, lty));
18181848
let matrix = matrix.specialize_constructor(cx, &ctor, ctor_wild_subpatterns);
18191849
v.specialize_constructor(cx, &ctor, ctor_wild_subpatterns)
1820-
.map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id, false))
1850+
.map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false))
18211851
.map(|u| u.apply_constructor(cx, &ctor, lty))
18221852
.unwrap_or(NotUseful)
18231853
}

src/librustc_mir_build/hair/pattern/check_match.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ fn check_arms<'p, 'tcx>(
360360
let mut catchall = None;
361361
for (arm_index, (pat, id, has_guard)) in arms.iter().copied().enumerate() {
362362
let v = PatStack::from_pattern(pat);
363-
match is_useful(cx, &seen, &v, LeaveOutWitness, id, true) {
363+
match is_useful(cx, &seen, &v, LeaveOutWitness, id, has_guard, true) {
364364
NotUseful => {
365365
match source {
366366
hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => bug!(),
@@ -410,7 +410,10 @@ fn check_not_useful<'p, 'tcx>(
410410
) -> Result<(), Vec<super::Pat<'tcx>>> {
411411
let wild_pattern = cx.pattern_arena.alloc(super::Pat::wildcard_from_ty(ty));
412412
let v = PatStack::from_pattern(wild_pattern);
413-
match is_useful(cx, matrix, &v, ConstructWitness, hir_id, true) {
413+
414+
// false is given for `is_under_guard` argument due to the wildcard
415+
// pattern not having a guard
416+
match is_useful(cx, matrix, &v, ConstructWitness, hir_id, false, true) {
414417
NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
415418
UsefulWithWitness(pats) => Err(if pats.is_empty() {
416419
bug!("Exhaustiveness check returned no witnesses")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// check-pass
2+
3+
#![deny(unreachable_patterns)]
4+
5+
#![feature(or_patterns)]
6+
fn main() {
7+
match (3,42) {
8+
(a,_) | (_,a) if a > 10 => {println!("{}", a)}
9+
_ => ()
10+
}
11+
12+
match Some((3,42)) {
13+
Some((a, _)) | Some((_, a)) if a > 10 => {println!("{}", a)}
14+
_ => ()
15+
16+
}
17+
18+
match Some((3,42)) {
19+
Some((a, _) | (_, a)) if a > 10 => {println!("{}", a)}
20+
_ => ()
21+
}
22+
}

0 commit comments

Comments
 (0)