12
12
//!
13
13
//! This lint is **warn** by default
14
14
15
+ use crate :: rustc:: hir:: { BindingAnnotation , Expr , ExprKind , Item , MutImmutable , Pat , PatKind } ;
15
16
use crate :: rustc:: lint:: { LateContext , LateLintPass , LintArray , LintPass } ;
16
- use crate :: rustc:: { declare_tool_lint, lint_array} ;
17
- use if_chain:: if_chain;
18
- use crate :: rustc:: hir:: { BindingAnnotation , Expr , ExprKind , MutImmutable , Pat , PatKind } ;
19
17
use crate :: rustc:: ty;
20
18
use crate :: rustc:: ty:: adjustment:: { Adjust , Adjustment } ;
21
- use crate :: utils :: { in_macro , snippet_opt , span_lint_and_then } ;
19
+ use crate :: rustc :: { declare_tool_lint , lint_array } ;
22
20
use crate :: rustc_errors:: Applicability ;
21
+ use crate :: utils:: { in_macro, snippet_opt, span_lint_and_then} ;
22
+ use crate :: syntax:: ast:: NodeId ;
23
+ use if_chain:: if_chain;
23
24
24
25
/// **What it does:** Checks for address of operations (`&`) that are going to
25
26
/// be dereferenced immediately by the compiler.
@@ -32,26 +33,17 @@ use crate::rustc_errors::Applicability;
32
33
/// let x: &i32 = &&&&&&5;
33
34
/// ```
34
35
///
35
- /// **Known problems:** This will cause false positives in code generated by `derive`.
36
- /// For instance in the following snippet:
37
- /// ```rust
38
- /// #[derive(Debug)]
39
- /// pub enum Error {
40
- /// Type(
41
- /// &'static str,
42
- /// ),
43
- /// }
44
- /// ```
45
- /// A warning will be emitted that `&'static str` should be replaced with `&'static str`,
46
- /// however there is nothing that can or should be done to fix this.
36
+ /// **Known problems:** None.
47
37
declare_clippy_lint ! {
48
38
pub NEEDLESS_BORROW ,
49
39
nursery,
50
40
"taking a reference that is going to be automatically dereferenced"
51
41
}
52
42
53
- #[ derive( Copy , Clone ) ]
54
- pub struct NeedlessBorrow ;
43
+ #[ derive( Default ) ]
44
+ pub struct NeedlessBorrow {
45
+ derived_item : Option < NodeId > ,
46
+ }
55
47
56
48
impl LintPass for NeedlessBorrow {
57
49
fn get_lints ( & self ) -> LintArray {
@@ -61,7 +53,7 @@ impl LintPass for NeedlessBorrow {
61
53
62
54
impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for NeedlessBorrow {
63
55
fn check_expr ( & mut self , cx : & LateContext < ' a , ' tcx > , e : & ' tcx Expr ) {
64
- if in_macro ( e. span ) {
56
+ if in_macro ( e. span ) || self . derived_item . is_some ( ) {
65
57
return ;
66
58
}
67
59
if let ExprKind :: AddrOf ( MutImmutable , ref inner) = e. node {
@@ -87,7 +79,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
87
79
|db| {
88
80
if let Some ( snippet) = snippet_opt ( cx, inner. span ) {
89
81
db. span_suggestion_with_applicability (
90
- e. span ,
82
+ e. span ,
91
83
"change this to" ,
92
84
snippet,
93
85
Applicability :: MachineApplicable ,
@@ -101,7 +93,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
101
93
}
102
94
}
103
95
fn check_pat ( & mut self , cx : & LateContext < ' a , ' tcx > , pat : & ' tcx Pat ) {
104
- if in_macro ( pat. span ) {
96
+ if in_macro ( pat. span ) || self . derived_item . is_some ( ) {
105
97
return ;
106
98
}
107
99
if_chain ! {
@@ -131,4 +123,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
131
123
}
132
124
}
133
125
}
126
+
127
+ fn check_item ( & mut self , _: & LateContext < ' a , ' tcx > , item : & ' tcx Item ) {
128
+ if item. attrs . iter ( ) . any ( |a| a. check_name ( "automatically_derived" ) ) {
129
+ debug_assert ! ( self . derived_item. is_none( ) ) ;
130
+ self . derived_item = Some ( item. id ) ;
131
+ }
132
+ }
133
+
134
+ fn check_item_post ( & mut self , _: & LateContext < ' a , ' tcx > , item : & ' tcx Item ) {
135
+ if let Some ( id) = self . derived_item {
136
+ if item. id == id {
137
+ self . derived_item = None ;
138
+ }
139
+ }
140
+ }
134
141
}
0 commit comments