Stabilize Index traits and most range notation
This commit marks as `#[stable]`: * The `Index` and `IndexMut` traits. These are stabilized as taking the index itself *by reference*; after extensive discussion it was determined that this is a better match with our choices elsewhere (e.g. making comparison operators auto-reference), and that the use cases for by-value indices are better handled through `IndexSet`. * The `Range`, `RangeFrom` and `RangeTo` structs, introduced for range notation. * Various impls of `Index` and `IndexMut`. The `FullRange` struct is left unstable as we may wish to rename it to `RangeFull` in the future. This commit also *removes* the `Step` trait in favor of direct implementation of iterator traits on ranges for integers. The `Step` trait was not a terribly useful factoring internally, and it is likely that external integer types are best off implementing range iterators directly. It was removed to simplify the API surface. We can always reintroduce `Step` later if it turns out to be useful. Due to this removal, this is a: [breaking-change]
This commit is contained in:
parent
6869645e86
commit
fba0bf63a9
@ -1229,7 +1229,7 @@ fn hash(&self, state: &mut S) {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable = "waiting on Index stability"]
|
||||
#[stable]
|
||||
impl<T> Index<uint> for Vec<T> {
|
||||
type Output = T;
|
||||
|
||||
@ -1239,6 +1239,7 @@ fn index<'a>(&'a self, index: &uint) -> &'a T {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<T> IndexMut<uint> for Vec<T> {
|
||||
type Output = T;
|
||||
|
||||
@ -1249,6 +1250,7 @@ fn index_mut<'a>(&'a mut self, index: &uint) -> &'a mut T {
|
||||
}
|
||||
|
||||
|
||||
#[stable]
|
||||
impl<T> ops::Index<ops::Range<uint>> for Vec<T> {
|
||||
type Output = [T];
|
||||
#[inline]
|
||||
@ -1256,6 +1258,7 @@ fn index(&self, index: &ops::Range<uint>) -> &[T] {
|
||||
self.as_slice().index(index)
|
||||
}
|
||||
}
|
||||
#[stable]
|
||||
impl<T> ops::Index<ops::RangeTo<uint>> for Vec<T> {
|
||||
type Output = [T];
|
||||
#[inline]
|
||||
@ -1263,6 +1266,7 @@ fn index(&self, index: &ops::RangeTo<uint>) -> &[T] {
|
||||
self.as_slice().index(index)
|
||||
}
|
||||
}
|
||||
#[stable]
|
||||
impl<T> ops::Index<ops::RangeFrom<uint>> for Vec<T> {
|
||||
type Output = [T];
|
||||
#[inline]
|
||||
@ -1270,6 +1274,7 @@ fn index(&self, index: &ops::RangeFrom<uint>) -> &[T] {
|
||||
self.as_slice().index(index)
|
||||
}
|
||||
}
|
||||
#[stable]
|
||||
impl<T> ops::Index<ops::FullRange> for Vec<T> {
|
||||
type Output = [T];
|
||||
#[inline]
|
||||
@ -1278,6 +1283,7 @@ fn index(&self, _index: &ops::FullRange) -> &[T] {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<T> ops::IndexMut<ops::Range<uint>> for Vec<T> {
|
||||
type Output = [T];
|
||||
#[inline]
|
||||
@ -1285,6 +1291,7 @@ fn index_mut(&mut self, index: &ops::Range<uint>) -> &mut [T] {
|
||||
self.as_mut_slice().index_mut(index)
|
||||
}
|
||||
}
|
||||
#[stable]
|
||||
impl<T> ops::IndexMut<ops::RangeTo<uint>> for Vec<T> {
|
||||
type Output = [T];
|
||||
#[inline]
|
||||
@ -1292,6 +1299,7 @@ fn index_mut(&mut self, index: &ops::RangeTo<uint>) -> &mut [T] {
|
||||
self.as_mut_slice().index_mut(index)
|
||||
}
|
||||
}
|
||||
#[stable]
|
||||
impl<T> ops::IndexMut<ops::RangeFrom<uint>> for Vec<T> {
|
||||
type Output = [T];
|
||||
#[inline]
|
||||
@ -1299,6 +1307,7 @@ fn index_mut(&mut self, index: &ops::RangeFrom<uint>) -> &mut [T] {
|
||||
self.as_mut_slice().index_mut(index)
|
||||
}
|
||||
}
|
||||
#[stable]
|
||||
impl<T> ops::IndexMut<ops::FullRange> for Vec<T> {
|
||||
type Output = [T];
|
||||
#[inline]
|
||||
@ -1307,7 +1316,6 @@ fn index_mut(&mut self, _index: &ops::FullRange) -> &mut [T] {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[stable]
|
||||
impl<T> ops::Deref for Vec<T> {
|
||||
type Target = [T];
|
||||
|
@ -2701,63 +2701,93 @@ fn next(&mut self) -> Option<A> {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! range_impl {
|
||||
($($t:ty)*) => ($(
|
||||
#[stable]
|
||||
impl Iterator for ::ops::Range<$t> {
|
||||
type Item = $t;
|
||||
|
||||
/// The `Step` trait identifies objects which can be stepped over in both
|
||||
/// directions. The `steps_between` function provides a way to
|
||||
/// compare two Step objects (it could be provided using `step()` and `Ord`,
|
||||
/// but the implementation would be so inefficient as to be useless).
|
||||
#[unstable = "design of range notation/iteration is in flux"]
|
||||
pub trait Step: Ord {
|
||||
/// Change self to the next object.
|
||||
fn step(&mut self);
|
||||
/// Change self to the previous object.
|
||||
fn step_back(&mut self);
|
||||
/// The steps_between two step objects.
|
||||
/// start should always be less than end, so the result should never be negative.
|
||||
/// Return None if it is not possible to calculate steps_between without
|
||||
/// overflow.
|
||||
fn steps_between(start: &Self, end: &Self) -> Option<uint>;
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<$t> {
|
||||
if self.start < self.end {
|
||||
let result = self.start;
|
||||
self.start += 1;
|
||||
return Some(result);
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
debug_assert!(self.end >= self.start);
|
||||
let hint = (self.end - self.start) as uint;
|
||||
(hint, Some(hint))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl ExactSizeIterator for ::ops::Range<$t> {}
|
||||
)*)
|
||||
}
|
||||
|
||||
macro_rules! step_impl {
|
||||
macro_rules! range_impl_no_hint {
|
||||
($($t:ty)*) => ($(
|
||||
#[unstable = "Trait is unstable."]
|
||||
impl Step for $t {
|
||||
#[stable]
|
||||
impl Iterator for ::ops::Range<$t> {
|
||||
type Item = $t;
|
||||
|
||||
#[inline]
|
||||
fn step(&mut self) { *self += 1; }
|
||||
#[inline]
|
||||
fn step_back(&mut self) { *self -= 1; }
|
||||
#[inline]
|
||||
fn steps_between(start: &$t, end: &$t) -> Option<uint> {
|
||||
debug_assert!(end >= start);
|
||||
Some((*end - *start) as uint)
|
||||
fn next(&mut self) -> Option<$t> {
|
||||
if self.start < self.end {
|
||||
let result = self.start;
|
||||
self.start += 1;
|
||||
return Some(result);
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
macro_rules! step_impl_no_between {
|
||||
macro_rules! range_other_impls {
|
||||
($($t:ty)*) => ($(
|
||||
#[unstable = "Trait is unstable."]
|
||||
impl Step for $t {
|
||||
#[stable]
|
||||
impl DoubleEndedIterator for ::ops::Range<$t> {
|
||||
#[inline]
|
||||
fn step(&mut self) { *self += 1; }
|
||||
fn next_back(&mut self) -> Option<$t> {
|
||||
if self.start < self.end {
|
||||
self.end -= 1;
|
||||
return Some(self.end);
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl Iterator for ::ops::RangeFrom<$t> {
|
||||
type Item = $t;
|
||||
|
||||
#[inline]
|
||||
fn step_back(&mut self) { *self -= 1; }
|
||||
#[inline]
|
||||
fn steps_between(_start: &$t, _end: &$t) -> Option<uint> {
|
||||
None
|
||||
fn next(&mut self) -> Option<$t> {
|
||||
let result = self.start;
|
||||
self.start += 1;
|
||||
debug_assert!(result < self.start);
|
||||
return Some(result);
|
||||
}
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
step_impl!(uint u8 u16 u32 int i8 i16 i32);
|
||||
range_impl!(uint u8 u16 u32 int i8 i16 i32);
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
step_impl!(u64 i64);
|
||||
range_impl!(u64 i64);
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
step_impl_no_between!(u64 i64);
|
||||
range_impl_no_hint!(u64 i64);
|
||||
|
||||
range_other_impls!(uint u8 u16 u32 u64 int i8 i16 i32 i64);
|
||||
|
||||
/// An iterator that repeats an element endlessly
|
||||
#[derive(Clone)]
|
||||
|
@ -69,10 +69,7 @@
|
||||
|
||||
#![stable]
|
||||
|
||||
use clone::Clone;
|
||||
use iter::{Step, Iterator,DoubleEndedIterator,ExactSizeIterator};
|
||||
use marker::Sized;
|
||||
use option::Option::{self, Some, None};
|
||||
use fmt;
|
||||
|
||||
/// The `Drop` trait is used to run some code when a value goes out of scope. This
|
||||
@ -924,10 +921,12 @@ macro_rules! shr_impl_all {
|
||||
/// }
|
||||
/// ```
|
||||
#[lang="index"]
|
||||
#[stable]
|
||||
pub trait Index<Index: ?Sized> {
|
||||
type Output: ?Sized;
|
||||
|
||||
/// The method for the indexing (`Foo[Bar]`) operation
|
||||
#[stable]
|
||||
fn index<'a>(&'a self, index: &Index) -> &'a Self::Output;
|
||||
}
|
||||
|
||||
@ -960,20 +959,22 @@ pub trait Index<Index: ?Sized> {
|
||||
/// }
|
||||
/// ```
|
||||
#[lang="index_mut"]
|
||||
#[stable]
|
||||
pub trait IndexMut<Index: ?Sized> {
|
||||
type Output: ?Sized;
|
||||
|
||||
/// The method for the indexing (`Foo[Bar]`) operation
|
||||
#[stable]
|
||||
fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Self::Output;
|
||||
}
|
||||
|
||||
/// An unbounded range.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[lang="full_range"]
|
||||
#[unstable = "API still in development"]
|
||||
#[unstable = "may be renamed to RangeFull"]
|
||||
pub struct FullRange;
|
||||
|
||||
#[unstable = "API still in development"]
|
||||
#[stable]
|
||||
impl fmt::Show for FullRange {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Show::fmt("..", fmt)
|
||||
@ -983,7 +984,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// A (half-open) range which is bounded at both ends.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[lang="range"]
|
||||
#[unstable = "API still in development"]
|
||||
#[stable]
|
||||
pub struct Range<Idx> {
|
||||
/// The lower bound of the range (inclusive).
|
||||
pub start: Idx,
|
||||
@ -991,48 +992,7 @@ pub struct Range<Idx> {
|
||||
pub end: Idx,
|
||||
}
|
||||
|
||||
#[unstable = "API still in development"]
|
||||
impl<Idx: Clone + Step> Iterator for Range<Idx> {
|
||||
type Item = Idx;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Idx> {
|
||||
if self.start < self.end {
|
||||
let result = self.start.clone();
|
||||
self.start.step();
|
||||
return Some(result);
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
if let Some(hint) = Step::steps_between(&self.start, &self.end) {
|
||||
(hint, Some(hint))
|
||||
} else {
|
||||
(0, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable = "API still in development"]
|
||||
impl<Idx: Clone + Step> DoubleEndedIterator for Range<Idx> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<Idx> {
|
||||
if self.start < self.end {
|
||||
self.end.step_back();
|
||||
return Some(self.end.clone());
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable = "API still in development"]
|
||||
impl<Idx: Clone + Step> ExactSizeIterator for Range<Idx> {}
|
||||
|
||||
#[unstable = "API still in development"]
|
||||
#[stable]
|
||||
impl<Idx: fmt::Show> fmt::Show for Range<Idx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{:?}..{:?}", self.start, self.end)
|
||||
@ -1042,26 +1002,15 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// A range which is only bounded below.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[lang="range_from"]
|
||||
#[unstable = "API still in development"]
|
||||
#[stable]
|
||||
pub struct RangeFrom<Idx> {
|
||||
/// The lower bound of the range (inclusive).
|
||||
pub start: Idx,
|
||||
}
|
||||
|
||||
#[unstable = "API still in development"]
|
||||
impl<Idx: Clone + Step> Iterator for RangeFrom<Idx> {
|
||||
type Item = Idx;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Idx> {
|
||||
// Deliberately overflow so we loop forever.
|
||||
let result = self.start.clone();
|
||||
self.start.step();
|
||||
return Some(result);
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable = "API still in development"]
|
||||
#[stable]
|
||||
impl<Idx: fmt::Show> fmt::Show for RangeFrom<Idx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{:?}..", self.start)
|
||||
@ -1071,13 +1020,13 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// A range which is only bounded above.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[lang="range_to"]
|
||||
#[unstable = "API still in development"]
|
||||
#[stable]
|
||||
pub struct RangeTo<Idx> {
|
||||
/// The upper bound of the range (exclusive).
|
||||
pub end: Idx,
|
||||
}
|
||||
|
||||
#[unstable = "API still in development"]
|
||||
#[stable]
|
||||
impl<Idx: fmt::Show> fmt::Show for RangeTo<Idx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "..{:?}", self.end)
|
||||
|
Loading…
Reference in New Issue
Block a user