]> git.lizzy.rs Git - rust.git/blob - tests/ui/methods.rs
Auto merge of #3666 - detrumi:map-or-on-non-copy, r=flip1995
[rust.git] / tests / ui / methods.rs
1 // aux-build:option_helpers.rs
2
3 #![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)]
4 #![allow(
5     clippy::blacklisted_name,
6     unused,
7     clippy::print_stdout,
8     clippy::non_ascii_literal,
9     clippy::new_without_default,
10     clippy::missing_docs_in_private_items,
11     clippy::needless_pass_by_value,
12     clippy::default_trait_access,
13     clippy::use_self,
14     clippy::new_ret_no_self,
15     clippy::useless_format
16 )]
17
18 #[macro_use]
19 extern crate option_helpers;
20
21 use std::collections::BTreeMap;
22 use std::collections::HashMap;
23 use std::collections::HashSet;
24 use std::collections::VecDeque;
25 use std::iter::FromIterator;
26 use std::ops::Mul;
27 use std::rc::{self, Rc};
28 use std::sync::{self, Arc};
29
30 use option_helpers::IteratorFalsePositives;
31
32 pub struct T;
33
34 impl T {
35     pub fn add(self, other: T) -> T {
36         self
37     }
38
39     // no error, not public interface
40     pub(crate) fn drop(&mut self) {}
41
42     // no error, private function
43     fn neg(self) -> Self {
44         self
45     }
46
47     // no error, private function
48     fn eq(&self, other: T) -> bool {
49         true
50     }
51
52     // no error, self is a ref
53     fn sub(&self, other: T) -> &T {
54         self
55     }
56
57     // no error, different #arguments
58     fn div(self) -> T {
59         self
60     }
61
62     fn rem(self, other: T) {} // no error, wrong return type
63
64     // fine
65     fn into_u32(self) -> u32 {
66         0
67     }
68
69     fn into_u16(&self) -> u16 {
70         0
71     }
72
73     fn to_something(self) -> u32 {
74         0
75     }
76
77     fn new(self) -> Self {
78         unimplemented!();
79     }
80 }
81
82 struct Lt<'a> {
83     foo: &'a u32,
84 }
85
86 impl<'a> Lt<'a> {
87     // The lifetime is different, but that’s irrelevant, see #734
88     #[allow(clippy::needless_lifetimes)]
89     pub fn new<'b>(s: &'b str) -> Lt<'b> {
90         unimplemented!()
91     }
92 }
93
94 struct Lt2<'a> {
95     foo: &'a u32,
96 }
97
98 impl<'a> Lt2<'a> {
99     // The lifetime is different, but that’s irrelevant, see #734
100     pub fn new(s: &str) -> Lt2 {
101         unimplemented!()
102     }
103 }
104
105 struct Lt3<'a> {
106     foo: &'a u32,
107 }
108
109 impl<'a> Lt3<'a> {
110     // The lifetime is different, but that’s irrelevant, see #734
111     pub fn new() -> Lt3<'static> {
112         unimplemented!()
113     }
114 }
115
116 #[derive(Clone, Copy)]
117 struct U;
118
119 impl U {
120     fn new() -> Self {
121         U
122     }
123     // ok because U is Copy
124     fn to_something(self) -> u32 {
125         0
126     }
127 }
128
129 struct V<T> {
130     _dummy: T,
131 }
132
133 impl<T> V<T> {
134     fn new() -> Option<V<T>> {
135         None
136     }
137 }
138
139 impl Mul<T> for T {
140     type Output = T;
141     // no error, obviously
142     fn mul(self, other: T) -> T {
143         self
144     }
145 }
146
147 /// Checks implementation of the following lints:
148 /// * `OPTION_MAP_UNWRAP_OR`
149 /// * `OPTION_MAP_UNWRAP_OR_ELSE`
150 /// * `OPTION_MAP_OR_NONE`
151 #[rustfmt::skip]
152 fn option_methods() {
153     let opt = Some(1);
154
155     // Check OPTION_MAP_UNWRAP_OR
156     // single line case
157     let _ = opt.map(|x| x + 1)
158
159                .unwrap_or(0); // should lint even though this call is on a separate line
160     // multi line cases
161     let _ = opt.map(|x| {
162                         x + 1
163                     }
164               ).unwrap_or(0);
165     let _ = opt.map(|x| x + 1)
166                .unwrap_or({
167                     0
168                 });
169     // single line `map(f).unwrap_or(None)` case
170     let _ = opt.map(|x| Some(x + 1)).unwrap_or(None);
171     // multiline `map(f).unwrap_or(None)` cases
172     let _ = opt.map(|x| {
173         Some(x + 1)
174     }
175     ).unwrap_or(None);
176     let _ = opt
177         .map(|x| Some(x + 1))
178         .unwrap_or(None);
179     // macro case
180     let _ = opt_map!(opt, |x| x + 1).unwrap_or(0); // should not lint
181
182     // Should not lint if not copyable
183     let id: String = "identifier".to_string();
184     let _ = Some("prefix").map(|p| format!("{}.{}", p, id)).unwrap_or(id);
185     // ...but DO lint if the `unwrap_or` argument is not used in the `map`
186     let id: String = "identifier".to_string();
187     let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id);
188
189     // Check OPTION_MAP_UNWRAP_OR_ELSE
190     // single line case
191     let _ = opt.map(|x| x + 1)
192
193                .unwrap_or_else(|| 0); // should lint even though this call is on a separate line
194     // multi line cases
195     let _ = opt.map(|x| {
196                         x + 1
197                     }
198               ).unwrap_or_else(|| 0);
199     let _ = opt.map(|x| x + 1)
200                .unwrap_or_else(||
201                     0
202                 );
203     // macro case
204     let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0); // should not lint
205
206     // Check OPTION_MAP_OR_NONE
207     // single line case
208     let _ = opt.map_or(None, |x| Some(x + 1));
209     // multi line case
210     let _ = opt.map_or(None, |x| {
211                         Some(x + 1)
212                        }
213                 );
214 }
215
216 /// Struct to generate false positives for things with .iter()
217 #[derive(Copy, Clone)]
218 struct HasIter;
219
220 impl HasIter {
221     fn iter(self) -> IteratorFalsePositives {
222         IteratorFalsePositives { foo: 0 }
223     }
224
225     fn iter_mut(self) -> IteratorFalsePositives {
226         IteratorFalsePositives { foo: 0 }
227     }
228 }
229
230 /// Checks implementation of `FILTER_NEXT` lint
231 #[rustfmt::skip]
232 fn filter_next() {
233     let v = vec![3, 2, 1, 0, -1, -2, -3];
234
235     // check single-line case
236     let _ = v.iter().filter(|&x| *x < 0).next();
237
238     // check multi-line case
239     let _ = v.iter().filter(|&x| {
240                                 *x < 0
241                             }
242                    ).next();
243
244     // check that we don't lint if the caller is not an Iterator
245     let foo = IteratorFalsePositives { foo: 0 };
246     let _ = foo.filter().next();
247 }
248
249 /// Checks implementation of `SEARCH_IS_SOME` lint
250 #[rustfmt::skip]
251 fn search_is_some() {
252     let v = vec![3, 2, 1, 0, -1, -2, -3];
253
254     // check `find().is_some()`, single-line
255     let _ = v.iter().find(|&x| *x < 0).is_some();
256
257     // check `find().is_some()`, multi-line
258     let _ = v.iter().find(|&x| {
259                               *x < 0
260                           }
261                    ).is_some();
262
263     // check `position().is_some()`, single-line
264     let _ = v.iter().position(|&x| x < 0).is_some();
265
266     // check `position().is_some()`, multi-line
267     let _ = v.iter().position(|&x| {
268                                   x < 0
269                               }
270                    ).is_some();
271
272     // check `rposition().is_some()`, single-line
273     let _ = v.iter().rposition(|&x| x < 0).is_some();
274
275     // check `rposition().is_some()`, multi-line
276     let _ = v.iter().rposition(|&x| {
277                                    x < 0
278                                }
279                    ).is_some();
280
281     // check that we don't lint if the caller is not an Iterator
282     let foo = IteratorFalsePositives { foo: 0 };
283     let _ = foo.find().is_some();
284     let _ = foo.position().is_some();
285     let _ = foo.rposition().is_some();
286 }
287
288 /// Checks implementation of the `OR_FUN_CALL` lint
289 fn or_fun_call() {
290     struct Foo;
291
292     impl Foo {
293         fn new() -> Foo {
294             Foo
295         }
296     }
297
298     enum Enum {
299         A(i32),
300     }
301
302     fn make<T>() -> T {
303         unimplemented!();
304     }
305
306     let with_enum = Some(Enum::A(1));
307     with_enum.unwrap_or(Enum::A(5));
308
309     let with_const_fn = Some(::std::time::Duration::from_secs(1));
310     with_const_fn.unwrap_or(::std::time::Duration::from_secs(5));
311
312     let with_constructor = Some(vec![1]);
313     with_constructor.unwrap_or(make());
314
315     let with_new = Some(vec![1]);
316     with_new.unwrap_or(Vec::new());
317
318     let with_const_args = Some(vec![1]);
319     with_const_args.unwrap_or(Vec::with_capacity(12));
320
321     let with_err: Result<_, ()> = Ok(vec![1]);
322     with_err.unwrap_or(make());
323
324     let with_err_args: Result<_, ()> = Ok(vec![1]);
325     with_err_args.unwrap_or(Vec::with_capacity(12));
326
327     let with_default_trait = Some(1);
328     with_default_trait.unwrap_or(Default::default());
329
330     let with_default_type = Some(1);
331     with_default_type.unwrap_or(u64::default());
332
333     let with_vec = Some(vec![1]);
334     with_vec.unwrap_or(vec![]);
335
336     // FIXME #944: ~|SUGGESTION with_vec.unwrap_or_else(|| vec![]);
337
338     let without_default = Some(Foo);
339     without_default.unwrap_or(Foo::new());
340
341     let mut map = HashMap::<u64, String>::new();
342     map.entry(42).or_insert(String::new());
343
344     let mut btree = BTreeMap::<u64, String>::new();
345     btree.entry(42).or_insert(String::new());
346
347     let stringy = Some(String::from(""));
348     let _ = stringy.unwrap_or("".to_owned());
349 }
350
351 /// Checks implementation of `ITER_NTH` lint
352 fn iter_nth() {
353     let mut some_vec = vec![0, 1, 2, 3];
354     let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
355     let mut some_vec_deque: VecDeque<_> = some_vec.iter().cloned().collect();
356
357     {
358         // Make sure we lint `.iter()` for relevant types
359         let bad_vec = some_vec.iter().nth(3);
360         let bad_slice = &some_vec[..].iter().nth(3);
361         let bad_boxed_slice = boxed_slice.iter().nth(3);
362         let bad_vec_deque = some_vec_deque.iter().nth(3);
363     }
364
365     {
366         // Make sure we lint `.iter_mut()` for relevant types
367         let bad_vec = some_vec.iter_mut().nth(3);
368     }
369     {
370         let bad_slice = &some_vec[..].iter_mut().nth(3);
371     }
372     {
373         let bad_vec_deque = some_vec_deque.iter_mut().nth(3);
374     }
375
376     // Make sure we don't lint for non-relevant types
377     let false_positive = HasIter;
378     let ok = false_positive.iter().nth(3);
379     let ok_mut = false_positive.iter_mut().nth(3);
380 }
381
382 #[allow(clippy::similar_names)]
383 fn main() {
384     let opt = Some(0);
385     let _ = opt.unwrap();
386 }