Add support for ..=
syntax
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
This commit is contained in:
parent
3eb19bf9b1
commit
e64efc91f4
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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)>,
|
||||
@ -193,18 +193,18 @@ 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]
|
||||
@ -212,7 +212,7 @@ 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]
|
||||
|
@ -361,13 +361,13 @@ 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]
|
||||
@ -375,7 +375,7 @@ fn test_str_slice_rangeinclusive_max_panics() {
|
||||
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]
|
||||
@ -383,7 +383,7 @@ fn test_str_slicemut_rangetoinclusive_max_panics() {
|
||||
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]
|
||||
@ -391,13 +391,13 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
@ -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]
|
||||
|
@ -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()]);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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]
|
||||
@ -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]);
|
||||
}
|
||||
@ -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]
|
||||
|
@ -241,9 +241,9 @@ 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
|
||||
@ -251,12 +251,12 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
|
||||
/// ```
|
||||
/// #![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")]
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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 {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
@ -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
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
@ -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
|
||||
|
@ -1094,21 +1094,21 @@ fn test_range() {
|
||||
|
||||
#[test]
|
||||
fn test_range_inclusive_exhaustion() {
|
||||
let mut r = 10...10;
|
||||
let mut r = 10..=10;
|
||||
assert_eq!(r.next(), Some(10));
|
||||
assert_eq!(r, 1...0);
|
||||
assert_eq!(r, 1..=0);
|
||||
|
||||
let mut r = 10...10;
|
||||
let mut r = 10..=10;
|
||||
assert_eq!(r.next_back(), Some(10));
|
||||
assert_eq!(r, 1...0);
|
||||
assert_eq!(r, 1..=0);
|
||||
|
||||
let mut r = 10...12;
|
||||
let mut r = 10..=12;
|
||||
assert_eq!(r.nth(2), Some(12));
|
||||
assert_eq!(r, 1...0);
|
||||
assert_eq!(r, 1..=0);
|
||||
|
||||
let mut r = 10...12;
|
||||
let mut r = 10..=12;
|
||||
assert_eq!(r.nth(5), None);
|
||||
assert_eq!(r, 1...0);
|
||||
assert_eq!(r, 1..=0);
|
||||
|
||||
}
|
||||
|
||||
@ -1145,20 +1145,20 @@ fn test_range_from_nth() {
|
||||
|
||||
#[test]
|
||||
fn test_range_inclusive_nth() {
|
||||
assert_eq!((10...15).nth(0), Some(10));
|
||||
assert_eq!((10...15).nth(1), Some(11));
|
||||
assert_eq!((10...15).nth(5), Some(15));
|
||||
assert_eq!((10...15).nth(6), None);
|
||||
assert_eq!((10..=15).nth(0), Some(10));
|
||||
assert_eq!((10..=15).nth(1), Some(11));
|
||||
assert_eq!((10..=15).nth(5), Some(15));
|
||||
assert_eq!((10..=15).nth(6), None);
|
||||
|
||||
let mut r = 10_u8...20;
|
||||
let mut r = 10_u8..=20;
|
||||
assert_eq!(r.nth(2), Some(12));
|
||||
assert_eq!(r, 13...20);
|
||||
assert_eq!(r, 13..=20);
|
||||
assert_eq!(r.nth(2), Some(15));
|
||||
assert_eq!(r, 16...20);
|
||||
assert_eq!(r, 16..=20);
|
||||
assert_eq!(r.is_empty(), false);
|
||||
assert_eq!(r.nth(10), None);
|
||||
assert_eq!(r.is_empty(), true);
|
||||
assert_eq!(r, 1...0); // We may not want to document/promise this detail
|
||||
assert_eq!(r, 1..=0); // We may not want to document/promise this detail
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -509,6 +509,7 @@ impl TokenTree {
|
||||
Dot => op!('.'),
|
||||
DotDot => joint!('.', Dot),
|
||||
DotDotDot => joint!('.', DotDot),
|
||||
DotDotEq => joint!('.', DotEq),
|
||||
Comma => op!(','),
|
||||
Semi => op!(';'),
|
||||
Colon => op!(':'),
|
||||
@ -531,6 +532,7 @@ impl TokenTree {
|
||||
})
|
||||
}
|
||||
|
||||
DotEq => unreachable!(),
|
||||
OpenDelim(..) | CloseDelim(..) => unreachable!(),
|
||||
Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
|
||||
};
|
||||
|
@ -202,8 +202,8 @@ impl Quote for Token {
|
||||
|
||||
gen_match! {
|
||||
Eq, Lt, Le, EqEq, Ne, Ge, Gt, AndAnd, OrOr, Not, Tilde, At, Dot, DotDot, DotDotDot,
|
||||
Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar, Question,
|
||||
Underscore;
|
||||
DotDotEq, Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar,
|
||||
Question, Underscore;
|
||||
|
||||
Token::OpenDelim(delim) => quote!(rt::token::OpenDelim((quote delim))),
|
||||
Token::CloseDelim(delim) => quote!(rt::token::CloseDelim((quote delim))),
|
||||
|
@ -272,6 +272,8 @@ fn hash_token<'gcx, W: StableHasherResult>(token: &token::Token,
|
||||
token::Token::Dot |
|
||||
token::Token::DotDot |
|
||||
token::Token::DotDotDot |
|
||||
token::Token::DotDotEq |
|
||||
token::Token::DotEq |
|
||||
token::Token::Comma |
|
||||
token::Token::Semi |
|
||||
token::Token::Colon |
|
||||
|
@ -249,8 +249,8 @@ impl<'a> Classifier<'a> {
|
||||
token::BinOpEq(..) | token::FatArrow => Class::Op,
|
||||
|
||||
// Miscellaneous, no highlighting.
|
||||
token::Dot | token::DotDot | token::DotDotDot | token::Comma | token::Semi |
|
||||
token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) |
|
||||
token::Dot | token::DotDot | token::DotDotDot | token::DotDotEq | token::Comma |
|
||||
token::Semi | token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) |
|
||||
token::CloseDelim(token::Brace) | token::CloseDelim(token::Paren) |
|
||||
token::CloseDelim(token::NoDelim) => Class::None,
|
||||
|
||||
@ -353,7 +353,7 @@ impl<'a> Classifier<'a> {
|
||||
token::Lifetime(..) => Class::Lifetime,
|
||||
|
||||
token::Underscore | token::Eof | token::Interpolated(..) |
|
||||
token::Tilde | token::At => Class::None,
|
||||
token::Tilde | token::At | token::DotEq => Class::None,
|
||||
};
|
||||
|
||||
// Anything that didn't return above is the simple case where we the
|
||||
|
@ -291,7 +291,7 @@ Erroneous code example:
|
||||
|
||||
fn main() {
|
||||
let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
|
||||
let x = &tmp[1...]; // error: inclusive range was used with no end
|
||||
let x = &tmp[1..=]; // error: inclusive range was used with no end
|
||||
}
|
||||
```
|
||||
|
||||
@ -312,7 +312,7 @@ Or put an end to your inclusive range:
|
||||
|
||||
fn main() {
|
||||
let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
|
||||
let x = &tmp[1...3]; // ok!
|
||||
let x = &tmp[1..=3]; // ok!
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
@ -686,7 +686,9 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
|
||||
token::At => "At",
|
||||
token::Dot => "Dot",
|
||||
token::DotDot => "DotDot",
|
||||
token::DotEq => "DotEq",
|
||||
token::DotDotDot => "DotDotDot",
|
||||
token::DotDotEq => "DotDotEq",
|
||||
token::Comma => "Comma",
|
||||
token::Semi => "Semi",
|
||||
token::Colon => "Colon",
|
||||
|
@ -261,7 +261,7 @@ declare_features! (
|
||||
// rustc internal
|
||||
(active, abi_vectorcall, "1.7.0", None),
|
||||
|
||||
// a...b and ...b
|
||||
// a..=b and ..=b
|
||||
(active, inclusive_range_syntax, "1.7.0", Some(28237)),
|
||||
|
||||
// X..Y patterns
|
||||
|
@ -1131,6 +1131,9 @@ impl<'a> StringReader<'a> {
|
||||
if self.ch_is('.') {
|
||||
self.bump();
|
||||
Ok(token::DotDotDot)
|
||||
} else if self.ch_is('=') {
|
||||
self.bump();
|
||||
Ok(token::DotDotEq)
|
||||
} else {
|
||||
Ok(token::DotDot)
|
||||
}
|
||||
|
@ -432,7 +432,7 @@ impl Error {
|
||||
Error::InclusiveRangeWithNoEnd => {
|
||||
let mut err = struct_span_err!(handler, sp, E0586,
|
||||
"inclusive range with no end");
|
||||
err.help("inclusive ranges must be bounded at the end (`...b` or `a...b`)");
|
||||
err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)");
|
||||
err
|
||||
}
|
||||
}
|
||||
@ -2710,7 +2710,7 @@ impl<'a> Parser<'a> {
|
||||
LhsExpr::AttributesParsed(attrs) => Some(attrs),
|
||||
_ => None,
|
||||
};
|
||||
if self.token == token::DotDot || self.token == token::DotDotDot {
|
||||
if [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token) {
|
||||
return self.parse_prefix_range_expr(attrs);
|
||||
} else {
|
||||
self.parse_prefix_expr(attrs)?
|
||||
@ -2744,6 +2744,10 @@ impl<'a> Parser<'a> {
|
||||
if op.precedence() < min_prec {
|
||||
break;
|
||||
}
|
||||
// Warn about deprecated ... syntax (until SNAP)
|
||||
if self.token == token::DotDotDot {
|
||||
self.warn_dotdoteq(self.span);
|
||||
}
|
||||
self.bump();
|
||||
if op.is_comparison() {
|
||||
self.check_no_chained_comparison(&lhs, &op);
|
||||
@ -2770,12 +2774,13 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
};
|
||||
continue
|
||||
} else if op == AssocOp::DotDot || op == AssocOp::DotDotDot {
|
||||
// If we didn’t have to handle `x..`/`x...`, it would be pretty easy to
|
||||
} else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
|
||||
// If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to
|
||||
// generalise it to the Fixity::None code.
|
||||
//
|
||||
// We have 2 alternatives here: `x..y`/`x...y` and `x..`/`x...` The other
|
||||
// We have 2 alternatives here: `x..y`/`x..=y` and `x..`/`x..=` The other
|
||||
// two variants are handled with `parse_prefix_range_expr` call above.
|
||||
// (and `x...y`/`x...` until SNAP)
|
||||
let rhs = if self.is_at_start_of_range_notation_rhs() {
|
||||
Some(self.parse_assoc_expr_with(op.precedence() + 1,
|
||||
LhsExpr::NotYetParsed)?)
|
||||
@ -2852,8 +2857,8 @@ impl<'a> Parser<'a> {
|
||||
let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
|
||||
self.mk_expr(span, aopexpr, ThinVec::new())
|
||||
}
|
||||
AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotDot => {
|
||||
self.bug("As, Colon, DotDot or DotDotDot branch reached")
|
||||
AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => {
|
||||
self.bug("AssocOp should have been handled by special case")
|
||||
}
|
||||
};
|
||||
|
||||
@ -2949,17 +2954,22 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse prefix-forms of range notation: `..expr`, `..`, `...expr`
|
||||
/// Parse prefix-forms of range notation: `..expr`, `..`, `..=expr` (and `...expr` until SNAP)
|
||||
fn parse_prefix_range_expr(&mut self,
|
||||
already_parsed_attrs: Option<ThinVec<Attribute>>)
|
||||
-> PResult<'a, P<Expr>> {
|
||||
debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot,
|
||||
"parse_prefix_range_expr: token {:?} is not DotDot or DotDotDot",
|
||||
// SNAP remove DotDotDot
|
||||
debug_assert!([token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token),
|
||||
"parse_prefix_range_expr: token {:?} is not DotDot/DotDotDot/DotDotEq",
|
||||
self.token);
|
||||
let tok = self.token.clone();
|
||||
let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
|
||||
let lo = self.span;
|
||||
let mut hi = self.span;
|
||||
// Warn about deprecated ... syntax (until SNAP)
|
||||
if tok == token::DotDotDot {
|
||||
self.warn_dotdoteq(self.span);
|
||||
}
|
||||
self.bump();
|
||||
let opt_end = if self.is_at_start_of_range_notation_rhs() {
|
||||
// RHS must be parsed with more associativity than the dots.
|
||||
@ -3450,7 +3460,7 @@ impl<'a> Parser<'a> {
|
||||
fn parse_as_ident(&mut self) -> bool {
|
||||
self.look_ahead(1, |t| match *t {
|
||||
token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
|
||||
token::DotDotDot | token::ModSep | token::Not => Some(false),
|
||||
token::DotDotDot | token::DotDotEq | token::ModSep | token::Not => Some(false),
|
||||
// ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the
|
||||
// range pattern branch
|
||||
token::DotDot => None,
|
||||
@ -3544,11 +3554,12 @@ impl<'a> Parser<'a> {
|
||||
let mac = respan(lo.to(self.prev_span), Mac_ { path: path, tts: tts });
|
||||
pat = PatKind::Mac(mac);
|
||||
}
|
||||
token::DotDotDot | token::DotDot => {
|
||||
token::DotDotDot | token::DotDotEq | token::DotDot => {
|
||||
let end_kind = match self.token {
|
||||
token::DotDot => RangeEnd::Excluded,
|
||||
token::DotDotDot => RangeEnd::Included,
|
||||
_ => panic!("can only parse `..` or `...` for ranges (checked above)"),
|
||||
token::DotDotDot | token::DotDotEq => RangeEnd::Included,
|
||||
_ => panic!("can only parse `..`/`...`/`..=` for ranges \
|
||||
(checked above)"),
|
||||
};
|
||||
// Parse range
|
||||
let span = lo.to(self.prev_span);
|
||||
@ -3590,6 +3601,9 @@ impl<'a> Parser<'a> {
|
||||
if self.eat(&token::DotDotDot) {
|
||||
let end = self.parse_pat_range_end()?;
|
||||
pat = PatKind::Range(begin, end, RangeEnd::Included);
|
||||
} else if self.eat(&token::DotDotEq) {
|
||||
let end = self.parse_pat_range_end()?;
|
||||
pat = PatKind::Range(begin, end, RangeEnd::Included);
|
||||
} else if self.eat(&token::DotDot) {
|
||||
let end = self.parse_pat_range_end()?;
|
||||
pat = PatKind::Range(begin, end, RangeEnd::Excluded);
|
||||
@ -3973,7 +3987,7 @@ impl<'a> Parser<'a> {
|
||||
token::BinOp(token::Minus) | token::BinOp(token::Star) |
|
||||
token::BinOp(token::And) | token::BinOp(token::Or) |
|
||||
token::AndAnd | token::OrOr |
|
||||
token::DotDot | token::DotDotDot => false,
|
||||
token::DotDot | token::DotDotDot | token::DotDotEq => false,
|
||||
_ => true,
|
||||
} {
|
||||
self.warn_missing_semicolon();
|
||||
@ -4195,6 +4209,12 @@ impl<'a> Parser<'a> {
|
||||
}).emit();
|
||||
}
|
||||
|
||||
fn warn_dotdoteq(&self, span: Span) {
|
||||
self.diagnostic().struct_span_warn(span, {
|
||||
"`...` is being replaced by `..=`"
|
||||
}).emit();
|
||||
}
|
||||
|
||||
// Parse bounds of a type parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
|
||||
// BOUND = TY_BOUND | LT_BOUND
|
||||
// LT_BOUND = LIFETIME (e.g. `'a`)
|
||||
|
@ -152,6 +152,8 @@ pub enum Token {
|
||||
Dot,
|
||||
DotDot,
|
||||
DotDotDot,
|
||||
DotDotEq,
|
||||
DotEq, // HACK(durka42) never produced by the parser, only used for libproc_macro
|
||||
Comma,
|
||||
Semi,
|
||||
Colon,
|
||||
@ -212,18 +214,19 @@ impl Token {
|
||||
pub fn can_begin_expr(&self) -> bool {
|
||||
match *self {
|
||||
Ident(ident) => ident_can_begin_expr(ident), // value name or keyword
|
||||
OpenDelim(..) | // tuple, array or block
|
||||
Literal(..) | // literal
|
||||
Not | // operator not
|
||||
BinOp(Minus) | // unary minus
|
||||
BinOp(Star) | // dereference
|
||||
BinOp(Or) | OrOr | // closure
|
||||
BinOp(And) | // reference
|
||||
AndAnd | // double reference
|
||||
DotDot | DotDotDot | // range notation
|
||||
Lt | BinOp(Shl) | // associated path
|
||||
ModSep | // global path
|
||||
Pound => true, // expression attributes
|
||||
OpenDelim(..) | // tuple, array or block
|
||||
Literal(..) | // literal
|
||||
Not | // operator not
|
||||
BinOp(Minus) | // unary minus
|
||||
BinOp(Star) | // dereference
|
||||
BinOp(Or) | OrOr | // closure
|
||||
BinOp(And) | // reference
|
||||
AndAnd | // double reference
|
||||
DotDot | DotDotDot | DotDotEq | // range notation
|
||||
// SNAP remove DotDotDot
|
||||
Lt | BinOp(Shl) | // associated path
|
||||
ModSep | // global path
|
||||
Pound => true, // expression attributes
|
||||
Interpolated(ref nt) => match nt.0 {
|
||||
NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) => true,
|
||||
_ => false,
|
||||
@ -402,10 +405,12 @@ impl Token {
|
||||
Dot => match joint {
|
||||
Dot => DotDot,
|
||||
DotDot => DotDotDot,
|
||||
DotEq => DotDotEq,
|
||||
_ => return None,
|
||||
},
|
||||
DotDot => match joint {
|
||||
Dot => DotDotDot,
|
||||
Eq => DotDotEq,
|
||||
_ => return None,
|
||||
},
|
||||
Colon => match joint {
|
||||
@ -413,9 +418,9 @@ impl Token {
|
||||
_ => return None,
|
||||
},
|
||||
|
||||
Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | Comma |
|
||||
Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question |
|
||||
OpenDelim(..) | CloseDelim(..) | Underscore => return None,
|
||||
Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | DotEq |
|
||||
DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
|
||||
Question | OpenDelim(..) | CloseDelim(..) | Underscore => return None,
|
||||
|
||||
Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
|
||||
Whitespace | Comment | Shebang(..) | Eof => return None,
|
||||
|
@ -203,6 +203,8 @@ pub fn token_to_string(tok: &Token) -> String {
|
||||
token::Dot => ".".to_string(),
|
||||
token::DotDot => "..".to_string(),
|
||||
token::DotDotDot => "...".to_string(),
|
||||
token::DotDotEq => "..=".to_string(),
|
||||
token::DotEq => ".=".to_string(),
|
||||
token::Comma => ",".to_string(),
|
||||
token::Semi => ";".to_string(),
|
||||
token::Colon => ":".to_string(),
|
||||
|
@ -62,8 +62,8 @@ pub enum AssocOp {
|
||||
As,
|
||||
/// `..` range
|
||||
DotDot,
|
||||
/// `...` range
|
||||
DotDotDot,
|
||||
/// `..=` range
|
||||
DotDotEq,
|
||||
/// `:`
|
||||
Colon,
|
||||
}
|
||||
@ -105,7 +105,8 @@ impl AssocOp {
|
||||
Token::AndAnd => Some(LAnd),
|
||||
Token::OrOr => Some(LOr),
|
||||
Token::DotDot => Some(DotDot),
|
||||
Token::DotDotDot => Some(DotDotDot),
|
||||
Token::DotDotEq => Some(DotDotEq),
|
||||
Token::DotDotDot => Some(DotDotEq), // remove this after SNAP
|
||||
Token::Colon => Some(Colon),
|
||||
_ if t.is_keyword(keywords::As) => Some(As),
|
||||
_ => None
|
||||
@ -151,7 +152,7 @@ impl AssocOp {
|
||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7,
|
||||
LAnd => 6,
|
||||
LOr => 5,
|
||||
DotDot | DotDotDot => 4,
|
||||
DotDot | DotDotEq => 4,
|
||||
Inplace => 3,
|
||||
Assign | AssignOp(_) => 2,
|
||||
}
|
||||
@ -166,7 +167,7 @@ impl AssocOp {
|
||||
As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd |
|
||||
BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual |
|
||||
LAnd | LOr | Colon => Fixity::Left,
|
||||
DotDot | DotDotDot => Fixity::None
|
||||
DotDot | DotDotEq => Fixity::None
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,7 +177,7 @@ impl AssocOp {
|
||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true,
|
||||
Inplace | Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract |
|
||||
ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr |
|
||||
DotDot | DotDotDot | Colon => false
|
||||
DotDot | DotDotEq | Colon => false
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,7 +187,7 @@ impl AssocOp {
|
||||
Assign | AssignOp(_) | Inplace => true,
|
||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide |
|
||||
Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd |
|
||||
LOr | DotDot | DotDotDot | Colon => false
|
||||
LOr | DotDot | DotDotEq | Colon => false
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +212,7 @@ impl AssocOp {
|
||||
BitOr => Some(BinOpKind::BitOr),
|
||||
LAnd => Some(BinOpKind::And),
|
||||
LOr => Some(BinOpKind::Or),
|
||||
Inplace | Assign | AssignOp(_) | As | DotDot | DotDotDot | Colon => None
|
||||
Inplace | Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,5 +10,5 @@
|
||||
|
||||
fn main() {
|
||||
let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
|
||||
let x = &tmp[1...]; //~ ERROR E0586
|
||||
let x = &tmp[1..=]; //~ ERROR E0586
|
||||
}
|
||||
|
@ -18,12 +18,12 @@ pub fn main() {
|
||||
..1;
|
||||
0..1;
|
||||
|
||||
...; //~ERROR inclusive range with no end
|
||||
..=; //~ERROR inclusive range with no end
|
||||
//~^HELP bounded at the end
|
||||
0...; //~ERROR inclusive range with no end
|
||||
0..=; //~ERROR inclusive range with no end
|
||||
//~^HELP bounded at the end
|
||||
...1;
|
||||
0...1;
|
||||
..=1;
|
||||
0..=1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
// #![feature(inclusive_range)]
|
||||
|
||||
pub fn main() {
|
||||
let _: std::ops::RangeInclusive<_> = { use std::intrinsics; 1 } ... { use std::intrinsics; 2 };
|
||||
let _: std::ops::RangeInclusive<_> = { use std::intrinsics; 1 } ..= { use std::intrinsics; 2 };
|
||||
//~^ ERROR use of unstable library feature 'inclusive_range'
|
||||
//~| ERROR core_intrinsics
|
||||
//~| ERROR core_intrinsics
|
||||
|
@ -153,5 +153,5 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
|
||||
&slice[3...7]
|
||||
&slice[3..=7]
|
||||
}
|
||||
|
@ -11,5 +11,5 @@
|
||||
// Parsing of range patterns
|
||||
|
||||
fn main() {
|
||||
let macropus!() ... 11 = 12; //~ error: expected one of `:`, `;`, or `=`, found `...`
|
||||
let macropus!() ..= 11 = 12; //~ error: expected one of `:`, `;`, or `=`, found `..=`
|
||||
}
|
||||
|
@ -11,5 +11,5 @@
|
||||
// Parsing of range patterns
|
||||
|
||||
fn main() {
|
||||
let 10 ... makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, or `=`, found `!`
|
||||
let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, or `=`, found `!`
|
||||
}
|
||||
|
@ -11,5 +11,5 @@
|
||||
// Parsing of range patterns
|
||||
|
||||
fn main() {
|
||||
let 10 ... 10 + 3 = 12; //~ expected one of `:`, `;`, or `=`, found `+`
|
||||
let 10 ..= 10 + 3 = 12; //~ expected one of `:`, `;`, or `=`, found `+`
|
||||
}
|
||||
|
@ -11,5 +11,6 @@
|
||||
// Parsing of range patterns
|
||||
|
||||
fn main() {
|
||||
let 10 - 3 ... 10 = 8; //~ error: expected one of `...`, `..`, `:`, `;`, or `=`, found `-`
|
||||
let 10 - 3 ..= 10 = 8;
|
||||
//~^ error: expected one of `...`, `..=`, `..`, `:`, `;`, or `=`, found `-`
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
#![feature(inclusive_range_syntax, inclusive_range)]
|
||||
|
||||
pub fn main() {
|
||||
for _ in 1... {} //~ERROR inclusive range with no end
|
||||
for _ in 1..= {} //~ERROR inclusive range with no end
|
||||
//~^HELP bounded at the end
|
||||
}
|
||||
|
||||
|
@ -15,21 +15,21 @@
|
||||
// #![feature(inclusive_range_syntax, inclusive_range)]
|
||||
|
||||
macro_rules! m {
|
||||
() => { for _ in 1...10 {} } //~ ERROR inclusive range syntax is experimental
|
||||
() => { for _ in 1..=10 {} } //~ ERROR inclusive range syntax is experimental
|
||||
}
|
||||
|
||||
#[cfg(nope)]
|
||||
fn f() {}
|
||||
#[cfg(not(nope))]
|
||||
fn f() {
|
||||
for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental
|
||||
for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental
|
||||
}
|
||||
|
||||
#[cfg(nope)]
|
||||
macro_rules! n { () => {} }
|
||||
#[cfg(not(nope))]
|
||||
macro_rules! n {
|
||||
() => { for _ in 1...10 {} } //~ ERROR inclusive range syntax is experimental
|
||||
() => { for _ in 1..=10 {} } //~ ERROR inclusive range syntax is experimental
|
||||
}
|
||||
|
||||
macro_rules! o {
|
||||
@ -38,7 +38,7 @@ macro_rules! o {
|
||||
fn g() {}
|
||||
#[cfg(not(nope))]
|
||||
fn g() {
|
||||
for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental
|
||||
for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental
|
||||
}
|
||||
|
||||
g();
|
||||
@ -54,7 +54,7 @@ macro_rules! p {
|
||||
fn h() {}
|
||||
#[cfg(not(nope))]
|
||||
fn h() {
|
||||
for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental
|
||||
for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental
|
||||
}
|
||||
|
||||
h();
|
||||
@ -62,8 +62,8 @@ macro_rules! p {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental
|
||||
for _ in ...10 {} //~ ERROR inclusive range syntax is experimental
|
||||
for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental
|
||||
for _ in ..=10 {} //~ ERROR inclusive range syntax is experimental
|
||||
|
||||
f(); // not allowed in cfg'ed functions
|
||||
|
||||
|
20
src/test/run-pass/inc-range-pat.rs
Normal file
20
src/test/run-pass/inc-range-pat.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test old and new syntax for inclusive range patterns.
|
||||
|
||||
fn main() {
|
||||
assert!(match 42 { 0 ... 100 => true, _ => false });
|
||||
assert!(match 42 { 0 ..= 100 => true, _ => false });
|
||||
|
||||
assert!(match 'x' { 'a' ... 'z' => true, _ => false });
|
||||
assert!(match 'x' { 'a' ..= 'z' => true, _ => false });
|
||||
}
|
||||
|
@ -17,18 +17,18 @@ use std::ops::{RangeInclusive, RangeToInclusive};
|
||||
fn foo() -> isize { 42 }
|
||||
|
||||
// Test that range syntax works in return statements
|
||||
fn return_range_to() -> RangeToInclusive<i32> { return ...1; }
|
||||
fn return_range_to() -> RangeToInclusive<i32> { return ..=1; }
|
||||
|
||||
pub fn main() {
|
||||
let mut count = 0;
|
||||
for i in 0_usize...10 {
|
||||
for i in 0_usize..=10 {
|
||||
assert!(i >= 0 && i <= 10);
|
||||
count += i;
|
||||
}
|
||||
assert_eq!(count, 55);
|
||||
|
||||
let mut count = 0;
|
||||
let mut range = 0_usize...10;
|
||||
let mut range = 0_usize..=10;
|
||||
for i in range {
|
||||
assert!(i >= 0 && i <= 10);
|
||||
count += i;
|
||||
@ -36,53 +36,53 @@ pub fn main() {
|
||||
assert_eq!(count, 55);
|
||||
|
||||
let mut count = 0;
|
||||
for i in (0_usize...10).step_by(2) {
|
||||
for i in (0_usize..=10).step_by(2) {
|
||||
assert!(i >= 0 && i <= 10 && i % 2 == 0);
|
||||
count += i;
|
||||
}
|
||||
assert_eq!(count, 30);
|
||||
|
||||
let _ = 0_usize...4+4-3;
|
||||
let _ = 0...foo();
|
||||
let _ = 0_usize..=4+4-3;
|
||||
let _ = 0..=foo();
|
||||
|
||||
let _ = { &42...&100 }; // references to literals are OK
|
||||
let _ = ...42_usize;
|
||||
let _ = { &42..=&100 }; // references to literals are OK
|
||||
let _ = ..=42_usize;
|
||||
|
||||
// Test we can use two different types with a common supertype.
|
||||
let x = &42;
|
||||
{
|
||||
let y = 42;
|
||||
let _ = x...&y;
|
||||
let _ = x..=&y;
|
||||
}
|
||||
|
||||
// test collection indexing
|
||||
let vec = (0...10).collect::<Vec<_>>();
|
||||
let vec = (0..=10).collect::<Vec<_>>();
|
||||
let slice: &[_] = &*vec;
|
||||
let string = String::from("hello world");
|
||||
let stir = "hello world";
|
||||
|
||||
assert_eq!(&vec[3...6], &[3, 4, 5, 6]);
|
||||
assert_eq!(&vec[ ...6], &[0, 1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(&vec[3..=6], &[3, 4, 5, 6]);
|
||||
assert_eq!(&vec[ ..=6], &[0, 1, 2, 3, 4, 5, 6]);
|
||||
|
||||
assert_eq!(&slice[3...6], &[3, 4, 5, 6]);
|
||||
assert_eq!(&slice[ ...6], &[0, 1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(&slice[3..=6], &[3, 4, 5, 6]);
|
||||
assert_eq!(&slice[ ..=6], &[0, 1, 2, 3, 4, 5, 6]);
|
||||
|
||||
assert_eq!(&string[3...6], "lo w");
|
||||
assert_eq!(&string[ ...6], "hello w");
|
||||
assert_eq!(&string[3..=6], "lo w");
|
||||
assert_eq!(&string[ ..=6], "hello w");
|
||||
|
||||
assert_eq!(&stir[3...6], "lo w");
|
||||
assert_eq!(&stir[ ...6], "hello w");
|
||||
assert_eq!(&stir[3..=6], "lo w");
|
||||
assert_eq!(&stir[ ..=6], "hello w");
|
||||
|
||||
// test the size hints and emptying
|
||||
let mut long = 0...255u8;
|
||||
let mut short = 42...42u8;
|
||||
let mut long = 0..=255u8;
|
||||
let mut short = 42..=42u8;
|
||||
assert_eq!(long.size_hint(), (256, Some(256)));
|
||||
assert_eq!(short.size_hint(), (1, Some(1)));
|
||||
long.next();
|
||||
short.next();
|
||||
assert_eq!(long.size_hint(), (255, Some(255)));
|
||||
assert_eq!(short.size_hint(), (0, Some(0)));
|
||||
assert_eq!(short, 1...0);
|
||||
assert_eq!(short, 1..=0);
|
||||
|
||||
assert_eq!(long.len(), 255);
|
||||
assert_eq!(short.len(), 0);
|
||||
@ -94,31 +94,31 @@ pub fn main() {
|
||||
assert_eq!(long.next(), Some(1));
|
||||
assert_eq!(long.next(), Some(2));
|
||||
assert_eq!(long.next_back(), Some(252));
|
||||
for i in 3...251 {
|
||||
for i in 3..=251 {
|
||||
assert_eq!(long.next(), Some(i));
|
||||
}
|
||||
assert_eq!(long, 1...0);
|
||||
assert_eq!(long, 1..=0);
|
||||
|
||||
// check underflow
|
||||
let mut narrow = 1...0;
|
||||
let mut narrow = 1..=0;
|
||||
assert_eq!(narrow.next_back(), None);
|
||||
assert_eq!(narrow, 1...0);
|
||||
let mut zero = 0u8...0;
|
||||
assert_eq!(narrow, 1..=0);
|
||||
let mut zero = 0u8..=0;
|
||||
assert_eq!(zero.next_back(), Some(0));
|
||||
assert_eq!(zero.next_back(), None);
|
||||
assert_eq!(zero, 1...0);
|
||||
let mut high = 255u8...255;
|
||||
assert_eq!(zero, 1..=0);
|
||||
let mut high = 255u8..=255;
|
||||
assert_eq!(high.next_back(), Some(255));
|
||||
assert_eq!(high.next_back(), None);
|
||||
assert_eq!(high, 1...0);
|
||||
assert_eq!(high, 1..=0);
|
||||
|
||||
// what happens if you have a nonsense range?
|
||||
let mut nonsense = 10...5;
|
||||
let mut nonsense = 10..=5;
|
||||
assert_eq!(nonsense.next(), None);
|
||||
assert_eq!(nonsense, 10...5);
|
||||
assert_eq!(nonsense, 10..=5);
|
||||
|
||||
// output
|
||||
assert_eq!(format!("{:?}", 0...10), "0...10");
|
||||
assert_eq!(format!("{:?}", ...10), "...10");
|
||||
assert_eq!(format!("{:?}", long), "1...0");
|
||||
assert_eq!(format!("{:?}", 0..=10), "0..=10");
|
||||
assert_eq!(format!("{:?}", ..=10), "..=10");
|
||||
assert_eq!(format!("{:?}", long), "1..=0");
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
fn main() {
|
||||
let mut count = 0;
|
||||
for i in 0_usize...10 {
|
||||
for i in 0_usize..=10 {
|
||||
assert!(i >= 0 && i <= 10);
|
||||
count += i;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user