From f70f19c7946c0d3dd8ac3c121c03975f6e056274 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Tue, 3 Nov 2026 00:02:49 +0100 Subject: [PATCH] Implement `Index` and `IndexMut` for `Vec` While it's already possible to use index syntax (e.g. `v[1]`) on `Vec` due to `Deref` coercion into slice, it's nevertheless useful to have `Index` and `IndexMut` traits implemented if you want to have code that is generic over indexable containers via trait bounds, like in this snippet: ``` fn increment(container: &mut C, index: usize) where C: std::ops::IndexMut, C::Output: std::ops::AddAssign, { container[index] += 1; } ``` Having these traits is consistent with Rust standard library's `Vec`, which also implements them. There are also other collections that could implement `Index` or `IndexMut`. If this PR is accepted, I will follow up with implementations for these as well. --- CHANGELOG.md | 1 + src/vec/mod.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d207e55c..f710f83b05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Limited max size of `IndexMap` to u16::MAX + 1. The implementation for sizes higher than u16::MAX were unsound anyway. - Added `shift_remove`, `shift_remove_entry` and `shift_remove_full` to `IndexMap` and `IndexSet`. +- Implemented `Index` and `IndexMut` for `Vec`. ## [v0.9.3] 2025-04-15 diff --git a/src/vec/mod.rs b/src/vec/mod.rs index 4ffeac8b60..1a6a804ca8 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -1813,6 +1813,28 @@ where } } +impl + ?Sized> ops::Index for VecInner +where + I: slice::SliceIndex<[T]>, +{ + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { + ops::Index::index(self.as_slice(), index) + } +} + +impl + ?Sized> ops::IndexMut for VecInner +where + I: slice::SliceIndex<[T]>, +{ + #[inline] + fn index_mut(&mut self, index: I) -> &mut Self::Output { + ops::IndexMut::index_mut(self.as_mut_slice(), index) + } +} + impl + ?Sized> ops::Deref for VecInner { type Target = [T]; @@ -1900,6 +1922,37 @@ mod tests { let mut _v: Vec = Vec::new(); } + #[test] + fn index() { + let mut v: Vec = Vec::from_array([1, 2, 3]); + assert_eq!(v[1], 2); + v[1] = 9; + assert_eq!(v[1], 9); + + // Now we test if code using `Index` and `IndexMut` trait bounds + // actually works. + + fn increment(container: &mut C, index: usize) + where + C: std::ops::IndexMut, + C::Output: std::ops::AddAssign, + { + container[index] += 1; + } + + increment(&mut v, 1); + assert_eq!(v[1], 10); + + fn get(container: &mut C, index: usize) -> &>::Output + where + C: std::ops::Index, + { + &container[index] + } + + assert_eq!(*get(&mut v, 1), 10); + } + #[test] fn is_full_empty() { let mut v: Vec = Vec::new();