rustc_index/
slice.rs

1use std::fmt;
2use std::marker::PhantomData;
3use std::ops::{Index, IndexMut, RangeBounds};
4use std::slice::GetDisjointMutError::*;
5use std::slice::{self, SliceIndex};
6
7use crate::{Idx, IndexVec, IntoSliceIdx};
8
9/// A view into contiguous `T`s, indexed by `I` rather than by `usize`.
10///
11/// One common pattern you'll see is code that uses [`IndexVec::from_elem`]
12/// to create the storage needed for a particular "universe" (aka the set of all
13/// the possible keys that need an associated value) then passes that working
14/// area as `&mut IndexSlice<I, T>` to clarify that nothing will be added nor
15/// removed during processing (and, as a bonus, to chase fewer pointers).
16#[derive(PartialEq, Eq, Hash)]
17#[repr(transparent)]
18pub struct IndexSlice<I: Idx, T> {
19    _marker: PhantomData<fn(&I)>,
20    pub raw: [T],
21}
22
23impl<I: Idx, T> IndexSlice<I, T> {
24    #[inline]
25    pub const fn empty<'a>() -> &'a Self {
26        Self::from_raw(&[])
27    }
28
29    #[inline]
30    pub const fn from_raw(raw: &[T]) -> &Self {
31        let ptr: *const [T] = raw;
32        // SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice
33        unsafe { &*(ptr as *const Self) }
34    }
35
36    #[inline]
37    pub fn from_raw_mut(raw: &mut [T]) -> &mut Self {
38        let ptr: *mut [T] = raw;
39        // SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice
40        unsafe { &mut *(ptr as *mut Self) }
41    }
42
43    #[inline]
44    pub const fn len(&self) -> usize {
45        self.raw.len()
46    }
47
48    #[inline]
49    pub const fn is_empty(&self) -> bool {
50        self.raw.is_empty()
51    }
52
53    /// Gives the next index that will be assigned when `push` is called.
54    ///
55    /// Manual bounds checks can be done using `idx < slice.next_index()`
56    /// (as opposed to `idx.index() < slice.len()`).
57    #[inline]
58    pub fn next_index(&self) -> I {
59        I::new(self.len())
60    }
61
62    #[inline]
63    pub fn iter(&self) -> slice::Iter<'_, T> {
64        self.raw.iter()
65    }
66
67    #[inline]
68    pub fn iter_enumerated(&self) -> impl DoubleEndedIterator<Item = (I, &T)> + ExactSizeIterator {
69        // Allow the optimizer to elide the bounds checking when creating each index.
70        let _ = I::new(self.len());
71        self.raw.iter().enumerate().map(|(n, t)| (I::new(n), t))
72    }
73
74    #[inline]
75    pub fn indices(
76        &self,
77    ) -> impl DoubleEndedIterator<Item = I> + ExactSizeIterator + Clone + 'static {
78        // Allow the optimizer to elide the bounds checking when creating each index.
79        let _ = I::new(self.len());
80        (0..self.len()).map(|n| I::new(n))
81    }
82
83    #[inline]
84    pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
85        self.raw.iter_mut()
86    }
87
88    #[inline]
89    pub fn iter_enumerated_mut(
90        &mut self,
91    ) -> impl DoubleEndedIterator<Item = (I, &mut T)> + ExactSizeIterator {
92        // Allow the optimizer to elide the bounds checking when creating each index.
93        let _ = I::new(self.len());
94        self.raw.iter_mut().enumerate().map(|(n, t)| (I::new(n), t))
95    }
96
97    #[inline]
98    pub fn last_index(&self) -> Option<I> {
99        self.len().checked_sub(1).map(I::new)
100    }
101
102    #[inline]
103    pub fn swap(&mut self, a: I, b: I) {
104        self.raw.swap(a.index(), b.index())
105    }
106
107    #[inline]
108    pub fn copy_within(
109        &mut self,
110        src: impl IntoSliceIdx<I, [T], Output: RangeBounds<usize>>,
111        dest: I,
112    ) where
113        T: Copy,
114    {
115        self.raw.copy_within(src.into_slice_idx(), dest.index());
116    }
117
118    #[inline]
119    pub fn get<R: IntoSliceIdx<I, [T]>>(
120        &self,
121        index: R,
122    ) -> Option<&<R::Output as SliceIndex<[T]>>::Output> {
123        self.raw.get(index.into_slice_idx())
124    }
125
126    #[inline]
127    pub fn get_mut<R: IntoSliceIdx<I, [T]>>(
128        &mut self,
129        index: R,
130    ) -> Option<&mut <R::Output as SliceIndex<[T]>>::Output> {
131        self.raw.get_mut(index.into_slice_idx())
132    }
133
134    /// Returns mutable references to two distinct elements, `a` and `b`.
135    ///
136    /// Panics if `a == b` or if some of them are out of bounds.
137    #[inline]
138    pub fn pick2_mut(&mut self, a: I, b: I) -> (&mut T, &mut T) {
139        let (ai, bi) = (a.index(), b.index());
140
141        match self.raw.get_disjoint_mut([ai, bi]) {
142            Ok([a, b]) => (a, b),
143            Err(OverlappingIndices) => panic!("Indices {ai:?} and {bi:?} are not disjoint!"),
144            Err(IndexOutOfBounds) => {
145                panic!("Some indices among ({ai:?}, {bi:?}) are out of bounds")
146            }
147        }
148    }
149
150    /// Returns mutable references to three distinct elements.
151    ///
152    /// Panics if the elements are not distinct or if some of them are out of bounds.
153    #[inline]
154    pub fn pick3_mut(&mut self, a: I, b: I, c: I) -> (&mut T, &mut T, &mut T) {
155        let (ai, bi, ci) = (a.index(), b.index(), c.index());
156
157        match self.raw.get_disjoint_mut([ai, bi, ci]) {
158            Ok([a, b, c]) => (a, b, c),
159            Err(OverlappingIndices) => {
160                panic!("Indices {ai:?}, {bi:?} and {ci:?} are not disjoint!")
161            }
162            Err(IndexOutOfBounds) => {
163                panic!("Some indices among ({ai:?}, {bi:?}, {ci:?}) are out of bounds")
164            }
165        }
166    }
167
168    #[inline]
169    pub fn binary_search(&self, value: &T) -> Result<I, I>
170    where
171        T: Ord,
172    {
173        match self.raw.binary_search(value) {
174            Ok(i) => Ok(Idx::new(i)),
175            Err(i) => Err(Idx::new(i)),
176        }
177    }
178}
179
180impl<I: Idx, J: Idx> IndexSlice<I, J> {
181    /// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`,
182    /// assuming the values in `self` are a permutation of `0..self.len()`.
183    ///
184    /// This is used to go between `memory_index` (source field order to memory order)
185    /// and `inverse_memory_index` (memory order to source field order).
186    /// See also `FieldsShape::Arbitrary::memory_index` for more details.
187    // FIXME(eddyb) build a better abstraction for permutations, if possible.
188    pub fn invert_bijective_mapping(&self) -> IndexVec<J, I> {
189        debug_assert_eq!(
190            self.iter().map(|x| x.index() as u128).sum::<u128>(),
191            (0..self.len() as u128).sum::<u128>(),
192            "The values aren't 0..N in input {self:?}",
193        );
194
195        let mut inverse = IndexVec::from_elem_n(Idx::new(0), self.len());
196        for (i1, &i2) in self.iter_enumerated() {
197            inverse[i2] = i1;
198        }
199
200        debug_assert_eq!(
201            inverse.iter().map(|x| x.index() as u128).sum::<u128>(),
202            (0..inverse.len() as u128).sum::<u128>(),
203            "The values aren't 0..N in result {self:?}",
204        );
205
206        inverse
207    }
208}
209
210impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexSlice<I, T> {
211    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
212        fmt::Debug::fmt(&self.raw, fmt)
213    }
214}
215
216impl<I: Idx, T, R: IntoSliceIdx<I, [T]>> Index<R> for IndexSlice<I, T> {
217    type Output = <R::Output as SliceIndex<[T]>>::Output;
218
219    #[inline]
220    fn index(&self, index: R) -> &Self::Output {
221        &self.raw[index.into_slice_idx()]
222    }
223}
224
225impl<I: Idx, T, R: IntoSliceIdx<I, [T]>> IndexMut<R> for IndexSlice<I, T> {
226    #[inline]
227    fn index_mut(&mut self, index: R) -> &mut Self::Output {
228        &mut self.raw[index.into_slice_idx()]
229    }
230}
231
232impl<'a, I: Idx, T> IntoIterator for &'a IndexSlice<I, T> {
233    type Item = &'a T;
234    type IntoIter = slice::Iter<'a, T>;
235
236    #[inline]
237    fn into_iter(self) -> slice::Iter<'a, T> {
238        self.raw.iter()
239    }
240}
241
242impl<'a, I: Idx, T> IntoIterator for &'a mut IndexSlice<I, T> {
243    type Item = &'a mut T;
244    type IntoIter = slice::IterMut<'a, T>;
245
246    #[inline]
247    fn into_iter(self) -> slice::IterMut<'a, T> {
248        self.raw.iter_mut()
249    }
250}
251
252impl<I: Idx, T: Clone> ToOwned for IndexSlice<I, T> {
253    type Owned = IndexVec<I, T>;
254
255    fn to_owned(&self) -> IndexVec<I, T> {
256        IndexVec::from_raw(self.raw.to_owned())
257    }
258
259    fn clone_into(&self, target: &mut IndexVec<I, T>) {
260        self.raw.clone_into(&mut target.raw)
261    }
262}
263
264impl<I: Idx, T> Default for &IndexSlice<I, T> {
265    #[inline]
266    fn default() -> Self {
267        IndexSlice::from_raw(Default::default())
268    }
269}
270
271impl<I: Idx, T> Default for &mut IndexSlice<I, T> {
272    #[inline]
273    fn default() -> Self {
274        IndexSlice::from_raw_mut(Default::default())
275    }
276}
277
278// Whether `IndexSlice` is `Send` depends only on the data,
279// not the phantom data.
280unsafe impl<I: Idx, T> Send for IndexSlice<I, T> where T: Send {}