]> git.lizzy.rs Git - rust.git/blob - tests/ui/for_loop.rs
Merge pull request #2984 from flip1995/single_char_pattern
[rust.git] / tests / ui / for_loop.rs
1
2
3
4 use std::collections::*;
5 use std::rc::Rc;
6
7 static STATIC: [usize; 4] = [0, 1, 8, 16];
8 const CONST: [usize; 4] = [0, 1, 8, 16];
9
10 #[warn(clippy)]
11 fn for_loop_over_option_and_result() {
12     let option = Some(1);
13     let result = option.ok_or("x not found");
14     let v = vec![0, 1, 2];
15
16     // check FOR_LOOP_OVER_OPTION lint
17     for x in option {
18         println!("{}", x);
19     }
20
21     // check FOR_LOOP_OVER_RESULT lint
22     for x in result {
23         println!("{}", x);
24     }
25
26     for x in option.ok_or("x not found") {
27         println!("{}", x);
28     }
29
30     // make sure LOOP_OVER_NEXT lint takes precedence when next() is the last call
31     // in the chain
32     for x in v.iter().next() {
33         println!("{}", x);
34     }
35
36     // make sure we lint when next() is not the last call in the chain
37     for x in v.iter().next().and(Some(0)) {
38         println!("{}", x);
39     }
40
41     for x in v.iter().next().ok_or("x not found") {
42         println!("{}", x);
43     }
44
45     // check for false positives
46
47     // for loop false positive
48     for x in v {
49         println!("{}", x);
50     }
51
52     // while let false positive for Option
53     while let Some(x) = option {
54         println!("{}", x);
55         break;
56     }
57
58     // while let false positive for Result
59     while let Ok(x) = result {
60         println!("{}", x);
61         break;
62     }
63 }
64
65 struct Unrelated(Vec<u8>);
66 impl Unrelated {
67     fn next(&self) -> std::slice::Iter<u8> {
68         self.0.iter()
69     }
70
71     fn iter(&self) -> std::slice::Iter<u8> {
72         self.0.iter()
73     }
74 }
75
76 #[warn(needless_range_loop, explicit_iter_loop, explicit_into_iter_loop, iter_next_loop, reverse_range_loop,
77        explicit_counter_loop, for_kv_map)]
78 #[warn(unused_collect)]
79 #[allow(linkedlist, shadow_unrelated, unnecessary_mut_passed, cyclomatic_complexity, similar_names)]
80 #[allow(many_single_char_names, unused_variables)]
81 fn main() {
82     const MAX_LEN: usize = 42;
83
84     let mut vec = vec![1, 2, 3, 4];
85     let vec2 = vec![1, 2, 3, 4];
86     for i in 0..vec.len() {
87         println!("{}", vec[i]);
88     }
89
90     for i in 0..vec.len() {
91         let i = 42; // make a different `i`
92         println!("{}", vec[i]); // ok, not the `i` of the for-loop
93     }
94
95     for i in 0..vec.len() {
96         let _ = vec[i];
97     }
98
99     // ICE #746
100     for j in 0..4 {
101         println!("{:?}", STATIC[j]);
102     }
103
104     for j in 0..4 {
105         println!("{:?}", CONST[j]);
106     }
107
108     for i in 0..vec.len() {
109         println!("{} {}", vec[i], i);
110     }
111     for i in 0..vec.len() {
112         // not an error, indexing more than one variable
113         println!("{} {}", vec[i], vec2[i]);
114     }
115
116     for i in 0..vec.len() {
117         println!("{}", vec2[i]);
118     }
119
120     for i in 5..vec.len() {
121         println!("{}", vec[i]);
122     }
123
124     for i in 0..MAX_LEN {
125         println!("{}", vec[i]);
126     }
127
128     for i in 0..=MAX_LEN {
129         println!("{}", vec[i]);
130     }
131
132     for i in 5..10 {
133         println!("{}", vec[i]);
134     }
135
136     for i in 5..=10 {
137         println!("{}", vec[i]);
138     }
139
140     for i in 5..vec.len() {
141         println!("{} {}", vec[i], i);
142     }
143
144     for i in 5..10 {
145         println!("{} {}", vec[i], i);
146     }
147
148     for i in 10..0 {
149         println!("{}", i);
150     }
151
152     for i in 10..=0 {
153         println!("{}", i);
154     }
155
156     for i in MAX_LEN..0 {
157         println!("{}", i);
158     }
159
160     for i in 5..5 {
161         println!("{}", i);
162     }
163
164     for i in 5..=5 {
165         // not an error, this is the range with only one element “5”
166         println!("{}", i);
167     }
168
169     for i in 0..10 {
170         // not an error, the start index is less than the end index
171         println!("{}", i);
172     }
173
174     for i in -10..0 {
175         // not an error
176         println!("{}", i);
177     }
178
179     for i in (10..0).map(|x| x * 2) {
180         // not an error, it can't be known what arbitrary methods do to a range
181         println!("{}", i);
182     }
183
184     // testing that the empty range lint folds constants
185     for i in 10..5 + 4 {
186         println!("{}", i);
187     }
188
189     for i in (5 + 2)..(3 - 1) {
190         println!("{}", i);
191     }
192
193     for i in (5 + 2)..(8 - 1) {
194         println!("{}", i);
195     }
196
197     for i in (2 * 2)..(2 * 3) {
198         // no error, 4..6 is fine
199         println!("{}", i);
200     }
201
202     let x = 42;
203     for i in x..10 {
204         // no error, not constant-foldable
205         println!("{}", i);
206     }
207
208     // See #601
209     for i in 0..10 {
210         // no error, id_col does not exist outside the loop
211         let mut id_col = vec![0f64; 10];
212         id_col[i] = 1f64;
213     }
214
215     for _v in vec.iter() {}
216
217     for _v in vec.iter_mut() {}
218
219     let out_vec = vec![1, 2, 3];
220     for _v in out_vec.into_iter() {}
221
222     let array = [1, 2, 3];
223     for _v in array.into_iter() {}
224
225     for _v in &vec {} // these are fine
226     for _v in &mut vec {} // these are fine
227
228     for _v in [1, 2, 3].iter() {}
229
230     for _v in (&mut [1, 2, 3]).iter() {} // no error
231
232     for _v in [0; 32].iter() {}
233
234     for _v in [0; 33].iter() {} // no error
235
236     let ll: LinkedList<()> = LinkedList::new();
237     for _v in ll.iter() {}
238
239     let vd: VecDeque<()> = VecDeque::new();
240     for _v in vd.iter() {}
241
242     let bh: BinaryHeap<()> = BinaryHeap::new();
243     for _v in bh.iter() {}
244
245     let hm: HashMap<(), ()> = HashMap::new();
246     for _v in hm.iter() {}
247
248     let bt: BTreeMap<(), ()> = BTreeMap::new();
249     for _v in bt.iter() {}
250
251     let hs: HashSet<()> = HashSet::new();
252     for _v in hs.iter() {}
253
254     let bs: BTreeSet<()> = BTreeSet::new();
255     for _v in bs.iter() {}
256
257     for _v in vec.iter().next() {}
258
259     let u = Unrelated(vec![]);
260     for _v in u.next() {} // no error
261     for _v in u.iter() {} // no error
262
263     let mut out = vec![];
264     vec.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>();
265     let _y = vec.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>(); // this is fine
266
267     // Loop with explicit counter variable
268     let mut _index = 0;
269     for _v in &vec {
270         _index += 1
271     }
272
273     let mut _index = 1;
274     _index = 0;
275     for _v in &vec {
276         _index += 1
277     }
278
279     // Potential false positives
280     let mut _index = 0;
281     _index = 1;
282     for _v in &vec {
283         _index += 1
284     }
285
286     let mut _index = 0;
287     _index += 1;
288     for _v in &vec {
289         _index += 1
290     }
291
292     let mut _index = 0;
293     if true {
294         _index = 1
295     }
296     for _v in &vec {
297         _index += 1
298     }
299
300     let mut _index = 0;
301     let mut _index = 1;
302     for _v in &vec {
303         _index += 1
304     }
305
306     let mut _index = 0;
307     for _v in &vec {
308         _index += 1;
309         _index += 1
310     }
311
312     let mut _index = 0;
313     for _v in &vec {
314         _index *= 2;
315         _index += 1
316     }
317
318     let mut _index = 0;
319     for _v in &vec {
320         _index = 1;
321         _index += 1
322     }
323
324     let mut _index = 0;
325
326     for _v in &vec {
327         let mut _index = 0;
328         _index += 1
329     }
330
331     let mut _index = 0;
332     for _v in &vec {
333         _index += 1;
334         _index = 0;
335     }
336
337     let mut _index = 0;
338     for _v in &vec {
339         for _x in 0..1 {
340             _index += 1;
341         }
342         _index += 1
343     }
344
345     let mut _index = 0;
346     for x in &vec {
347         if *x == 1 {
348             _index += 1
349         }
350     }
351
352     let mut _index = 0;
353     if true {
354         _index = 1
355     };
356     for _v in &vec {
357         _index += 1
358     }
359
360     let mut _index = 1;
361     if false {
362         _index = 0
363     };
364     for _v in &vec {
365         _index += 1
366     }
367
368     let mut index = 0;
369     {
370         let mut _x = &mut index;
371     }
372     for _v in &vec {
373         _index += 1
374     }
375
376     let mut index = 0;
377     for _v in &vec {
378         index += 1
379     }
380     println!("index: {}", index);
381
382     for_loop_over_option_and_result();
383
384     let m: HashMap<u64, u64> = HashMap::new();
385     for (_, v) in &m {
386         let _v = v;
387     }
388
389     let m: Rc<HashMap<u64, u64>> = Rc::new(HashMap::new());
390     for (_, v) in &*m {
391         let _v = v;
392         // Here the `*` is not actually necessary, but the test tests that we don't
393         // suggest
394         // `in *m.values()` as we used to
395     }
396
397     let mut m: HashMap<u64, u64> = HashMap::new();
398     for (_, v) in &mut m {
399         let _v = v;
400     }
401
402     let m: &mut HashMap<u64, u64> = &mut HashMap::new();
403     for (_, v) in &mut *m {
404         let _v = v;
405     }
406
407     let m: HashMap<u64, u64> = HashMap::new();
408     let rm = &m;
409     for (k, _value) in rm {
410         let _k = k;
411     }
412
413     test_for_kv_map();
414
415     fn f<T>(_: &T, _: &T) -> bool {
416         unimplemented!()
417     }
418     fn g<T>(_: &mut [T], _: usize, _: usize) {
419         unimplemented!()
420     }
421     for i in 1..vec.len() {
422         if f(&vec[i - 1], &vec[i]) {
423             g(&mut vec, i - 1, i);
424         }
425     }
426
427     for mid in 1..vec.len() {
428         let (_, _) = vec.split_at(mid);
429     }
430 }
431
432 #[allow(used_underscore_binding)]
433 fn test_for_kv_map() {
434     let m: HashMap<u64, u64> = HashMap::new();
435
436     // No error, _value is actually used
437     for (k, _value) in &m {
438         let _ = _value;
439         let _k = k;
440     }
441 }
442
443 #[allow(dead_code)]
444 fn partition<T: PartialOrd + Send>(v: &mut [T]) -> usize {
445     let pivot = v.len() - 1;
446     let mut i = 0;
447     for j in 0..pivot {
448         if v[j] <= v[pivot] {
449             v.swap(i, j);
450             i += 1;
451         }
452     }
453     v.swap(i, pivot);
454     i
455 }
456
457 const LOOP_OFFSET: usize = 5000;
458
459 #[warn(needless_range_loop)]
460 pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) {
461     // plain manual memcpy
462     for i in 0..src.len() {
463         dst[i] = src[i];
464     }
465
466     // dst offset memcpy
467     for i in 0..src.len() {
468         dst[i + 10] = src[i];
469     }
470
471     // src offset memcpy
472     for i in 0..src.len() {
473         dst[i] = src[i + 10];
474     }
475
476     // src offset memcpy
477     for i in 11..src.len() {
478         dst[i] = src[i - 10];
479     }
480
481     // overwrite entire dst
482     for i in 0..dst.len() {
483         dst[i] = src[i];
484     }
485
486     // manual copy with branch - can't easily convert to memcpy!
487     for i in 0..src.len() {
488         dst[i] = src[i];
489         if dst[i] > 5 {
490             break;
491         }
492     }
493
494     // multiple copies - suggest two memcpy statements
495     for i in 10..256 {
496         dst[i] = src[i - 5];
497         dst2[i + 500] = src[i]
498     }
499
500     // this is a reversal - the copy lint shouldn't be triggered
501     for i in 10..LOOP_OFFSET {
502         dst[i + LOOP_OFFSET] = src[LOOP_OFFSET - i];
503     }
504
505     let some_var = 5;
506     // Offset in variable
507     for i in 10..LOOP_OFFSET {
508         dst[i + LOOP_OFFSET] = src[i - some_var];
509     }
510
511     // Non continuous copy - don't trigger lint
512     for i in 0..10 {
513         dst[i + i] = src[i];
514     }
515
516     let src_vec = vec![1, 2, 3, 4, 5];
517     let mut dst_vec = vec![0, 0, 0, 0, 0];
518
519     // make sure vectors are supported
520     for i in 0..src_vec.len() {
521         dst_vec[i] = src_vec[i];
522     }
523
524     // lint should not trigger when either
525     // source or destination type is not
526     // slice-like, like DummyStruct
527     struct DummyStruct(i32);
528
529     impl ::std::ops::Index<usize> for DummyStruct {
530         type Output = i32;
531
532         fn index(&self, _: usize) -> &i32 {
533             &self.0
534         }
535     }
536
537     let src = DummyStruct(5);
538     let mut dst_vec = vec![0; 10];
539
540     for i in 0..10 {
541         dst_vec[i] = src[i];
542     }
543 }
544
545 #[warn(needless_range_loop)]
546 pub fn manual_clone(src: &[String], dst: &mut [String]) {
547     for i in 0..src.len() {
548         dst[i] = src[i].clone();
549     }
550 }
551
552 #[warn(needless_range_loop)]
553 pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) {
554     // Same source and destination - don't trigger lint
555     for i in 0..dst.len() {
556         dst[d + i] = dst[s + i];
557     }
558 }
559
560 mod issue_2496 {
561     pub trait Handle {
562         fn new_for_index(index: usize) -> Self;
563         fn index(&self) -> usize;
564     }
565
566     pub fn test<H: Handle>() -> H {
567         for x in 0..5 {
568             let next_handle = H::new_for_index(x);
569             println!("{}", next_handle.index());
570         }
571         unimplemented!()
572     }
573 }