@@ -76,33 +76,41 @@ fn extract_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<
76
76
let ( target, kind, resolved_method) = match expr. kind {
77
77
ExprKind :: MethodCall ( path, receiver, [ ] , _span) => {
78
78
let args = cx. typeck_results ( ) . node_args ( expr. hir_id ) ;
79
- let resolved_method = Instance :: resolve ( cx. tcx , cx. param_env , fn_def_id, args) ;
79
+
80
+ // If we could not resolve the method, don't apply the lint
81
+ let Ok ( Some ( resolved_method) ) = Instance :: resolve ( cx. tcx , cx. param_env , fn_def_id, args) else {
82
+ return None ;
83
+ } ;
80
84
if is_trait_method ( cx, expr, sym:: Clone ) && path. ident . name == sym:: clone {
81
85
( TargetTrait :: Clone , CallKind :: MethodCall { receiver } , resolved_method)
82
- } else if is_trait_method ( cx, expr, sym:: ToOwned ) && path. ident . name == sym ! ( to_owned) {
86
+ } else if is_trait_method ( cx, expr, sym:: ToOwned ) && path. ident . name . as_str ( ) == " to_owned" {
83
87
( TargetTrait :: ToOwned , CallKind :: MethodCall { receiver } , resolved_method)
84
88
} else {
85
89
return None ;
86
90
}
87
91
} ,
88
- ExprKind :: Call ( function, args ) if args . len ( ) == 1 => {
92
+ ExprKind :: Call ( function, [ arg ] ) => {
89
93
let kind = cx. typeck_results ( ) . node_type ( function. hir_id ) . kind ( ) ;
90
- let resolved_method = match kind {
94
+
95
+ // If we could not resolve the method, don't apply the lint
96
+ let Ok ( Some ( resolved_method) ) = ( match kind {
91
97
ty:: FnDef ( _, args) => Instance :: resolve ( cx. tcx , cx. param_env , fn_def_id, args) ,
92
- _ => return None ,
98
+ _ => Ok ( None ) ,
99
+ } ) else {
100
+ return None ;
93
101
} ;
94
102
if cx. tcx . is_diagnostic_item ( sym:: to_owned_method, fn_def_id) {
95
103
(
96
104
TargetTrait :: ToOwned ,
97
- CallKind :: FunctionCall { self_arg : & args [ 0 ] } ,
105
+ CallKind :: FunctionCall { self_arg : arg } ,
98
106
resolved_method,
99
107
)
100
108
} else if let Some ( trait_did) = cx. tcx . trait_of_item ( fn_def_id)
101
109
&& cx. tcx . is_diagnostic_item ( sym:: Clone , trait_did)
102
110
{
103
111
(
104
112
TargetTrait :: Clone ,
105
- CallKind :: FunctionCall { self_arg : & args [ 0 ] } ,
113
+ CallKind :: FunctionCall { self_arg : arg } ,
106
114
resolved_method,
107
115
)
108
116
} else {
@@ -111,10 +119,6 @@ fn extract_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<
111
119
} ,
112
120
_ => return None ,
113
121
} ;
114
- let Ok ( Some ( resolved_method) ) = resolved_method else {
115
- // If we could not resolve the method, don't apply the lint
116
- return None ;
117
- } ;
118
122
119
123
Some ( CallCandidate {
120
124
target,
@@ -144,7 +148,7 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC
144
148
} ;
145
149
146
150
// If the method implementation comes from #[derive(Clone)], then don't suggest the lint.
147
- // Automatically generated Clone impls do not override `clone_from`.
151
+ // Automatically generated Clone impls do not currently override `clone_from`.
148
152
// See e.g. https://github.com/rust-lang/rust/pull/98445#issuecomment-1190681305 for more details.
149
153
if cx. tcx . is_builtin_derived ( impl_block) {
150
154
return false ;
@@ -160,7 +164,7 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC
160
164
TargetTrait :: ToOwned => cx. tcx . get_diagnostic_item ( sym:: ToOwned ) . and_then ( |to_owned| {
161
165
cx. tcx
162
166
. provided_trait_methods ( to_owned)
163
- . find ( |item| item. name == sym ! ( clone_into) )
167
+ . find ( |item| item. name . as_str ( ) == " clone_into" )
164
168
} ) ,
165
169
} ;
166
170
let Some ( provided_fn) = provided_fn else {
@@ -213,13 +217,15 @@ struct CallCandidate<'tcx> {
213
217
}
214
218
215
219
impl < ' tcx > CallCandidate < ' tcx > {
220
+ #[ inline]
216
221
fn message ( & self ) -> & ' static str {
217
222
match self . target {
218
223
TargetTrait :: Clone => "assigning the result of `Clone::clone()` may be inefficient" ,
219
224
TargetTrait :: ToOwned => "assigning the result of `ToOwned::to_owned()` may be inefficient" ,
220
225
}
221
226
}
222
227
228
+ #[ inline]
223
229
fn suggestion_msg ( & self ) -> & ' static str {
224
230
match self . target {
225
231
TargetTrait :: Clone => "use `clone_from()`" ,
@@ -269,9 +275,7 @@ impl<'tcx> CallCandidate<'tcx> {
269
275
// The RHS had to be exactly correct before the call, there is no auto-deref for function calls.
270
276
let rhs_sugg = Sugg :: hir_with_applicability ( cx, self_arg, "_" , applicability) ;
271
277
272
- // TODO: how to get rid of the full path? Modify the function call function's (q)path? Or
273
- // auto-import it the trait?
274
- format ! ( "::std::clone::Clone::clone_from({self_sugg}, {rhs_sugg})" )
278
+ format ! ( "Clone::clone_from({self_sugg}, {rhs_sugg})" )
275
279
} ,
276
280
}
277
281
} ,
@@ -303,7 +307,7 @@ impl<'tcx> CallCandidate<'tcx> {
303
307
} ,
304
308
CallKind :: FunctionCall { self_arg, .. } => {
305
309
let self_sugg = Sugg :: hir_with_applicability ( cx, self_arg, "_" , applicability) ;
306
- format ! ( "::std::borrow:: ToOwned::clone_into({self_sugg}, {rhs_sugg})" )
310
+ format ! ( "ToOwned::clone_into({self_sugg}, {rhs_sugg})" )
307
311
} ,
308
312
}
309
313
} ,
0 commit comments