diff options
| -rw-r--r-- | clippy_lints/src/loops/manual_slice_fill.rs | 4 | ||||
| -rw-r--r-- | clippy_utils/src/ty/mod.rs | 7 | ||||
| -rw-r--r-- | tests/ui/manual_slice_fill.fixed | 37 | ||||
| -rw-r--r-- | tests/ui/manual_slice_fill.rs | 37 |
4 files changed, 84 insertions, 1 deletions
diff --git a/clippy_lints/src/loops/manual_slice_fill.rs b/clippy_lints/src/loops/manual_slice_fill.rs index 343f7c5d2d1..15c656cc7bc 100644 --- a/clippy_lints/src/loops/manual_slice_fill.rs +++ b/clippy_lints/src/loops/manual_slice_fill.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::eager_or_lazy::switch_to_eager_eval; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{HasSession, snippet_with_applicability}; -use clippy_utils::ty::implements_trait; +use clippy_utils::ty::{implements_trait, is_slice_like}; use clippy_utils::visitors::is_local_used; use clippy_utils::{higher, peel_blocks_with_stmt, span_contains_comment}; use rustc_ast::ast::LitKind; @@ -58,6 +58,8 @@ pub(super) fn check<'tcx>( && let Res::Local(idx_hir) = idx_path.res && !is_local_used(cx, assignval, idx_hir) && msrv.meets(cx, msrvs::SLICE_FILL) + && let slice_ty = cx.typeck_results().expr_ty(slice).peel_refs() + && is_slice_like(cx, slice_ty) { sugg(cx, body, expr, slice.span, assignval.span); } diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index d30acfb75f3..db723312695 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -1369,3 +1369,10 @@ pub fn has_non_owning_mutable_access<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<' let mut phantoms = FxHashSet::default(); has_non_owning_mutable_access_inner(cx, &mut phantoms, iter_ty) } + +/// Check if `ty` is slice-like, i.e., `&[T]`, `[T; N]`, or `Vec<T>`. +pub fn is_slice_like<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + ty.is_slice() + || ty.is_array() + || matches!(ty.kind(), ty::Adt(adt_def, _) if cx.tcx.is_diagnostic_item(sym::Vec, adt_def.did())) +} diff --git a/tests/ui/manual_slice_fill.fixed b/tests/ui/manual_slice_fill.fixed index bba863247f5..d07d1d60e2c 100644 --- a/tests/ui/manual_slice_fill.fixed +++ b/tests/ui/manual_slice_fill.fixed @@ -123,3 +123,40 @@ fn issue14189() { *b = !*b; } } + +mod issue14685 { + use std::ops::{Index, IndexMut}; + + #[derive(Clone)] + struct ZipList<T>(T); + + impl<T> ZipList<T> { + fn len(&self) -> usize { + todo!() + } + + fn is_empty(&self) -> bool { + todo!() + } + } + + impl<T> Index<usize> for ZipList<T> { + type Output = T; + + fn index(&self, _: usize) -> &Self::Output { + todo!() + } + } + + impl<T> IndexMut<usize> for ZipList<T> { + fn index_mut(&mut self, _: usize) -> &mut Self::Output { + todo!() + } + } + + fn index_mut(mut zl: ZipList<usize>) { + for i in 0..zl.len() { + zl[i] = 6; + } + } +} diff --git a/tests/ui/manual_slice_fill.rs b/tests/ui/manual_slice_fill.rs index 44c60dc40f0..c74ab2225c0 100644 --- a/tests/ui/manual_slice_fill.rs +++ b/tests/ui/manual_slice_fill.rs @@ -136,3 +136,40 @@ fn issue14189() { *b = !*b; } } + +mod issue14685 { + use std::ops::{Index, IndexMut}; + + #[derive(Clone)] + struct ZipList<T>(T); + + impl<T> ZipList<T> { + fn len(&self) -> usize { + todo!() + } + + fn is_empty(&self) -> bool { + todo!() + } + } + + impl<T> Index<usize> for ZipList<T> { + type Output = T; + + fn index(&self, _: usize) -> &Self::Output { + todo!() + } + } + + impl<T> IndexMut<usize> for ZipList<T> { + fn index_mut(&mut self, _: usize) -> &mut Self::Output { + todo!() + } + } + + fn index_mut(mut zl: ZipList<usize>) { + for i in 0..zl.len() { + zl[i] = 6; + } + } +} |
