Skip to content

Commit e865dca

Browse files
committed
Auto merge of #12010 - granddaifuku:fix/manual-memcpy-indexing-for-multi-dimension-arrays, r=Alexendoo
fix: `manual_memcpy` wrong indexing for multi dimensional arrays fixes: #9334 This PR fixes an invalid suggestion for multi-dimensional arrays. For example, ```rust let src = vec![vec![0; 5]; 5]; let mut dst = vec![0; 5]; for i in 0..5 { dst[i] = src[i][i]; } ``` For the above code, Clippy suggests `dst.copy_from_slice(&src[i]);`, but it is not compilable because `i` is only used to loop the array. I adjusted it so that Clippy `manual_memcpy` works properly for multi-dimensional arrays. changelog: [`manual_memcpy`]: Fixes invalid indexing suggestions for multi-dimensional arrays
2 parents 225d377 + dfedadc commit e865dca

File tree

3 files changed

+79
-6
lines changed

3 files changed

+79
-6
lines changed

clippy_lints/src/loops/manual_memcpy.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
33
use clippy_utils::source::snippet;
44
use clippy_utils::sugg::Sugg;
55
use clippy_utils::ty::is_copy;
6+
use clippy_utils::usage::local_used_in;
67
use clippy_utils::{get_enclosing_block, higher, path_to_local, sugg};
78
use rustc_ast::ast;
89
use rustc_errors::Applicability;
@@ -63,8 +64,9 @@ pub(super) fn check<'tcx>(
6364
&& get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_right)).is_some()
6465
&& let Some((start_left, offset_left)) = get_details_from_idx(cx, idx_left, &starts)
6566
&& let Some((start_right, offset_right)) = get_details_from_idx(cx, idx_right, &starts)
66-
67-
// Source and destination must be different
67+
&& !local_used_in(cx, canonical_id, base_left)
68+
&& !local_used_in(cx, canonical_id, base_right)
69+
// Source and destination must be different
6870
&& path_to_local(base_left) != path_to_local(base_right)
6971
{
7072
Some((

tests/ui/manual_memcpy/without_loop_counters.rs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#![warn(clippy::needless_range_loop, clippy::manual_memcpy)]
2-
#![allow(clippy::useless_vec)]
1+
#![warn(clippy::manual_memcpy)]
2+
#![allow(clippy::useless_vec, clippy::needless_range_loop)]
33
//@no-rustfix
44
const LOOP_OFFSET: usize = 5000;
55

@@ -158,6 +158,59 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) {
158158
//~^ ERROR: it looks like you're manually copying between slices
159159
dst[i] = src[i];
160160
}
161+
162+
// Don't trigger lint for following multi-dimensional arrays
163+
let src = [[0; 5]; 5];
164+
for i in 0..4 {
165+
dst[i] = src[i + 1][i];
166+
}
167+
for i in 0..5 {
168+
dst[i] = src[i][i];
169+
}
170+
for i in 0..5 {
171+
dst[i] = src[i][3];
172+
}
173+
174+
let src = [0; 5];
175+
let mut dst = [[0; 5]; 5];
176+
for i in 0..5 {
177+
dst[i][i] = src[i];
178+
}
179+
180+
let src = [[[0; 5]; 5]; 5];
181+
let mut dst = [0; 5];
182+
for i in 0..5 {
183+
dst[i] = src[i][i][i];
184+
}
185+
for i in 0..5 {
186+
dst[i] = src[i][i][0];
187+
}
188+
for i in 0..5 {
189+
dst[i] = src[i][0][i];
190+
}
191+
for i in 0..5 {
192+
dst[i] = src[0][i][i];
193+
}
194+
for i in 0..5 {
195+
dst[i] = src[0][i][1];
196+
}
197+
for i in 0..5 {
198+
dst[i] = src[i][0][1];
199+
}
200+
201+
// Trigger lint
202+
let src = [[0; 5]; 5];
203+
let mut dst = [0; 5];
204+
for i in 0..5 {
205+
//~^ ERROR: it looks like you're manually copying between slices
206+
dst[i] = src[0][i];
207+
}
208+
209+
let src = [[[0; 5]; 5]; 5];
210+
for i in 0..5 {
211+
//~^ ERROR: it looks like you're manually copying between slices
212+
dst[i] = src[0][1][i];
213+
}
161214
}
162215

163216
#[warn(clippy::needless_range_loop, clippy::manual_memcpy)]

tests/ui/manual_memcpy/without_loop_counters.stderr

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,31 @@ LL | | }
145145
| |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src);`
146146

147147
error: it looks like you're manually copying between slices
148-
--> tests/ui/manual_memcpy/without_loop_counters.rs:165:5
148+
--> tests/ui/manual_memcpy/without_loop_counters.rs:204:5
149+
|
150+
LL | / for i in 0..5 {
151+
LL | |
152+
LL | | dst[i] = src[0][i];
153+
LL | | }
154+
| |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[0]);`
155+
156+
error: it looks like you're manually copying between slices
157+
--> tests/ui/manual_memcpy/without_loop_counters.rs:210:5
158+
|
159+
LL | / for i in 0..5 {
160+
LL | |
161+
LL | | dst[i] = src[0][1][i];
162+
LL | | }
163+
| |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[0][1]);`
164+
165+
error: it looks like you're manually copying between slices
166+
--> tests/ui/manual_memcpy/without_loop_counters.rs:218:5
149167
|
150168
LL | / for i in 0..src.len() {
151169
LL | |
152170
LL | | dst[i] = src[i].clone();
153171
LL | | }
154172
| |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..]);`
155173

156-
error: aborting due to 16 previous errors
174+
error: aborting due to 18 previous errors
157175

0 commit comments

Comments
 (0)