1
Fork 0

Cleanup the reporting of unreachable patterns

This commit is contained in:
Nadrieril 2021-09-13 15:49:57 +01:00
parent 003bbcb799
commit ff90c6353b

View file

@ -190,20 +190,16 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
let scrut_ty = self.typeck_results.expr_ty_adjusted(scrut); let scrut_ty = self.typeck_results.expr_ty_adjusted(scrut);
let report = compute_match_usefulness(&cx, &arms, scrut.hir_id, scrut_ty); let report = compute_match_usefulness(&cx, &arms, scrut.hir_id, scrut_ty);
report_arm_reachability(&cx, &report, |arm_span, arm_hir_id, catchall| { match source {
match source { hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => {
hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => { report_arm_reachability(&cx, &report)
unreachable_pattern(cx.tcx, arm_span, arm_hir_id, catchall);
}
// 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 => {}
} }
}); // 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 => {}
}
// Check if the match is exhaustive. // Check if the match is exhaustive.
// Note: An empty match isn't the same as an empty matrix for diagnostics purposes,
// since an empty matrix can occur when there are arms, if those arms all have guards.
let is_empty_match = arms.is_empty(); let is_empty_match = arms.is_empty();
let witnesses = report.non_exhaustiveness_witnesses; let witnesses = report.non_exhaustiveness_witnesses;
if !witnesses.is_empty() { if !witnesses.is_empty() {
@ -434,9 +430,10 @@ fn check_let_reachability<'p, 'tcx>(
let arms = [MatchArm { pat, hir_id: pat_id, has_guard: false }]; let arms = [MatchArm { pat, hir_id: pat_id, has_guard: false }];
let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty); let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty);
report_arm_reachability(&cx, &report, |arm_span, arm_hir_id, _| { // Report if the pattern is unreachable, which can only occur when the type is uninhabited.
unreachable_pattern(cx.tcx, arm_span, arm_hir_id, None) // This also reports unreachable sub-patterns though, so we can't just replace it with an
}); // `is_uninhabited` check.
report_arm_reachability(&cx, &report);
if report.non_exhaustiveness_witnesses.is_empty() { if report.non_exhaustiveness_witnesses.is_empty() {
// The match is exhaustive, i.e. the `if let` pattern is irrefutable. // The match is exhaustive, i.e. the `if let` pattern is irrefutable.
@ -445,18 +442,15 @@ fn check_let_reachability<'p, 'tcx>(
} }
/// Report unreachable arms, if any. /// Report unreachable arms, if any.
fn report_arm_reachability<'p, 'tcx, F>( fn report_arm_reachability<'p, 'tcx>(
cx: &MatchCheckCtxt<'p, 'tcx>, cx: &MatchCheckCtxt<'p, 'tcx>,
report: &UsefulnessReport<'p, 'tcx>, report: &UsefulnessReport<'p, 'tcx>,
unreachable: F, ) {
) where
F: Fn(Span, HirId, Option<Span>),
{
use Reachability::*; use Reachability::*;
let mut catchall = None; let mut catchall = None;
for (arm, is_useful) in report.arm_usefulness.iter() { for (arm, is_useful) in report.arm_usefulness.iter() {
match is_useful { match is_useful {
Unreachable => unreachable(arm.pat.span, arm.hir_id, catchall), Unreachable => unreachable_pattern(cx.tcx, arm.pat.span, arm.hir_id, catchall),
Reachable(unreachables) if unreachables.is_empty() => {} Reachable(unreachables) if unreachables.is_empty() => {}
// The arm is reachable, but contains unreachable subpatterns (from or-patterns). // The arm is reachable, but contains unreachable subpatterns (from or-patterns).
Reachable(unreachables) => { Reachable(unreachables) => {