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