From b400f22c7b5125a3f35c12ecae1d31251e90fdc5 Mon Sep 17 00:00:00 2001 From: Jacob Adam Date: Tue, 7 Apr 2026 10:04:24 +0100 Subject: [PATCH] Show the guard exhaustivity note only when it's the guards alone that cause non-exhaustiveness Only show the "match arms with guards don't count towards exhaustivity" note when removing all guards would make the match exhaustive. Previously, this note was shown whenever all arms had guards, even if the patterns themselves were insufficient to cover all valid values of a type. Re-run the exhaustiveness analysis with guards stripped to determine whether the guards are actually the cause of non-exhaustiveness. This only happens on an actual exhaustiveness error, so should not be a performance concern. --- .../src/thir/pattern/check_match.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index baabc1afe3fa..eae798358b11 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -532,6 +532,18 @@ fn check_match( | hir::MatchSource::AwaitDesugar | hir::MatchSource::FormatArgs => None, }; + + // Check if the match would be exhaustive if all guards were removed. + // If so, we leave a note that guards don't count towards exhaustivity. + let would_be_exhaustive_without_guards = { + let any_arm_has_guard = tarms.iter().any(|arm| arm.has_guard); + any_arm_has_guard && { + let guardless_arms: Vec<_> = + tarms.iter().map(|arm| MatchArm { has_guard: false, ..*arm }).collect(); + rustc_pattern_analysis::rustc::analyze_match(&cx, &guardless_arms, scrut.ty) + .is_ok_and(|report| report.non_exhaustiveness_witnesses.is_empty()) + } + }; self.error = Err(report_non_exhaustive_match( &cx, self.thir, @@ -540,6 +552,7 @@ fn check_match( witnesses, arms, braces_span, + would_be_exhaustive_without_guards, )); } } @@ -1154,6 +1167,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( witnesses: Vec>, arms: &[ArmId], braces_span: Option, + would_be_exhaustive_without_guards: bool, ) -> ErrorGuaranteed { let is_empty_match = arms.is_empty(); let non_empty_enum = match scrut_ty.kind() { @@ -1364,8 +1378,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( }, ); - let all_arms_have_guards = arms.iter().all(|arm_id| thir[*arm_id].guard.is_some()); - if !is_empty_match && all_arms_have_guards { + if would_be_exhaustive_without_guards { err.subdiagnostic(NonExhaustiveMatchAllArmsGuarded); } if let Some((span, sugg)) = suggestion {