use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::sugg::Sugg;
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_ast::visit as ast_visit;
use rustc_hir as hir;
use rustc_hir::intravisit as hir_visit;
use rustc_hir::intravisit::Visitor as HirVisitor;
-use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
+use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc_middle::hir::nested_filter;
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
/// complexity.
///
/// ### Example
- /// ```rust,ignore
- /// // Bad
- /// let a = (|| 42)()
+ /// ```rust
+ /// let a = (|| 42)();
+ /// ```
///
- /// // Good
- /// let a = 42
+ /// Use instead:
+ /// ```rust
+ /// let a = 42;
/// ```
#[clippy::version = "pre 1.29.0"]
pub REDUNDANT_CLOSURE_CALL,
impl EarlyLintPass for RedundantClosureCall {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
- if in_external_macro(cx.sess, expr.span) {
+ if in_external_macro(cx.sess(), expr.span) {
return;
}
if_chain! {
if let ast::ExprKind::Call(ref paren, _) = expr.kind;
if let ast::ExprKind::Paren(ref closure) = paren.kind;
- if let ast::ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.kind;
+ if let ast::ExprKind::Closure(_, _, ref r#async, _, ref decl, ref block, _) = closure.kind;
then {
let mut visitor = ReturnVisitor::new();
visitor.visit_expr(block);
"try not to call a closure in the expression where it is declared",
|diag| {
if decl.inputs.is_empty() {
- let mut app = Applicability::MachineApplicable;
- let hint =
- snippet_with_applicability(cx, block.span, "..", &mut app).into_owned();
- diag.span_suggestion(expr.span, "try doing something like", hint, app);
+ let app = Applicability::MachineApplicable;
+ let mut hint = Sugg::ast(cx, block, "..");
+
+ if r#async.is_async() {
+ // `async x` is a syntax error, so it becomes `async { x }`
+ if !matches!(block.kind, ast::ExprKind::Block(_, _)) {
+ hint = hint.blockify();
+ }
+
+ hint = hint.asyncify();
+ }
+
+ diag.span_suggestion(expr.span, "try doing something like", hint.to_string(), app);
}
},
);
count: usize,
}
impl<'a, 'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'a, 'tcx> {
- type Map = Map<'tcx>;
+ type NestedFilter = nested_filter::OnlyBodies;
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
if_chain! {
hir_visit::walk_expr(self, expr);
}
- fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
- hir_visit::NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.cx.tcx.hir()
}
}
let mut closure_usage_count = ClosureUsageCount { cx, path, count: 0 };
if_chain! {
if let hir::StmtKind::Local(local) = w[0].kind;
if let Option::Some(t) = local.init;
- if let hir::ExprKind::Closure(..) = t.kind;
+ if let hir::ExprKind::Closure { .. } = t.kind;
if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind;
if let hir::StmtKind::Semi(second) = w[1].kind;
if let hir::ExprKind::Assign(_, call, _) = second.kind;