Skip to content

Commit f4c75cd

Browse files
committed
Fix any() not taking reference in search_is_some lint
1 parent 38bd251 commit f4c75cd

File tree

4 files changed

+103
-3
lines changed

4 files changed

+103
-3
lines changed

clippy_lints/src/methods/search_is_some.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,27 @@ pub(super) fn check<'tcx>(
4545
then {
4646
if let hir::PatKind::Ref(..) = closure_arg.pat.kind {
4747
Some(search_snippet.replacen('&', "", 1))
48-
} else if let PatKind::Binding(_, _, ident, _) = strip_pat_refs(closure_arg.pat).kind {
48+
} else if let PatKind::Binding(annotation, _, ident, _) = strip_pat_refs(closure_arg.pat).kind {
4949
let name = &*ident.name.as_str();
50-
Some(search_snippet.replace(&format!("*{}", name), name))
50+
let old_search_snippet = search_snippet.clone();
51+
let search_snippet = search_snippet.replace(&format!("*{}", name), name);
52+
53+
if_chain! {
54+
// if there is no dereferencing used in closure body
55+
if old_search_snippet == search_snippet;
56+
if annotation == hir::BindingAnnotation::Unannotated;
57+
if let ty::Ref(_, inner_ty, _) = cx.typeck_results().node_type(closure_arg.hir_id).kind();
58+
if let ty::Ref(..) = inner_ty.kind();
59+
// put an `&` in the closure body, but skip closure params
60+
if let Some((start, end)) = old_search_snippet.split_once(&name);
61+
62+
then {
63+
let end = end.replace(name, &format!("&{}", name));
64+
Some(format!("{}{}{}", start, name, end))
65+
} else {
66+
Some(search_snippet)
67+
}
68+
}
5169
} else {
5270
None
5371
}

tests/ui/search_is_some_fixable.fixed

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,38 @@ fn is_none() {
6666
let _ = !s1[2..].contains(&s2);
6767
let _ = !s1[2..].contains(&s2[2..]);
6868
}
69+
70+
#[allow(clippy::clone_on_copy, clippy::map_clone)]
71+
mod issue7392 {
72+
struct Player {
73+
hand: Vec<usize>,
74+
}
75+
fn filter() {
76+
let p = Player {
77+
hand: vec![1, 2, 3, 4, 5],
78+
};
79+
let filter_hand = vec![5];
80+
let _ = p
81+
.hand
82+
.iter()
83+
.filter(|c| !filter_hand.iter().any(|cc| c == &cc))
84+
.map(|c| c.clone())
85+
.collect::<Vec<_>>();
86+
}
87+
88+
struct PlayerTuple {
89+
hand: Vec<(usize, char)>,
90+
}
91+
fn filter_tuple() {
92+
let p = PlayerTuple {
93+
hand: vec![(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')],
94+
};
95+
let filter_hand = vec![5];
96+
let _ = p
97+
.hand
98+
.iter()
99+
.filter(|(c, _)| !filter_hand.iter().any(|cc| c == cc))
100+
.map(|c| c.clone())
101+
.collect::<Vec<_>>();
102+
}
103+
}

tests/ui/search_is_some_fixable.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,38 @@ fn is_none() {
6666
let _ = s1[2..].find(&s2).is_none();
6767
let _ = s1[2..].find(&s2[2..]).is_none();
6868
}
69+
70+
#[allow(clippy::clone_on_copy, clippy::map_clone)]
71+
mod issue7392 {
72+
struct Player {
73+
hand: Vec<usize>,
74+
}
75+
fn filter() {
76+
let p = Player {
77+
hand: vec![1, 2, 3, 4, 5],
78+
};
79+
let filter_hand = vec![5];
80+
let _ = p
81+
.hand
82+
.iter()
83+
.filter(|c| filter_hand.iter().find(|cc| c == cc).is_none())
84+
.map(|c| c.clone())
85+
.collect::<Vec<_>>();
86+
}
87+
88+
struct PlayerTuple {
89+
hand: Vec<(usize, char)>,
90+
}
91+
fn filter_tuple() {
92+
let p = PlayerTuple {
93+
hand: vec![(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')],
94+
};
95+
let filter_hand = vec![5];
96+
let _ = p
97+
.hand
98+
.iter()
99+
.filter(|(c, _)| filter_hand.iter().find(|cc| c == *cc).is_none())
100+
.map(|c| c.clone())
101+
.collect::<Vec<_>>();
102+
}
103+
}

tests/ui/search_is_some_fixable.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,5 +180,17 @@ error: called `is_none()` after calling `find()` on a string
180180
LL | let _ = s1[2..].find(&s2[2..]).is_none();
181181
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1[2..].contains(&s2[2..])`
182182

183-
error: aborting due to 30 previous errors
183+
error: called `is_none()` after searching an `Iterator` with `find`
184+
--> $DIR/search_is_some_fixable.rs:83:25
185+
|
186+
LL | .filter(|c| filter_hand.iter().find(|cc| c == cc).is_none())
187+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!filter_hand.iter().any(|cc| c == &cc)`
188+
189+
error: called `is_none()` after searching an `Iterator` with `find`
190+
--> $DIR/search_is_some_fixable.rs:99:30
191+
|
192+
LL | .filter(|(c, _)| filter_hand.iter().find(|cc| c == *cc).is_none())
193+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!filter_hand.iter().any(|cc| c == cc)`
194+
195+
error: aborting due to 32 previous errors
184196

0 commit comments

Comments
 (0)