Skip to content

Commit 6cf00e9

Browse files
committed
fix: needless_range_loop FP on array literals
1 parent ae8ff77 commit 6cf00e9

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

clippy_lints/src/loops/needless_range_loop.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,21 @@ pub(super) fn check<'tcx>(
3939
var: canonical_id,
4040
indexed_mut: FxHashSet::default(),
4141
indexed_indirectly: FxHashMap::default(),
42+
unnamed_indexed_indirectly: false,
4243
indexed_directly: FxIndexMap::default(),
44+
unnamed_indexed_directly: false,
4345
referenced: FxHashSet::default(),
4446
nonindex: false,
4547
prefer_mutable: false,
4648
};
4749
walk_expr(&mut visitor, body);
4850

4951
// linting condition: we only indexed one variable, and indexed it directly
50-
if visitor.indexed_indirectly.is_empty() && visitor.indexed_directly.len() == 1 {
52+
if visitor.indexed_indirectly.is_empty()
53+
&& !visitor.unnamed_indexed_indirectly
54+
&& !visitor.unnamed_indexed_directly
55+
&& visitor.indexed_directly.len() == 1
56+
{
5157
let (indexed, (indexed_extent, indexed_ty)) = visitor
5258
.indexed_directly
5359
.into_iter()
@@ -217,6 +223,7 @@ fn is_end_eq_array_len<'tcx>(
217223
false
218224
}
219225

226+
#[expect(clippy::struct_excessive_bools)]
220227
struct VarVisitor<'a, 'tcx> {
221228
/// context reference
222229
cx: &'a LateContext<'tcx>,
@@ -226,9 +233,13 @@ struct VarVisitor<'a, 'tcx> {
226233
indexed_mut: FxHashSet<Symbol>,
227234
/// indirectly indexed variables (`v[(i + 4) % N]`), the extend is `None` for global
228235
indexed_indirectly: FxHashMap<Symbol, Option<region::Scope>>,
236+
/// indirectly indexed literals, like `[1, 2, 3][(i + 4) % N]`
237+
unnamed_indexed_indirectly: bool,
229238
/// subset of `indexed` of vars that are indexed directly: `v[i]`
230239
/// this will not contain cases like `v[calc_index(i)]` or `v[(i + 4) % N]`
231240
indexed_directly: FxIndexMap<Symbol, (Option<region::Scope>, Ty<'tcx>)>,
241+
/// directly indexed literals, like `[1, 2, 3][i]`
242+
unnamed_indexed_directly: bool,
232243
/// Any names that are used outside an index operation.
233244
/// Used to detect things like `&mut vec` used together with `vec[i]`
234245
referenced: FxHashSet<Symbol>,
@@ -242,6 +253,7 @@ struct VarVisitor<'a, 'tcx> {
242253

243254
impl<'tcx> VarVisitor<'_, 'tcx> {
244255
fn check(&mut self, idx: &'tcx Expr<'_>, seqexpr: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) -> bool {
256+
let index_used_directly = matches!(idx.kind, ExprKind::Path(_));
245257
if let ExprKind::Path(ref seqpath) = seqexpr.kind
246258
// the indexed container is referenced by a name
247259
&& let QPath::Resolved(None, seqvar) = *seqpath
@@ -251,7 +263,6 @@ impl<'tcx> VarVisitor<'_, 'tcx> {
251263
if self.prefer_mutable {
252264
self.indexed_mut.insert(seqvar.segments[0].ident.name);
253265
}
254-
let index_used_directly = matches!(idx.kind, ExprKind::Path(_));
255266
let res = self.cx.qpath_res(seqpath, seqexpr.hir_id);
256267
match res {
257268
Res::Local(hir_id) => {
@@ -286,6 +297,13 @@ impl<'tcx> VarVisitor<'_, 'tcx> {
286297
},
287298
_ => (),
288299
}
300+
} else if let ExprKind::Repeat(..) | ExprKind::Array(..) = seqexpr.kind {
301+
if index_used_directly {
302+
self.unnamed_indexed_directly = true;
303+
} else {
304+
self.unnamed_indexed_indirectly = true;
305+
}
306+
return false;
289307
}
290308
true
291309
}

tests/ui/needless_range_loop.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,28 @@ mod issue_2496 {
185185
unimplemented!()
186186
}
187187
}
188+
189+
fn needless_loop() {
190+
use std::hint::black_box;
191+
let x = [0; 64];
192+
for i in 0..64 {
193+
let y = [0; 64];
194+
195+
black_box(x[i]);
196+
black_box(y[i]);
197+
}
198+
199+
for i in 0..64 {
200+
black_box(x[i]);
201+
black_box([0; 64][i]);
202+
}
203+
204+
for i in 0..64 {
205+
black_box(x[i]);
206+
black_box([1, 2, 3, 4, 5, 6, 7, 8][i]);
207+
}
208+
209+
for i in 0..64 {
210+
black_box([1, 2, 3, 4, 5, 6, 7, 8][i]);
211+
}
212+
}

0 commit comments

Comments
 (0)