implements_trait, is_adjusted, iter_input_pats, snippet_opt, span_lint_and_sugg, span_lint_and_then,
type_is_unsafe_function,
};
+use clippy_utils::higher;
+use clippy_utils::higher::VecArgs;
declare_clippy_lint! {
/// **What it does:** Checks for closures which just call another function where
/// **Known problems:** If creating the closure inside the closure has a side-
/// effect then moving the closure creation out will change when that side-
/// effect runs.
- /// See rust-lang/rust-clippy#1439 for more details.
+ /// See [#1439](https://github.com/rust-lang/rust-clippy/issues/1439) for more details.
///
/// **Example:**
/// ```rust,ignore
///
/// **Why is this bad?** It's unnecessary to create the closure.
///
- /// **Known problems:** rust-lang/rust-clippy#3071, rust-lang/rust-clippy#4002,
- /// rust-lang/rust-clippy#3942
+ /// **Known problems:** [#3071](https://github.com/rust-lang/rust-clippy/issues/3071),
+ /// [#3942](https://github.com/rust-lang/rust-clippy/issues/3942),
+ /// [#4002](https://github.com/rust-lang/rust-clippy/issues/4002)
///
///
/// **Example:**
match expr.kind {
ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => {
for arg in args {
- check_closure(cx, arg)
+ // skip `foo(macro!())`
+ if arg.span.ctxt() == expr.span.ctxt() {
+ check_closure(cx, arg)
+ }
}
},
_ => (),
let body = cx.tcx.hir().body(eid);
let ex = &body.value;
+ if ex.span.ctxt() != expr.span.ctxt() {
+ if let Some(VecArgs::Vec(&[])) = higher::vec_macro(cx, ex) {
+ // replace `|| vec![]` with `Vec::new`
+ span_lint_and_sugg(
+ cx,
+ REDUNDANT_CLOSURE,
+ expr.span,
+ "redundant closure",
+ "replace the closure with `Vec::new`",
+ "std::vec::Vec::new".into(),
+ Applicability::MachineApplicable,
+ );
+ }
+ // skip `foo(|| macro!())`
+ return;
+ }
+
if_chain!(
if let ExprKind::Call(ref caller, ref args) = ex.kind;
if compare_inputs(&mut iter_input_pats(decl, body), &mut args.iter());
then {
- span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |diag| {
+ span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
if let Some(snippet) = snippet_opt(cx, caller.span) {
diag.span_suggestion(
expr.span,
- "remove closure as shown",
+ "replace the closure with the function itself",
snippet,
Applicability::MachineApplicable,
);
cx,
REDUNDANT_CLOSURE_FOR_METHOD_CALLS,
expr.span,
- "redundant closure found",
- "remove closure as shown",
+ "redundant closure",
+ "replace the closure with the method itself",
format!("{}::{}", name, path.ident.name),
Applicability::MachineApplicable,
);