@@ -27,6 +27,12 @@ macro_rules! some_false {
2727 };
2828}
2929
30+ macro_rules! into_iter {
31+ ($x:expr) => {
32+ $x.into_iter()
33+ };
34+ }
35+
3036macro_rules! mac {
3137 (some $e:expr) => {
3238 Some($e)
@@ -42,8 +48,51 @@ macro_rules! mac {
4248 };
4349}
4450
51+ #[clippy::msrv = "1.69"]
52+ fn under_msrv_is_some_and(opt: Option<u32>, res: Result<u32, ()>) {
53+ let _ = res.into_iter().any(|x| x != 0);
54+ let _ = opt.map(|x| x != 0).unwrap_or_default();
55+ let _ = opt.iter().all(|x| *x != 0);
56+ let _ = opt.iter().any(|&x| x != 0);
57+ }
58+
59+ #[clippy::msrv = "1.70"]
60+ fn meets_msrv_is_some_and(opt: Option<u32>, res: Result<u32, ()>) {
61+ let _ = res.is_ok_and(|x| x != 0);
62+ //~^ manual_is_variant_and
63+ let _ = opt.is_some_and(|x| x != 0);
64+ //~^ manual_is_variant_and
65+ let _ = opt.iter().all(|x| *x != 0);
66+ let _ = opt.is_some_and(|x| x != 0);
67+ //~^ manual_is_variant_and
68+ }
69+
70+ #[clippy::msrv = "1.81"]
71+ fn under_msrv_is_none_or(opt: Option<u32>, res: Result<u32, ()>) {
72+ let _ = res.is_ok_and(|x| x != 0);
73+ //~^ manual_is_variant_and
74+ let _ = opt.is_some_and(|x| x != 0);
75+ //~^ manual_is_variant_and
76+ let _ = opt.iter().all(|x| *x != 0);
77+ let _ = opt.is_some_and(|x| x != 0);
78+ //~^ manual_is_variant_and
79+ }
80+
81+ #[clippy::msrv = "1.82"]
82+ fn meets_msrv_is_none_or(opt: Option<u32>, res: Result<u32, ()>) {
83+ let _ = res.is_ok_and(|x| x != 0);
84+ //~^ manual_is_variant_and
85+ let _ = opt.is_some_and(|x| x != 0);
86+ //~^ manual_is_variant_and
87+ let _ = opt.is_none_or(|x| x != 0);
88+ //~^ manual_is_variant_and
89+ let _ = opt.is_some_and(|x| x != 0);
90+ //~^ manual_is_variant_and
91+ }
92+
4593#[rustfmt::skip]
4694fn option_methods() {
95+ let opt_non_copy: Option<String> = None;
4796 let opt = Some(1);
4897
4998 // Check for `option.map(_).unwrap_or_default()` use.
@@ -67,6 +116,36 @@ fn option_methods() {
67116 //~^ manual_is_variant_and
68117 let _ = Some(2).is_none_or(|x| x % 2 == 0);
69118 //~^ manual_is_variant_and
119+ let _ = opt.is_none_or(|x| x != 0);
120+ //~^ manual_is_variant_and
121+ let _ = (opt).is_none_or(|x| x != 0);
122+ //~^ manual_is_variant_and
123+ let _ = opt.is_some_and(i32::is_negative);
124+ //~^ manual_is_variant_and
125+ let _ = opt.is_some_and(|x| x != 0);
126+ //~^ manual_is_variant_and
127+
128+ // The type does not copy. The linter should suggest `as_ref`.
129+ let _ = (opt_non_copy).as_ref().is_some_and(|x| x.is_empty());
130+ //~^ manual_is_variant_and
131+ let _ = opt_non_copy.as_ref().is_some_and(|x| x.is_empty());
132+ //~^ manual_is_variant_and
133+ let _ = opt_non_copy.as_ref().is_some_and(|x| ".." == *x);
134+ //~^ manual_is_variant_and
135+ // The type copies. The linter should not suggest `as_ref`.
136+ let _ = opt.is_none_or(|x| x != 0);
137+ //~^ manual_is_variant_and
138+ let _ = opt.as_ref().is_none_or(|_| false);
139+ //~^ manual_is_variant_and
140+ let _ = opt.is_some_and(|x| x != 0);
141+ //~^ manual_is_variant_and
142+ let _ = opt.is_none_or(|_| false);
143+ //~^ manual_is_variant_and
144+ // The argument is defined elsewhere. It cannot be changed to take the
145+ // value. The linter should suggest `as_ref`.
146+ let zerop = |x: &i32| *x == 0;
147+ let _ = opt.as_ref().is_none_or(zerop);
148+ //~^ manual_is_variant_and
70149
71150 // won't fix because the return type of the closure is not `bool`
72151 let _ = opt.map(|x| x + 1).unwrap_or_default();
@@ -83,10 +162,13 @@ fn option_methods() {
83162 let _ = mac!(some 2).map(|x| x % 2 == 0) == Some(true);
84163 let _ = mac!(some_map 2) == Some(true);
85164 let _ = mac!(map Some(2)) == Some(true);
165+ // The first method call is elsewhere. The linter cannot change it.
166+ let _ = into_iter!(opt).any(|x| x != 0);
86167}
87168
88169#[rustfmt::skip]
89170fn result_methods() {
171+ let res_non_copy: Result<i32, String> = Ok(1);
90172 let res: Result<i32, ()> = Ok(1);
91173
92174 // multi line cases
@@ -102,14 +184,24 @@ fn result_methods() {
102184 //~^ manual_is_variant_and
103185 let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2));
104186 //~^ manual_is_variant_and
187+ let _ = res.is_ok_and(i32::is_negative);
188+ //~^ manual_is_variant_and
189+ let _ = res_non_copy.as_ref().is_ok_and(|x| *x != 0);
190+ //~^ manual_is_variant_and
191+ let _ = res.is_ok_and(|x| x != 0);
192+ //~^ manual_is_variant_and
105193
106194 // won't fix because the return type of the closure is not `bool`
107195 let _ = res.map(|x| x + 1).unwrap_or_default();
108196
109197 let res2: Result<char, ()> = Ok('a');
110198 let _ = res2.is_ok_and(char::is_alphanumeric); // should lint
111199 //~^ manual_is_variant_and
112- let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default(); // should not lint
200+
201+ // should not lint
202+ let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default();
203+ // The result type comes with no shorthand for all.
204+ let _ = res.into_iter().all(i32::is_negative);
113205}
114206
115207fn main() {
0 commit comments