Skip to content

Commit 56f0182

Browse files
authored
fix: manual_slice_fill FP on IndexMut overload (#14719)
Closes #14685 changelog: [`manual_slice_fill`] fix FP on `IndexMut` overload
2 parents fb9508d + 33ea0b4 commit 56f0182

File tree

4 files changed

+84
-1
lines changed

4 files changed

+84
-1
lines changed

clippy_lints/src/loops/manual_slice_fill.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
33
use clippy_utils::msrvs::{self, Msrv};
44
use clippy_utils::source::{HasSession, snippet_with_applicability};
5-
use clippy_utils::ty::implements_trait;
5+
use clippy_utils::ty::{implements_trait, is_slice_like};
66
use clippy_utils::visitors::is_local_used;
77
use clippy_utils::{higher, peel_blocks_with_stmt, span_contains_comment};
88
use rustc_ast::ast::LitKind;
@@ -58,6 +58,8 @@ pub(super) fn check<'tcx>(
5858
&& let Res::Local(idx_hir) = idx_path.res
5959
&& !is_local_used(cx, assignval, idx_hir)
6060
&& msrv.meets(cx, msrvs::SLICE_FILL)
61+
&& let slice_ty = cx.typeck_results().expr_ty(slice).peel_refs()
62+
&& is_slice_like(cx, slice_ty)
6163
{
6264
sugg(cx, body, expr, slice.span, assignval.span);
6365
}

clippy_utils/src/ty/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1369,3 +1369,10 @@ pub fn has_non_owning_mutable_access<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'
13691369
let mut phantoms = FxHashSet::default();
13701370
has_non_owning_mutable_access_inner(cx, &mut phantoms, iter_ty)
13711371
}
1372+
1373+
/// Check if `ty` is slice-like, i.e., `&[T]`, `[T; N]`, or `Vec<T>`.
1374+
pub fn is_slice_like<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
1375+
ty.is_slice()
1376+
|| ty.is_array()
1377+
|| matches!(ty.kind(), ty::Adt(adt_def, _) if cx.tcx.is_diagnostic_item(sym::Vec, adt_def.did()))
1378+
}

tests/ui/manual_slice_fill.fixed

+37
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,40 @@ fn issue14189() {
123123
*b = !*b;
124124
}
125125
}
126+
127+
mod issue14685 {
128+
use std::ops::{Index, IndexMut};
129+
130+
#[derive(Clone)]
131+
struct ZipList<T>(T);
132+
133+
impl<T> ZipList<T> {
134+
fn len(&self) -> usize {
135+
todo!()
136+
}
137+
138+
fn is_empty(&self) -> bool {
139+
todo!()
140+
}
141+
}
142+
143+
impl<T> Index<usize> for ZipList<T> {
144+
type Output = T;
145+
146+
fn index(&self, _: usize) -> &Self::Output {
147+
todo!()
148+
}
149+
}
150+
151+
impl<T> IndexMut<usize> for ZipList<T> {
152+
fn index_mut(&mut self, _: usize) -> &mut Self::Output {
153+
todo!()
154+
}
155+
}
156+
157+
fn index_mut(mut zl: ZipList<usize>) {
158+
for i in 0..zl.len() {
159+
zl[i] = 6;
160+
}
161+
}
162+
}

tests/ui/manual_slice_fill.rs

+37
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,40 @@ fn issue14189() {
136136
*b = !*b;
137137
}
138138
}
139+
140+
mod issue14685 {
141+
use std::ops::{Index, IndexMut};
142+
143+
#[derive(Clone)]
144+
struct ZipList<T>(T);
145+
146+
impl<T> ZipList<T> {
147+
fn len(&self) -> usize {
148+
todo!()
149+
}
150+
151+
fn is_empty(&self) -> bool {
152+
todo!()
153+
}
154+
}
155+
156+
impl<T> Index<usize> for ZipList<T> {
157+
type Output = T;
158+
159+
fn index(&self, _: usize) -> &Self::Output {
160+
todo!()
161+
}
162+
}
163+
164+
impl<T> IndexMut<usize> for ZipList<T> {
165+
fn index_mut(&mut self, _: usize) -> &mut Self::Output {
166+
todo!()
167+
}
168+
}
169+
170+
fn index_mut(mut zl: ZipList<usize>) {
171+
for i in 0..zl.len() {
172+
zl[i] = 6;
173+
}
174+
}
175+
}

0 commit comments

Comments
 (0)