+define_index!(LiveRangeIdx);
+
+pub trait Entries<'a, I>: Index<I>
+where
+ I: IndexTy,
+ Self::Output: 'a,
+{
+ type Iter: Iterator<Item = (I, &'a Self::Output)>
+ + DoubleEndedIterator
+ + ExactSizeIterator
+ + FusedIterator;
+ fn entries(&'a self) -> Self::Iter;
+ fn keys(&'a self) -> RangeIter<I>;
+}
+
+pub trait EntriesMut<'a, I>: Entries<'a, I> + IndexMut<I>
+where
+ I: IndexTy,
+ Self::Output: 'a,
+{
+ type IterMut: Iterator<Item = (I, &'a mut Self::Output)>
+ + DoubleEndedIterator
+ + ExactSizeIterator
+ + FusedIterator;
+ fn entries_mut(&'a mut self) -> Self::IterMut;
+}
+
+pub trait TryIndex<I>: for<'a> Entries<'a, I>
+where
+ I: IndexTy,
+{
+ type Error;
+ fn try_index(&self, idx: I) -> Result<&Self::Output, Self::Error>;
+}
+
+pub trait TryIndexMut<I>: TryIndex<I> + for<'a> EntriesMut<'a, I>
+where
+ I: IndexTy,
+{
+ fn try_index_mut(&mut self, idx: I) -> Result<&mut Self::Output, Self::Error>;
+}
+
+macro_rules! impl_index {
+ (
+ #[$(error = $Error:ident, )?iter = $Iter:ident, iter_mut = $IterMut:ident]
+ impl Index<$I:ty> for Vec<$T:ty> {}
+ ) => {
+ #[derive(Clone, Debug)]
+ pub struct $Iter<'a> {
+ iter: std::iter::Enumerate<std::slice::Iter<'a, $T>>,
+ }
+
+ impl<'a> Iterator for $Iter<'a> {
+ type Item = ($I, &'a $T);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(|(i, v)| (<$I>::new(i), v))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter
+ .fold(init, move |a, (i, v)| f(a, (<$I>::new(i), v)))
+ }
+ }
+
+ impl DoubleEndedIterator for $Iter<'_> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back().map(|(i, v)| (<$I>::new(i), v))
+ }
+
+ fn rfold<B, F>(self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter
+ .rfold(init, move |a, (i, v)| f(a, (<$I>::new(i), v)))
+ }
+ }
+
+ impl ExactSizeIterator for $Iter<'_> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+ }
+
+ impl FusedIterator for $Iter<'_> {}
+
+ #[derive(Debug)]
+ pub struct $IterMut<'a> {
+ iter: std::iter::Enumerate<std::slice::IterMut<'a, $T>>,
+ }
+
+ impl<'a> Iterator for $IterMut<'a> {
+ type Item = ($I, &'a mut $T);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(|(i, v)| (<$I>::new(i), v))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter
+ .fold(init, move |a, (i, v)| f(a, (<$I>::new(i), v)))
+ }
+ }
+
+ impl DoubleEndedIterator for $IterMut<'_> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back().map(|(i, v)| (<$I>::new(i), v))
+ }
+
+ fn rfold<B, F>(self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter
+ .rfold(init, move |a, (i, v)| f(a, (<$I>::new(i), v)))
+ }
+ }
+
+ impl ExactSizeIterator for $IterMut<'_> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+ }
+
+ impl FusedIterator for $IterMut<'_> {}
+
+ impl Index<$I> for Vec<$T> {
+ type Output = $T;
+
+ fn index(&self, index: $I) -> &Self::Output {
+ &self[index.get()]
+ }
+ }
+
+ impl IndexMut<$I> for Vec<$T> {
+ fn index_mut(&mut self, index: $I) -> &mut Self::Output {
+ &mut self[index.get()]
+ }
+ }
+
+ impl<'a> Entries<'a, $I> for Vec<$T> {
+ type Iter = $Iter<'a>;
+ fn entries(&'a self) -> Self::Iter {
+ $Iter {
+ iter: (**self).iter().enumerate(),
+ }
+ }
+ fn keys(&'a self) -> RangeIter<$I> {
+ RangeIter::from_usize_range(0..self.len())
+ }
+ }
+
+ impl<'a> EntriesMut<'a, $I> for Vec<$T> {
+ type IterMut = $IterMut<'a>;
+ fn entries_mut(&'a mut self) -> Self::IterMut {
+ $IterMut {
+ iter: (**self).iter_mut().enumerate(),
+ }
+ }
+ }
+
+ $(
+ impl TryIndex<$I> for Vec<$T> {
+ type Error = $Error;
+
+ fn try_index(&self, idx: $I) -> Result<&Self::Output, Self::Error> {
+ self.get(idx.get()).ok_or($Error { idx })
+ }
+ }
+
+ impl TryIndexMut<$I> for Vec<$T> {
+ fn try_index_mut(&mut self, idx: $I) -> Result<&mut Self::Output, Self::Error> {
+ self.get_mut(idx.get()).ok_or($Error { idx })
+ }
+ }
+ )?
+
+ impl Index<$I> for [$T] {
+ type Output = $T;
+
+ fn index(&self, index: $I) -> &Self::Output {
+ &self[index.get()]
+ }
+ }
+
+ impl IndexMut<$I> for [$T] {
+ fn index_mut(&mut self, index: $I) -> &mut Self::Output {
+ &mut self[index.get()]
+ }
+ }
+
+ impl<'a> Entries<'a, $I> for [$T] {
+ type Iter = $Iter<'a>;
+ fn entries(&'a self) -> Self::Iter {
+ $Iter {
+ iter: self.iter().enumerate(),
+ }
+ }
+ fn keys(&'a self) -> RangeIter<$I> {
+ RangeIter::from_usize_range(0..self.len())
+ }
+ }
+
+ impl<'a> EntriesMut<'a, $I> for [$T] {
+ type IterMut = $IterMut<'a>;
+ fn entries_mut(&'a mut self) -> Self::IterMut {
+ $IterMut {
+ iter: self.iter_mut().enumerate(),
+ }
+ }
+ }
+
+ $(
+ impl TryIndex<$I> for [$T] {
+ type Error = $Error;
+
+ fn try_index(&self, idx: $I) -> Result<&Self::Output, Self::Error> {
+ self.get(idx.get()).ok_or($Error { idx })
+ }
+ }
+
+ impl TryIndexMut<$I> for [$T] {
+ fn try_index_mut(&mut self, idx: $I) -> Result<&mut Self::Output, Self::Error> {
+ self.get_mut(idx.get()).ok_or($Error { idx })
+ }
+ }
+ )?
+ };
+}
+
+impl_index! {
+ #[error = SSAValIdxOutOfRange, iter = SSAValEntriesIter, iter_mut = SSAValEntriesIterMut]
+ impl Index<SSAValIdx> for Vec<SSAVal> {}
+}
+
+impl_index! {
+ #[error = BlockParamIdxOutOfRange, iter = BlockParamEntriesIter, iter_mut = BlockParamEntriesIterMut]
+ impl Index<BlockParamIdx> for Vec<SSAValIdx> {}
+}
+
+impl_index! {
+ #[error = OperandIdxOutOfRange, iter = OperandEntriesIter, iter_mut = OperandEntriesIterMut]
+ impl Index<OperandIdx> for Vec<Operand> {}
+}
+
+impl_index! {
+ #[error = InstIdxOutOfRange, iter = InstEntriesIter, iter_mut = InstEntriesIterMut]
+ impl Index<InstIdx> for Vec<Inst> {}
+}
+
+impl_index! {
+ #[error = BlockIdxOutOfRange, iter = BlockEntriesIter, iter_mut = BlockEntriesIterMut]
+ impl Index<BlockIdx> for Vec<Block> {}
+}
+
+impl_index! {
+ #[iter = LiveRangeEntriesIter, iter_mut = LiveRangeEntriesIterMut]
+ impl Index<LiveRangeIdx> for Vec<LiveRange> {}
+}