Remove top-level or-pattern hack
This commit is contained in:
parent
ef087d96f0
commit
1c1bec2f6d
3 changed files with 83 additions and 112 deletions
|
@ -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
|
||||||
|
|
|
@ -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 => {},
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue