1- use crate :: utils:: { get_parent_expr, method_calls, snippet, span_lint_and_sugg} ;
1+ use crate :: utils:: {
2+ get_parent_expr, get_trait_def_id, implements_trait, method_calls, paths, snippet, span_lint_and_sugg,
3+ } ;
24use if_chain:: if_chain;
35use rustc_errors:: Applicability ;
46use rustc_hir as hir;
@@ -15,18 +17,19 @@ declare_clippy_lint! {
1517 ///
1618 /// **Example:**
1719 /// ```rust
18- /// let b = a.deref();
19- /// let c = a.deref_mut();
20+ /// use std::ops::Deref;
21+ /// let a: &mut String = &mut String::from("foo");
22+ /// let b: &str = a.deref();
2023 /// ```
2124 /// Could be written as:
2225 /// ```rust
26+ /// let a: &mut String = &mut String::from("foo");
2327 /// let b = &*a;
24- /// let c = &mut *a;
2528 /// ```
2629 ///
2730 /// This lint excludes
28- /// ```rust
29- /// let e = d.unwrap().deref();
31+ /// ```rust,ignore
32+ /// let _ = d.unwrap().deref();
3033 /// ```
3134 pub EXPLICIT_DEREF_METHOD ,
3235 pedantic,
@@ -49,7 +52,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing {
4952 for arg in args {
5053 if_chain! {
5154 // Caller must call only one other function (deref or deref_mut)
52- // otherwise it can lead to error prone suggestions (ex : &*a.len())
55+ // otherwise it can lead to error prone suggestions (ie : &*a.len())
5356 let ( method_names, arg_list, _) = method_calls( arg, 2 ) ;
5457 if method_names. len( ) == 1 ;
5558 // Caller must be a variable
@@ -59,7 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing {
5962
6063 then {
6164 let name = method_names[ 0 ] . as_str( ) ;
62- lint_deref( cx, & * name, variables[ 0 ] . span, arg. span) ;
65+ lint_deref( cx, & * name, & variables [ 0 ] , variables[ 0 ] . span, arg. span) ;
6366 }
6467 }
6568 }
@@ -72,7 +75,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing {
7275 if args. len( ) == 1 ;
7376 if let ExprKind :: Path ( QPath :: Resolved ( None , _) ) = args[ 0 ] . kind;
7477 // Caller must call only one other function (deref or deref_mut)
75- // otherwise it can lead to error prone suggestions (ex : &*a.len())
78+ // otherwise it can lead to error prone suggestions (ie : &*a.len())
7679 let ( method_names, arg_list, _) = method_calls( init, 2 ) ;
7780 if method_names. len( ) == 1 ;
7881 // Caller must be a variable
@@ -82,7 +85,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing {
8285
8386 then {
8487 let name = method_name. ident. as_str( ) ;
85- lint_deref( cx, & * name, args[ 0 ] . span, init. span) ;
88+ lint_deref( cx, & * name, init , args[ 0 ] . span, init. span) ;
8689 }
8790 }
8891 }
@@ -99,23 +102,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing {
99102 if let Some ( parent) = get_parent_expr( cx, & expr) ;
100103
101104 then {
102- // Call and MethodCall exprs are better reported using statements
103105 match parent. kind {
104- ExprKind :: Call ( _ , _ ) => return ,
105- ExprKind :: MethodCall ( _, _, _) => return ,
106+ // Already linted using statements
107+ ExprKind :: Call ( _ , _ ) | ExprKind :: MethodCall ( _, _, _) => ( ) ,
106108 _ => {
107109 let name = method_name. ident. as_str( ) ;
108- lint_deref( cx, & * name, args[ 0 ] . span, expr. span) ;
110+ lint_deref( cx, & * name, & args [ 0 ] , args[ 0 ] . span, expr. span) ;
109111 }
110112 }
111113 }
112114 }
113115 }
114116}
115117
116- fn lint_deref ( cx : & LateContext < ' _ , ' _ > , fn_name : & str , var_span : Span , expr_span : Span ) {
118+ fn lint_deref ( cx : & LateContext < ' _ , ' _ > , fn_name : & str , call_expr : & Expr < ' _ > , var_span : Span , expr_span : Span ) {
117119 match fn_name {
118120 "deref" => {
121+ if !get_trait_def_id ( cx, & paths:: DEREF_TRAIT )
122+ . map_or ( false , |id| implements_trait ( cx, cx. tables . expr_ty ( & call_expr) , id, & [ ] ) )
123+ {
124+ return ;
125+ }
119126 span_lint_and_sugg (
120127 cx,
121128 EXPLICIT_DEREF_METHOD ,
@@ -127,6 +134,11 @@ fn lint_deref(cx: &LateContext<'_, '_>, fn_name: &str, var_span: Span, expr_span
127134 ) ;
128135 } ,
129136 "deref_mut" => {
137+ if !get_trait_def_id ( cx, & paths:: DEREF_MUT_TRAIT )
138+ . map_or ( false , |id| implements_trait ( cx, cx. tables . expr_ty ( & call_expr) , id, & [ ] ) )
139+ {
140+ return ;
141+ }
130142 span_lint_and_sugg (
131143 cx,
132144 EXPLICIT_DEREF_METHOD ,
0 commit comments