Skip to content

Commit ecb51fe

Browse files
committed
Lint explicit_auto_deref in implicit return positions for closures
1 parent 5285928 commit ecb51fe

File tree

5 files changed

+42
-20
lines changed

5 files changed

+42
-20
lines changed

clippy_lints/src/dereference.rs

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
22
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
33
use clippy_utils::sugg::has_enclosing_paren;
4-
use clippy_utils::ty::{expr_sig, peel_mid_ty_refs, variant_of_res};
4+
use clippy_utils::ty::{expr_sig, peel_mid_ty_refs, ty_sig, variant_of_res};
55
use clippy_utils::{get_parent_expr, is_lint_allowed, path_to_local, walk_to_expr_usage};
66
use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX};
77
use rustc_data_structures::fx::FxIndexMap;
@@ -704,24 +704,13 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, &
704704
let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap());
705705
Some(
706706
if let Node::Expr(
707-
closure @ Expr {
708-
kind: ExprKind::Closure(&Closure { fn_decl, .. }),
707+
closure_expr @ Expr {
708+
kind: ExprKind::Closure(closure),
709709
..
710710
},
711711
) = cx.tcx.hir().get(owner_id)
712712
{
713-
match fn_decl.output {
714-
FnRetTy::Return(ty) => {
715-
if let Some(sig) = expr_sig(cx, closure)
716-
&& let Some(output) = sig.output()
717-
{
718-
binding_ty_auto_deref_stability(cx, ty, precedence, output.bound_vars())
719-
} else {
720-
Position::Other(precedence)
721-
}
722-
},
723-
FnRetTy::DefaultReturn(_) => Position::Other(precedence),
724-
}
713+
closure_result_position(cx, closure, cx.typeck_results().expr_ty(closure_expr), precedence)
725714
} else {
726715
let output = cx
727716
.tcx
@@ -730,6 +719,12 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, &
730719
},
731720
)
732721
},
722+
ExprKind::Closure(closure) => Some(closure_result_position(
723+
cx,
724+
closure,
725+
cx.typeck_results().expr_ty(parent),
726+
precedence,
727+
)),
733728
ExprKind::Call(func, _) if func.hir_id == child_id => {
734729
(child_id == e.hir_id).then_some(Position::Callee)
735730
},
@@ -825,6 +820,26 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, &
825820
(position, adjustments)
826821
}
827822

823+
fn closure_result_position<'tcx>(
824+
cx: &LateContext<'tcx>,
825+
closure: &'tcx Closure<'_>,
826+
ty: Ty<'tcx>,
827+
precedence: i8,
828+
) -> Position {
829+
match closure.fn_decl.output {
830+
FnRetTy::Return(hir_ty) => {
831+
if let Some(sig) = ty_sig(cx, ty)
832+
&& let Some(output) = sig.output()
833+
{
834+
binding_ty_auto_deref_stability(cx, hir_ty, precedence, output.bound_vars())
835+
} else {
836+
Position::Other(precedence)
837+
}
838+
},
839+
FnRetTy::DefaultReturn(_) => Position::Other(precedence),
840+
}
841+
}
842+
828843
// Checks the stability of auto-deref when assigned to a binding with the given explicit type.
829844
//
830845
// e.g.

clippy_utils/src/ty.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,8 @@ pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option<ExprFnS
572572
}
573573
}
574574

575-
fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'tcx>> {
575+
/// If the type is function like, get the signature for it.
576+
pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'tcx>> {
576577
if ty.is_box() {
577578
return ty_sig(cx, ty.boxed_ty());
578579
}

tests/ui/explicit_auto_deref.fixed

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,13 +257,13 @@ fn main() {
257257
let x = S7([0]);
258258
let _: &[u32] = &*x;
259259

260-
let c1 = |x: &Vec<&u32>| {};
260+
let c1 = |_: &Vec<&u32>| {};
261261
let x = &&vec![&1u32];
262262
c1(x);
263263
let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> {
264264
if b {
265265
return x;
266266
}
267-
*x
267+
x
268268
};
269269
}

tests/ui/explicit_auto_deref.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ fn main() {
257257
let x = S7([0]);
258258
let _: &[u32] = &*x;
259259

260-
let c1 = |x: &Vec<&u32>| {};
260+
let c1 = |_: &Vec<&u32>| {};
261261
let x = &&vec![&1u32];
262262
c1(*x);
263263
let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> {

tests/ui/explicit_auto_deref.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,5 +228,11 @@ error: deref which would be done by auto-deref
228228
LL | return *x;
229229
| ^^ help: try this: `x`
230230

231-
error: aborting due to 38 previous errors
231+
error: deref which would be done by auto-deref
232+
--> $DIR/explicit_auto_deref.rs:267:9
233+
|
234+
LL | *x
235+
| ^^ help: try this: `x`
236+
237+
error: aborting due to 39 previous errors
232238

0 commit comments

Comments
 (0)