about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJason Newcomb <jsnewcomb@pm.me>2022-08-08 10:25:05 -0400
committerJason Newcomb <jsnewcomb@pm.me>2022-08-08 10:25:05 -0400
commitecb51fe6a55f975f2d3bfd65d3568c263c248460 (patch)
tree82adc266358f5dfa2c222a5537cff6bca1f2dd75
parent5285928bc0190efb54495d8126b68778873884b9 (diff)
downloadrust-ecb51fe6a55f975f2d3bfd65d3568c263c248460.tar.gz
rust-ecb51fe6a55f975f2d3bfd65d3568c263c248460.zip
Lint `explicit_auto_deref` in implicit return positions for closures
-rw-r--r--clippy_lints/src/dereference.rs45
-rw-r--r--clippy_utils/src/ty.rs3
-rw-r--r--tests/ui/explicit_auto_deref.fixed4
-rw-r--r--tests/ui/explicit_auto_deref.rs2
-rw-r--r--tests/ui/explicit_auto_deref.stderr8
5 files changed, 42 insertions, 20 deletions
diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index 821528d7ab9..1c19a9e0e60 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::ty::{expr_sig, peel_mid_ty_refs, variant_of_res};
+use clippy_utils::ty::{expr_sig, peel_mid_ty_refs, ty_sig, variant_of_res};
 use clippy_utils::{get_parent_expr, is_lint_allowed, path_to_local, walk_to_expr_usage};
 use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX};
 use rustc_data_structures::fx::FxIndexMap;
@@ -704,24 +704,13 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, &
                     let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap());
                     Some(
                         if let Node::Expr(
-                            closure @ Expr {
-                                kind: ExprKind::Closure(&Closure { fn_decl, .. }),
+                            closure_expr @ Expr {
+                                kind: ExprKind::Closure(closure),
                                 ..
                             },
                         ) = cx.tcx.hir().get(owner_id)
                         {
-                            match fn_decl.output {
-                                FnRetTy::Return(ty) => {
-                                    if let Some(sig) = expr_sig(cx, closure)
-                                        && let Some(output) = sig.output()
-                                    {
-                                        binding_ty_auto_deref_stability(cx, ty, precedence, output.bound_vars())
-                                    } else {
-                                        Position::Other(precedence)
-                                    }
-                                },
-                                FnRetTy::DefaultReturn(_) => Position::Other(precedence),
-                            }
+                            closure_result_position(cx, closure, cx.typeck_results().expr_ty(closure_expr), precedence)
                         } else {
                             let output = cx
                                 .tcx
@@ -730,6 +719,12 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, &
                         },
                     )
                 },
+                ExprKind::Closure(closure) => Some(closure_result_position(
+                    cx,
+                    closure,
+                    cx.typeck_results().expr_ty(parent),
+                    precedence,
+                )),
                 ExprKind::Call(func, _) if func.hir_id == child_id => {
                     (child_id == e.hir_id).then_some(Position::Callee)
                 },
@@ -825,6 +820,26 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, &
     (position, adjustments)
 }
 
+fn closure_result_position<'tcx>(
+    cx: &LateContext<'tcx>,
+    closure: &'tcx Closure<'_>,
+    ty: Ty<'tcx>,
+    precedence: i8,
+) -> Position {
+    match closure.fn_decl.output {
+        FnRetTy::Return(hir_ty) => {
+            if let Some(sig) = ty_sig(cx, ty)
+                && let Some(output) = sig.output()
+            {
+                binding_ty_auto_deref_stability(cx, hir_ty, precedence, output.bound_vars())
+            } else {
+                Position::Other(precedence)
+            }
+        },
+        FnRetTy::DefaultReturn(_) => Position::Other(precedence),
+    }
+}
+
 // Checks the stability of auto-deref when assigned to a binding with the given explicit type.
 //
 // e.g.
diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index d394360fc67..e7d670766a0 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -572,7 +572,8 @@ pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option<ExprFnS
     }
 }
 
-fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'tcx>> {
+/// If the type is function like, get the signature for it.
+pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'tcx>> {
     if ty.is_box() {
         return ty_sig(cx, ty.boxed_ty());
     }
diff --git a/tests/ui/explicit_auto_deref.fixed b/tests/ui/explicit_auto_deref.fixed
index 27bc7fbfae3..d1d35e5c0eb 100644
--- a/tests/ui/explicit_auto_deref.fixed
+++ b/tests/ui/explicit_auto_deref.fixed
@@ -257,13 +257,13 @@ fn main() {
     let x = S7([0]);
     let _: &[u32] = &*x;
 
-    let c1 = |x: &Vec<&u32>| {};
+    let c1 = |_: &Vec<&u32>| {};
     let x = &&vec![&1u32];
     c1(x);
     let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> {
         if b {
             return x;
         }
-        *x
+        x
     };
 }
diff --git a/tests/ui/explicit_auto_deref.rs b/tests/ui/explicit_auto_deref.rs
index 64aea9f464e..deedafad153 100644
--- a/tests/ui/explicit_auto_deref.rs
+++ b/tests/ui/explicit_auto_deref.rs
@@ -257,7 +257,7 @@ fn main() {
     let x = S7([0]);
     let _: &[u32] = &*x;
 
-    let c1 = |x: &Vec<&u32>| {};
+    let c1 = |_: &Vec<&u32>| {};
     let x = &&vec![&1u32];
     c1(*x);
     let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> {
diff --git a/tests/ui/explicit_auto_deref.stderr b/tests/ui/explicit_auto_deref.stderr
index 12db0c6f87f..91863abcc5d 100644
--- a/tests/ui/explicit_auto_deref.stderr
+++ b/tests/ui/explicit_auto_deref.stderr
@@ -228,5 +228,11 @@ error: deref which would be done by auto-deref
 LL |             return *x;
    |                    ^^ help: try this: `x`
 
-error: aborting due to 38 previous errors
+error: deref which would be done by auto-deref
+  --> $DIR/explicit_auto_deref.rs:267:9
+   |
+LL |         *x
+   |         ^^ help: try this: `x`
+
+error: aborting due to 39 previous errors