+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::higher;
+use clippy_utils::higher::VecArgs;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::{implements_trait, type_is_unsafe_function};
+use clippy_utils::{is_adjusted, iter_input_pats};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{def_id, Expr, ExprKind, Param, PatKind, QPath};
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
-use crate::utils::{
- implements_trait, is_adjusted, iter_input_pats, snippet_opt, span_lint_and_sugg, span_lint_and_then,
- type_is_unsafe_function,
-};
-
declare_clippy_lint! {
/// **What it does:** Checks for closures which just call another function where
/// the function can be called directly. `unsafe` functions or calls where types
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,
);