@@ -113,9 +113,15 @@ fn handle_path(
113
113
if let Some ( path_def_id) = cx. qpath_res ( qpath, arg. hir_id ) . opt_def_id ( )
114
114
&& match_def_path ( cx, path_def_id, & paths:: CLONE_TRAIT_METHOD )
115
115
{
116
- // FIXME: It would be better to infer the type to check if it's copyable or not
117
- // to suggest to use `.copied()` instead of `.cloned()` where applicable.
118
- lint_path ( cx, e. span , recv. span ) ;
116
+ // The `copied` and `cloned` methods are only available on `&T` and `&mut T` in `Option`
117
+ // and `Result`.
118
+ if let ty:: Adt ( _, args) = cx. typeck_results ( ) . expr_ty ( recv) . kind ( )
119
+ && let args = args. as_slice ( )
120
+ && let Some ( ty) = args. iter ( ) . find_map ( |generic_arg| generic_arg. as_type ( ) )
121
+ && ty. is_ref ( )
122
+ {
123
+ lint_path ( cx, e. span , recv. span , is_copy ( cx, ty. peel_refs ( ) ) ) ;
124
+ }
119
125
}
120
126
}
121
127
@@ -139,17 +145,19 @@ fn lint_needless_cloning(cx: &LateContext<'_>, root: Span, receiver: Span) {
139
145
) ;
140
146
}
141
147
142
- fn lint_path ( cx : & LateContext < ' _ > , replace : Span , root : Span ) {
148
+ fn lint_path ( cx : & LateContext < ' _ > , replace : Span , root : Span , is_copy : bool ) {
143
149
let mut applicability = Applicability :: MachineApplicable ;
144
150
151
+ let replacement = if is_copy { "copied" } else { "cloned" } ;
152
+
145
153
span_lint_and_sugg (
146
154
cx,
147
155
MAP_CLONE ,
148
156
replace,
149
157
"you are explicitly cloning with `.map()`" ,
150
- "consider calling the dedicated `cloned ` method" ,
158
+ & format ! ( "consider calling the dedicated `{replacement} ` method" ) ,
151
159
format ! (
152
- "{}.cloned ()" ,
160
+ "{}.{replacement} ()" ,
153
161
snippet_with_applicability( cx, root, ".." , & mut applicability) ,
154
162
) ,
155
163
applicability,
0 commit comments