Skip to content

Commit

Permalink
Add support for ..= syntax
Browse files Browse the repository at this point in the history
Add ..= to the parser

Add ..= to libproc_macro

Add ..= to ICH

Highlight ..= in rustdoc

Update impl Debug for RangeInclusive to ..=

Replace `...` to `..=` in range docs

Make the dotdoteq warning point to the ...

Add warning for ... in expressions

Updated more tests to the ..= syntax

Updated even more tests to the ..= syntax

Updated the inclusive_range entry in unstable book
  • Loading branch information
durka authored and Badel2 committed Sep 22, 2017
1 parent 3eb19bf commit e64efc9
Show file tree
Hide file tree
Showing 33 changed files with 244 additions and 182 deletions.
Expand Up @@ -7,13 +7,13 @@ The tracking issue for this feature is: [#28237]
------------------------

To get a range that goes from 0 to 10 and includes the value 10, you
can write `0...10`:
can write `0..=10`:

```rust
#![feature(inclusive_range_syntax)]

fn main() {
for i in 0...10 {
for i in 0..=10 {
println!("{}", i);
}
}
Expand Down
28 changes: 14 additions & 14 deletions src/liballoc/tests/btree/map.rs
Expand Up @@ -182,7 +182,7 @@ fn test_range_small() {
fn test_range_inclusive() {
let size = 500;

let map: BTreeMap<_, _> = (0...size).map(|i| (i, i)).collect();
let map: BTreeMap<_, _> = (0..=size).map(|i| (i, i)).collect();

fn check<'a, L, R>(lhs: L, rhs: R)
where L: IntoIterator<Item=(&'a i32, &'a i32)>,
Expand All @@ -193,26 +193,26 @@ fn test_range_inclusive() {
assert_eq!(lhs, rhs);
}

check(map.range(size + 1...size + 1), vec![]);
check(map.range(size...size), vec![(&size, &size)]);
check(map.range(size...size + 1), vec![(&size, &size)]);
check(map.range(0...0), vec![(&0, &0)]);
check(map.range(0...size - 1), map.range(..size));
check(map.range(-1...-1), vec![]);
check(map.range(-1...size), map.range(..));
check(map.range(...size), map.range(..));
check(map.range(...200), map.range(..201));
check(map.range(5...8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
check(map.range(-1...0), vec![(&0, &0)]);
check(map.range(-1...2), vec![(&0, &0), (&1, &1), (&2, &2)]);
check(map.range(size + 1..=size + 1), vec![]);
check(map.range(size..=size), vec![(&size, &size)]);
check(map.range(size..=size + 1), vec![(&size, &size)]);
check(map.range(0..=0), vec![(&0, &0)]);
check(map.range(0..=size - 1), map.range(..size));
check(map.range(-1..=-1), vec![]);
check(map.range(-1..=size), map.range(..));
check(map.range(..=size), map.range(..));
check(map.range(..=200), map.range(..201));
check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
check(map.range(-1..=0), vec![(&0, &0)]);
check(map.range(-1..=2), vec![(&0, &0), (&1, &1), (&2, &2)]);
}

#[test]
fn test_range_inclusive_max_value() {
let max = ::std::usize::MAX;
let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect();

assert_eq!(map.range(max...max).collect::<Vec<_>>(), &[(&max, &0)]);
assert_eq!(map.range(max..=max).collect::<Vec<_>>(), &[(&max, &0)]);
}

#[test]
Expand Down
16 changes: 8 additions & 8 deletions src/liballoc/tests/str.rs
Expand Up @@ -361,43 +361,43 @@ fn test_slice_fail() {
#[test]
#[should_panic]
fn test_str_slice_rangetoinclusive_max_panics() {
&"hello"[...usize::max_value()];
&"hello"[..=usize::max_value()];
}

#[test]
#[should_panic]
fn test_str_slice_rangeinclusive_max_panics() {
&"hello"[1...usize::max_value()];
&"hello"[1..=usize::max_value()];
}

#[test]
#[should_panic]
fn test_str_slicemut_rangetoinclusive_max_panics() {
let mut s = "hello".to_owned();
let s: &mut str = &mut s;
&mut s[...usize::max_value()];
&mut s[..=usize::max_value()];
}

#[test]
#[should_panic]
fn test_str_slicemut_rangeinclusive_max_panics() {
let mut s = "hello".to_owned();
let s: &mut str = &mut s;
&mut s[1...usize::max_value()];
&mut s[1..=usize::max_value()];
}

#[test]
fn test_str_get_maxinclusive() {
let mut s = "hello".to_owned();
{
let s: &str = &s;
assert_eq!(s.get(...usize::max_value()), None);
assert_eq!(s.get(1...usize::max_value()), None);
assert_eq!(s.get(..=usize::max_value()), None);
assert_eq!(s.get(1..=usize::max_value()), None);
}
{
let s: &mut str = &mut s;
assert_eq!(s.get(...usize::max_value()), None);
assert_eq!(s.get(1...usize::max_value()), None);
assert_eq!(s.get(..=usize::max_value()), None);
assert_eq!(s.get(1..=usize::max_value()), None);
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/liballoc/tests/string.rs
Expand Up @@ -456,9 +456,9 @@ fn test_splice_char_boundary() {
#[test]
fn test_splice_inclusive_range() {
let mut v = String::from("12345");
v.splice(2...3, "789");
v.splice(2..=3, "789");
assert_eq!(v, "127895");
v.splice(1...2, "A");
v.splice(1..=2, "A");
assert_eq!(v, "1A895");
}

Expand All @@ -473,7 +473,7 @@ fn test_splice_out_of_bounds() {
#[should_panic]
fn test_splice_inclusive_out_of_bounds() {
let mut s = String::from("12345");
s.splice(5...5, "789");
s.splice(5..=5, "789");
}

#[test]
Expand Down
28 changes: 14 additions & 14 deletions src/liballoc/tests/vec.rs
Expand Up @@ -537,27 +537,27 @@ fn test_drain_range() {
#[test]
fn test_drain_inclusive_range() {
let mut v = vec!['a', 'b', 'c', 'd', 'e'];
for _ in v.drain(1...3) {
for _ in v.drain(1..=3) {
}
assert_eq!(v, &['a', 'e']);

let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect();
for _ in v.drain(1...5) {
let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect();
for _ in v.drain(1..=5) {
}
assert_eq!(v, &["0".to_string()]);

let mut v: Vec<String> = (0...5).map(|x| x.to_string()).collect();
for _ in v.drain(0...5) {
let mut v: Vec<String> = (0..=5).map(|x| x.to_string()).collect();
for _ in v.drain(0..=5) {
}
assert_eq!(v, Vec::<String>::new());

let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect();
for _ in v.drain(0...3) {
let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect();
for _ in v.drain(0..=3) {
}
assert_eq!(v, &["4".to_string(), "5".to_string()]);

let mut v: Vec<_> = (0...1).map(|x| x.to_string()).collect();
for _ in v.drain(...0) {
let mut v: Vec<_> = (0..=1).map(|x| x.to_string()).collect();
for _ in v.drain(..=0) {
}
assert_eq!(v, &["1".to_string()]);
}
Expand All @@ -572,7 +572,7 @@ fn test_drain_max_vec_size() {

let mut v = Vec::<()>::with_capacity(usize::max_value());
unsafe { v.set_len(usize::max_value()); }
for _ in v.drain(usize::max_value() - 1...usize::max_value() - 1) {
for _ in v.drain(usize::max_value() - 1..=usize::max_value() - 1) {
}
assert_eq!(v.len(), usize::max_value() - 1);
}
Expand All @@ -581,7 +581,7 @@ fn test_drain_max_vec_size() {
#[should_panic]
fn test_drain_inclusive_out_of_bounds() {
let mut v = vec![1, 2, 3, 4, 5];
v.drain(5...5);
v.drain(5..=5);
}

#[test]
Expand All @@ -598,10 +598,10 @@ fn test_splice() {
fn test_splice_inclusive_range() {
let mut v = vec![1, 2, 3, 4, 5];
let a = [10, 11, 12];
let t1: Vec<_> = v.splice(2...3, a.iter().cloned()).collect();
let t1: Vec<_> = v.splice(2..=3, a.iter().cloned()).collect();
assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
assert_eq!(t1, &[3, 4]);
let t2: Vec<_> = v.splice(1...2, Some(20)).collect();
let t2: Vec<_> = v.splice(1..=2, Some(20)).collect();
assert_eq!(v, &[1, 20, 11, 12, 5]);
assert_eq!(t2, &[2, 10]);
}
Expand All @@ -619,7 +619,7 @@ fn test_splice_out_of_bounds() {
fn test_splice_inclusive_out_of_bounds() {
let mut v = vec![1, 2, 3, 4, 5];
let a = [10, 11, 12];
v.splice(5...5, a.iter().cloned());
v.splice(5..=5, a.iter().cloned());
}

#[test]
Expand Down
50 changes: 25 additions & 25 deletions src/libcore/ops/range.rs
Expand Up @@ -241,22 +241,22 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
}
}

/// An range bounded inclusively below and above (`start...end`).
/// An range bounded inclusively below and above (`start..=end`).
///
/// The `RangeInclusive` `start...end` contains all values with `x >= start`
/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
/// and `x <= end`.
///
/// # Examples
///
/// ```
/// #![feature(inclusive_range,inclusive_range_syntax)]
///
/// assert_eq!((3...5), std::ops::RangeInclusive { start: 3, end: 5 });
/// assert_eq!(3 + 4 + 5, (3...5).sum());
/// assert_eq!((3..=5), std::ops::RangeInclusive { start: 3, end: 5 });
/// assert_eq!(3 + 4 + 5, (3..=5).sum());
///
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ ...2], [0,1,2 ]);
/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive
/// assert_eq!(arr[ ..=2], [0,1,2 ]);
/// assert_eq!(arr[1..=2], [ 1,2 ]); // RangeInclusive
/// ```
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
Expand All @@ -276,7 +276,7 @@ pub struct RangeInclusive<Idx> {
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{:?}...{:?}", self.start, self.end)
write!(fmt, "{:?}..={:?}", self.start, self.end)
}
}

