Skip to content

Commit b3c26f1

Browse files
committed
Extract shared helper function is_const_pat_that_looks_like_binding
1 parent 67944d6 commit b3c26f1

1 file changed

Lines changed: 23 additions & 13 deletions

File tree

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
55
use rustc_errors::codes::*;
66
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_err};
77
use rustc_hir::def::*;
8-
use rustc_hir::def_id::LocalDefId;
8+
use rustc_hir::def_id::{DefId, LocalDefId};
99
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, MatchSource};
1010
use rustc_infer::infer::TyCtxtInferExt;
1111
use rustc_lint::Level;
@@ -687,12 +687,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
687687
unpeeled_pat = subpattern;
688688
}
689689

690-
if let PatKind::ExpandedConstant { def_id, .. } = unpeeled_pat.kind
691-
&& let DefKind::Const = self.tcx.def_kind(def_id)
692-
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
693-
// We filter out paths with multiple path::segments.
694-
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
695-
{
690+
if let Some(def_id) = is_const_pat_that_looks_like_binding(self.tcx, unpeeled_pat) {
696691
let span = self.tcx.def_span(def_id);
697692
let variable = self.tcx.item_name(def_id).to_string();
698693
// When we encounter a constant as the binding name, point at the `const` definition.
@@ -1209,6 +1204,26 @@ fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool {
12091204
}
12101205
}
12111206

1207+
/// If the given pattern is a named constant that looks like it could have been
1208+
/// intended to be a binding, returns the `DefId` of the named constant.
1209+
///
1210+
/// Diagnostics use this to give more detailed suggestions for non-exhaustive
1211+
/// matches.
1212+
fn is_const_pat_that_looks_like_binding<'tcx>(tcx: TyCtxt<'tcx>, pat: &Pat<'tcx>) -> Option<DefId> {
1213+
// The pattern must be a named constant, and the name that appears in
1214+
// the pattern's source text must resemble a plain identifier without any
1215+
// `::` namespace separators or other non-identifier characters.
1216+
if let PatKind::ExpandedConstant { def_id, .. } = pat.kind
1217+
&& matches!(tcx.def_kind(def_id), DefKind::Const)
1218+
&& let Ok(snippet) = tcx.sess.source_map().span_to_snippet(pat.span)
1219+
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
1220+
{
1221+
Some(def_id)
1222+
} else {
1223+
None
1224+
}
1225+
}
1226+
12121227
/// Report that a match is not exhaustive.
12131228
fn report_non_exhaustive_match<'p, 'tcx>(
12141229
cx: &PatCtxt<'p, 'tcx>,
@@ -1303,12 +1318,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
13031318

13041319
for &arm in arms {
13051320
let arm = &thir.arms[arm];
1306-
if let PatKind::ExpandedConstant { def_id, .. } = arm.pattern.kind
1307-
&& !matches!(cx.tcx.def_kind(def_id), DefKind::InlineConst)
1308-
&& let Ok(snippet) = cx.tcx.sess.source_map().span_to_snippet(arm.pattern.span)
1309-
// We filter out paths with multiple path::segments.
1310-
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
1311-
{
1321+
if let Some(def_id) = is_const_pat_that_looks_like_binding(cx.tcx, &arm.pattern) {
13121322
let const_name = cx.tcx.item_name(def_id);
13131323
err.span_label(
13141324
arm.pattern.span,

0 commit comments

Comments
 (0)