Rollup merge of #136610 - Jarcho:range_idx, r=Noratrieb
Allow `IndexSlice` to be indexed by ranges. This comes with some annoyances as the index type can no longer inferred from indexing expressions. The biggest offender for this is `IndexVec::from_fn_n(|idx| ..., n)` where the index type won't be inferred from the call site or any index expressions inside the closure. My main use case for this is mapping a `Place` to `Range<Idx>` for value tracking where the range represents all the values the place contains.
This commit is contained in:
commit
6aa015ae9d
12 changed files with 144 additions and 42 deletions
|
@ -1,5 +1,7 @@
|
|||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::ops;
|
||||
use std::slice::SliceIndex;
|
||||
|
||||
/// Represents some newtyped `usize` wrapper.
|
||||
///
|
||||
|
@ -43,3 +45,92 @@ impl Idx for u32 {
|
|||
self as usize
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper trait for indexing operations with a custom index type.
|
||||
pub trait IntoSliceIdx<I, T: ?Sized> {
|
||||
type Output: SliceIndex<T>;
|
||||
fn into_slice_idx(self) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<I: Idx, T> IntoSliceIdx<I, [T]> for I {
|
||||
type Output = usize;
|
||||
#[inline]
|
||||
fn into_slice_idx(self) -> Self::Output {
|
||||
self.index()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T> IntoSliceIdx<I, [T]> for ops::RangeFull {
|
||||
type Output = ops::RangeFull;
|
||||
#[inline]
|
||||
fn into_slice_idx(self) -> Self::Output {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::Range<I> {
|
||||
type Output = ops::Range<usize>;
|
||||
#[inline]
|
||||
fn into_slice_idx(self) -> Self::Output {
|
||||
ops::Range { start: self.start.index(), end: self.end.index() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeFrom<I> {
|
||||
type Output = ops::RangeFrom<usize>;
|
||||
#[inline]
|
||||
fn into_slice_idx(self) -> Self::Output {
|
||||
ops::RangeFrom { start: self.start.index() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeTo<I> {
|
||||
type Output = ops::RangeTo<usize>;
|
||||
#[inline]
|
||||
fn into_slice_idx(self) -> Self::Output {
|
||||
..self.end.index()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeInclusive<I> {
|
||||
type Output = ops::RangeInclusive<usize>;
|
||||
#[inline]
|
||||
fn into_slice_idx(self) -> Self::Output {
|
||||
ops::RangeInclusive::new(self.start().index(), self.end().index())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeToInclusive<I> {
|
||||
type Output = ops::RangeToInclusive<usize>;
|
||||
#[inline]
|
||||
fn into_slice_idx(self) -> Self::Output {
|
||||
..=self.end.index()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::Range<I> {
|
||||
type Output = core::range::Range<usize>;
|
||||
#[inline]
|
||||
fn into_slice_idx(self) -> Self::Output {
|
||||
core::range::Range { start: self.start.index(), end: self.end.index() }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeFrom<I> {
|
||||
type Output = core::range::RangeFrom<usize>;
|
||||
#[inline]
|
||||
fn into_slice_idx(self) -> Self::Output {
|
||||
core::range::RangeFrom { start: self.start.index() }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeInclusive<I> {
|
||||
type Output = core::range::RangeInclusive<usize>;
|
||||
#[inline]
|
||||
fn into_slice_idx(self) -> Self::Output {
|
||||
core::range::RangeInclusive { start: self.start.index(), end: self.end.index() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))]
|
||||
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
||||
#![cfg_attr(feature = "nightly", feature(extend_one, step_trait, test))]
|
||||
#![cfg_attr(feature = "nightly", feature(new_range_api))]
|
||||
#![cfg_attr(feature = "nightly", feature(new_zeroed_alloc))]
|
||||
#![warn(unreachable_pub)]
|
||||
// tidy-alphabetical-end
|
||||
|
@ -14,7 +15,7 @@ mod idx;
|
|||
mod slice;
|
||||
mod vec;
|
||||
|
||||
pub use idx::Idx;
|
||||
pub use idx::{Idx, IntoSliceIdx};
|
||||
pub use rustc_index_macros::newtype_index;
|
||||
pub use slice::IndexSlice;
|
||||
#[doc(no_inline)]
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::{fmt, slice};
|
||||
use std::slice::{self, SliceIndex};
|
||||
|
||||
use crate::{Idx, IndexVec};
|
||||
use crate::{Idx, IndexVec, IntoSliceIdx};
|
||||
|
||||
/// A view into contiguous `T`s, indexed by `I` rather than by `usize`.
|
||||
///
|
||||
|
@ -97,13 +98,19 @@ impl<I: Idx, T> IndexSlice<I, T> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(&self, index: I) -> Option<&T> {
|
||||
self.raw.get(index.index())
|
||||
pub fn get<R: IntoSliceIdx<I, [T]>>(
|
||||
&self,
|
||||
index: R,
|
||||
) -> Option<&<R::Output as SliceIndex<[T]>>::Output> {
|
||||
self.raw.get(index.into_slice_idx())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_mut(&mut self, index: I) -> Option<&mut T> {
|
||||
self.raw.get_mut(index.index())
|
||||
pub fn get_mut<R: IntoSliceIdx<I, [T]>>(
|
||||
&mut self,
|
||||
index: R,
|
||||
) -> Option<&mut <R::Output as SliceIndex<[T]>>::Output> {
|
||||
self.raw.get_mut(index.into_slice_idx())
|
||||
}
|
||||
|
||||
/// Returns mutable references to two distinct elements, `a` and `b`.
|
||||
|
@ -184,19 +191,19 @@ impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexSlice<I, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> Index<I> for IndexSlice<I, T> {
|
||||
type Output = T;
|
||||
impl<I: Idx, T, R: IntoSliceIdx<I, [T]>> Index<R> for IndexSlice<I, T> {
|
||||
type Output = <R::Output as SliceIndex<[T]>>::Output;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: I) -> &T {
|
||||
&self.raw[index.index()]
|
||||
fn index(&self, index: R) -> &Self::Output {
|
||||
&self.raw[index.into_slice_idx()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> IndexMut<I> for IndexSlice<I, T> {
|
||||
impl<I: Idx, T, R: IntoSliceIdx<I, [T]>> IndexMut<R> for IndexSlice<I, T> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: I) -> &mut T {
|
||||
&mut self.raw[index.index()]
|
||||
fn index_mut(&mut self, index: R) -> &mut Self::Output {
|
||||
&mut self.raw[index.into_slice_idx()]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue