Change:
ranges are and index access is normally bounds checked, e.g. or panics, however / is an exception, it just returns an empty slice despite the first inclusive index being out of bounds. I agree this is convenient and I guess this was implemented intentionally, and we can't silently break this now, but it at least needs to be 1) documented as intentional behavior, 2) tested as intentional behavior. So far I haven't found neither documentation, nor tests, nor design rationale in the range indexing RFCs and their implementations.
It's definitely intentional that is a valid slicing index. Our problem is that we use no documentation at all (in rustdoc) for trait implementations. Index for slice and str should have this information.
Doc-comments in the source code would be enough for a start, even if they are not displayed by .
is pretty ingrained, is drain really the only place that spells it out completely? We need more people to tell about doc blind spots like this!
Fixed by
I need to follow it up with an improvement for slice slicing as well. (Pr was for strings).

Discussion:
// FIXME implement indexing with inclusive ranges <ins> /// Implements slicing with syntax `&self[begin .. end]`. /// /// Returns a slice of self for the index range [`begin`..`end`). /// /// This operation is `O(1)`. /// /// # Panics /// /// Requires that `begin <= end` and `end <= self.len()`, /// otherwise slicing will panic. </ins> #[stable(feature = "rust1", since = "1.0.0")] impl<T> ops::Index<ops::Range<usize>> for [T] { type Output = [T];

} } } <ins> /// Implements slicing with syntax `&self[.. end]`. /// /// Returns a slice of self from the beginning until but not including /// the index `end`. /// /// Equivalent to `&self[0 .. end]` </ins> #[stable(feature = "rust1", since = "1.0.0")] impl<T> ops::Index<ops::RangeTo<usize>> for [T] { type Output = [T];

self.index(0 .. index.end) } } <ins> /// Implements slicing with syntax `&self[begin ..]`. /// /// Returns a slice of self from and including the index `begin` until the end. /// /// Equivalent to `&self[begin .. self.len()]` </ins> #[stable(feature = "rust1", since = "1.0.0")] impl<T> ops::Index<ops::RangeFrom<usize>> for [T] { type Output = [T];

self.index(index.start .. self.len()) } } <ins> /// Implements slicing with syntax `&self[..]`. /// /// Returns a slice of the whole slice. This operation can not panic. /// /// Equivalent to `&self[0 .. self.len()]` </ins> #[stable(feature = "rust1", since = "1.0.0")] impl<T> ops::Index<RangeFull> for [T] { type Output = [T];

} } <ins> /// Implements mutable slicing with syntax `&mut self[begin .. end]`. /// /// Returns a slice of self for the index range [`begin`..`end`). /// /// This operation is `O(1)`. /// /// # Panics /// /// Requires that `begin <= end` and `end <= self.len()`, /// otherwise slicing will panic. </ins> #[stable(feature = "rust1", since = "1.0.0")] impl<T> ops::IndexMut<ops::Range<usize>> for [T] { #[inline]

} } } <ins> /// Implements mutable slicing with syntax `&mut self[.. end]`. /// /// Returns a slice of self from the beginning until but not including /// the index `end`. /// /// Equivalent to `&mut self[0 .. end]` </ins> #[stable(feature = "rust1", since = "1.0.0")] impl<T> ops::IndexMut<ops::RangeTo<usize>> for [T] { #[inline]

self.index_mut(0 .. index.end) } } <ins> /// Implements mutable slicing with syntax `&mut self[begin ..]`. /// /// Returns a slice of self from and including the index `begin` until the end. /// /// Equivalent to `&mut self[begin .. self.len()]` </ins> #[stable(feature = "rust1", since = "1.0.0")] impl<T> ops::IndexMut<ops::RangeFrom<usize>> for [T] { #[inline]

self.index_mut(index.start .. len) } } <ins> /// Implements mutable slicing with syntax `&mut self[..]`. /// /// Returns a slice of the whole slice. This operation can not panic. /// /// Equivalent to `&mut self[0 .. self.len()]` </ins> #[stable(feature = "rust1", since = "1.0.0")] impl<T> ops::IndexMut<RangeFull> for [T] { #[inline]