summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/manual_async_fn.rs')
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs194
1 files changed, 90 insertions, 104 deletions
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index 998de38a9..eaaaea0be 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
-use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
@@ -8,7 +7,7 @@ use rustc_hir::{
ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, TypeBindingKind,
};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span};
@@ -47,61 +46,57 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
span: Span,
def_id: LocalDefId,
) {
- if_chain! {
- if let Some(header) = kind.header();
- if !header.asyncness.is_async();
+ if let Some(header) = kind.header()
+ && !header.asyncness.is_async()
// Check that this function returns `impl Future`
- if let FnRetTy::Return(ret_ty) = decl.output;
- if let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty);
- if let Some(output) = future_output_ty(trait_ref);
- if captures_all_lifetimes(decl.inputs, &output_lifetimes);
+ && let FnRetTy::Return(ret_ty) = decl.output
+ && let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty)
+ && let Some(output) = future_output_ty(trait_ref)
+ && captures_all_lifetimes(decl.inputs, &output_lifetimes)
// Check that the body of the function consists of one async block
- if let ExprKind::Block(block, _) = body.value.kind;
- if block.stmts.is_empty();
- if let Some(closure_body) = desugared_async_block(cx, block);
- if let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) =
- cx.tcx.hir().get_by_def_id(def_id);
- then {
- let header_span = span.with_hi(ret_ty.span.hi());
-
- span_lint_and_then(
- cx,
- MANUAL_ASYNC_FN,
- header_span,
- "this function can be simplified using the `async fn` syntax",
- |diag| {
- if_chain! {
- if let Some(vis_snip) = snippet_opt(cx, *vis_span);
- if let Some(header_snip) = snippet_opt(cx, header_span);
- if let Some(ret_pos) = position_before_rarrow(&header_snip);
- if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output);
- then {
- let header_snip = if vis_snip.is_empty() {
- format!("async {}", &header_snip[..ret_pos])
- } else {
- format!("{} async {}", vis_snip, &header_snip[vis_snip.len() + 1..ret_pos])
- };
-
- let help = format!("make the function `async` and {ret_sugg}");
- diag.span_suggestion(
- header_span,
- help,
- format!("{header_snip}{ret_snip}"),
- Applicability::MachineApplicable
- );
-
- let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span));
- diag.span_suggestion(
- block.span,
- "move the body of the async block to the enclosing function",
- body_snip,
- Applicability::MachineApplicable
- );
- }
- }
- },
- );
- }
+ && let ExprKind::Block(block, _) = body.value.kind
+ && block.stmts.is_empty()
+ && let Some(closure_body) = desugared_async_block(cx, block)
+ && let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) =
+ cx.tcx.hir_node_by_def_id(def_id)
+ {
+ let header_span = span.with_hi(ret_ty.span.hi());
+
+ span_lint_and_then(
+ cx,
+ MANUAL_ASYNC_FN,
+ header_span,
+ "this function can be simplified using the `async fn` syntax",
+ |diag| {
+ if let Some(vis_snip) = snippet_opt(cx, *vis_span)
+ && let Some(header_snip) = snippet_opt(cx, header_span)
+ && let Some(ret_pos) = position_before_rarrow(&header_snip)
+ && let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output)
+ {
+ let header_snip = if vis_snip.is_empty() {
+ format!("async {}", &header_snip[..ret_pos])
+ } else {
+ format!("{} async {}", vis_snip, &header_snip[vis_snip.len() + 1..ret_pos])
+ };
+
+ let help = format!("make the function `async` and {ret_sugg}");
+ diag.span_suggestion(
+ header_span,
+ help,
+ format!("{header_snip}{ret_snip}"),
+ Applicability::MachineApplicable,
+ );
+
+ let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span));
+ diag.span_suggestion(
+ block.span,
+ "move the body of the async block to the enclosing function",
+ body_snip,
+ Applicability::MachineApplicable,
+ );
+ }
+ },
+ );
}
}
}
@@ -110,48 +105,44 @@ fn future_trait_ref<'tcx>(
cx: &LateContext<'tcx>,
ty: &'tcx Ty<'tcx>,
) -> Option<(&'tcx TraitRef<'tcx>, Vec<LifetimeName>)> {
- if_chain! {
- if let TyKind::OpaqueDef(item_id, bounds, false) = ty.kind;
- let item = cx.tcx.hir().item(item_id);
- if let ItemKind::OpaqueTy(opaque) = &item.kind;
- if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
+ if let TyKind::OpaqueDef(item_id, bounds, false) = ty.kind
+ && let item = cx.tcx.hir().item(item_id)
+ && let ItemKind::OpaqueTy(opaque) = &item.kind
+ && let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
if let GenericBound::Trait(poly, _) = bound {
Some(&poly.trait_ref)
} else {
None
}
- });
- if trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait();
- then {
- let output_lifetimes = bounds
- .iter()
- .filter_map(|bound| {
- if let GenericArg::Lifetime(lt) = bound {
- Some(lt.res)
- } else {
- None
- }
- })
- .collect();
-
- return Some((trait_ref, output_lifetimes));
- }
+ })
+ && trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait()
+ {
+ let output_lifetimes = bounds
+ .iter()
+ .filter_map(|bound| {
+ if let GenericArg::Lifetime(lt) = bound {
+ Some(lt.res)
+ } else {
+ None
+ }
+ })
+ .collect();
+
+ return Some((trait_ref, output_lifetimes));
}
None
}
fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'tcx>> {
- if_chain! {
- if let Some(segment) = trait_ref.path.segments.last();
- if let Some(args) = segment.args;
- if args.bindings.len() == 1;
- let binding = &args.bindings[0];
- if binding.ident.name == sym::Output;
- if let TypeBindingKind::Equality { term: Term::Ty(output) } = binding.kind;
- then {
- return Some(output);
- }
+ if let Some(segment) = trait_ref.path.segments.last()
+ && let Some(args) = segment.args
+ && args.bindings.len() == 1
+ && let binding = &args.bindings[0]
+ && binding.ident.name == sym::Output
+ && let TypeBindingKind::Equality { term: Term::Ty(output) } = binding.kind
+ {
+ return Some(output);
}
None
@@ -181,31 +172,26 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
}
fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
- if_chain! {
- if let Some(block_expr) = block.expr;
- if let Expr {
+ if let Some(block_expr) = block.expr
+ && let Expr {
kind: ExprKind::Closure(&Closure { body, .. }),
..
- } = block_expr;
- let closure_body = cx.tcx.hir().body(body);
- if closure_body.coroutine_kind == Some(CoroutineKind::Async(CoroutineSource::Block));
- then {
- return Some(closure_body);
- }
+ } = block_expr
+ && let closure_body = cx.tcx.hir().body(body)
+ && closure_body.coroutine_kind == Some(CoroutineKind::Async(CoroutineSource::Block))
+ {
+ return Some(closure_body);
}
None
}
fn suggested_ret(cx: &LateContext<'_>, output: &Ty<'_>) -> Option<(&'static str, String)> {
- match output.kind {
- TyKind::Tup(tys) if tys.is_empty() => {
- let sugg = "remove the return type";
- Some((sugg, String::new()))
- },
- _ => {
- let sugg = "return the output of the future directly";
- snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {snip}")))
- },
+ if let TyKind::Tup([]) = output.kind {
+ let sugg = "remove the return type";
+ Some((sugg, String::new()))
+ } else {
+ let sugg = "return the output of the future directly";
+ snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {snip}")))
}
}