@@ -113,9 +113,15 @@ fn handle_path(
113113 if let Some ( path_def_id) = cx. qpath_res ( qpath, arg. hir_id ) . opt_def_id ( )
114114 && match_def_path ( cx, path_def_id, & paths:: CLONE_TRAIT_METHOD )
115115 {
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+ }
119125 }
120126}
121127
@@ -139,17 +145,19 @@ fn lint_needless_cloning(cx: &LateContext<'_>, root: Span, receiver: Span) {
139145 ) ;
140146}
141147
142- fn lint_path ( cx : & LateContext < ' _ > , replace : Span , root : Span ) {
148+ fn lint_path ( cx : & LateContext < ' _ > , replace : Span , root : Span , is_copy : bool ) {
143149 let mut applicability = Applicability :: MachineApplicable ;
144150
151+ let replacement = if is_copy { "copied" } else { "cloned" } ;
152+
145153 span_lint_and_sugg (
146154 cx,
147155 MAP_CLONE ,
148156 replace,
149157 "you are explicitly cloning with `.map()`" ,
150- "consider calling the dedicated `cloned ` method" ,
158+ & format ! ( "consider calling the dedicated `{replacement} ` method" ) ,
151159 format ! (
152- "{}.cloned ()" ,
160+ "{}.{replacement} ()" ,
153161 snippet_with_applicability( cx, root, ".." , & mut applicability) ,
154162 ) ,
155163 applicability,
0 commit comments