React to review

This commit is contained in:
Jakub Beránek 2024-01-22 20:41:40 +01:00
parent 0fcc33e29c
commit 41f5ee1189
No known key found for this signature in database
GPG Key ID: 909CD0D26483516B
3 changed files with 35 additions and 31 deletions

View File

@ -76,25 +76,33 @@ fn extract_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<
let (target, kind, resolved_method) = match expr.kind {
ExprKind::MethodCall(path, receiver, [], _span) => {
let args = cx.typeck_results().node_args(expr.hir_id);
let resolved_method = Instance::resolve(cx.tcx, cx.param_env, fn_def_id, args);
// If we could not resolve the method, don't apply the lint
let Ok(Some(resolved_method)) = Instance::resolve(cx.tcx, cx.param_env, fn_def_id, args) else {
return None;
};
if is_trait_method(cx, expr, sym::Clone) && path.ident.name == sym::clone {
(TargetTrait::Clone, CallKind::MethodCall { receiver }, resolved_method)
} else if is_trait_method(cx, expr, sym::ToOwned) && path.ident.name == sym!(to_owned) {
} else if is_trait_method(cx, expr, sym::ToOwned) && path.ident.name.as_str() == "to_owned" {
(TargetTrait::ToOwned, CallKind::MethodCall { receiver }, resolved_method)
} else {
return None;
}
},
ExprKind::Call(function, args) if args.len() == 1 => {
ExprKind::Call(function, [arg]) => {
let kind = cx.typeck_results().node_type(function.hir_id).kind();
let resolved_method = match kind {
// If we could not resolve the method, don't apply the lint
let Ok(Some(resolved_method)) = (match kind {
ty::FnDef(_, args) => Instance::resolve(cx.tcx, cx.param_env, fn_def_id, args),
_ => return None,
_ => Ok(None),
}) else {
return None;
};
if cx.tcx.is_diagnostic_item(sym::to_owned_method, fn_def_id) {
(
TargetTrait::ToOwned,
CallKind::FunctionCall { self_arg: &args[0] },
CallKind::FunctionCall { self_arg: arg },
resolved_method,
)
} else if let Some(trait_did) = cx.tcx.trait_of_item(fn_def_id)
@ -102,7 +110,7 @@ fn extract_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<
{
(
TargetTrait::Clone,
CallKind::FunctionCall { self_arg: &args[0] },
CallKind::FunctionCall { self_arg: arg },
resolved_method,
)
} else {
@ -111,10 +119,6 @@ fn extract_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<
},
_ => return None,
};
let Ok(Some(resolved_method)) = resolved_method else {
// If we could not resolve the method, don't apply the lint
return None;
};
Some(CallCandidate {
target,
@ -144,7 +148,7 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC
};
// If the method implementation comes from #[derive(Clone)], then don't suggest the lint.
// Automatically generated Clone impls do not override `clone_from`.
// Automatically generated Clone impls do not currently override `clone_from`.
// See e.g. https://github.com/rust-lang/rust/pull/98445#issuecomment-1190681305 for more details.
if cx.tcx.is_builtin_derived(impl_block) {
return false;
@ -160,7 +164,7 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC
TargetTrait::ToOwned => cx.tcx.get_diagnostic_item(sym::ToOwned).and_then(|to_owned| {
cx.tcx
.provided_trait_methods(to_owned)
.find(|item| item.name == sym!(clone_into))
.find(|item| item.name.as_str() == "clone_into")
}),
};
let Some(provided_fn) = provided_fn else {
@ -213,6 +217,7 @@ struct CallCandidate<'tcx> {
}
impl<'tcx> CallCandidate<'tcx> {
#[inline]
fn message(&self) -> &'static str {
match self.target {
TargetTrait::Clone => "assigning the result of `Clone::clone()` may be inefficient",
@ -220,6 +225,7 @@ impl<'tcx> CallCandidate<'tcx> {
}
}
#[inline]
fn suggestion_msg(&self) -> &'static str {
match self.target {
TargetTrait::Clone => "use `clone_from()`",
@ -269,9 +275,7 @@ impl<'tcx> CallCandidate<'tcx> {
// The RHS had to be exactly correct before the call, there is no auto-deref for function calls.
let rhs_sugg = Sugg::hir_with_applicability(cx, self_arg, "_", applicability);
// TODO: how to get rid of the full path? Modify the function call function's (q)path? Or
// auto-import it the trait?
format!("::std::clone::Clone::clone_from({self_sugg}, {rhs_sugg})")
format!("Clone::clone_from({self_sugg}, {rhs_sugg})")
},
}
},
@ -303,7 +307,7 @@ impl<'tcx> CallCandidate<'tcx> {
},
CallKind::FunctionCall { self_arg, .. } => {
let self_sugg = Sugg::hir_with_applicability(cx, self_arg, "_", applicability);
format!("::std::borrow::ToOwned::clone_into({self_sugg}, {rhs_sugg})")
format!("ToOwned::clone_into({self_sugg}, {rhs_sugg})")
},
}
},

View File

@ -34,23 +34,23 @@ fn clone_method_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) {
}
fn clone_function_lhs_mut_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
::std::clone::Clone::clone_from(mut_thing, ref_thing);
Clone::clone_from(mut_thing, ref_thing);
}
fn clone_function_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) {
::std::clone::Clone::clone_from(&mut mut_thing, ref_thing);
Clone::clone_from(&mut mut_thing, ref_thing);
}
fn clone_function_through_trait(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
::std::clone::Clone::clone_from(mut_thing, ref_thing);
Clone::clone_from(mut_thing, ref_thing);
}
fn clone_function_through_type(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
::std::clone::Clone::clone_from(mut_thing, ref_thing);
Clone::clone_from(mut_thing, ref_thing);
}
fn clone_function_fully_qualified(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
::std::clone::Clone::clone_from(mut_thing, ref_thing);
Clone::clone_from(mut_thing, ref_thing);
}
fn clone_method_lhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
@ -164,11 +164,11 @@ fn owned_method_deref(mut_box_string: &mut HasDeref, ref_str: &str) {
}
fn owned_function_mut_ref(mut_thing: &mut String, ref_str: &str) {
::std::borrow::ToOwned::clone_into(ref_str, mut_thing);
ToOwned::clone_into(ref_str, mut_thing);
}
fn owned_function_val(mut mut_thing: String, ref_str: &str) {
::std::borrow::ToOwned::clone_into(ref_str, &mut mut_thing);
ToOwned::clone_into(ref_str, &mut mut_thing);
}
struct FakeToOwned;

