diff options
Diffstat (limited to 'src/tools/clippy/tests/ui/manual_memcpy')
4 files changed, 450 insertions, 0 deletions
diff --git a/src/tools/clippy/tests/ui/manual_memcpy/with_loop_counters.rs b/src/tools/clippy/tests/ui/manual_memcpy/with_loop_counters.rs new file mode 100644 index 000000000..c826b082a --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_memcpy/with_loop_counters.rs @@ -0,0 +1,88 @@ +#![warn(clippy::needless_range_loop, clippy::manual_memcpy)] + +pub fn manual_copy_with_counters(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { + let mut count = 0; + for i in 3..src.len() { + dst[i] = src[count]; + count += 1; + } + + let mut count = 0; + for i in 3..src.len() { + dst[count] = src[i]; + count += 1; + } + + let mut count = 3; + for i in 0..src.len() { + dst[count] = src[i]; + count += 1; + } + + let mut count = 3; + for i in 0..src.len() { + dst[i] = src[count]; + count += 1; + } + + let mut count = 0; + for i in 3..(3 + src.len()) { + dst[i] = src[count]; + count += 1; + } + + let mut count = 3; + for i in 5..src.len() { + dst[i] = src[count - 2]; + count += 1; + } + + let mut count = 2; + for i in 0..dst.len() { + dst[i] = src[count]; + count += 1; + } + + let mut count = 5; + for i in 3..10 { + dst[i] = src[count]; + count += 1; + } + + let mut count = 3; + let mut count2 = 30; + for i in 0..src.len() { + dst[count] = src[i]; + dst2[count2] = src[i]; + count += 1; + count2 += 1; + } + + // make sure parentheses are added properly to bitwise operators, which have lower precedence than + // arithmetic ones + let mut count = 0 << 1; + for i in 0..1 << 1 { + dst[count] = src[i + 2]; + count += 1; + } + + // make sure incrementing expressions without semicolons at the end of loops are handled correctly. + let mut count = 0; + for i in 3..src.len() { + dst[i] = src[count]; + count += 1 + } + + // make sure ones where the increment is not at the end of the loop. + // As a possible enhancement, one could adjust the offset in the suggestion according to + // the position. For example, if the increment is at the top of the loop; + // treating the loop counter as if it were initialized 1 greater than the original value. + let mut count = 0; + #[allow(clippy::needless_range_loop)] + for i in 0..src.len() { + count += 1; + dst[i] = src[count]; + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/manual_memcpy/with_loop_counters.stderr b/src/tools/clippy/tests/ui/manual_memcpy/with_loop_counters.stderr new file mode 100644 index 000000000..79d40c0bc --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_memcpy/with_loop_counters.stderr @@ -0,0 +1,111 @@ +error: it looks like you're manually copying between slices + --> $DIR/with_loop_counters.rs:5:5 + | +LL | / for i in 3..src.len() { +LL | | dst[i] = src[count]; +LL | | count += 1; +LL | | } + | |_____^ help: try replacing the loop by: `dst[3..src.len()].copy_from_slice(&src[..(src.len() - 3)]);` + | + = note: `-D clippy::manual-memcpy` implied by `-D warnings` + +error: it looks like you're manually copying between slices + --> $DIR/with_loop_counters.rs:11:5 + | +LL | / for i in 3..src.len() { +LL | | dst[count] = src[i]; +LL | | count += 1; +LL | | } + | |_____^ help: try replacing the loop by: `dst[..(src.len() - 3)].copy_from_slice(&src[3..]);` + +error: it looks like you're manually copying between slices + --> $DIR/with_loop_counters.rs:17:5 + | +LL | / for i in 0..src.len() { +LL | | dst[count] = src[i]; +LL | | count += 1; +LL | | } + | |_____^ help: try replacing the loop by: `dst[3..(src.len() + 3)].copy_from_slice(&src[..]);` + +error: it looks like you're manually copying between slices + --> $DIR/with_loop_counters.rs:23:5 + | +LL | / for i in 0..src.len() { +LL | | dst[i] = src[count]; +LL | | count += 1; +LL | | } + | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[3..(src.len() + 3)]);` + +error: it looks like you're manually copying between slices + --> $DIR/with_loop_counters.rs:29:5 + | +LL | / for i in 3..(3 + src.len()) { +LL | | dst[i] = src[count]; +LL | | count += 1; +LL | | } + | |_____^ help: try replacing the loop by: `dst[3..(3 + src.len())].copy_from_slice(&src[..(3 + src.len() - 3)]);` + +error: it looks like you're manually copying between slices + --> $DIR/with_loop_counters.rs:35:5 + | +LL | / for i in 5..src.len() { +LL | | dst[i] = src[count - 2]; +LL | | count += 1; +LL | | } + | |_____^ help: try replacing the loop by: `dst[5..src.len()].copy_from_slice(&src[(3 - 2)..((src.len() - 2) + 3 - 5)]);` + +error: it looks like you're manually copying between slices + --> $DIR/with_loop_counters.rs:41:5 + | +LL | / for i in 0..dst.len() { +LL | | dst[i] = src[count]; +LL | | count += 1; +LL | | } + | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[2..(dst.len() + 2)]);` + +error: it looks like you're manually copying between slices + --> $DIR/with_loop_counters.rs:47:5 + | +LL | / for i in 3..10 { +LL | | dst[i] = src[count]; +LL | | count += 1; +LL | | } + | |_____^ help: try replacing the loop by: `dst[3..10].copy_from_slice(&src[5..(10 + 5 - 3)]);` + +error: it looks like you're manually copying between slices + --> $DIR/with_loop_counters.rs:54:5 + | +LL | / for i in 0..src.len() { +LL | | dst[count] = src[i]; +LL | | dst2[count2] = src[i]; +LL | | count += 1; +LL | | count2 += 1; +LL | | } + | |_____^ + | +help: try replacing the loop by + | +LL ~ dst[3..(src.len() + 3)].copy_from_slice(&src[..]); +LL + dst2[30..(src.len() + 30)].copy_from_slice(&src[..]); + | + +error: it looks like you're manually copying between slices + --> $DIR/with_loop_counters.rs:64:5 + | +LL | / for i in 0..1 << 1 { +LL | | dst[count] = src[i + 2]; +LL | | count += 1; +LL | | } + | |_____^ help: try replacing the loop by: `dst[(0 << 1)..((1 << 1) + (0 << 1))].copy_from_slice(&src[2..((1 << 1) + 2)]);` + +error: it looks like you're manually copying between slices + --> $DIR/with_loop_counters.rs:71:5 + | +LL | / for i in 3..src.len() { +LL | | dst[i] = src[count]; +LL | | count += 1 +LL | | } + | |_____^ help: try replacing the loop by: `dst[3..src.len()].copy_from_slice(&src[..(src.len() - 3)]);` + +error: aborting due to 11 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs new file mode 100644 index 000000000..ea0535d07 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs @@ -0,0 +1,136 @@ +#![warn(clippy::needless_range_loop, clippy::manual_memcpy)] + +const LOOP_OFFSET: usize = 5000; + +pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { + // plain manual memcpy + for i in 0..src.len() { + dst[i] = src[i]; + } + + // dst offset memcpy + for i in 0..src.len() { + dst[i + 10] = src[i]; + } + + // src offset memcpy + for i in 0..src.len() { + dst[i] = src[i + 10]; + } + + // src offset memcpy + for i in 11..src.len() { + dst[i] = src[i - 10]; + } + + // overwrite entire dst + for i in 0..dst.len() { + dst[i] = src[i]; + } + + // manual copy with branch - can't easily convert to memcpy! + for i in 0..src.len() { + dst[i] = src[i]; + if dst[i] > 5 { + break; + } + } + + // multiple copies - suggest two memcpy statements + for i in 10..256 { + dst[i] = src[i - 5]; + dst2[i + 500] = src[i] + } + + // this is a reversal - the copy lint shouldn't be triggered + for i in 10..LOOP_OFFSET { + dst[i + LOOP_OFFSET] = src[LOOP_OFFSET - i]; + } + + let some_var = 5; + // Offset in variable + for i in 10..LOOP_OFFSET { + dst[i + LOOP_OFFSET] = src[i - some_var]; + } + + // Non continuous copy - don't trigger lint + for i in 0..10 { + dst[i + i] = src[i]; + } + + let src_vec = vec![1, 2, 3, 4, 5]; + let mut dst_vec = vec![0, 0, 0, 0, 0]; + + // make sure vectors are supported + for i in 0..src_vec.len() { + dst_vec[i] = src_vec[i]; + } + + // lint should not trigger when either + // source or destination type is not + // slice-like, like DummyStruct + struct DummyStruct(i32); + + impl ::std::ops::Index<usize> for DummyStruct { + type Output = i32; + + fn index(&self, _: usize) -> &i32 { + &self.0 + } + } + + let src = DummyStruct(5); + let mut dst_vec = vec![0; 10]; + + for i in 0..10 { + dst_vec[i] = src[i]; + } + + // Simplify suggestion (issue #3004) + let src = [0, 1, 2, 3, 4]; + let mut dst = [0, 0, 0, 0, 0, 0]; + let from = 1; + + for i in from..from + src.len() { + dst[i] = src[i - from]; + } + + for i in from..from + 3 { + dst[i] = src[i - from]; + } + + #[allow(clippy::identity_op)] + for i in 0..5 { + dst[i - 0] = src[i]; + } + + #[allow(clippy::reversed_empty_ranges)] + for i in 0..0 { + dst[i] = src[i]; + } + + // `RangeTo` `for` loop - don't trigger lint + for i in 0.. { + dst[i] = src[i]; + } + + // VecDeque - ideally this would work, but would require something like `range_as_slices` + let mut dst = std::collections::VecDeque::from_iter([0; 5]); + let src = std::collections::VecDeque::from_iter([0, 1, 2, 3, 4]); + for i in 0..dst.len() { + dst[i] = src[i]; + } + let src = vec![0, 1, 2, 3, 4]; + for i in 0..dst.len() { + dst[i] = src[i]; + } +} + +#[warn(clippy::needless_range_loop, clippy::manual_memcpy)] +pub fn manual_clone(src: &[String], dst: &mut [String]) { + for i in 0..src.len() { + dst[i] = src[i].clone(); + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr new file mode 100644 index 000000000..c163ae061 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr @@ -0,0 +1,115 @@ +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:7:5 + | +LL | / for i in 0..src.len() { +LL | | dst[i] = src[i]; +LL | | } + | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[..]);` + | + = note: `-D clippy::manual-memcpy` implied by `-D warnings` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:12:5 + | +LL | / for i in 0..src.len() { +LL | | dst[i + 10] = src[i]; +LL | | } + | |_____^ help: try replacing the loop by: `dst[10..(src.len() + 10)].copy_from_slice(&src[..]);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:17:5 + | +LL | / for i in 0..src.len() { +LL | | dst[i] = src[i + 10]; +LL | | } + | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[10..(src.len() + 10)]);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:22:5 + | +LL | / for i in 11..src.len() { +LL | | dst[i] = src[i - 10]; +LL | | } + | |_____^ help: try replacing the loop by: `dst[11..src.len()].copy_from_slice(&src[(11 - 10)..(src.len() - 10)]);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:27:5 + | +LL | / for i in 0..dst.len() { +LL | | dst[i] = src[i]; +LL | | } + | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..dst.len()]);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:40:5 + | +LL | / for i in 10..256 { +LL | | dst[i] = src[i - 5]; +LL | | dst2[i + 500] = src[i] +LL | | } + | |_____^ + | +help: try replacing the loop by + | +LL ~ dst[10..256].copy_from_slice(&src[(10 - 5)..(256 - 5)]); +LL + dst2[(10 + 500)..(256 + 500)].copy_from_slice(&src[10..256]); + | + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:52:5 + | +LL | / for i in 10..LOOP_OFFSET { +LL | | dst[i + LOOP_OFFSET] = src[i - some_var]; +LL | | } + | |_____^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].copy_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)]);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:65:5 + | +LL | / for i in 0..src_vec.len() { +LL | | dst_vec[i] = src_vec[i]; +LL | | } + | |_____^ help: try replacing the loop by: `dst_vec[..src_vec.len()].copy_from_slice(&src_vec[..]);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:94:5 + | +LL | / for i in from..from + src.len() { +LL | | dst[i] = src[i - from]; +LL | | } + | |_____^ help: try replacing the loop by: `dst[from..(from + src.len())].copy_from_slice(&src[..(from + src.len() - from)]);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:98:5 + | +LL | / for i in from..from + 3 { +LL | | dst[i] = src[i - from]; +LL | | } + | |_____^ help: try replacing the loop by: `dst[from..(from + 3)].copy_from_slice(&src[..(from + 3 - from)]);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:103:5 + | +LL | / for i in 0..5 { +LL | | dst[i - 0] = src[i]; +LL | | } + | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src[..5]);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:108:5 + | +LL | / for i in 0..0 { +LL | | dst[i] = src[i]; +LL | | } + | |_____^ help: try replacing the loop by: `dst[..0].copy_from_slice(&src[..0]);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:131:5 + | +LL | / for i in 0..src.len() { +LL | | dst[i] = src[i].clone(); +LL | | } + | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..]);` + +error: aborting due to 13 previous errors + |