diff options
| author | Amin Arria <arria.amin@gmail.com> | 2020-03-25 20:07:01 -0300 |
|---|---|---|
| committer | Amin Arria <arria.amin@gmail.com> | 2020-03-26 12:34:22 -0300 |
| commit | 5796e6e4618fd02bb7423b8f1a62f5b01ada63a7 (patch) | |
| tree | 15556d671458c462cb12d8cd61e6867f25350158 | |
| parent | 3c1d9adb3cb3aad4233075fa296fc3c70b42cdb8 (diff) | |
| download | rust-5796e6e4618fd02bb7423b8f1a62f5b01ada63a7.tar.gz rust-5796e6e4618fd02bb7423b8f1a62f5b01ada63a7.zip | |
Fix incorrect pattern warning "unreachable pattern"
- Added is_under_guard parameter to _match::is_useful and only add to the matrix if false - Added comments explaining behavior
| -rw-r--r-- | src/librustc_mir_build/hair/pattern/_match.rs | 42 | ||||
| -rw-r--r-- | src/librustc_mir_build/hair/pattern/check_match.rs | 7 |
2 files changed, 41 insertions, 8 deletions
diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 89063a4227f..b4a42aefca3 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -1619,12 +1619,17 @@ impl<'tcx> fmt::Debug for MissingConstructors<'tcx> { /// relation to preceding patterns, it is not reachable) and exhaustiveness /// checking (if a wildcard pattern is useful in relation to a matrix, the /// matrix isn't exhaustive). +/// +/// `is_under_guard` is used to inform if the pattern has a guard. If it +/// has one it must not be inserted into the matrix. This shouldn't be +/// relied on for soundness. crate fn is_useful<'p, 'tcx>( cx: &mut MatchCheckCtxt<'p, 'tcx>, matrix: &Matrix<'p, 'tcx>, v: &PatStack<'p, 'tcx>, witness_preference: WitnessPreference, hir_id: HirId, + is_under_guard: bool, is_top_level: bool, ) -> Usefulness<'tcx, 'p> { let &Matrix(ref rows) = matrix; @@ -1653,7 +1658,7 @@ crate fn is_useful<'p, 'tcx>( let mut unreachable_pats = Vec::new(); let mut any_is_useful = false; for v in vs { - let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, false); + let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false); match res { Useful(pats) => { any_is_useful = true; @@ -1664,7 +1669,10 @@ crate fn is_useful<'p, 'tcx>( bug!("Encountered or-pat in `v` during exhaustiveness checking") } } - matrix.push(v); + // If pattern has a guard don't add it to the matrix + if !is_under_guard { + matrix.push(v); + } } return if any_is_useful { Useful(unreachable_pats) } else { NotUseful }; } @@ -1712,7 +1720,18 @@ crate fn is_useful<'p, 'tcx>( Some(hir_id), ) .into_iter() - .map(|c| is_useful_specialized(cx, matrix, v, c, pcx.ty, witness_preference, hir_id)) + .map(|c| { + is_useful_specialized( + cx, + matrix, + v, + c, + pcx.ty, + witness_preference, + hir_id, + is_under_guard, + ) + }) .find(|result| result.is_useful()) .unwrap_or(NotUseful) } else { @@ -1746,14 +1765,24 @@ crate fn is_useful<'p, 'tcx>( split_grouped_constructors(cx.tcx, cx.param_env, pcx, all_ctors, matrix, DUMMY_SP, None) .into_iter() .map(|c| { - is_useful_specialized(cx, matrix, v, c, pcx.ty, witness_preference, hir_id) + is_useful_specialized( + cx, + matrix, + v, + c, + pcx.ty, + witness_preference, + hir_id, + is_under_guard, + ) }) .find(|result| result.is_useful()) .unwrap_or(NotUseful) } else { let matrix = matrix.specialize_wildcard(); let v = v.to_tail(); - let usefulness = is_useful(cx, &matrix, &v, witness_preference, hir_id, false); + let usefulness = + is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false); // In this case, there's at least one "free" // constructor that is only matched against by @@ -1810,6 +1839,7 @@ fn is_useful_specialized<'p, 'tcx>( lty: Ty<'tcx>, witness_preference: WitnessPreference, hir_id: HirId, + is_under_guard: bool, ) -> Usefulness<'tcx, 'p> { debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty); @@ -1817,7 +1847,7 @@ fn is_useful_specialized<'p, 'tcx>( cx.pattern_arena.alloc_from_iter(ctor.wildcard_subpatterns(cx, lty)); let matrix = matrix.specialize_constructor(cx, &ctor, ctor_wild_subpatterns); v.specialize_constructor(cx, &ctor, ctor_wild_subpatterns) - .map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id, false)) + .map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false)) .map(|u| u.apply_constructor(cx, &ctor, lty)) .unwrap_or(NotUseful) } diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index 9c86669cf9d..c2eeac60b8b 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -360,7 +360,7 @@ fn check_arms<'p, 'tcx>( let mut catchall = None; for (arm_index, (pat, id, has_guard)) in arms.iter().copied().enumerate() { let v = PatStack::from_pattern(pat); - match is_useful(cx, &seen, &v, LeaveOutWitness, id, true) { + match is_useful(cx, &seen, &v, LeaveOutWitness, id, has_guard, true) { NotUseful => { match source { hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => bug!(), @@ -410,7 +410,10 @@ fn check_not_useful<'p, 'tcx>( ) -> Result<(), Vec<super::Pat<'tcx>>> { let wild_pattern = cx.pattern_arena.alloc(super::Pat::wildcard_from_ty(ty)); let v = PatStack::from_pattern(wild_pattern); - match is_useful(cx, matrix, &v, ConstructWitness, hir_id, true) { + + // false is given for `is_under_guard` argument due to the wildcard + // pattern not having a guard + match is_useful(cx, matrix, &v, ConstructWitness, hir_id, false, true) { NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable. UsefulWithWitness(pats) => Err(if pats.is_empty() { bug!("Exhaustiveness check returned no witnesses") |
