1 use clippy_utils
::diagnostics
::span_lint_and_then
;
2 use clippy_utils
::source
::snippet_with_applicability
;
3 use if_chain
::if_chain
;
4 use rustc_errors
::Applicability
;
5 use rustc_hir
::{BindingAnnotation, Mutability, Node, Pat, PatKind}
;
6 use rustc_lint
::{LateContext, LateLintPass}
;
7 use rustc_session
::{declare_lint_pass, declare_tool_lint}
;
11 /// Checks for bindings that destructure a reference and borrow the inner
12 /// value with `&ref`.
14 /// ### Why is this bad?
15 /// This pattern has no effect in almost all cases.
17 /// ### Known problems
18 /// In some cases, `&ref` is needed to avoid a lifetime mismatch error.
21 /// fn foo(a: &Option<String>, b: &Option<String>) {
23 /// (None, &ref c) | (&ref c, None) => (),
24 /// (&Some(ref c), _) => (),
31 /// let mut v = Vec::<String>::new();
32 /// # #[allow(unused)]
33 /// v.iter_mut().filter(|&ref a| a.is_empty());
38 /// let mut v = Vec::<String>::new();
39 /// # #[allow(unused)]
40 /// v.iter_mut().filter(|a| a.is_empty());
42 #[clippy::version = "pre 1.29.0"]
43 pub NEEDLESS_BORROWED_REFERENCE
,
45 "destructuring a reference and borrowing the inner value"
48 declare_lint_pass
!(NeedlessBorrowedRef
=> [NEEDLESS_BORROWED_REFERENCE
]);
50 impl<'tcx
> LateLintPass
<'tcx
> for NeedlessBorrowedRef
{
51 fn check_pat(&mut self, cx
: &LateContext
<'tcx
>, pat
: &'tcx Pat
<'_
>) {
52 if pat
.span
.from_expansion() {
53 // OK, simple enough, lints doesn't check in macro.
58 // Only lint immutable refs, because `&mut ref T` may be useful.
59 if let PatKind
::Ref(sub_pat
, Mutability
::Not
) = pat
.kind
;
61 // Check sub_pat got a `ref` keyword (excluding `ref mut`).
62 if let PatKind
::Binding(BindingAnnotation
::Ref
, .., spanned_name
, _
) = sub_pat
.kind
;
63 let parent_id
= cx
.tcx
.hir().get_parent_node(pat
.hir_id
);
64 if let Some(parent_node
) = cx
.tcx
.hir().find(parent_id
);
66 // do not recurse within patterns, as they may have other references
67 // XXXManishearth we can relax this constraint if we only check patterns
68 // with a single ref pattern inside them
69 if let Node
::Pat(_
) = parent_node
{
72 let mut applicability
= Applicability
::MachineApplicable
;
73 span_lint_and_then(cx
, NEEDLESS_BORROWED_REFERENCE
, pat
.span
,
74 "this pattern takes a reference on something that is being de-referenced",
76 let hint
= snippet_with_applicability(cx
, spanned_name
.span
, "..", &mut applicability
).into_owned();
79 "try removing the `&ref` part and just keep",