View File

@ -23,31 +23,31 @@ error: assigning the result of `Clone::clone()` may be inefficient
--> $DIR/assigning_clones.rs:37:5
|
LL | *mut_thing = Clone::clone(ref_thing);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `::std::clone::Clone::clone_from(mut_thing, ref_thing)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
--> $DIR/assigning_clones.rs:41:5
|
LL | mut_thing = Clone::clone(ref_thing);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `::std::clone::Clone::clone_from(&mut mut_thing, ref_thing)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut mut_thing, ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
--> $DIR/assigning_clones.rs:45:5
|
LL | *mut_thing = Clone::clone(ref_thing);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `::std::clone::Clone::clone_from(mut_thing, ref_thing)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
--> $DIR/assigning_clones.rs:49:5
|
LL | *mut_thing = HasCloneFrom::clone(ref_thing);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `::std::clone::Clone::clone_from(mut_thing, ref_thing)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
--> $DIR/assigning_clones.rs:53:5
|
LL | *mut_thing = <HasCloneFrom as Clone>::clone(ref_thing);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `::std::clone::Clone::clone_from(mut_thing, ref_thing)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
--> $DIR/assigning_clones.rs:58:5
@ -95,13 +95,13 @@ error: assigning the result of `ToOwned::to_owned()` may be inefficient
--> $DIR/assigning_clones.rs:167:5
|
LL | *mut_thing = ToOwned::to_owned(ref_str);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `::std::borrow::ToOwned::clone_into(ref_str, mut_thing)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, mut_thing)`
error: assigning the result of `ToOwned::to_owned()` may be inefficient
--> $DIR/assigning_clones.rs:171:5
|
LL | mut_thing = ToOwned::to_owned(ref_str);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `::std::borrow::ToOwned::clone_into(ref_str, &mut mut_thing)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, &mut mut_thing)`
error: aborting due to 17 previous errors