Skip to content

Commit 5af79de

Browse files
author
ceptontech
committed
refactor(search_is_some): Move some logic for transforming closures
The lint `search_is_some` involves converting a closure that takes the reference into one that takes the value. The code is split between the function for the lint and a shared function. The new feature that we are adding involves the same transformation. To do so it needs some of the same code that is currently in the `search_is_some` lint. So it is moved from the lint into the shared function. Before this patch, line 799 in the file `clippy_utils/src/sugg.rs` had a check. It made the function return none in case the closure did not dereference the argument. However, the code for the lint `search_is_some` would then fall back to using the original closure. That achieved the same effect as the check not existing. So the check is now removed.
1 parent 5e7ce90 commit 5af79de

File tree

3 files changed

+29
-28
lines changed

3 files changed

+29
-28
lines changed

clippy_lints/src/methods/search_is_some.rs

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
33
use clippy_utils::source::{snippet, snippet_with_applicability};
44
use clippy_utils::sugg::deref_closure_args;
5-
use clippy_utils::{is_receiver_of_method_call, strip_pat_refs, sym};
6-
use hir::ExprKind;
5+
use clippy_utils::{is_receiver_of_method_call, sym};
76
use rustc_errors::Applicability;
87
use rustc_hir as hir;
9-
use rustc_hir::PatKind;
108
use rustc_lint::LateContext;
119
use rustc_span::{Span, Symbol};
1210

@@ -34,25 +32,15 @@ pub(super) fn check<'tcx>(
3432
{
3533
let msg = format!("called `{option_check_method}()` after searching an `Iterator` with `{search_method}`");
3634
let search_snippet = snippet(cx, search_arg.span, "..");
35+
// `find()` provides a reference to the item, but `any` does not, so we
36+
// should fix item usages for suggestion
3737
// suggest `any(|x| ..)` instead of `any(|&x| ..)` for `find(|&x| ..).is_some()`
3838
// suggest `any(|..| *..)` instead of `any(|..| **..)` for `find(|..| **..).is_some()`
3939
let mut applicability = Applicability::MachineApplicable;
40-
let any_search_snippet = if search_method == sym::find
41-
&& let ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind
42-
&& let closure_body = cx.tcx.hir_body(body)
43-
&& let Some(closure_arg) = closure_body.params.first()
44-
{
45-
if let PatKind::Ref(..) = closure_arg.pat.kind {
46-
Some(search_snippet.replacen('&', "", 1))
47-
} else if let PatKind::Binding(..) = strip_pat_refs(closure_arg.pat).kind {
48-
// `find()` provides a reference to the item, but `any` does not,
49-
// so we should fix item usages for suggestion
50-
if let Some(closure_sugg) = deref_closure_args(cx, search_arg) {
51-
applicability = closure_sugg.applicability;
52-
Some(closure_sugg.suggestion)
53-
} else {
54-
Some(search_snippet.to_string())
55-
}
40+
let any_search_snippet = if search_method == sym::find {
41+
if let Some(closure_sugg) = deref_closure_args(cx, search_arg) {
42+
applicability = closure_sugg.applicability;
43+
Some(closure_sugg.suggestion)
5644
} else {
5745
None
5846
}

clippy_utils/src/sugg.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33

44
use crate::source::{snippet, snippet_opt, snippet_with_applicability, snippet_with_context};
55
use crate::ty::expr_sig;
6-
use crate::{get_parent_expr_for_hir, higher};
6+
use crate::{get_parent_expr_for_hir, higher, strip_pat_refs};
77
use rustc_ast::util::parser::AssocOp;
88
use rustc_ast::{UnOp, ast};
99
use rustc_data_structures::fx::FxHashSet;
1010
use rustc_errors::Applicability;
11-
use rustc_hir::{self as hir, Closure, ExprKind, HirId, MutTy, Node, TyKind};
11+
use rustc_hir::{self as hir, Closure, ExprKind, HirId, MutTy, Node, PatKind, TyKind};
1212
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
1313
use rustc_lint::{EarlyContext, LateContext, LintContext};
1414
use rustc_middle::hir::place::ProjectionKind;
@@ -770,8 +770,22 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti
770770
if let ExprKind::Closure(&Closure {
771771
fn_decl, def_id, body, ..
772772
}) = closure.kind
773+
&& let closure_body = cx.tcx.hir_body(body)
774+
&& let [closure_arg] = closure_body.params
773775
{
774-
let closure_body = cx.tcx.hir_body(body);
776+
// suggest `any(|x| ..)` instead of `any(|&x| ..)` for `find(|&x| ..).is_some()`
777+
if matches!(closure_arg.pat.kind, PatKind::Ref(..)) {
778+
let mut applicability = Applicability::MachineApplicable;
779+
let suggestion =
780+
snippet_with_applicability(cx, closure.span, "..", &mut applicability).replacen('&', "", 1);
781+
return Some(DerefClosure {
782+
applicability,
783+
suggestion,
784+
});
785+
}
786+
if !matches!(strip_pat_refs(closure_arg.pat).kind, PatKind::Binding(..)) {
787+
return None;
788+
}
775789
// is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`)
776790
// a type annotation is present if param `kind` is different from `TyKind::Infer`
777791
let closure_arg_is_type_annotated_double_ref = if let TyKind::Ref(_, MutTy { ty, .. }) = fn_decl.inputs[0].kind
@@ -796,12 +810,10 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti
796810
.consume_body(closure_body)
797811
.into_ok();
798812

799-
if !visitor.suggestion_start.is_empty() {
800-
return Some(DerefClosure {
801-
applicability: visitor.applicability,
802-
suggestion: visitor.finish(),
803-
});
804-
}
813+
return Some(DerefClosure {
814+
applicability: visitor.applicability,
815+
suggestion: visitor.finish(),
816+
});
805817
}
806818
None
807819
}

clippy_utils/src/sym.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ generate! {
198198
is_none,
199199
is_none_or,
200200
is_ok,
201+
is_ok_and,
201202
is_partitioned,
202203
is_some,
203204
is_some_and,

0 commit comments

Comments
 (0)