use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
- AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId,
- IsAsync, ItemKind, LifetimeName, TraitRef, Ty, TyKind, TypeBindingKind,
+ AsyncGeneratorKind, Block, Body, Closure, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound,
+ HirId, IsAsync, ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, Span};
declare_clippy_lint! {
- /// **What it does:** It checks for manual implementations of `async` functions.
+ /// ### What it does
+ /// It checks for manual implementations of `async` functions.
///
- /// **Why is this bad?** It's more idiomatic to use the dedicated syntax.
- ///
- /// **Known problems:** None.
- ///
- /// **Example:**
+ /// ### Why is this bad?
+ /// It's more idiomatic to use the dedicated syntax.
///
+ /// ### Example
/// ```rust
/// use std::future::Future;
///
/// ```rust
/// async fn foo() -> i32 { 42 }
/// ```
+ #[clippy::version = "1.45.0"]
pub MANUAL_ASYNC_FN,
style,
"manual implementations of `async` functions can be simplified using the dedicated syntax"
) {
if_chain! {
if let Some(header) = kind.header();
- if let IsAsync::NotAsync = header.asyncness;
+ if header.asyncness == IsAsync::NotAsync;
// 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);
diag.span_suggestion(
block.span,
"move the body of the async block to the enclosing function",
- body_snip.to_string(),
+ body_snip,
Applicability::MachineApplicable
);
}
if args.bindings.len() == 1;
let binding = &args.bindings[0];
if binding.ident.name == sym::Output;
- if let TypeBindingKind::Equality{ty: output} = binding.kind;
+ if let TypeBindingKind::Equality{term: Term::Ty(output)} = binding.kind;
then {
return Some(output)
}
if let Some(block_expr) = block.expr;
if let Some(args) = match_function_call(cx, block_expr, &FUTURE_FROM_GENERATOR);
if args.len() == 1;
- if let Expr{kind: ExprKind::Closure(_, _, body_id, ..), ..} = args[0];
- let closure_body = cx.tcx.hir().body(body_id);
- if let Some(GeneratorKind::Async(AsyncGeneratorKind::Block)) = closure_body.generator_kind;
+ if let Expr{kind: ExprKind::Closure(&Closure { body, .. }), ..} = args[0];
+ let closure_body = cx.tcx.hir().body(body);
+ if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
then {
return Some(closure_body);
}