Expand All @@ -289,32 +289,32 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// ```
/// #![feature(range_contains,inclusive_range_syntax)]
///
/// assert!(!(3...5).contains(2));
/// assert!( (3...5).contains(3));
/// assert!( (3...5).contains(4));
/// assert!( (3...5).contains(5));
/// assert!(!(3...5).contains(6));
/// assert!(!(3..=5).contains(2));
/// assert!( (3..=5).contains(3));
/// assert!( (3..=5).contains(4));
/// assert!( (3..=5).contains(5));
/// assert!(!(3..=5).contains(6));
///
/// assert!( (3...3).contains(3));
/// assert!(!(3...2).contains(3));
/// assert!( (3..=3).contains(3));
/// assert!(!(3..=2).contains(3));
/// ```
pub fn contains(&self, item: Idx) -> bool {
self.start <= item && item <= self.end
}
}

/// A range only bounded inclusively above (`...end`).
/// A range only bounded inclusively above (`..=end`).
///
/// The `RangeToInclusive` `...end` contains all values with `x <= end`.
/// The `RangeToInclusive` `..=end` contains all values with `x <= end`.
/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
///
/// # Examples
///
/// The `...end` syntax is a `RangeToInclusive`:
/// The `..=end` syntax is a `RangeToInclusive`:
///
/// ```
/// #![feature(inclusive_range,inclusive_range_syntax)]
/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 });
/// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 });
/// ```
///
/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
Expand All @@ -325,7 +325,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
///
/// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>:
/// // std::iter::Iterator` is not satisfied
/// for i in ...5 {
/// for i in ..=5 {
/// // ...
/// }
/// ```
Expand All @@ -337,8 +337,8 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// #![feature(inclusive_range_syntax)]
///
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive
/// assert_eq!(arr[1...2], [ 1,2 ]);
/// assert_eq!(arr[ ..=2], [0,1,2 ]); // RangeToInclusive
/// assert_eq!(arr[1..=2], [ 1,2 ]);
/// ```
///
/// [`IntoIterator`]: ../iter/trait.Iterator.html
Expand All @@ -357,7 +357,7 @@ pub struct RangeToInclusive<Idx> {
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "...{:?}", self.end)
write!(fmt, "..={:?}", self.end)
}
}

Expand All @@ -370,9 +370,9 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
/// ```
/// #![feature(range_contains,inclusive_range_syntax)]
///
/// assert!( (...5).contains(-1_000_000_000));
/// assert!( (...5).contains(5));
/// assert!(!(...5).contains(6));
/// assert!( (..=5).contains(-1_000_000_000));
/// assert!( (..=5).contains(5));
/// assert!(!(..=5).contains(6));
/// ```
pub fn contains(&self, item: Idx) -> bool {
(item <= self.end)
Expand Down
4 changes: 4 additions & 0 deletions src/libcore/slice/mod.rs
Expand Up @@ -16,6 +16,10 @@

#![stable(feature = "rust1", since = "1.0.0")]

// FIXME: replace remaining ... by ..= after next stage0
// Silence warning: "... is being replaced by ..="
#![cfg_attr(not(stage0), allow(warnings))]

// How this module is organized.
//
// The library infrastructure for slices is fairly messy. There's
Expand Down

0 comments on commit e64efc9

Please sign in to comment.