diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 8045926b1ded..cde9528cd878 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -305,7 +305,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { RefOp::Method { mutbl, is_ufcs } if !is_lint_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id) // Allow explicit deref in method chains. e.g. `foo.deref().bar()` - && (is_ufcs || !in_postfix_position(cx, expr)) => + && (is_ufcs || !is_in_method_chain(cx, expr)) => { let ty_changed_count = usize::from(!deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr))); self.state = Some(( @@ -728,7 +728,13 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool { } } -fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { +fn is_in_method_chain<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { + if let ExprKind::MethodCall(_, recv, _, _) = e.kind + && matches!(recv.kind, ExprKind::MethodCall(..)) + { + return true; + } + if let Some(parent) = get_parent_expr(cx, e) && parent.span.eq_ctxt(e.span) { diff --git a/tests/ui/explicit_deref_methods.fixed b/tests/ui/explicit_deref_methods.fixed index 619329a6ade0..52c4d1b1f301 100644 --- a/tests/ui/explicit_deref_methods.fixed +++ b/tests/ui/explicit_deref_methods.fixed @@ -81,12 +81,10 @@ fn main() { let b: String = concat(just_return(a)); //~^ explicit_deref_methods - let b: &str = &**a; - //~^ explicit_deref_methods + let b: &str = a.deref().deref(); let opt_a = Some(a.clone()); - let b = &*opt_a.unwrap(); - //~^ explicit_deref_methods + let b = opt_a.unwrap().deref(); Aaa::deref(&Aaa); Aaa::deref_mut(&mut Aaa); diff --git a/tests/ui/explicit_deref_methods.rs b/tests/ui/explicit_deref_methods.rs index 9f2d513283c9..706d6cb2b79a 100644 --- a/tests/ui/explicit_deref_methods.rs +++ b/tests/ui/explicit_deref_methods.rs @@ -82,11 +82,9 @@ fn main() { //~^ explicit_deref_methods let b: &str = a.deref().deref(); - //~^ explicit_deref_methods let opt_a = Some(a.clone()); let b = opt_a.unwrap().deref(); - //~^ explicit_deref_methods Aaa::deref(&Aaa); Aaa::deref_mut(&mut Aaa); diff --git a/tests/ui/explicit_deref_methods.stderr b/tests/ui/explicit_deref_methods.stderr index a81e2f60317b..5036884366cf 100644 --- a/tests/ui/explicit_deref_methods.stderr +++ b/tests/ui/explicit_deref_methods.stderr @@ -56,40 +56,28 @@ LL | let b: String = concat(just_return(a).deref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `just_return(a)` error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:84:19 - | -LL | let b: &str = a.deref().deref(); - | ^^^^^^^^^^^^^^^^^ help: try: `&**a` - -error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:88:13 - | -LL | let b = opt_a.unwrap().deref(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*opt_a.unwrap()` - -error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:123:31 + --> tests/ui/explicit_deref_methods.rs:121:31 | LL | let b: &str = expr_deref!(a.deref()); | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:141:14 + --> tests/ui/explicit_deref_methods.rs:139:14 | LL | let _ = &Deref::deref(&"foo"); | ^^^^^^^^^^^^^^^^^^^^ help: try: `*&"foo"` error: explicit `deref_mut` method call - --> tests/ui/explicit_deref_methods.rs:143:14 + --> tests/ui/explicit_deref_methods.rs:141:14 | LL | let _ = &DerefMut::deref_mut(&mut x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut **&mut x` error: explicit `deref_mut` method call - --> tests/ui/explicit_deref_methods.rs:144:14 + --> tests/ui/explicit_deref_methods.rs:142:14 | LL | let _ = &DerefMut::deref_mut((&mut &mut x).deref_mut()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut ***(&mut &mut x)` -error: aborting due to 15 previous errors +error: aborting due to 13 previous errors