mirror of
https://github.com/rust-lang/rust-clippy
synced 2025-02-17 06:28:42 +00:00
Handle args taken by ref also for MethodCall
This commit is contained in:
parent
7a55407cc3
commit
90a72f506c
7 changed files with 85 additions and 26 deletions
|
@ -227,23 +227,23 @@ impl DerefDelegate<'_, 'tcx> {
|
|||
}
|
||||
|
||||
fn func_takes_arg_by_ref(&self, parent_expr: &'tcx hir::Expr<'_>, cmt_hir_id: HirId) -> bool {
|
||||
if_chain! {
|
||||
if let ExprKind::Call(func, call_args) = parent_expr.kind;
|
||||
let typ = self.cx.typeck_results().expr_ty(func);
|
||||
if let ty::FnDef(..) = typ.kind();
|
||||
|
||||
then {
|
||||
let mut takes_by_ref = false;
|
||||
for (arg, ty) in iter::zip(call_args, typ.fn_sig(self.cx.tcx).skip_binder().inputs()) {
|
||||
if arg.hir_id == cmt_hir_id {
|
||||
takes_by_ref = matches!(ty.kind(), ty::Ref(_, inner, _) if inner.is_ref());
|
||||
}
|
||||
let (call_args, inputs) = match parent_expr.kind {
|
||||
ExprKind::MethodCall(_, _, call_args, _) => {
|
||||
if let Some(method_did) = self.cx.typeck_results().type_dependent_def_id(parent_expr.hir_id) {
|
||||
(call_args, self.cx.tcx.fn_sig(method_did).skip_binder().inputs())
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
takes_by_ref
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
},
|
||||
ExprKind::Call(func, call_args) => {
|
||||
let typ = self.cx.typeck_results().expr_ty(func);
|
||||
(call_args, typ.fn_sig(self.cx.tcx).skip_binder().inputs())
|
||||
},
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
iter::zip(call_args, inputs)
|
||||
.any(|(arg, ty)| arg.hir_id == cmt_hir_id && matches!(ty.kind(), ty::Ref(_, inner, _) if inner.is_ref()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,10 +271,6 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
|||
let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind();
|
||||
|
||||
if matches!(arg_ty_kind, ty::Ref(_, _, Mutability::Not)) {
|
||||
let start_span = Span::new(self.next_pos, span.lo(), span.ctxt());
|
||||
let start_snip =
|
||||
snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability);
|
||||
|
||||
// suggest ampersand if call function is taking args by ref
|
||||
let takes_arg_by_ref = self.func_takes_arg_by_ref(parent_expr, cmt.hir_id);
|
||||
|
||||
|
@ -294,14 +290,12 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// handle item projections by removing one explicit deref
|
||||
// i.e.: suggest `*x` instead of `**x`
|
||||
let mut replacement_str = ident_str;
|
||||
|
||||
let mut projections_handled = false;
|
||||
cmt.place.projections.iter().enumerate().for_each(|(i, proj)| {
|
||||
match proj.kind {
|
||||
// Field projection like `|v| v.foo`
|
||||
// no adjustment needed here, as field projections are handled by the compiler
|
||||
ProjectionKind::Field(idx, variant) => match cmt.place.ty_before_projection(i).kind() {
|
||||
ty::Adt(def, ..) => {
|
||||
replacement_str = format!(
|
||||
|
@ -342,7 +336,8 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
|||
}
|
||||
});
|
||||
|
||||
// handle `ProjectionKind::Deref` if no special case detected
|
||||
// handle `ProjectionKind::Deref` by removing one explicit deref
|
||||
// if no special case was detected (i.e.: suggest `*x` instead of `**x`)
|
||||
if !projections_handled {
|
||||
let last_deref = cmt
|
||||
.place
|
||||
|
|
|
@ -161,4 +161,17 @@ mod issue7392 {
|
|||
let vfoo = vec![&&[0, 1, 2, 3]];
|
||||
let _ = !vfoo.iter().any(|x| (**x)[0] == 9);
|
||||
}
|
||||
|
||||
fn method_call_by_ref() {
|
||||
struct Foo {
|
||||
bar: u32,
|
||||
}
|
||||
impl Foo {
|
||||
pub fn by_ref(&self, x: &u32) -> bool {
|
||||
*x == self.bar
|
||||
}
|
||||
}
|
||||
let vfoo = vec![Foo { bar: 1 }];
|
||||
let _ = !vfoo.iter().any(|v| v.by_ref(&v.bar));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,4 +167,17 @@ mod issue7392 {
|
|||
let vfoo = vec![&&[0, 1, 2, 3]];
|
||||
let _ = vfoo.iter().find(|x| (**x)[0] == 9).is_none();
|
||||
}
|
||||
|
||||
fn method_call_by_ref() {
|
||||
struct Foo {
|
||||
bar: u32,
|
||||
}
|
||||
impl Foo {
|
||||
pub fn by_ref(&self, x: &u32) -> bool {
|
||||
*x == self.bar
|
||||
}
|
||||
}
|
||||
let vfoo = vec![Foo { bar: 1 }];
|
||||
let _ = vfoo.iter().find(|v| v.by_ref(&v.bar)).is_none();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -221,5 +221,11 @@ error: called `is_none()` after searching an `Iterator` with `find`
|
|||
LL | let _ = vfoo.iter().find(|x| (**x)[0] == 9).is_none();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!vfoo.iter().any(|x| (**x)[0] == 9)`
|
||||
|
||||
error: aborting due to 33 previous errors
|
||||
error: called `is_none()` after searching an `Iterator` with `find`
|
||||
--> $DIR/search_is_some_fixable_none.rs:181:17
|
||||
|
|
||||
LL | let _ = vfoo.iter().find(|v| v.by_ref(&v.bar)).is_none();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!vfoo.iter().any(|v| v.by_ref(&v.bar))`
|
||||
|
||||
error: aborting due to 34 previous errors
|
||||
|
||||
|
|
|
@ -163,4 +163,17 @@ mod issue7392 {
|
|||
let vfoo = vec![&&[0, 1, 2, 3]];
|
||||
let _ = vfoo.iter().any(|x| (**x)[0] == 9);
|
||||
}
|
||||
|
||||
fn method_call_by_ref() {
|
||||
struct Foo {
|
||||
bar: u32,
|
||||
}
|
||||
impl Foo {
|
||||
pub fn by_ref(&self, x: &u32) -> bool {
|
||||
*x == self.bar
|
||||
}
|
||||
}
|
||||
let vfoo = vec![Foo { bar: 1 }];
|
||||
let _ = vfoo.iter().any(|v| v.by_ref(&v.bar));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -166,4 +166,17 @@ mod issue7392 {
|
|||
let vfoo = vec![&&[0, 1, 2, 3]];
|
||||
let _ = vfoo.iter().find(|x| (**x)[0] == 9).is_some();
|
||||
}
|
||||
|
||||
fn method_call_by_ref() {
|
||||
struct Foo {
|
||||
bar: u32,
|
||||
}
|
||||
impl Foo {
|
||||
pub fn by_ref(&self, x: &u32) -> bool {
|
||||
*x == self.bar
|
||||
}
|
||||
}
|
||||
let vfoo = vec![Foo { bar: 1 }];
|
||||
let _ = vfoo.iter().find(|v| v.by_ref(&v.bar)).is_some();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -204,5 +204,11 @@ error: called `is_some()` after searching an `Iterator` with `find`
|
|||
LL | let _ = vfoo.iter().find(|x| (**x)[0] == 9).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| (**x)[0] == 9)`
|
||||
|
||||
error: aborting due to 33 previous errors
|
||||
error: called `is_some()` after searching an `Iterator` with `find`
|
||||
--> $DIR/search_is_some_fixable_some.rs:180:29
|
||||
|
|
||||
LL | let _ = vfoo.iter().find(|v| v.by_ref(&v.bar)).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|v| v.by_ref(&v.bar))`
|
||||
|
||||
error: aborting due to 34 previous errors
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue