1212//!
1313//! This lint is **warn** by default
1414
15+ use crate :: rustc:: hir:: { BindingAnnotation , Expr , ExprKind , Item , MutImmutable , Pat , PatKind } ;
1516use 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 } ;
1917use crate :: rustc:: ty;
2018use 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 } ;
2220use 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;
2324
2425/// **What it does:** Checks for address of operations (`&`) that are going to
2526/// be dereferenced immediately by the compiler.
@@ -32,26 +33,17 @@ use crate::rustc_errors::Applicability;
3233/// let x: &i32 = &&&&&&5;
3334/// ```
3435///
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.
4737declare_clippy_lint ! {
4838 pub NEEDLESS_BORROW ,
4939 nursery,
5040 "taking a reference that is going to be automatically dereferenced"
5141}
5242
53- #[ derive( Copy , Clone ) ]
54- pub struct NeedlessBorrow ;
43+ #[ derive( Default ) ]
44+ pub struct NeedlessBorrow {
45+ derived_item : Option < NodeId > ,
46+ }
5547
5648impl LintPass for NeedlessBorrow {
5749 fn get_lints ( & self ) -> LintArray {
@@ -61,7 +53,7 @@ impl LintPass for NeedlessBorrow {
6153
6254impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for NeedlessBorrow {
6355 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 ( ) {
6557 return ;
6658 }
6759 if let ExprKind :: AddrOf ( MutImmutable , ref inner) = e. node {
@@ -87,7 +79,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
8779 |db| {
8880 if let Some ( snippet) = snippet_opt ( cx, inner. span ) {
8981 db. span_suggestion_with_applicability (
90- e. span ,
82+ e. span ,
9183 "change this to" ,
9284 snippet,
9385 Applicability :: MachineApplicable ,
@@ -101,7 +93,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
10193 }
10294 }
10395 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 ( ) {
10597 return ;
10698 }
10799 if_chain ! {
@@ -131,4 +123,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
131123 }
132124 }
133125 }
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+ }
134141}
0 commit comments