Lint explicit_auto_deref in implicit return positions for closures
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
|
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::source::{snippet_with_applicability, snippet_with_context};
|
||||||
use clippy_utils::sugg::has_enclosing_paren;
|
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 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_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX};
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
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());
|
let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap());
|
||||||
Some(
|
Some(
|
||||||
if let Node::Expr(
|
if let Node::Expr(
|
||||||
closure @ Expr {
|
closure_expr @ Expr {
|
||||||
kind: ExprKind::Closure(&Closure { fn_decl, .. }),
|
kind: ExprKind::Closure(closure),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
) = cx.tcx.hir().get(owner_id)
|
) = cx.tcx.hir().get(owner_id)
|
||||||
{
|
{
|
||||||
match fn_decl.output {
|
closure_result_position(cx, closure, cx.typeck_results().expr_ty(closure_expr), precedence)
|
||||||
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),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let output = cx
|
let output = cx
|
||||||
.tcx
|
.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 => {
|
ExprKind::Call(func, _) if func.hir_id == child_id => {
|
||||||
(child_id == e.hir_id).then_some(Position::Callee)
|
(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)
|
(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.
|
// Checks the stability of auto-deref when assigned to a binding with the given explicit type.
|
||||||
//
|
//
|
||||||
// e.g.
|
// e.g.
|
||||||
|
|||||||
@@ -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() {
|
if ty.is_box() {
|
||||||
return ty_sig(cx, ty.boxed_ty());
|
return ty_sig(cx, ty.boxed_ty());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,13 +257,13 @@ fn main() {
|
|||||||
let x = S7([0]);
|
let x = S7([0]);
|
||||||
let _: &[u32] = &*x;
|
let _: &[u32] = &*x;
|
||||||
|
|
||||||
let c1 = |x: &Vec<&u32>| {};
|
let c1 = |_: &Vec<&u32>| {};
|
||||||
let x = &&vec![&1u32];
|
let x = &&vec![&1u32];
|
||||||
c1(x);
|
c1(x);
|
||||||
let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> {
|
let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> {
|
||||||
if b {
|
if b {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
*x
|
x
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ fn main() {
|
|||||||
let x = S7([0]);
|
let x = S7([0]);
|
||||||
let _: &[u32] = &*x;
|
let _: &[u32] = &*x;
|
||||||
|
|
||||||
let c1 = |x: &Vec<&u32>| {};
|
let c1 = |_: &Vec<&u32>| {};
|
||||||
let x = &&vec![&1u32];
|
let x = &&vec![&1u32];
|
||||||
c1(*x);
|
c1(*x);
|
||||||
let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> {
|
let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> {
|
||||||
|
|||||||
@@ -228,5 +228,11 @@ error: deref which would be done by auto-deref
|
|||||||
LL | return *x;
|
LL | return *x;
|
||||||
| ^^ help: try this: `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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user