Skip to content

Commit c5d58de

Browse files
committed
core: add inclusive ranges to core::ops
Since it removes the old iter::{range_inclusive, RangeInclusive} which were unstable and deprecated, this is a [breaking-change] on nightly.
1 parent f1e191c commit c5d58de

File tree

3 files changed

+167
-91
lines changed

3 files changed

+167
-91
lines changed

src/libcore/iter.rs

Lines changed: 96 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -4375,95 +4375,6 @@ impl<A> Iterator for StepBy<A, RangeFrom<A>> where
43754375
}
43764376
}
43774377

4378-
/// An iterator over the range [start, stop]
4379-
#[derive(Clone)]
4380-
#[unstable(feature = "range_inclusive",
4381-
reason = "likely to be replaced by range notation and adapters",
4382-
issue = "27777")]
4383-
#[rustc_deprecated(since = "1.5.0", reason = "replaced with ... syntax")]
4384-
#[allow(deprecated)]
4385-
pub struct RangeInclusive<A> {
4386-
range: ops::Range<A>,
4387-
done: bool,
4388-
}
4389-
4390-
/// Returns an iterator over the range [start, stop].
4391-
#[inline]
4392-
#[unstable(feature = "range_inclusive",
4393-
reason = "likely to be replaced by range notation and adapters",
4394-
issue = "27777")]
4395-
#[rustc_deprecated(since = "1.5.0", reason = "replaced with ... syntax")]
4396-
#[allow(deprecated)]
4397-
pub fn range_inclusive<A>(start: A, stop: A) -> RangeInclusive<A>
4398-
where A: Step + One + Clone
4399-
{
4400-
RangeInclusive {
4401-
range: start..stop,
4402-
done: false,
4403-
}
4404-
}
4405-
4406-
#[unstable(feature = "range_inclusive",
4407-
reason = "likely to be replaced by range notation and adapters",
4408-
issue = "27777")]
4409-
#[rustc_deprecated(since = "1.5.0", reason = "replaced with ... syntax")]
4410-
#[allow(deprecated)]
4411-
impl<A> Iterator for RangeInclusive<A> where
4412-
A: PartialEq + Step + One + Clone,
4413-
for<'a> &'a A: Add<&'a A, Output = A>
4414-
{
4415-
type Item = A;
4416-
4417-
#[inline]
4418-
fn next(&mut self) -> Option<A> {
4419-
self.range.next().or_else(|| {
4420-
if !self.done && self.range.start == self.range.end {
4421-
self.done = true;
4422-
Some(self.range.end.clone())
4423-
} else {
4424-
None
4425-
}
4426-
})
4427-
}
4428-
4429-
#[inline]
4430-
fn size_hint(&self) -> (usize, Option<usize>) {
4431-
let (lo, hi) = self.range.size_hint();
4432-
if self.done {
4433-
(lo, hi)
4434-
} else {
4435-
let lo = lo.saturating_add(1);
4436-
let hi = hi.and_then(|x| x.checked_add(1));
4437-
(lo, hi)
4438-
}
4439-
}
4440-
}
4441-
4442-
#[unstable(feature = "range_inclusive",
4443-
reason = "likely to be replaced by range notation and adapters",
4444-
issue = "27777")]
4445-
#[rustc_deprecated(since = "1.5.0", reason = "replaced with ... syntax")]
4446-
#[allow(deprecated)]
4447-
impl<A> DoubleEndedIterator for RangeInclusive<A> where
4448-
A: PartialEq + Step + One + Clone,
4449-
for<'a> &'a A: Add<&'a A, Output = A>,
4450-
for<'a> &'a A: Sub<Output=A>
4451-
{
4452-
#[inline]
4453-
fn next_back(&mut self) -> Option<A> {
4454-
if self.range.end > self.range.start {
4455-
let result = self.range.end.clone();
4456-
self.range.end = &self.range.end - &A::one();
4457-
Some(result)
4458-
} else if !self.done && self.range.start == self.range.end {
4459-
self.done = true;
4460-
Some(self.range.end.clone())
4461-
} else {
4462-
None
4463-
}
4464-
}
4465-
}
4466-
44674378
#[stable(feature = "rust1", since = "1.0.0")]
44684379
impl<A: Step + Zero + Clone> Iterator for StepBy<A, ops::Range<A>> {
44694380
type Item = A;
@@ -4505,6 +4416,9 @@ macro_rules! range_exact_iter_impl {
45054416
($($t:ty)*) => ($(
45064417
#[stable(feature = "rust1", since = "1.0.0")]
45074418
impl ExactSizeIterator for ops::Range<$t> { }
4419+
4420+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
4421+
impl ExactSizeIterator for ops::RangeInclusive<$t> { }
45084422
)*)
45094423
}
45104424

@@ -4568,6 +4482,99 @@ impl<A: Step + One> Iterator for ops::RangeFrom<A> where
45684482
}
45694483
}
45704484

