summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_index
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_index')
-rw-r--r--compiler/rustc_index/src/bit_set.rs12
-rw-r--r--compiler/rustc_index/src/idx.rs45
-rw-r--r--compiler/rustc_index/src/interval.rs36
-rw-r--r--compiler/rustc_index/src/lib.rs7
-rw-r--r--compiler/rustc_index/src/slice.rs256
-rw-r--r--compiler/rustc_index/src/vec.rs424
6 files changed, 412 insertions, 368 deletions
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 271ab8306..15bc3b4e3 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -1,6 +1,3 @@
-use crate::vec::{Idx, IndexVec};
-use arrayvec::ArrayVec;
-use smallvec::{smallvec, SmallVec};
use std::fmt;
use std::iter;
use std::marker::PhantomData;
@@ -9,8 +6,13 @@ use std::ops::{BitAnd, BitAndAssign, BitOrAssign, Bound, Not, Range, RangeBounds
use std::rc::Rc;
use std::slice;
+use arrayvec::ArrayVec;
+use smallvec::{smallvec, SmallVec};
+
use rustc_macros::{Decodable, Encodable};
+use crate::{Idx, IndexVec};
+
use Chunk::*;
#[cfg(test)]
@@ -1542,7 +1544,7 @@ impl<T: Idx> GrowableBitSet<T> {
#[inline]
pub fn contains(&self, elem: T) -> bool {
let (word_index, mask) = word_index_and_mask(elem);
- self.bit_set.words.get(word_index).map_or(false, |word| (word & mask) != 0)
+ self.bit_set.words.get(word_index).is_some_and(|word| (word & mask) != 0)
}
#[inline]
@@ -1816,7 +1818,7 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
/// if the matrix represents (transitive) reachability, can
/// `row` reach `column`?
pub fn contains(&self, row: R, column: C) -> bool {
- self.row(row).map_or(false, |r| r.contains(column))
+ self.row(row).is_some_and(|r| r.contains(column))
}
/// Adds the bits from row `read` to the bits from row `write`, and
diff --git a/compiler/rustc_index/src/idx.rs b/compiler/rustc_index/src/idx.rs
new file mode 100644
index 000000000..b85160540
--- /dev/null
+++ b/compiler/rustc_index/src/idx.rs
@@ -0,0 +1,45 @@
+use std::fmt::Debug;
+use std::hash::Hash;
+
+/// Represents some newtyped `usize` wrapper.
+///
+/// Purpose: avoid mixing indexes for different bitvector domains.
+pub trait Idx: Copy + 'static + Eq + PartialEq + Debug + Hash {
+ fn new(idx: usize) -> Self;
+
+ fn index(self) -> usize;
+
+ #[inline]
+ fn increment_by(&mut self, amount: usize) {
+ *self = self.plus(amount);
+ }
+
+ #[inline]
+ #[must_use = "Use `increment_by` if you wanted to update the index in-place"]
+ fn plus(self, amount: usize) -> Self {
+ Self::new(self.index() + amount)
+ }
+}
+
+impl Idx for usize {
+ #[inline]
+ fn new(idx: usize) -> Self {
+ idx
+ }
+ #[inline]
+ fn index(self) -> usize {
+ self
+ }
+}
+
+impl Idx for u32 {
+ #[inline]
+ fn new(idx: usize) -> Self {
+ assert!(idx <= u32::MAX as usize);
+ idx as u32
+ }
+ #[inline]
+ fn index(self) -> usize {
+ self as usize
+ }
+}
diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs
index d809740c6..d3cf267dc 100644
--- a/compiler/rustc_index/src/interval.rs
+++ b/compiler/rustc_index/src/interval.rs
@@ -3,10 +3,11 @@ use std::marker::PhantomData;
use std::ops::RangeBounds;
use std::ops::{Bound, Range};
-use crate::vec::Idx;
-use crate::vec::IndexVec;
use smallvec::SmallVec;
+use crate::idx::Idx;
+use crate::vec::IndexVec;
+
#[cfg(test)]
mod tests;
@@ -180,6 +181,30 @@ impl<I: Idx> IntervalSet<I> {
self.map.is_empty()
}
+ /// Equivalent to `range.iter().find(|i| !self.contains(i))`.
+ pub fn first_unset_in(&self, range: impl RangeBounds<I> + Clone) -> Option<I> {
+ let start = inclusive_start(range.clone());
+ let Some(end) = inclusive_end(self.domain, range) else {
+ // empty range
+ return None;
+ };
+ if start > end {
+ return None;
+ }
+ let Some(last) = self.map.partition_point(|r| r.0 <= start).checked_sub(1) else {
+ // All ranges in the map start after the new range's end
+ return Some(I::new(start as usize));
+ };
+ let (_, prev_end) = self.map[last];
+ if start > prev_end {
+ Some(I::new(start as usize))
+ } else if prev_end < end {
+ Some(I::new(prev_end as usize + 1))
+ } else {
+ None
+ }
+ }
+
/// Returns the maximum (last) element present in the set from `range`.
pub fn last_set_in(&self, range: impl RangeBounds<I> + Clone) -> Option<I> {
let start = inclusive_start(range.clone());
@@ -223,7 +248,7 @@ impl<I: Idx> IntervalSet<I> {
fn check_invariants(&self) -> bool {
let mut current: Option<u32> = None;
for (start, end) in &self.map {
- if start > end || current.map_or(false, |x| x + 1 >= *start) {
+ if start > end || current.is_some_and(|x| x + 1 >= *start) {
return false;
}
current = Some(*end);
@@ -261,8 +286,7 @@ impl<R: Idx, C: Step + Idx> SparseIntervalMatrix<R, C> {
}
fn ensure_row(&mut self, row: R) -> &mut IntervalSet<C> {
- self.rows.ensure_contains_elem(row, || IntervalSet::new(self.column_size));
- &mut self.rows[row]
+ self.rows.ensure_contains_elem(row, || IntervalSet::new(self.column_size))
}
pub fn union_row(&mut self, row: R, from: &IntervalSet<C>) -> bool
@@ -297,6 +321,6 @@ impl<R: Idx, C: Step + Idx> SparseIntervalMatrix<R, C> {
}
pub fn contains(&self, row: R, point: C) -> bool {
- self.row(row).map_or(false, |r| r.contains(point))
+ self.row(row).is_some_and(|r| r.contains(point))
}
}
diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index db2c79152..6fd9f34b2 100644
--- a/compiler/rustc_index/src/lib.rs
+++ b/compiler/rustc_index/src/lib.rs
@@ -17,7 +17,12 @@
pub mod bit_set;
#[cfg(feature = "nightly")]
pub mod interval;
-pub mod vec;
+
+mod idx;
+mod slice;
+mod vec;
+
+pub use {idx::Idx, slice::IndexSlice, vec::IndexVec};
#[cfg(feature = "rustc_macros")]
pub use rustc_macros::newtype_index;
diff --git a/compiler/rustc_index/src/slice.rs b/compiler/rustc_index/src/slice.rs
new file mode 100644
index 000000000..0663c7247
--- /dev/null
+++ b/compiler/rustc_index/src/slice.rs
@@ -0,0 +1,256 @@
+use std::{
+ fmt,
+ marker::PhantomData,
+ ops::{Index, IndexMut},
+ slice,
+};
+
+use crate::{Idx, IndexVec};
+
+/// A view into contiguous `T`s, indexed by `I` rather than by `usize`.
+///
+/// One common pattern you'll see is code that uses [`IndexVec::from_elem`]
+/// to create the storage needed for a particular "universe" (aka the set of all
+/// the possible keys that need an associated value) then passes that working
+/// area as `&mut IndexSlice<I, T>` to clarify that nothing will be added nor
+/// removed during processing (and, as a bonus, to chase fewer pointers).
+#[derive(PartialEq, Eq, Hash)]
+#[repr(transparent)]
+pub struct IndexSlice<I: Idx, T> {
+ _marker: PhantomData<fn(&I)>,
+ pub raw: [T],
+}
+
+impl<I: Idx, T> IndexSlice<I, T> {
+ #[inline]
+ pub const fn empty() -> &'static Self {
+ Self::from_raw(&[])
+ }
+
+ #[inline]
+ pub const fn from_raw(raw: &[T]) -> &Self {
+ let ptr: *const [T] = raw;
+ // SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice
+ unsafe { &*(ptr as *const Self) }
+ }
+
+ #[inline]
+ pub fn from_raw_mut(raw: &mut [T]) -> &mut Self {
+ let ptr: *mut [T] = raw;
+ // SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice
+ unsafe { &mut *(ptr as *mut Self) }
+ }
+
+ #[inline]
+ pub const fn len(&self) -> usize {
+ self.raw.len()
+ }
+
+ #[inline]
+ pub const fn is_empty(&self) -> bool {
+ self.raw.is_empty()
+ }
+
+ /// Gives the next index that will be assigned when `push` is called.
+ ///
+ /// Manual bounds checks can be done using `idx < slice.next_index()`
+ /// (as opposed to `idx.index() < slice.len()`).
+ #[inline]
+ pub fn next_index(&self) -> I {
+ I::new(self.len())
+ }
+
+ #[inline]
+ pub fn iter(&self) -> slice::Iter<'_, T> {
+ self.raw.iter()
+ }
+
+ #[inline]
+ pub fn iter_enumerated(
+ &self,
+ ) -> impl DoubleEndedIterator<Item = (I, &T)> + ExactSizeIterator + '_ {
+ self.raw.iter().enumerate().map(|(n, t)| (I::new(n), t))
+ }
+
+ #[inline]
+ pub fn indices(
+ &self,
+ ) -> impl DoubleEndedIterator<Item = I> + ExactSizeIterator + Clone + 'static {
+ (0..self.len()).map(|n| I::new(n))
+ }
+
+ #[inline]
+ pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
+ self.raw.iter_mut()
+ }
+
+ #[inline]
+ pub fn iter_enumerated_mut(
+ &mut self,
+ ) -> impl DoubleEndedIterator<Item = (I, &mut T)> + ExactSizeIterator + '_ {
+ self.raw.iter_mut().enumerate().map(|(n, t)| (I::new(n), t))
+ }
+
+ #[inline]
+ pub fn last_index(&self) -> Option<I> {
+ self.len().checked_sub(1).map(I::new)
+ }
+
+ #[inline]
+ pub fn swap(&mut self, a: I, b: I) {
+ self.raw.swap(a.index(), b.index())
+ }
+
+ #[inline]
+ pub fn get(&self, index: I) -> Option<&T> {
+ self.raw.get(index.index())
+ }
+
+ #[inline]
+ pub fn get_mut(&mut self, index: I) -> Option<&mut T> {
+ self.raw.get_mut(index.index())
+ }
+
+ /// Returns mutable references to two distinct elements, `a` and `b`.
+ ///
+ /// Panics if `a == b`.
+ #[inline]
+ pub fn pick2_mut(&mut self, a: I, b: I) -> (&mut T, &mut T) {
+ let (ai, bi) = (a.index(), b.index());
+ assert!(ai != bi);
+
+ if ai < bi {
+ let (c1, c2) = self.raw.split_at_mut(bi);
+ (&mut c1[ai], &mut c2[0])
+ } else {
+ let (c2, c1) = self.pick2_mut(b, a);
+ (c1, c2)
+ }
+ }
+
+ /// Returns mutable references to three distinct elements.
+ ///
+ /// Panics if the elements are not distinct.
+ #[inline]
+ pub fn pick3_mut(&mut self, a: I, b: I, c: I) -> (&mut T, &mut T, &mut T) {
+ let (ai, bi, ci) = (a.index(), b.index(), c.index());
+ assert!(ai != bi && bi != ci && ci != ai);
+ let len = self.raw.len();
+ assert!(ai < len && bi < len && ci < len);
+ let ptr = self.raw.as_mut_ptr();
+ unsafe { (&mut *ptr.add(ai), &mut *ptr.add(bi), &mut *ptr.add(ci)) }
+ }
+
+ #[inline]
+ pub fn binary_search(&self, value: &T) -> Result<I, I>
+ where
+ T: Ord,
+ {
+ match self.raw.binary_search(value) {
+ Ok(i) => Ok(Idx::new(i)),
+ Err(i) => Err(Idx::new(i)),
+ }
+ }
+}
+
+impl<I: Idx, J: Idx> IndexSlice<I, J> {
+ /// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`,
+ /// assuming the values in `self` are a permutation of `0..self.len()`.
+ ///
+ /// This is used to go between `memory_index` (source field order to memory order)
+ /// and `inverse_memory_index` (memory order to source field order).
+ /// See also `FieldsShape::Arbitrary::memory_index` for more details.
+ // FIXME(eddyb) build a better abstraction for permutations, if possible.
+ pub fn invert_bijective_mapping(&self) -> IndexVec<J, I> {
+ debug_assert_eq!(
+ self.iter().map(|x| x.index() as u128).sum::<u128>(),
+ (0..self.len() as u128).sum::<u128>(),
+ "The values aren't 0..N in input {self:?}",
+ );
+
+ let mut inverse = IndexVec::from_elem_n(Idx::new(0), self.len());
+ for (i1, &i2) in self.iter_enumerated() {
+ inverse[i2] = i1;
+ }
+
+ debug_assert_eq!(
+ inverse.iter().map(|x| x.index() as u128).sum::<u128>(),
+ (0..inverse.len() as u128).sum::<u128>(),
+ "The values aren't 0..N in result {self:?}",
+ );
+
+ inverse
+ }
+}
+
+impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexSlice<I, T> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&self.raw, fmt)
+ }
+}
+
+impl<I: Idx, T> Index<I> for IndexSlice<I, T> {
+ type Output = T;
+
+ #[inline]
+ fn index(&self, index: I) -> &T {
+ &self.raw[index.index()]
+ }
+}
+
+impl<I: Idx, T> IndexMut<I> for IndexSlice<I, T> {
+ #[inline]
+ fn index_mut(&mut self, index: I) -> &mut T {
+ &mut self.raw[index.index()]
+ }
+}
+
+impl<'a, I: Idx, T> IntoIterator for &'a IndexSlice<I, T> {
+ type Item = &'a T;
+ type IntoIter = slice::Iter<'a, T>;
+
+ #[inline]
+ fn into_iter(self) -> slice::Iter<'a, T> {
+ self.raw.iter()
+ }
+}
+
+impl<'a, I: Idx, T> IntoIterator for &'a mut IndexSlice<I, T> {
+ type Item = &'a mut T;
+ type IntoIter = slice::IterMut<'a, T>;
+
+ #[inline]
+ fn into_iter(self) -> slice::IterMut<'a, T> {
+ self.raw.iter_mut()
+ }
+}
+
+impl<I: Idx, T: Clone> ToOwned for IndexSlice<I, T> {
+ type Owned = IndexVec<I, T>;
+
+ fn to_owned(&self) -> IndexVec<I, T> {
+ IndexVec::from_raw(self.raw.to_owned())
+ }
+
+ fn clone_into(&self, target: &mut IndexVec<I, T>) {
+ self.raw.clone_into(&mut target.raw)
+ }
+}
+
+impl<I: Idx, T> Default for &IndexSlice<I, T> {
+ #[inline]
+ fn default() -> Self {
+ IndexSlice::from_raw(Default::default())
+ }
+}
+
+impl<I: Idx, T> Default for &mut IndexSlice<I, T> {
+ #[inline]
+ fn default() -> Self {
+ IndexSlice::from_raw_mut(Default::default())
+ }
+}
+
+// Whether `IndexSlice` is `Send` depends only on the data,
+// not the phantom data.
+unsafe impl<I: Idx, T> Send for IndexSlice<I, T> where T: Send {}
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index ae2f52c51..99e72e49f 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -3,55 +3,13 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::borrow::{Borrow, BorrowMut};
use std::fmt;
-use std::fmt::Debug;
use std::hash::Hash;
use std::marker::PhantomData;
-use std::ops::{Deref, DerefMut, Index, IndexMut, RangeBounds};
+use std::ops::{Deref, DerefMut, RangeBounds};
use std::slice;
use std::vec;
-/// Represents some newtyped `usize` wrapper.
-///
-/// Purpose: avoid mixing indexes for different bitvector domains.
-pub trait Idx: Copy + 'static + Eq + PartialEq + Debug + Hash {
- fn new(idx: usize) -> Self;
-
- fn index(self) -> usize;
-
- #[inline]
- fn increment_by(&mut self, amount: usize) {
- *self = self.plus(amount);
- }
-
- #[inline]
- #[must_use = "Use `increment_by` if you wanted to update the index in-place"]
- fn plus(self, amount: usize) -> Self {
- Self::new(self.index() + amount)
- }
-}
-
-impl Idx for usize {
- #[inline]
- fn new(idx: usize) -> Self {
- idx
- }
- #[inline]
- fn index(self) -> usize {
- self
- }
-}
-
-impl Idx for u32 {
- #[inline]
- fn new(idx: usize) -> Self {
- assert!(idx <= u32::MAX as usize);
- idx as u32
- }
- #[inline]
- fn index(self) -> usize {
- self as usize
- }
-}
+use crate::{Idx, IndexSlice};
/// An owned contiguous collection of `T`s, indexed by `I` rather than by `usize`.
///
@@ -66,68 +24,20 @@ pub struct IndexVec<I: Idx, T> {
_marker: PhantomData<fn(&I)>,
}
-/// A view into contiguous `T`s, indexed by `I` rather than by `usize`.
-///
-/// One common pattern you'll see is code that uses [`IndexVec::from_elem`]
-/// to create the storage needed for a particular "universe" (aka the set of all
-/// the possible keys that need an associated value) then passes that working
-/// area as `&mut IndexSlice<I, T>` to clarify that nothing will be added nor
-/// removed during processing (and, as a bonus, to chase fewer pointers).
-#[derive(PartialEq, Eq, Hash)]
-#[repr(transparent)]
-pub struct IndexSlice<I: Idx, T> {
- _marker: PhantomData<fn(&I)>,
- pub raw: [T],
-}
-
-// Whether `IndexVec` is `Send` depends only on the data,
-// not the phantom data.
-unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {}
-
-// Whether `IndexSlice` is `Send` depends only on the data,
-// not the phantom data.
-unsafe impl<I: Idx, T> Send for IndexSlice<I, T> where T: Send {}
-
-#[cfg(feature = "rustc_serialize")]
-impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> {
- fn encode(&self, s: &mut S) {
- Encodable::encode(&self.raw, s);
- }
-}
-
-#[cfg(feature = "rustc_serialize")]
-impl<D: Decoder, I: Idx, T: Decodable<D>> Decodable<D> for IndexVec<I, T> {
- fn decode(d: &mut D) -> Self {
- IndexVec { raw: Decodable::decode(d), _marker: PhantomData }
- }
-}
-
-impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexVec<I, T> {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Debug::fmt(&self.raw, fmt)
- }
-}
-
-impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexSlice<I, T> {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Debug::fmt(&self.raw, fmt)
- }
-}
-
impl<I: Idx, T> IndexVec<I, T> {
#[inline]
- pub fn new() -> Self {
- IndexVec { raw: Vec::new(), _marker: PhantomData }
+ pub const fn new() -> Self {
+ IndexVec::from_raw(Vec::new())
}
#[inline]
- pub fn from_raw(raw: Vec<T>) -> Self {
+ pub const fn from_raw(raw: Vec<T>) -> Self {
IndexVec { raw, _marker: PhantomData }
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
- IndexVec { raw: Vec::with_capacity(capacity), _marker: PhantomData }
+ IndexVec::from_raw(Vec::with_capacity(capacity))
}
/// Creates a new vector with a copy of `elem` for each index in `universe`.
@@ -146,7 +56,7 @@ impl<I: Idx, T> IndexVec<I, T> {
where
T: Clone,
{
- IndexVec { raw: vec![elem; universe.len()], _marker: PhantomData }
+ IndexVec::from_raw(vec![elem; universe.len()])
}
#[inline]
@@ -154,7 +64,7 @@ impl<I: Idx, T> IndexVec<I, T> {
where
T: Clone,
{
- IndexVec { raw: vec![elem; n], _marker: PhantomData }
+ IndexVec::from_raw(vec![elem; n])
}
/// Create an `IndexVec` with `n` elements, where the value of each
@@ -162,8 +72,7 @@ impl<I: Idx, T> IndexVec<I, T> {
/// be allocated only once, with a capacity of at least `n`.)
#[inline]
pub fn from_fn_n(func: impl FnMut(I) -> T, n: usize) -> Self {
- let indices = (0..n).map(I::new);
- Self::from_raw(indices.map(func).collect())
+ IndexVec::from_raw((0..n).map(I::new).map(func).collect())
}
#[inline]
@@ -178,7 +87,7 @@ impl<I: Idx, T> IndexVec<I, T> {
#[inline]
pub fn push(&mut self, d: T) -> I {
- let idx = I::new(self.len());
+ let idx = self.next_index();
self.raw.push(d);
idx
}
@@ -229,216 +138,37 @@ impl<I: Idx, T> IndexVec<I, T> {
}
pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> {
- IndexVec { raw: self.raw, _marker: PhantomData }
+ IndexVec::from_raw(self.raw)
}
/// Grows the index vector so that it contains an entry for
/// `elem`; if that is already true, then has no
/// effect. Otherwise, inserts new values as needed by invoking
/// `fill_value`.
+ ///
+ /// Returns a reference to the `elem` entry.
#[inline]
- pub fn ensure_contains_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
+ pub fn ensure_contains_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) -> &mut T {
let min_new_len = elem.index() + 1;
if self.len() < min_new_len {
self.raw.resize_with(min_new_len, fill_value);
}
- }
-
- #[inline]
- pub fn resize_to_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
- let min_new_len = elem.index() + 1;
- self.raw.resize_with(min_new_len, fill_value);
- }
-}
-
-impl<I: Idx, T> Deref for IndexVec<I, T> {
- type Target = IndexSlice<I, T>;
-
- #[inline]
- fn deref(&self) -> &Self::Target {
- self.as_slice()
- }
-}
-
-impl<I: Idx, T> DerefMut for IndexVec<I, T> {
- #[inline]
- fn deref_mut(&mut self) -> &mut Self::Target {
- self.as_mut_slice()
- }
-}
-
-impl<I: Idx, T> Borrow<IndexSlice<I, T>> for IndexVec<I, T> {
- fn borrow(&self) -> &IndexSlice<I, T> {
- self
- }
-}
-
-impl<I: Idx, T> BorrowMut<IndexSlice<I, T>> for IndexVec<I, T> {
- fn borrow_mut(&mut self) -> &mut IndexSlice<I, T> {
- self
- }
-}
-
-impl<I: Idx, T: Clone> ToOwned for IndexSlice<I, T> {
- type Owned = IndexVec<I, T>;
-
- fn to_owned(&self) -> IndexVec<I, T> {
- IndexVec::from_raw(self.raw.to_owned())
- }
-
- fn clone_into(&self, target: &mut IndexVec<I, T>) {
- self.raw.clone_into(&mut target.raw)
- }
-}
-
-impl<I: Idx, T> IndexSlice<I, T> {
- #[inline]
- pub fn empty() -> &'static Self {
- Default::default()
- }
-
- #[inline]
- pub fn from_raw(raw: &[T]) -> &Self {
- let ptr: *const [T] = raw;
- // SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice
- unsafe { &*(ptr as *const Self) }
- }
-
- #[inline]
- pub fn from_raw_mut(raw: &mut [T]) -> &mut Self {
- let ptr: *mut [T] = raw;
- // SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice
- unsafe { &mut *(ptr as *mut Self) }
- }
-
- #[inline]
- pub fn len(&self) -> usize {
- self.raw.len()
- }
-
- /// Gives the next index that will be assigned when `push` is called.
- ///
- /// Manual bounds checks can be done using `idx < slice.next_index()`
- /// (as opposed to `idx.index() < slice.len()`).
- #[inline]
- pub fn next_index(&self) -> I {
- I::new(self.len())
- }
-
- #[inline]
- pub fn is_empty(&self) -> bool {
- self.raw.is_empty()
- }
-
- #[inline]
- pub fn iter(&self) -> slice::Iter<'_, T> {
- self.raw.iter()
- }
- #[inline]
- pub fn iter_enumerated(
- &self,
- ) -> impl DoubleEndedIterator<Item = (I, &T)> + ExactSizeIterator + '_ {
- self.raw.iter().enumerate().map(|(n, t)| (I::new(n), t))
- }
-
- #[inline]
- pub fn indices(
- &self,
- ) -> impl DoubleEndedIterator<Item = I> + ExactSizeIterator + Clone + 'static {
- (0..self.len()).map(|n| I::new(n))
- }
-
- #[inline]
- pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
- self.raw.iter_mut()
+ &mut self[elem]
}
#[inline]
- pub fn iter_enumerated_mut(
- &mut self,
- ) -> impl DoubleEndedIterator<Item = (I, &mut T)> + ExactSizeIterator + '_ {
- self.raw.iter_mut().enumerate().map(|(n, t)| (I::new(n), t))
- }
-
- #[inline]
- pub fn last_index(&self) -> Option<I> {
- self.len().checked_sub(1).map(I::new)
- }
-
- #[inline]
- pub fn swap(&mut self, a: I, b: I) {
- self.raw.swap(a.index(), b.index())
- }
-
- #[inline]
- pub fn get(&self, index: I) -> Option<&T> {
- self.raw.get(index.index())
- }
-
- #[inline]
- pub fn get_mut(&mut self, index: I) -> Option<&mut T> {
- self.raw.get_mut(index.index())
- }
-
- /// Returns mutable references to two distinct elements, `a` and `b`.
- ///
- /// Panics if `a == b`.
- #[inline]
- pub fn pick2_mut(&mut self, a: I, b: I) -> (&mut T, &mut T) {
- let (ai, bi) = (a.index(), b.index());
- assert!(ai != bi);
-
- if ai < bi {
- let (c1, c2) = self.raw.split_at_mut(bi);
- (&mut c1[ai], &mut c2[0])
- } else {
- let (c2, c1) = self.pick2_mut(b, a);
- (c1, c2)
- }
+ pub fn resize(&mut self, new_len: usize, value: T)
+ where
+ T: Clone,
+ {
+ self.raw.resize(new_len, value)
}
- /// Returns mutable references to three distinct elements.
- ///
- /// Panics if the elements are not distinct.
#[inline]
- pub fn pick3_mut(&mut self, a: I, b: I, c: I) -> (&mut T, &mut T, &mut T) {
- let (ai, bi, ci) = (a.index(), b.index(), c.index());
- assert!(ai != bi && bi != ci && ci != ai);
- let len = self.raw.len();
- assert!(ai < len && bi < len && ci < len);
- let ptr = self.raw.as_mut_ptr();
- unsafe { (&mut *ptr.add(ai), &mut *ptr.add(bi), &mut *ptr.add(ci)) }
- }
-}
-
-impl<I: Idx, J: Idx> IndexSlice<I, J> {
- /// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`,
- /// assuming the values in `self` are a permutation of `0..self.len()`.
- ///
- /// This is used to go between `memory_index` (source field order to memory order)
- /// and `inverse_memory_index` (memory order to source field order).
- /// See also `FieldsShape::Arbitrary::memory_index` for more details.
- // FIXME(eddyb) build a better abstraction for permutations, if possible.
- pub fn invert_bijective_mapping(&self) -> IndexVec<J, I> {
- debug_assert_eq!(
- self.iter().map(|x| x.index() as u128).sum::<u128>(),
- (0..self.len() as u128).sum::<u128>(),
- "The values aren't 0..N in input {self:?}",
- );
-
- let mut inverse = IndexVec::from_elem_n(Idx::new(0), self.len());
- for (i1, &i2) in self.iter_enumerated() {
- inverse[i2] = i1;
- }
-
- debug_assert_eq!(
- inverse.iter().map(|x| x.index() as u128).sum::<u128>(),
- (0..inverse.len() as u128).sum::<u128>(),
- "The values aren't 0..N in result {self:?}",
- );
-
- inverse
+ pub fn resize_to_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
+ let min_new_len = elem.index() + 1;
+ self.raw.resize_with(min_new_len, fill_value);
}
}
@@ -446,74 +176,51 @@ impl<I: Idx, J: Idx> IndexSlice<I, J> {
impl<I: Idx, T> IndexVec<I, Option<T>> {
#[inline]
pub fn insert(&mut self, index: I, value: T) -> Option<T> {
- self.ensure_contains_elem(index, || None);
- self[index].replace(value)
+ self.ensure_contains_elem(index, || None).replace(value)
}
#[inline]
pub fn get_or_insert_with(&mut self, index: I, value: impl FnOnce() -> T) -> &mut T {
- self.ensure_contains_elem(index, || None);
- self[index].get_or_insert_with(value)
+ self.ensure_contains_elem(index, || None).get_or_insert_with(value)
}
#[inline]
pub fn remove(&mut self, index: I) -> Option<T> {
- self.ensure_contains_elem(index, || None);
- self[index].take()
- }
-}
-
-impl<I: Idx, T: Clone> IndexVec<I, T> {
- #[inline]
- pub fn resize(&mut self, new_len: usize, value: T) {
- self.raw.resize(new_len, value)
+ self.get_mut(index)?.take()
}
}
-impl<I: Idx, T: Ord> IndexSlice<I, T> {
- #[inline]
- pub fn binary_search(&self, value: &T) -> Result<I, I> {
- match self.raw.binary_search(value) {
- Ok(i) => Ok(Idx::new(i)),
- Err(i) => Err(Idx::new(i)),
- }
+impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexVec<I, T> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&self.raw, fmt)
}
}
-impl<I: Idx, T> Index<I> for IndexSlice<I, T> {
- type Output = T;
-
- #[inline]
- fn index(&self, index: I) -> &T {
- &self.raw[index.index()]
- }
-}
+impl<I: Idx, T> Deref for IndexVec<I, T> {
+ type Target = IndexSlice<I, T>;
-impl<I: Idx, T> IndexMut<I> for IndexSlice<I, T> {
#[inline]
- fn index_mut(&mut self, index: I) -> &mut T {
- &mut self.raw[index.index()]
+ fn deref(&self) -> &Self::Target {
+ self.as_slice()
}
}
-impl<I: Idx, T> Default for IndexVec<I, T> {
+impl<I: Idx, T> DerefMut for IndexVec<I, T> {
#[inline]
- fn default() -> Self {
- Self::new()
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ self.as_mut_slice()
}
}
-impl<I: Idx, T> Default for &IndexSlice<I, T> {
- #[inline]
- fn default() -> Self {
- IndexSlice::from_raw(Default::default())
+impl<I: Idx, T> Borrow<IndexSlice<I, T>> for IndexVec<I, T> {
+ fn borrow(&self) -> &IndexSlice<I, T> {
+ self
}
}
-impl<I: Idx, T> Default for &mut IndexSlice<I, T> {
- #[inline]
- fn default() -> Self {
- IndexSlice::from_raw_mut(Default::default())
+impl<I: Idx, T> BorrowMut<IndexSlice<I, T>> for IndexVec<I, T> {
+ fn borrow_mut(&mut self) -> &mut IndexSlice<I, T> {
+ self
}
}
@@ -542,14 +249,7 @@ impl<I: Idx, T> FromIterator<T> for IndexVec<I, T> {
where
J: IntoIterator<Item = T>,
{
- IndexVec { raw: FromIterator::from_iter(iter), _marker: PhantomData }
- }
-}
-
-impl<I: Idx, T, const N: usize> From<[T; N]> for IndexVec<I, T> {
- #[inline]
- fn from(array: [T; N]) -> Self {
- IndexVec::from_raw(array.into())
+ IndexVec::from_raw(Vec::from_iter(iter))
}
}
@@ -569,7 +269,7 @@ impl<'a, I: Idx, T> IntoIterator for &'a IndexVec<I, T> {
#[inline]
fn into_iter(self) -> slice::Iter<'a, T> {
- self.raw.iter()
+ self.iter()
}
}
@@ -579,29 +279,41 @@ impl<'a, I: Idx, T> IntoIterator for &'a mut IndexVec<I, T> {
#[inline]
fn into_iter(self) -> slice::IterMut<'a, T> {
- self.raw.iter_mut()
+ self.iter_mut()
}
}
-impl<'a, I: Idx, T> IntoIterator for &'a IndexSlice<I, T> {
- type Item = &'a T;
- type IntoIter = slice::Iter<'a, T>;
+impl<I: Idx, T> Default for IndexVec<I, T> {
+ #[inline]
+ fn default() -> Self {
+ IndexVec::new()
+ }
+}
+impl<I: Idx, T, const N: usize> From<[T; N]> for IndexVec<I, T> {
#[inline]
- fn into_iter(self) -> slice::Iter<'a, T> {
- self.raw.iter()
+ fn from(array: [T; N]) -> Self {
+ IndexVec::from_raw(array.into())
}
}
-impl<'a, I: Idx, T> IntoIterator for &'a mut IndexSlice<I, T> {
- type Item = &'a mut T;
- type IntoIter = slice::IterMut<'a, T>;
+#[cfg(feature = "rustc_serialize")]
+impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> {
+ fn encode(&self, s: &mut S) {
+ Encodable::encode(&self.raw, s);
+ }
+}
- #[inline]
- fn into_iter(self) -> slice::IterMut<'a, T> {
- self.raw.iter_mut()
+#[cfg(feature = "rustc_serialize")]
+impl<D: Decoder, I: Idx, T: Decodable<D>> Decodable<D> for IndexVec<I, T> {
+ fn decode(d: &mut D) -> Self {
+ IndexVec::from_raw(Vec::<T>::decode(d))
}
}
+// Whether `IndexVec` is `Send` depends only on the data,
+// not the phantom data.
+unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {}
+
#[cfg(test)]
mod tests;