Skip to content

Commit aeb9d3f

Browse files
committed
Split out match_ref_pats
1 parent 3479e94 commit aeb9d3f

File tree

2 files changed

+71
-64
lines changed

2 files changed

+71
-64
lines changed
+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
2+
use clippy_utils::source::snippet;
3+
use clippy_utils::sugg::Sugg;
4+
use core::iter::once;
5+
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
6+
use rustc_lint::LateContext;
7+
8+
use super::MATCH_REF_PATS;
9+
10+
pub(crate) fn check<'a, 'b, I>(cx: &LateContext<'_>, ex: &Expr<'_>, pats: I, expr: &Expr<'_>)
11+
where
12+
'b: 'a,
13+
I: Clone + Iterator<Item = &'a Pat<'b>>,
14+
{
15+
if !has_multiple_ref_pats(pats.clone()) {
16+
return;
17+
}
18+
19+
let (first_sugg, msg, title);
20+
let span = ex.span.source_callsite();
21+
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = ex.kind {
22+
first_sugg = once((span, Sugg::hir_with_macro_callsite(cx, inner, "..").to_string()));
23+
msg = "try";
24+
title = "you don't need to add `&` to both the expression and the patterns";
25+
} else {
26+
first_sugg = once((span, Sugg::hir_with_macro_callsite(cx, ex, "..").deref().to_string()));
27+
msg = "instead of prefixing all patterns with `&`, you can dereference the expression";
28+
title = "you don't need to add `&` to all patterns";
29+
}
30+
31+
let remaining_suggs = pats.filter_map(|pat| {
32+
if let PatKind::Ref(refp, _) = pat.kind {
33+
Some((pat.span, snippet(cx, refp.span, "..").to_string()))
34+
} else {
35+
None
36+
}
37+
});
38+
39+
span_lint_and_then(cx, MATCH_REF_PATS, expr.span, title, |diag| {
40+
if !expr.span.from_expansion() {
41+
multispan_sugg(diag, msg, first_sugg.chain(remaining_suggs));
42+
}
43+
});
44+
}
45+
46+
fn has_multiple_ref_pats<'a, 'b, I>(pats: I) -> bool
47+
where
48+
'b: 'a,
49+
I: Iterator<Item = &'a Pat<'b>>,
50+
{
51+
let mut ref_count = 0;
52+
for opt in pats.map(|pat| match pat.kind {
53+
PatKind::Ref(..) => Some(true), // &-patterns
54+
PatKind::Wild => Some(false), // an "anything" wildcard is also fine
55+
_ => None, // any other pattern is not fine
56+
}) {
57+
if let Some(inner) = opt {
58+
if inner {
59+
ref_count += 1;
60+
}
61+
} else {
62+
return false;
63+
}
64+
}
65+
ref_count > 1
66+
}

clippy_lints/src/matches/mod.rs

+5-64
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
2-
use clippy_utils::source::{snippet, snippet_with_applicability};
3-
use clippy_utils::sugg::Sugg;
1+
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
2+
use clippy_utils::source::snippet_with_applicability;
43
use clippy_utils::{is_wild, meets_msrv, msrvs, path_to_local_id, peel_blocks, strip_pat_refs};
5-
use core::iter::once;
64
use if_chain::if_chain;
75
use rustc_errors::Applicability;
8-
use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, Pat, PatKind, QPath};
6+
use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat, PatKind, QPath};
97
use rustc_lint::{LateContext, LateLintPass};
108
use rustc_middle::ty;
119
use rustc_semver::RustcVersion;
@@ -14,6 +12,7 @@ use rustc_session::{declare_tool_lint, impl_lint_pass};
1412
mod match_as_ref;
1513
mod match_bool;
1614
mod match_like_matches;
15+
mod match_ref_pats;
1716
mod match_same_arms;
1817
mod match_single_binding;
1918
mod match_wild_enum;
@@ -633,7 +632,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
633632
}
634633
}
635634
if let ExprKind::Match(ex, arms, _) = expr.kind {
636-
check_match_ref_pats(cx, ex, arms.iter().map(|el| el.pat), expr);
635+
match_ref_pats::check(cx, ex, arms.iter().map(|el| el.pat), expr);
637636
}
638637
}
639638

@@ -698,42 +697,6 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
698697
extract_msrv_attr!(LateContext);
699698
}
700699

701-
fn check_match_ref_pats<'a, 'b, I>(cx: &LateContext<'_>, ex: &Expr<'_>, pats: I, expr: &Expr<'_>)
702-
where
703-
'b: 'a,
704-
I: Clone + Iterator<Item = &'a Pat<'b>>,
705-
{
706-
if !has_multiple_ref_pats(pats.clone()) {
707-
return;
708-
}
709-
710-
let (first_sugg, msg, title);
711-
let span = ex.span.source_callsite();
712-
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = ex.kind {
713-
first_sugg = once((span, Sugg::hir_with_macro_callsite(cx, inner, "..").to_string()));
714-
msg = "try";
715-
title = "you don't need to add `&` to both the expression and the patterns";
716-
} else {
717-
first_sugg = once((span, Sugg::hir_with_macro_callsite(cx, ex, "..").deref().to_string()));
718-
msg = "instead of prefixing all patterns with `&`, you can dereference the expression";
719-
title = "you don't need to add `&` to all patterns";
720-
}
721-
722-
let remaining_suggs = pats.filter_map(|pat| {
723-
if let PatKind::Ref(refp, _) = pat.kind {
724-
Some((pat.span, snippet(cx, refp.span, "..").to_string()))
725-
} else {
726-
None
727-
}
728-
});
729-
730-
span_lint_and_then(cx, MATCH_REF_PATS, expr.span, title, |diag| {
731-
if !expr.span.from_expansion() {
732-
multispan_sugg(diag, msg, first_sugg.chain(remaining_suggs));
733-
}
734-
});
735-
}
736-
737700
fn check_wild_in_or_pats(cx: &LateContext<'_>, arms: &[Arm<'_>]) {
738701
for arm in arms {
739702
if let PatKind::Or(fields) = arm.pat.kind {
@@ -751,25 +714,3 @@ fn check_wild_in_or_pats(cx: &LateContext<'_>, arms: &[Arm<'_>]) {
751714
}
752715
}
753716
}
754-
755-
fn has_multiple_ref_pats<'a, 'b, I>(pats: I) -> bool
756-
where
757-
'b: 'a,
758-
I: Iterator<Item = &'a Pat<'b>>,
759-
{
760-
let mut ref_count = 0;
761-
for opt in pats.map(|pat| match pat.kind {
762-
PatKind::Ref(..) => Some(true), // &-patterns
763-
PatKind::Wild => Some(false), // an "anything" wildcard is also fine
764-
_ => None, // any other pattern is not fine
765-
}) {
766-
if let Some(inner) = opt {
767-
if inner {
768-
ref_count += 1;
769-
}
770-
} else {
771-
return false;
772-
}
773-
}
774-
ref_count > 1
775-
}

0 commit comments

Comments
 (0)