4485+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
4486+
impl<A: Step + One> Iterator for ops::RangeInclusive<A> where
4487+
for<'a> &'a A: Add<&'a A, Output = A>
4488+
{
4489+
type Item = A;
4490+
4491+
#[inline]
4492+
fn next(&mut self) -> Option<A> {
4493+
use ops::RangeInclusive::*;
4494+
4495+
// this function has a sort of odd structure due to borrowck issues
4496+
// we may need to replace self, so borrows of self.start and self.end need to end early
4497+
4498+
let (finishing, n) = match *self {
4499+
Empty { .. } => (None, None), // empty iterators yield no values
4500+
4501+
NonEmpty { ref mut start, ref mut end } => {
4502+
let one = A::one();
4503+
if start <= end {
4504+
let mut n = &*start + &one;
4505+
mem::swap(&mut n, start);
4506+
4507+
// if the iterator is done iterating, it will change from NonEmpty to Empty
4508+
// to avoid unnecessary drops or clones, we'll reuse either start or end
4509+
// (they are equal now, so it doesn't matter which)
4510+
// to pull out end, we need to swap something back in -- use the previously
4511+
// created A::one() as a dummy value
4512+
4513+
(if n == *end { Some(mem::replace(end, one)) } else { None },
4514+
// ^ are we done yet?
4515+
Some(n)) // < the value to output
4516+
} else {
4517+
(Some(mem::replace(start, one)), None)
4518+
}
4519+
}
4520+
};
4521+
4522+
// turn into an empty iterator if this is the last value
4523+
if let Some(end) = finishing {
4524+
*self = Empty { at: end };
4525+
}
4526+
4527+
n
4528+
}
4529+
4530+
#[inline]
4531+
fn size_hint(&self) -> (usize, Option<usize>) {
4532+
use ops::RangeInclusive::*;
4533+
4534+
match *self {
4535+
Empty { .. } => (0, Some(0)),
4536+
4537+
NonEmpty { ref start, ref end } =>
4538+
match Step::steps_between(start, end, &A::one()) {
4539+
Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
4540+
None => (0, None),
4541+
}
4542+
}
4543+
}
4544+
}
4545+
4546+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
4547+
impl<A: Step + One> DoubleEndedIterator for ops::RangeInclusive<A> where
4548+
for<'a> &'a A: Add<&'a A, Output = A>,
4549+
for<'a> &'a A: Sub<&'a A, Output = A>
4550+
{
4551+
#[inline]
4552+
fn next_back(&mut self) -> Option<A> {
4553+
use ops::RangeInclusive::*;
4554+
4555+
// see Iterator::next for comments
4556+
4557+
let (finishing, n) = match *self {
4558+
Empty { .. } => return None,
4559+
4560+
NonEmpty { ref mut start, ref mut end } => {
4561+
let one = A::one();
4562+
let mut n = &*end - &one;
4563+
mem::swap(&mut n, end);
4564+
4565+
(if n == *start { Some(mem::replace(start, one)) } else { None },
4566+
n)
4567+
}
4568+
};
4569+
4570+
if let Some(start) = finishing {
4571+
*self = Empty { at: start };
4572+
}
4573+
4574+
Some(n)
4575+
}
4576+
}
4577+
45714578
/// An iterator that repeats an element endlessly.
45724579
///
45734580
/// This `struct` is created by the [`repeat()`] function. See its documentation for more.

src/libcore/ops.rs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,11 @@
6767
6868
#![stable(feature = "rust1", since = "1.0.0")]
6969

70-
use marker::{Sized, Unsize};
70+
use cmp::PartialOrd;
7171
use fmt;
72+
use convert::From;
73+
use marker::{Sized, Unsize};
74+
use num::One;
7275

7376
/// The `Drop` trait is used to run some code when a value goes out of scope.
7477
/// This is sometimes called a 'destructor'.
@@ -1530,6 +1533,73 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
15301533
}
15311534
}
15321535

1536+
/// An inclusive range which is bounded at both ends.
1537+
#[derive(Copy, Clone, PartialEq, Eq)]
1538+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
1539+
pub enum RangeInclusive<Idx> {
1540+
/// Empty range (iteration has finished)
1541+
Empty {
1542+
/// The point at which iteration finished
1543+
at: Idx
1544+
},
1545+
/// Non-empty range (iteration will yield value(s))
1546+
NonEmpty {
1547+
/// The lower bound of the range (inclusive).
1548+
start: Idx,
1549+
/// The upper bound of the range (inclusive).
1550+
end: Idx,
1551+
},
1552+
}
1553+
1554+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
1555+
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
1556+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1557+
use self::RangeInclusive::*;
1558+
1559+
match *self {
1560+
Empty { ref at } => write!(fmt, "[empty range @ {:?}]", at),
1561+
NonEmpty { ref start, ref end } => write!(fmt, "{:?}...{:?}", start, end),
1562+
}
1563+
}
1564+
}
1565+
1566+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
1567+
impl<Idx: PartialOrd + One + Sub<Output=Idx>> From<Range<Idx>> for RangeInclusive<Idx> {
1568+
fn from(range: Range<Idx>) -> RangeInclusive<Idx> {
1569+
use self::RangeInclusive::*;
1570+
1571+
if range.start < range.end {
1572+
NonEmpty {
1573+
start: range.start,
1574+
end: range.end - Idx::one() // can't underflow because end > start >= MIN
1575+
}
1576+
} else {
1577+
Empty {
1578+
at: range.start
1579+
}
1580+
}
1581+
}
1582+
}
1583+
1584+
/// An inclusive range which is only bounded above.
1585+
#[derive(Copy, Clone, PartialEq, Eq)]
1586+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
1587+
pub struct RangeToInclusive<Idx> {
1588+
/// The upper bound of the range (inclusive)
1589+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
1590+
pub end: Idx,
1591+
}
1592+
1593+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
1594+
impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
1595+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1596+
write!(fmt, "...{:?}", self.end)
1597+
}
1598+
}
1599+
1600+
// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
1601+
// because underflow would be possible with (..0).into()
1602+
15331603
/// The `Deref` trait is used to specify the functionality of dereferencing
15341604
/// operations, like `*v`.
15351605
///

src/libstd/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,6 @@
247247
#![feature(optin_builtin_traits)]
248248
#![feature(placement_in_syntax)]
249249
#![feature(rand)]
250-
#![feature(range_inclusive)]
251250
#![feature(raw)]
252251
#![feature(repr_simd)]
253252
#![feature(reflect_marker)]

0 commit comments

Comments
 (0)