mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-23 05:03:47 +00:00
Check for exhaustion in SliceIndex for RangeInclusive
This commit is contained in:
parent
9fd79a3904
commit
9202fbdbdb
@ -529,6 +529,13 @@ mod slice_index {
|
|||||||
message: "out of bounds";
|
message: "out of bounds";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in mod rangeinclusive_len {
|
||||||
|
data: "abcdef";
|
||||||
|
good: data[0..=5] == "abcdef";
|
||||||
|
bad: data[0..=6];
|
||||||
|
message: "out of bounds";
|
||||||
|
}
|
||||||
|
|
||||||
in mod range_len_len {
|
in mod range_len_len {
|
||||||
data: "abcdef";
|
data: "abcdef";
|
||||||
good: data[6..6] == "";
|
good: data[6..6] == "";
|
||||||
@ -544,6 +551,28 @@ mod slice_index {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
panic_cases! {
|
||||||
|
in mod rangeinclusive_exhausted {
|
||||||
|
data: "abcdef";
|
||||||
|
|
||||||
|
good: data[0..=5] == "abcdef";
|
||||||
|
good: data[{
|
||||||
|
let mut iter = 0..=5;
|
||||||
|
iter.by_ref().count(); // exhaust it
|
||||||
|
iter
|
||||||
|
}] == "";
|
||||||
|
|
||||||
|
// 0..=6 is out of bounds before exhaustion, so it
|
||||||
|
// stands to reason that it still would be after.
|
||||||
|
bad: data[{
|
||||||
|
let mut iter = 0..=6;
|
||||||
|
iter.by_ref().count(); // exhaust it
|
||||||
|
iter
|
||||||
|
}];
|
||||||
|
message: "out of bounds";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
panic_cases! {
|
panic_cases! {
|
||||||
in mod range_neg_width {
|
in mod range_neg_width {
|
||||||
data: "abcdef";
|
data: "abcdef";
|
||||||
|
@ -446,6 +446,20 @@ impl<Idx> RangeInclusive<Idx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RangeInclusive<usize> {
|
||||||
|
/// Converts to an exclusive `Range` for `SliceIndex` implementations.
|
||||||
|
/// The caller is responsible for dealing with `end == usize::MAX`.
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn into_slice_range(self) -> Range<usize> {
|
||||||
|
// If we're not exhausted, we want to simply slice `start..end + 1`.
|
||||||
|
// If we are exhausted, then slicing with `end + 1..end + 1` gives us an
|
||||||
|
// empty range that is still subject to bounds-checks for that endpoint.
|
||||||
|
let exclusive_end = self.end + 1;
|
||||||
|
let start = if self.exhausted { exclusive_end } else { self.start };
|
||||||
|
start..exclusive_end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
||||||
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
|
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
@ -376,28 +376,24 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(self, slice: &[T]) -> Option<&[T]> {
|
fn get(self, slice: &[T]) -> Option<&[T]> {
|
||||||
if *self.end() == usize::MAX { None } else { (*self.start()..self.end() + 1).get(slice) }
|
if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
|
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
|
||||||
if *self.end() == usize::MAX {
|
if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
|
||||||
None
|
|
||||||
} else {
|
|
||||||
(*self.start()..self.end() + 1).get_mut(slice)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
|
unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
|
||||||
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
|
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
|
||||||
unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) }
|
unsafe { self.into_slice_range().get_unchecked(slice) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
|
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
|
||||||
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
|
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
|
||||||
unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) }
|
unsafe { self.into_slice_range().get_unchecked_mut(slice) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -405,7 +401,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
|
|||||||
if *self.end() == usize::MAX {
|
if *self.end() == usize::MAX {
|
||||||
slice_end_index_overflow_fail();
|
slice_end_index_overflow_fail();
|
||||||
}
|
}
|
||||||
(*self.start()..self.end() + 1).index(slice)
|
self.into_slice_range().index(slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -413,7 +409,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
|
|||||||
if *self.end() == usize::MAX {
|
if *self.end() == usize::MAX {
|
||||||
slice_end_index_overflow_fail();
|
slice_end_index_overflow_fail();
|
||||||
}
|
}
|
||||||
(*self.start()..self.end() + 1).index_mut(slice)
|
self.into_slice_range().index_mut(slice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,39 +398,35 @@ unsafe impl SliceIndex<str> for ops::RangeInclusive<usize> {
|
|||||||
type Output = str;
|
type Output = str;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(self, slice: &str) -> Option<&Self::Output> {
|
fn get(self, slice: &str) -> Option<&Self::Output> {
|
||||||
if *self.end() == usize::MAX { None } else { (*self.start()..self.end() + 1).get(slice) }
|
if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
||||||
if *self.end() == usize::MAX {
|
if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
|
||||||
None
|
|
||||||
} else {
|
|
||||||
(*self.start()..self.end() + 1).get_mut(slice)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
|
unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
|
||||||
// SAFETY: the caller must uphold the safety contract for `get_unchecked`.
|
// SAFETY: the caller must uphold the safety contract for `get_unchecked`.
|
||||||
unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) }
|
unsafe { self.into_slice_range().get_unchecked(slice) }
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
|
unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
|
||||||
// SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
|
// SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
|
||||||
unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) }
|
unsafe { self.into_slice_range().get_unchecked_mut(slice) }
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(self, slice: &str) -> &Self::Output {
|
fn index(self, slice: &str) -> &Self::Output {
|
||||||
if *self.end() == usize::MAX {
|
if *self.end() == usize::MAX {
|
||||||
str_index_overflow_fail();
|
str_index_overflow_fail();
|
||||||
}
|
}
|
||||||
(*self.start()..self.end() + 1).index(slice)
|
self.into_slice_range().index(slice)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||||
if *self.end() == usize::MAX {
|
if *self.end() == usize::MAX {
|
||||||
str_index_overflow_fail();
|
str_index_overflow_fail();
|
||||||
}
|
}
|
||||||
(*self.start()..self.end() + 1).index_mut(slice)
|
self.into_slice_range().index_mut(slice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1341,6 +1341,14 @@ mod slice_index {
|
|||||||
message: "out of range";
|
message: "out of range";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in mod rangeinclusive_len {
|
||||||
|
data: [0, 1, 2, 3, 4, 5];
|
||||||
|
|
||||||
|
good: data[0..=5] == [0, 1, 2, 3, 4, 5];
|
||||||
|
bad: data[0..=6];
|
||||||
|
message: "out of range";
|
||||||
|
}
|
||||||
|
|
||||||
in mod range_len_len {
|
in mod range_len_len {
|
||||||
data: [0, 1, 2, 3, 4, 5];
|
data: [0, 1, 2, 3, 4, 5];
|
||||||
|
|
||||||
@ -1358,6 +1366,28 @@ mod slice_index {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
panic_cases! {
|
||||||
|
in mod rangeinclusive_exhausted {
|
||||||
|
data: [0, 1, 2, 3, 4, 5];
|
||||||
|
|
||||||
|
good: data[0..=5] == [0, 1, 2, 3, 4, 5];
|
||||||
|
good: data[{
|
||||||
|
let mut iter = 0..=5;
|
||||||
|
iter.by_ref().count(); // exhaust it
|
||||||
|
iter
|
||||||
|
}] == [];
|
||||||
|
|
||||||
|
// 0..=6 is out of range before exhaustion, so it
|
||||||
|
// stands to reason that it still would be after.
|
||||||
|
bad: data[{
|
||||||
|
let mut iter = 0..=6;
|
||||||
|
iter.by_ref().count(); // exhaust it
|
||||||
|
iter
|
||||||
|
}];
|
||||||
|
message: "out of range";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
panic_cases! {
|
panic_cases! {
|
||||||
in mod range_neg_width {
|
in mod range_neg_width {
|
||||||
data: [0, 1, 2, 3, 4, 5];
|
data: [0, 1, 2, 3, 4, 5];
|
||||||
|
Loading…
Reference in New Issue
Block a user