Skip to content

Commit 58eb03d

Browse files
committed
check_match: simplify check_arm
1 parent 78f0c7f commit 58eb03d

File tree

4 files changed

+46
-63
lines changed

4 files changed

+46
-63
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3763,6 +3763,7 @@ dependencies = [
37633763
"rustc_hir",
37643764
"rustc_index",
37653765
"rustc_macros",
3766+
"rustc_session",
37663767
"rustc_span",
37673768
"rustc_target",
37683769
"serialize",

src/librustc_mir_build/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ rustc_errors = { path = "../librustc_errors" }
2121
rustc_hir = { path = "../librustc_hir" }
2222
rustc_macros = { path = "../librustc_macros" }
2323
rustc_serialize = { path = "../libserialize", package = "serialize" }
24+
rustc_session = { path = "../librustc_session" }
2425
rustc_span = { path = "../librustc_span" }
2526
rustc_target = { path = "../librustc_target" }
2627
syntax = { path = "../libsyntax" }

src/librustc_mir_build/hair/pattern/check_match.rs

+41-62
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@ use super::_match::{expand_pattern, is_useful, MatchCheckCtxt, Matrix, PatStack}
55
use super::{PatCtxt, PatKind, PatternError};
66

77
use rustc::hir::map::Map;
8-
use rustc::lint;
9-
use rustc::session::parse::feature_err;
10-
use rustc::session::Session;
118
use rustc::ty::{self, Ty, TyCtxt};
129
use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder};
1310
use rustc_hir as hir;
1411
use rustc_hir::def::*;
1512
use rustc_hir::def_id::DefId;
1613
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
1714
use rustc_hir::{HirId, Pat};
15+
use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME;
16+
use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
17+
use rustc_session::parse::feature_err;
18+
use rustc_session::Session;
1819
use rustc_span::symbol::sym;
1920
use rustc_span::{MultiSpan, Span};
2021
use syntax::ast::Mutability;
@@ -156,9 +157,8 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
156157

157158
let inlined_arms: Vec<_> = arms
158159
.iter()
159-
.map(|arm| {
160-
let (pattern, _) = self.lower_pattern(cx, &arm.pat, &mut have_errors);
161-
(pattern, &*arm.pat, arm.guard.is_some())
160+
.map(|hir::Arm { pat, guard, .. }| {
161+
(self.lower_pattern(cx, pat, &mut have_errors).0, pat.hir_id, guard.is_some())
162162
})
163163
.collect();
164164

@@ -285,7 +285,7 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa
285285
let ty_path = cx.tcx.def_path_str(edef.did);
286286
cx.tcx
287287
.struct_span_lint_hir(
288-
lint::builtin::BINDINGS_WITH_VARIANT_NAME,
288+
BINDINGS_WITH_VARIANT_NAME,
289289
p.hir_id,
290290
p.span,
291291
&format!(
@@ -310,79 +310,63 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa
310310
}
311311

312312
/// Checks for common cases of "catchall" patterns that may not be intended as such.
313-
fn pat_is_catchall(pat: &Pat<'_>) -> bool {
314-
match pat.kind {
315-
hir::PatKind::Binding(.., None) => true,
316-
hir::PatKind::Binding(.., Some(ref s)) => pat_is_catchall(s),
317-
hir::PatKind::Ref(ref s, _) => pat_is_catchall(s),
318-
hir::PatKind::Tuple(ref v, _) => v.iter().all(|p| pat_is_catchall(&p)),
313+
fn pat_is_catchall(pat: &super::Pat<'_>) -> bool {
314+
use super::PatKind::*;
315+
match &*pat.kind {
316+
Binding { subpattern: None, .. } => true,
317+
Binding { subpattern: Some(s), .. } | Deref { subpattern: s } => pat_is_catchall(s),
318+
Leaf { subpatterns: s } => s.iter().all(|p| pat_is_catchall(&p.pattern)),
319319
_ => false,
320320
}
321321
}
322322

323+
fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<Span>) {
324+
let mut err = tcx.struct_span_lint_hir(UNREACHABLE_PATTERNS, id, span, "unreachable pattern");
325+
if let Some(catchall) = catchall {
326+
// We had a catchall pattern, hint at that.
327+
err.span_label(span, "unreachable pattern");
328+
err.span_label(catchall, "matches any value");
329+
}
330+
err.emit();
331+
}
332+
333+
fn irrefutable_let_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, source: hir::MatchSource) {
334+
let msg = match source {
335+
hir::MatchSource::IfLetDesugar { .. } => "irrefutable if-let pattern",
336+
hir::MatchSource::WhileLetDesugar => "irrefutable while-let pattern",
337+
_ => bug!(),
338+
};
339+
tcx.lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, msg);
340+
}
341+
323342
/// Check for unreachable patterns.
324343
fn check_arms<'p, 'tcx>(
325344
cx: &mut MatchCheckCtxt<'p, 'tcx>,
326-
arms: &[(&'p super::Pat<'tcx>, &hir::Pat<'_>, bool)],
345+
arms: &[(&'p super::Pat<'tcx>, HirId, bool)],
327346
source: hir::MatchSource,
328347
) -> Matrix<'p, 'tcx> {
329348
let mut seen = Matrix::empty();
330349
let mut catchall = None;
331-
for (arm_index, (pat, hir_pat, has_guard)) in arms.iter().enumerate() {
350+
for (arm_index, (pat, id, has_guard)) in arms.iter().copied().enumerate() {
332351
let v = PatStack::from_pattern(pat);
333-
334-
match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id, true) {
352+
match is_useful(cx, &seen, &v, LeaveOutWitness, id, true) {
335353
NotUseful => {
336354
match source {
337355
hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => bug!(),
338356

339357
hir::MatchSource::IfLetDesugar { .. } | hir::MatchSource::WhileLetDesugar => {
340-
// check which arm we're on.
358+
// Check which arm we're on.
341359
match arm_index {
342360
// The arm with the user-specified pattern.
343-
0 => {
344-
cx.tcx.lint_hir(
345-
lint::builtin::UNREACHABLE_PATTERNS,
346-
hir_pat.hir_id,
347-
pat.span,
348-
"unreachable pattern",
349-
);
350-
}
361+
0 => unreachable_pattern(cx.tcx, pat.span, id, None),
351362
// The arm with the wildcard pattern.
352-
1 => {
353-
let msg = match source {
354-
hir::MatchSource::IfLetDesugar { .. } => {
355-
"irrefutable if-let pattern"
356-
}
357-
hir::MatchSource::WhileLetDesugar => {
358-
"irrefutable while-let pattern"
359-
}
360-
_ => bug!(),
361-
};
362-
cx.tcx.lint_hir(
363-
lint::builtin::IRREFUTABLE_LET_PATTERNS,
364-
hir_pat.hir_id,
365-
pat.span,
366-
msg,
367-
);
368-
}
363+
1 => irrefutable_let_pattern(cx.tcx, pat.span, id, source),
369364
_ => bug!(),
370365
}
371366
}
372367

373368
hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => {
374-
let mut err = cx.tcx.struct_span_lint_hir(
375-
lint::builtin::UNREACHABLE_PATTERNS,
376-
hir_pat.hir_id,
377-
pat.span,
378-
"unreachable pattern",
379-
);
380-
// if we had a catchall pattern, hint at that
381-
if let Some(catchall) = catchall {
382-
err.span_label(pat.span, "unreachable pattern");
383-
err.span_label(catchall, "matches any value");
384-
}
385-
err.emit();
369+
unreachable_pattern(cx.tcx, pat.span, id, catchall);
386370
}
387371

388372
// Unreachable patterns in try and await expressions occur when one of
@@ -392,19 +376,14 @@ fn check_arms<'p, 'tcx>(
392376
}
393377
Useful(unreachable_subpatterns) => {
394378
for pat in unreachable_subpatterns {
395-
cx.tcx.lint_hir(
396-
lint::builtin::UNREACHABLE_PATTERNS,
397-
hir_pat.hir_id,
398-
pat.span,
399-
"unreachable pattern",
400-
);
379+
unreachable_pattern(cx.tcx, pat.span, id, None);
401380
}
402381
}
403382
UsefulWithWitness(_) => bug!(),
404383
}
405384
if !has_guard {
406385
seen.push(v);
407-
if catchall.is_none() && pat_is_catchall(hir_pat) {
386+
if catchall.is_none() && pat_is_catchall(pat) {
408387
catchall = Some(pat.span);
409388
}
410389
}

src/test/ui/pattern/usefulness/struct-pattern-match-useless.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
error: unreachable pattern
22
--> $DIR/struct-pattern-match-useless.rs:12:9
33
|
4+
LL | Foo { x: _x, y: _y } => (),
5+
| -------------------- matches any value
46
LL | Foo { .. } => ()
5-
| ^^^^^^^^^^
7+
| ^^^^^^^^^^ unreachable pattern
68
|
79
note: lint level defined here
810
--> $DIR/struct-pattern-match-useless.rs:1:9

0 commit comments

Comments
 (0)