Skip to content

Commit c226088

Browse files
committed
needless_borrowed_ref: Check HIR tree first.
1 parent 58aa804 commit c226088

File tree

1 file changed

+67
-75
lines changed

1 file changed

+67
-75
lines changed

clippy_lints/src/needless_borrowed_ref.rs

Lines changed: 67 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -37,83 +37,75 @@ declare_lint_pass!(NeedlessBorrowedRef => [NEEDLESS_BORROWED_REFERENCE]);
3737

3838
impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
3939
fn check_pat(&mut self, cx: &LateContext<'tcx>, ref_pat: &'tcx Pat<'_>) {
40-
if ref_pat.span.from_expansion() {
41-
// OK, simple enough, lints doesn't check in macro.
42-
return;
43-
}
44-
45-
// Do not lint patterns that are part of an OR `|` pattern, the binding mode must match in all arms
46-
for (_, node) in cx.tcx.hir().parent_iter(ref_pat.hir_id) {
47-
let Node::Pat(pat) = node else { break };
48-
49-
if matches!(pat.kind, PatKind::Or(_)) {
50-
return;
40+
if let PatKind::Ref(pat, Mutability::Not) = ref_pat.kind
41+
&& !ref_pat.span.from_expansion()
42+
&& cx
43+
.tcx
44+
.hir()
45+
.parent_iter(ref_pat.hir_id)
46+
.map_while(|(_, parent)| if let Node::Pat(pat) = parent { Some(pat) } else { None })
47+
// Do not lint patterns that are part of an OR `|` pattern, the binding mode must match in all arms
48+
.all(|pat| !matches!(pat.kind, PatKind::Or(_)))
49+
{
50+
match pat.kind {
51+
// Check sub_pat got a `ref` keyword (excluding `ref mut`).
52+
PatKind::Binding(BindingMode::REF, _, ident, None) => {
53+
span_lint_and_then(
54+
cx,
55+
NEEDLESS_BORROWED_REFERENCE,
56+
ref_pat.span,
57+
"this pattern takes a reference on something that is being dereferenced",
58+
|diag| {
59+
// `&ref ident`
60+
// ^^^^^
61+
let span = ref_pat.span.until(ident.span);
62+
diag.span_suggestion_verbose(
63+
span,
64+
"try removing the `&ref` part",
65+
String::new(),
66+
Applicability::MachineApplicable,
67+
);
68+
},
69+
);
70+
},
71+
// Slices where each element is `ref`: `&[ref a, ref b, ..., ref z]`
72+
PatKind::Slice(
73+
before,
74+
None
75+
| Some(Pat {
76+
kind: PatKind::Wild, ..
77+
}),
78+
after,
79+
) => {
80+
check_subpatterns(
81+
cx,
82+
"dereferencing a slice pattern where every element takes a reference",
83+
ref_pat,
84+
pat,
85+
itertools::chain(before, after),
86+
);
87+
},
88+
PatKind::Tuple(subpatterns, _) | PatKind::TupleStruct(_, subpatterns, _) => {
89+
check_subpatterns(
90+
cx,
91+
"dereferencing a tuple pattern where every element takes a reference",
92+
ref_pat,
93+
pat,
94+
subpatterns,
95+
);
96+
},
97+
PatKind::Struct(_, fields, _) => {
98+
check_subpatterns(
99+
cx,
100+
"dereferencing a struct pattern where every field's pattern takes a reference",
101+
ref_pat,
102+
pat,
103+
fields.iter().map(|field| field.pat),
104+
);
105+
},
106+
_ => {},
51107
}
52108
}
53-
54-
// Only lint immutable refs, because `&mut ref T` may be useful.
55-
let PatKind::Ref(pat, Mutability::Not) = ref_pat.kind else {
56-
return;
57-
};
58-
59-
match pat.kind {
60-
// Check sub_pat got a `ref` keyword (excluding `ref mut`).
61-
PatKind::Binding(BindingMode::REF, _, ident, None) => {
62-
span_lint_and_then(
63-
cx,
64-
NEEDLESS_BORROWED_REFERENCE,
65-
ref_pat.span,
66-
"this pattern takes a reference on something that is being dereferenced",
67-
|diag| {
68-
// `&ref ident`
69-
// ^^^^^
70-
let span = ref_pat.span.until(ident.span);
71-
diag.span_suggestion_verbose(
72-
span,
73-
"try removing the `&ref` part",
74-
String::new(),
75-
Applicability::MachineApplicable,
76-
);
77-
},
78-
);
79-
},
80-
// Slices where each element is `ref`: `&[ref a, ref b, ..., ref z]`
81-
PatKind::Slice(
82-
before,
83-
None
84-
| Some(Pat {
85-
kind: PatKind::Wild, ..
86-
}),
87-
after,
88-
) => {
89-
check_subpatterns(
90-
cx,
91-
"dereferencing a slice pattern where every element takes a reference",
92-
ref_pat,
93-
pat,
94-
itertools::chain(before, after),
95-
);
96-
},
97-
PatKind::Tuple(subpatterns, _) | PatKind::TupleStruct(_, subpatterns, _) => {
98-
check_subpatterns(
99-
cx,
100-
"dereferencing a tuple pattern where every element takes a reference",
101-
ref_pat,
102-
pat,
103-
subpatterns,
104-
);
105-
},
106-
PatKind::Struct(_, fields, _) => {
107-
check_subpatterns(
108-
cx,
109-
"dereferencing a struct pattern where every field's pattern takes a reference",
110-
ref_pat,
111-
pat,
112-
fields.iter().map(|field| field.pat),
113-
);
114-
},
115-
_ => {},
116-
}
117109
}
118110
}
119111

0 commit comments

Comments
 (0)