1
Fork 0

Remove top-level or-pattern hack

This commit is contained in:
Nadrieril 2019-11-29 15:53:54 +00:00
parent ef087d96f0
commit 1c1bec2f6d
3 changed files with 83 additions and 112 deletions

View file

@ -139,39 +139,22 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| { MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| {
let mut have_errors = false; let mut have_errors = false;
let inlined_arms: Vec<(Vec<_>, _)> = arms let inlined_arms: Vec<_> = arms
.iter() .iter()
.map(|arm| { .map(|arm| {
( let mut patcx = PatCtxt::new(
// HACK(or_patterns; Centril | dlrobertson): Remove this and self.tcx,
// correctly handle exhaustiveness checking for nested or-patterns. self.param_env.and(self.identity_substs),
match &arm.pat.kind { self.tables,
hir::PatKind::Or(pats) => pats, );
_ => std::slice::from_ref(&arm.pat), patcx.include_lint_checks();
} let pattern: &_ =
.iter() cx.pattern_arena.alloc(expand_pattern(cx, patcx.lower_pattern(&arm.pat)));
.map(|pat| { if !patcx.errors.is_empty() {
let mut patcx = PatCtxt::new( patcx.report_inlining_errors(arm.pat.span);
self.tcx, have_errors = true;
self.param_env.and(self.identity_substs), }
self.tables, (pattern, &*arm.pat, arm.guard.is_some())
);
patcx.include_lint_checks();
let pattern = cx
.pattern_arena
.alloc(expand_pattern(cx, patcx.lower_pattern(&pat)))
as &_;
if !patcx.errors.is_empty() {
patcx.report_inlining_errors(pat.span);
have_errors = true;
}
(pattern, &**pat)
})
.collect(),
arm.guard.as_ref().map(|g| match g {
hir::Guard::If(ref e) => &**e,
}),
)
}) })
.collect(); .collect();
@ -399,95 +382,90 @@ fn pat_is_catchall(pat: &Pat) -> bool {
// Check for unreachable patterns // Check for unreachable patterns
fn check_arms<'p, 'tcx>( fn check_arms<'p, 'tcx>(
cx: &mut MatchCheckCtxt<'p, 'tcx>, cx: &mut MatchCheckCtxt<'p, 'tcx>,
arms: &[(Vec<(&'p super::Pat<'tcx>, &hir::Pat)>, Option<&hir::Expr>)], arms: &[(&'p super::Pat<'tcx>, &hir::Pat, bool)],
source: hir::MatchSource, source: hir::MatchSource,
) -> Matrix<'p, 'tcx> { ) -> Matrix<'p, 'tcx> {
let mut seen = Matrix::empty(); let mut seen = Matrix::empty();
let mut catchall = None; let mut catchall = None;
for (arm_index, &(ref pats, guard)) in arms.iter().enumerate() { for (arm_index, (pat, hir_pat, has_guard)) in arms.iter().enumerate() {
for &(pat, hir_pat) in pats { let v = PatStack::from_pattern(pat);
let v = PatStack::from_pattern(pat);
match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id) { match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id) {
NotUseful => { NotUseful => {
match source { match source {
hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => { hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => bug!(),
bug!()
}
hir::MatchSource::IfLetDesugar { .. } hir::MatchSource::IfLetDesugar { .. } | hir::MatchSource::WhileLetDesugar => {
| hir::MatchSource::WhileLetDesugar => { // check which arm we're on.
// check which arm we're on. match arm_index {
match arm_index { // The arm with the user-specified pattern.
// The arm with the user-specified pattern. 0 => {
0 => { cx.tcx.lint_hir(
cx.tcx.lint_hir( lint::builtin::UNREACHABLE_PATTERNS,
lint::builtin::UNREACHABLE_PATTERNS, hir_pat.hir_id,
hir_pat.hir_id, pat.span,
pat.span, "unreachable pattern",
"unreachable pattern", );
);
}
// The arm with the wildcard pattern.
1 => {
let msg = match source {
hir::MatchSource::IfLetDesugar { .. } => {
"irrefutable if-let pattern"
}
hir::MatchSource::WhileLetDesugar => {
"irrefutable while-let pattern"
}
_ => bug!(),
};
cx.tcx.lint_hir(
lint::builtin::IRREFUTABLE_LET_PATTERNS,
hir_pat.hir_id,
pat.span,
msg,
);
}
_ => bug!(),
} }
} // The arm with the wildcard pattern.
1 => {
hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => { let msg = match source {
let mut err = cx.tcx.struct_span_lint_hir( hir::MatchSource::IfLetDesugar { .. } => {
lint::builtin::UNREACHABLE_PATTERNS, "irrefutable if-let pattern"
hir_pat.hir_id, }
pat.span, hir::MatchSource::WhileLetDesugar => {
"unreachable pattern", "irrefutable while-let pattern"
); }
// if we had a catchall pattern, hint at that _ => bug!(),
if let Some(catchall) = catchall { };
err.span_label(pat.span, "unreachable pattern"); cx.tcx.lint_hir(
err.span_label(catchall, "matches any value"); lint::builtin::IRREFUTABLE_LET_PATTERNS,
hir_pat.hir_id,
pat.span,
msg,
);
} }
err.emit(); _ => bug!(),
} }
// Unreachable patterns in try and await expressions occur when one of
// the arms are an uninhabited type. Which is OK.
hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar => {}
} }
}
Useful(unreachable_subpatterns) => { hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => {
for pat in unreachable_subpatterns { let mut err = cx.tcx.struct_span_lint_hir(
cx.tcx.lint_hir(
lint::builtin::UNREACHABLE_PATTERNS, lint::builtin::UNREACHABLE_PATTERNS,
hir_pat.hir_id, hir_pat.hir_id,
pat.span, pat.span,
"unreachable pattern", "unreachable pattern",
); );
// if we had a catchall pattern, hint at that
if let Some(catchall) = catchall {
err.span_label(pat.span, "unreachable pattern");
err.span_label(catchall, "matches any value");
}
err.emit();
} }
// Unreachable patterns in try and await expressions occur when one of
// the arms are an uninhabited type. Which is OK.
hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar => {}
} }
UsefulWithWitness(_) => bug!(),
} }
if guard.is_none() { Useful(unreachable_subpatterns) => {
seen.push(v); for pat in unreachable_subpatterns {
if catchall.is_none() && pat_is_catchall(hir_pat) { cx.tcx.lint_hir(
catchall = Some(pat.span); lint::builtin::UNREACHABLE_PATTERNS,
hir_pat.hir_id,
pat.span,
"unreachable pattern",
);
} }
} }
UsefulWithWitness(_) => bug!(),
}
if !has_guard {
seen.push(v);
if catchall.is_none() && pat_is_catchall(hir_pat) {
catchall = Some(pat.span);
}
} }
} }
seen seen

View file

@ -46,8 +46,7 @@ fn main() {
match Some(0u8) { match Some(0u8) {
Some(_) => {} Some(_) => {}
None => {} None => {}
None //~ ERROR unreachable pattern None | Some(_) => {} //~ ERROR unreachable pattern
| Some(_) => {} //~ ERROR unreachable pattern
} }
match 0u8 { match 0u8 {
1 | 2 => {}, 1 | 2 => {},

View file

@ -55,20 +55,14 @@ LL | None => {}
error: unreachable pattern error: unreachable pattern
--> $DIR/top-level-alternation.rs:49:9 --> $DIR/top-level-alternation.rs:49:9
| |
LL | None LL | None | Some(_) => {}
| ^^^^ | ^^^^^^^^^^^^^^
error: unreachable pattern error: unreachable pattern
--> $DIR/top-level-alternation.rs:50:15 --> $DIR/top-level-alternation.rs:53:9
|
LL | | Some(_) => {}
| ^^^^^^^
error: unreachable pattern
--> $DIR/top-level-alternation.rs:54:9
| |
LL | 1..=2 => {}, LL | 1..=2 => {},
| ^^^^^ | ^^^^^
error: aborting due to 11 previous errors error: aborting due to 10 previous errors