[useless_asref
]: check that the clone receiver is the local
This commit is contained in:
parent
e899684254
commit
153b83f61b
@ -1,7 +1,7 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use clippy_utils::ty::walk_ptrs_ty_depth;
|
use clippy_utils::ty::walk_ptrs_ty_depth;
|
||||||
use clippy_utils::{get_parent_expr, is_diag_trait_item, match_def_path, paths, peel_blocks};
|
use clippy_utils::{get_parent_expr, is_diag_trait_item, match_def_path, path_to_local_id, paths, peel_blocks};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
@ -111,6 +111,23 @@ fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool {
|
|||||||
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
|
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
|
||||||
// If it's a closure, we need to check what is called.
|
// If it's a closure, we need to check what is called.
|
||||||
let closure_body = cx.tcx.hir().body(body);
|
let closure_body = cx.tcx.hir().body(body);
|
||||||
|
|
||||||
|
// |x| ...
|
||||||
|
// ^
|
||||||
|
let [
|
||||||
|
hir::Param {
|
||||||
|
pat:
|
||||||
|
hir::Pat {
|
||||||
|
kind: hir::PatKind::Binding(_, local_id, ..),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
..
|
||||||
|
},
|
||||||
|
] = closure_body.params
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
let closure_expr = peel_blocks(closure_body.value);
|
let closure_expr = peel_blocks(closure_body.value);
|
||||||
match closure_expr.kind {
|
match closure_expr.kind {
|
||||||
hir::ExprKind::MethodCall(method, obj, [], _) => {
|
hir::ExprKind::MethodCall(method, obj, [], _) => {
|
||||||
@ -122,14 +139,17 @@ fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool {
|
|||||||
// no autoderefs
|
// no autoderefs
|
||||||
&& !cx.typeck_results().expr_adjustments(obj).iter()
|
&& !cx.typeck_results().expr_adjustments(obj).iter()
|
||||||
.any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
|
.any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
|
||||||
|
&& path_to_local_id(obj, *local_id)
|
||||||
{
|
{
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hir::ExprKind::Call(call, [_]) => {
|
hir::ExprKind::Call(call, [recv]) => {
|
||||||
if let hir::ExprKind::Path(qpath) = call.kind {
|
if let hir::ExprKind::Path(qpath) = call.kind
|
||||||
|
&& path_to_local_id(recv, *local_id)
|
||||||
|
{
|
||||||
check_qpath(cx, qpath, call.hir_id)
|
check_qpath(cx, qpath, call.hir_id)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -144,6 +144,37 @@ fn foo() {
|
|||||||
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod issue12135 {
|
||||||
|
pub struct Struct {
|
||||||
|
field: Option<InnerStruct>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Foo;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct InnerStruct {
|
||||||
|
x: Foo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InnerStruct {
|
||||||
|
fn method(&self) -> &Foo {
|
||||||
|
&self.x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn f(x: &Struct) -> Option<Foo> {
|
||||||
|
x.field.clone();
|
||||||
|
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||||
|
x.field.clone();
|
||||||
|
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||||
|
x.field.clone();
|
||||||
|
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||||
|
|
||||||
|
x.field.as_ref().map(|v| v.method().clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
not_ok();
|
not_ok();
|
||||||
ok();
|
ok();
|
||||||
|
@ -144,6 +144,37 @@ fn foo() {
|
|||||||
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod issue12135 {
|
||||||
|
pub struct Struct {
|
||||||
|
field: Option<InnerStruct>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Foo;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct InnerStruct {
|
||||||
|
x: Foo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InnerStruct {
|
||||||
|
fn method(&self) -> &Foo {
|
||||||
|
&self.x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn f(x: &Struct) -> Option<Foo> {
|
||||||
|
x.field.as_ref().map(|v| v.clone());
|
||||||
|
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||||
|
x.field.as_ref().map(Clone::clone);
|
||||||
|
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||||
|
x.field.as_ref().map(|v| Clone::clone(v));
|
||||||
|
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||||
|
|
||||||
|
x.field.as_ref().map(|v| v.method().clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
not_ok();
|
not_ok();
|
||||||
ok();
|
ok();
|
||||||
|
@ -88,5 +88,23 @@ error: this call to `as_ref.map(...)` does nothing
|
|||||||
LL | let z = x.as_ref().map(|z| String::clone(z));
|
LL | let z = x.as_ref().map(|z| String::clone(z));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()`
|
||||||
|
|
||||||
error: aborting due to 14 previous errors
|
error: this call to `as_ref.map(...)` does nothing
|
||||||
|
--> $DIR/useless_asref.rs:167:9
|
||||||
|
|
|
||||||
|
LL | x.field.as_ref().map(|v| v.clone());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()`
|
||||||
|
|
||||||
|
error: this call to `as_ref.map(...)` does nothing
|
||||||
|
--> $DIR/useless_asref.rs:169:9
|
||||||
|
|
|
||||||
|
LL | x.field.as_ref().map(Clone::clone);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()`
|
||||||
|
|
||||||
|
error: this call to `as_ref.map(...)` does nothing
|
||||||
|
--> $DIR/useless_asref.rs:171:9
|
||||||
|
|
|
||||||
|
LL | x.field.as_ref().map(|v| Clone::clone(v));
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()`
|
||||||
|
|
||||||
|
error: aborting due to 17 previous errors
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user