Skip to content

Commit 0337145

Browse files
authored
fix: manual_memcpy wrong indexing for multi diemnsion arrays
1 parent 370615b commit 0337145

File tree

3 files changed

+89
-4
lines changed

3 files changed

+89
-4
lines changed

clippy_lints/src/loops/manual_memcpy.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ pub(super) fn check<'tcx>(
5959
let rhs = fetch_cloned_expr(rhs);
6060
if let ExprKind::Index(base_left, idx_left, _) = lhs.kind
6161
&& let ExprKind::Index(base_right, idx_right, _) = rhs.kind
62+
&& is_index_suggestable(base_left) && is_index_suggestable(base_right)
6263
&& let Some(ty) = get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_left))
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)
@@ -486,3 +487,19 @@ fn is_array_length_equal_to_range(cx: &LateContext<'_>, start: &Expr<'_>, end: &
486487
false
487488
}
488489
}
490+
491+
// Returns true if index is suggestable
492+
// i.e. Returns false if patterns are Index(Path(_), Path(_)) or Index(Index(_, _, _), Path(_))
493+
fn is_index_suggestable(expr: &Expr<'_>) -> bool {
494+
if let ExprKind::Index(left_expr, right_expr, _) = expr.kind {
495+
// Index(Path(_), Path(_), _) returns false
496+
if matches!(left_expr.kind, ExprKind::Path(_)) {
497+
return !matches!(right_expr.kind, ExprKind::Path(_));
498+
}
499+
500+
// Nested Index pattern
501+
return is_index_suggestable(left_expr) && !matches!(right_expr.kind, ExprKind::Path(_));
502+
}
503+
504+
true
505+
}

tests/ui/manual_memcpy/without_loop_counters.rs

Lines changed: 52 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,56 @@ 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-dimension arrays
163+
let src = [[0; 5]; 5];
164+
for i in 0..5 {
165+
dst[i] = src[i][i];
166+
}
167+
for i in 0..5 {
168+
dst[i] = src[i][3];
169+
}
170+
171+
let src = [0; 5];
172+
let mut dst = [[0; 5]; 5];
173+
for i in 0..5 {
174+
dst[i][i] = src[i];
175+
}
176+
177+
let src = [[[0; 5]; 5]; 5];
178+
let mut dst = [0; 5];
179+
for i in 0..5 {
180+
dst[i] = src[i][i][i];
181+
}
182+
for i in 0..5 {
183+
dst[i] = src[i][i][0];
184+
}
185+
for i in 0..5 {
186+
dst[i] = src[i][0][i];
187+
}
188+
for i in 0..5 {
189+
dst[i] = src[0][i][i];
190+
}
191+
for i in 0..5 {
192+
dst[i] = src[0][i][1];
193+
}
194+
for i in 0..5 {
195+
dst[i] = src[i][0][1];
196+
}
197+
198+
// Trigger lint
199+
let src = [[0; 5]; 5];
200+
let mut dst = [0; 5];
201+
for i in 0..5 {
202+
//~^ ERROR: it looks like you're manually copying between slices
203+
dst[i] = src[0][i];
204+
}
205+
206+
let src = [[[0; 5]; 5]; 5];
207+
for i in 0..5 {
208+
//~^ ERROR: it looks like you're manually copying between slices
209+
dst[i] = src[0][1][i];
210+
}
161211
}
162212

163213
#[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-
--> $DIR/without_loop_counters.rs:165:5
148+
--> $DIR/without_loop_counters.rs:201: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+
--> $DIR/without_loop_counters.rs:207: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+
--> $DIR/without_loop_counters.rs:215: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)