use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
use clippy_utils::source::{snippet, snippet_with_applicability};
+use clippy_utils::sugg::deref_closure_args;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_trait_method, strip_pat_refs};
use if_chain::if_chain;
if search_snippet.lines().count() <= 1 {
// suggest `any(|x| ..)` instead of `any(|&x| ..)` for `find(|&x| ..).is_some()`
// suggest `any(|..| *..)` instead of `any(|..| **..)` for `find(|..| **..).is_some()`
+ let mut applicability = Applicability::MachineApplicable;
let any_search_snippet = if_chain! {
if search_method == "find";
if let hir::ExprKind::Closure(_, _, body_id, ..) = search_arg.kind;
then {
if let hir::PatKind::Ref(..) = closure_arg.pat.kind {
Some(search_snippet.replacen('&', "", 1))
- } else if let PatKind::Binding(_, _, ident, _) = strip_pat_refs(&closure_arg.pat).kind {
- let name = &*ident.name.as_str();
- Some(search_snippet.replace(&format!("*{}", name), name))
+ } else if let PatKind::Binding(..) = strip_pat_refs(closure_arg.pat).kind {
+ // `find()` provides a reference to the item, but `any` does not,
+ // so we should fix item usages for suggestion
+ if let Some(closure_sugg) = deref_closure_args(cx, search_arg) {
+ applicability = closure_sugg.applicability;
+ Some(closure_sugg.suggestion)
+ } else {
+ Some(search_snippet.to_string())
+ }
} else {
None
}
"any({})",
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
),
- Applicability::MachineApplicable,
+ applicability,
);
} else {
let iter = snippet(cx, search_recv.span, "..");
iter,
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
),
- Applicability::MachineApplicable,
+ applicability,
);
}
} else {
else if search_method == "find" {
let is_string_or_str_slice = |e| {
let self_ty = cx.typeck_results().expr_ty(e).peel_refs();
- if is_type_diagnostic_item(cx, self_ty, sym::string_type) {
+ if is_type_diagnostic_item(cx, self_ty, sym::String) {
true
} else {
*self_ty.kind() == ty::Str
}
};
if_chain! {
- if is_string_or_str_slice(&search_recv);
- if is_string_or_str_slice(&search_arg);
+ if is_string_or_str_slice(search_recv);
+ if is_string_or_str_slice(search_arg);
then {
let msg = format!("called `{}()` after calling `find()` on a string", option_check_method);
match option_check_method {