mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-07 12:48:30 +00:00
Auto merge of #44709 - Badel2:inclusive-range-dotdoteq, r=petrochenkov
Initial support for `..=` syntax #28237 This PR adds `..=` as a synonym for `...` in patterns and expressions. Since `...` in expressions was never stable, we now issue a warning. cc @durka r? @aturon
This commit is contained in:
commit
0e6f4cf51c
4
src/Cargo.lock
generated
4
src/Cargo.lock
generated
@ -1356,7 +1356,7 @@ dependencies = [
|
|||||||
"rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustfmt-nightly 0.2.5",
|
"rustfmt-nightly 0.2.7",
|
||||||
"serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1837,7 +1837,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustfmt-nightly"
|
name = "rustfmt-nightly"
|
||||||
version = "0.2.5"
|
version = "0.2.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -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
|
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
|
```rust
|
||||||
#![feature(inclusive_range_syntax)]
|
#![feature(inclusive_range_syntax)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
for i in 0...10 {
|
for i in 0..=10 {
|
||||||
println!("{}", i);
|
println!("{}", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ fn test_range_small() {
|
|||||||
fn test_range_inclusive() {
|
fn test_range_inclusive() {
|
||||||
let size = 500;
|
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)
|
fn check<'a, L, R>(lhs: L, rhs: R)
|
||||||
where L: IntoIterator<Item=(&'a i32, &'a i32)>,
|
where L: IntoIterator<Item=(&'a i32, &'a i32)>,
|
||||||
@ -193,18 +193,18 @@ fn test_range_inclusive() {
|
|||||||
assert_eq!(lhs, rhs);
|
assert_eq!(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
check(map.range(size + 1...size + 1), vec![]);
|
check(map.range(size + 1..=size + 1), vec![]);
|
||||||
check(map.range(size...size), vec![(&size, &size)]);
|
check(map.range(size..=size), vec![(&size, &size)]);
|
||||||
check(map.range(size...size + 1), vec![(&size, &size)]);
|
check(map.range(size..=size + 1), vec![(&size, &size)]);
|
||||||
check(map.range(0...0), vec![(&0, &0)]);
|
check(map.range(0..=0), vec![(&0, &0)]);
|
||||||
check(map.range(0...size - 1), map.range(..size));
|
check(map.range(0..=size - 1), map.range(..size));
|
||||||
check(map.range(-1...-1), vec![]);
|
check(map.range(-1..=-1), vec![]);
|
||||||
check(map.range(-1...size), map.range(..));
|
check(map.range(-1..=size), map.range(..));
|
||||||
check(map.range(...size), map.range(..));
|
check(map.range(..=size), map.range(..));
|
||||||
check(map.range(...200), map.range(..201));
|
check(map.range(..=200), map.range(..201));
|
||||||
check(map.range(5...8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
|
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..=0), vec![(&0, &0)]);
|
||||||
check(map.range(-1...2), vec![(&0, &0), (&1, &1), (&2, &2)]);
|
check(map.range(-1..=2), vec![(&0, &0), (&1, &1), (&2, &2)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -212,7 +212,7 @@ fn test_range_inclusive_max_value() {
|
|||||||
let max = ::std::usize::MAX;
|
let max = ::std::usize::MAX;
|
||||||
let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect();
|
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]
|
#[test]
|
||||||
|
@ -361,13 +361,13 @@ fn test_slice_fail() {
|
|||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn test_str_slice_rangetoinclusive_max_panics() {
|
fn test_str_slice_rangetoinclusive_max_panics() {
|
||||||
&"hello"[...usize::max_value()];
|
&"hello"[..=usize::max_value()];
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn test_str_slice_rangeinclusive_max_panics() {
|
fn test_str_slice_rangeinclusive_max_panics() {
|
||||||
&"hello"[1...usize::max_value()];
|
&"hello"[1..=usize::max_value()];
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -375,7 +375,7 @@ fn test_str_slice_rangeinclusive_max_panics() {
|
|||||||
fn test_str_slicemut_rangetoinclusive_max_panics() {
|
fn test_str_slicemut_rangetoinclusive_max_panics() {
|
||||||
let mut s = "hello".to_owned();
|
let mut s = "hello".to_owned();
|
||||||
let s: &mut str = &mut s;
|
let s: &mut str = &mut s;
|
||||||
&mut s[...usize::max_value()];
|
&mut s[..=usize::max_value()];
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -383,7 +383,7 @@ fn test_str_slicemut_rangetoinclusive_max_panics() {
|
|||||||
fn test_str_slicemut_rangeinclusive_max_panics() {
|
fn test_str_slicemut_rangeinclusive_max_panics() {
|
||||||
let mut s = "hello".to_owned();
|
let mut s = "hello".to_owned();
|
||||||
let s: &mut str = &mut s;
|
let s: &mut str = &mut s;
|
||||||
&mut s[1...usize::max_value()];
|
&mut s[1..=usize::max_value()];
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -391,13 +391,13 @@ fn test_str_get_maxinclusive() {
|
|||||||
let mut s = "hello".to_owned();
|
let mut s = "hello".to_owned();
|
||||||
{
|
{
|
||||||
let s: &str = &s;
|
let s: &str = &s;
|
||||||
assert_eq!(s.get(...usize::max_value()), None);
|
assert_eq!(s.get(..=usize::max_value()), None);
|
||||||
assert_eq!(s.get(1...usize::max_value()), None);
|
assert_eq!(s.get(1..=usize::max_value()), None);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let s: &mut str = &mut s;
|
let s: &mut str = &mut s;
|
||||||
assert_eq!(s.get(...usize::max_value()), None);
|
assert_eq!(s.get(..=usize::max_value()), None);
|
||||||
assert_eq!(s.get(1...usize::max_value()), None);
|
assert_eq!(s.get(1..=usize::max_value()), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,9 +456,9 @@ fn test_splice_char_boundary() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_splice_inclusive_range() {
|
fn test_splice_inclusive_range() {
|
||||||
let mut v = String::from("12345");
|
let mut v = String::from("12345");
|
||||||
v.splice(2...3, "789");
|
v.splice(2..=3, "789");
|
||||||
assert_eq!(v, "127895");
|
assert_eq!(v, "127895");
|
||||||
v.splice(1...2, "A");
|
v.splice(1..=2, "A");
|
||||||
assert_eq!(v, "1A895");
|
assert_eq!(v, "1A895");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,7 +473,7 @@ fn test_splice_out_of_bounds() {
|
|||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn test_splice_inclusive_out_of_bounds() {
|
fn test_splice_inclusive_out_of_bounds() {
|
||||||
let mut s = String::from("12345");
|
let mut s = String::from("12345");
|
||||||
s.splice(5...5, "789");
|
s.splice(5..=5, "789");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -537,27 +537,27 @@ fn test_drain_range() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_drain_inclusive_range() {
|
fn test_drain_inclusive_range() {
|
||||||
let mut v = vec!['a', 'b', 'c', 'd', 'e'];
|
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']);
|
assert_eq!(v, &['a', 'e']);
|
||||||
|
|
||||||
let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect();
|
let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect();
|
||||||
for _ in v.drain(1...5) {
|
for _ in v.drain(1..=5) {
|
||||||
}
|
}
|
||||||
assert_eq!(v, &["0".to_string()]);
|
assert_eq!(v, &["0".to_string()]);
|
||||||
|
|
||||||
let mut v: Vec<String> = (0...5).map(|x| x.to_string()).collect();
|
let mut v: Vec<String> = (0..=5).map(|x| x.to_string()).collect();
|
||||||
for _ in v.drain(0...5) {
|
for _ in v.drain(0..=5) {
|
||||||
}
|
}
|
||||||
assert_eq!(v, Vec::<String>::new());
|
assert_eq!(v, Vec::<String>::new());
|
||||||
|
|
||||||
let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect();
|
let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect();
|
||||||
for _ in v.drain(0...3) {
|
for _ in v.drain(0..=3) {
|
||||||
}
|
}
|
||||||
assert_eq!(v, &["4".to_string(), "5".to_string()]);
|
assert_eq!(v, &["4".to_string(), "5".to_string()]);
|
||||||
|
|
||||||
let mut v: Vec<_> = (0...1).map(|x| x.to_string()).collect();
|
let mut v: Vec<_> = (0..=1).map(|x| x.to_string()).collect();
|
||||||
for _ in v.drain(...0) {
|
for _ in v.drain(..=0) {
|
||||||
}
|
}
|
||||||
assert_eq!(v, &["1".to_string()]);
|
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());
|
let mut v = Vec::<()>::with_capacity(usize::max_value());
|
||||||
unsafe { v.set_len(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);
|
assert_eq!(v.len(), usize::max_value() - 1);
|
||||||
}
|
}
|
||||||
@ -581,7 +581,7 @@ fn test_drain_max_vec_size() {
|
|||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn test_drain_inclusive_out_of_bounds() {
|
fn test_drain_inclusive_out_of_bounds() {
|
||||||
let mut v = vec![1, 2, 3, 4, 5];
|
let mut v = vec![1, 2, 3, 4, 5];
|
||||||
v.drain(5...5);
|
v.drain(5..=5);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -598,10 +598,10 @@ fn test_splice() {
|
|||||||
fn test_splice_inclusive_range() {
|
fn test_splice_inclusive_range() {
|
||||||
let mut v = vec![1, 2, 3, 4, 5];
|
let mut v = vec![1, 2, 3, 4, 5];
|
||||||
let a = [10, 11, 12];
|
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!(v, &[1, 2, 10, 11, 12, 5]);
|
||||||
assert_eq!(t1, &[3, 4]);
|
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!(v, &[1, 20, 11, 12, 5]);
|
||||||
assert_eq!(t2, &[2, 10]);
|
assert_eq!(t2, &[2, 10]);
|
||||||
}
|
}
|
||||||
@ -619,7 +619,7 @@ fn test_splice_out_of_bounds() {
|
|||||||
fn test_splice_inclusive_out_of_bounds() {
|
fn test_splice_inclusive_out_of_bounds() {
|
||||||
let mut v = vec![1, 2, 3, 4, 5];
|
let mut v = vec![1, 2, 3, 4, 5];
|
||||||
let a = [10, 11, 12];
|
let a = [10, 11, 12];
|
||||||
v.splice(5...5, a.iter().cloned());
|
v.splice(5..=5, a.iter().cloned());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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`.
|
/// and `x <= end`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -251,12 +251,12 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
|
|||||||
/// ```
|
/// ```
|
||||||
/// #![feature(inclusive_range,inclusive_range_syntax)]
|
/// #![feature(inclusive_range,inclusive_range_syntax)]
|
||||||
///
|
///
|
||||||
/// assert_eq!((3...5), std::ops::RangeInclusive { start: 3, end: 5 });
|
/// assert_eq!((3..=5), std::ops::RangeInclusive { start: 3, end: 5 });
|
||||||
/// assert_eq!(3 + 4 + 5, (3...5).sum());
|
/// assert_eq!(3 + 4 + 5, (3..=5).sum());
|
||||||
///
|
///
|
||||||
/// let arr = [0, 1, 2, 3];
|
/// let arr = [0, 1, 2, 3];
|
||||||
/// assert_eq!(arr[ ...2], [0,1,2 ]);
|
/// assert_eq!(arr[ ..=2], [0,1,2 ]);
|
||||||
/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive
|
/// assert_eq!(arr[1..=2], [ 1,2 ]); // RangeInclusive
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
|
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
|
||||||
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
#[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")]
|
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
||||||
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
|
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
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)]
|
/// #![feature(range_contains,inclusive_range_syntax)]
|
||||||
///
|
///
|
||||||
/// assert!(!(3...5).contains(2));
|
/// assert!(!(3..=5).contains(2));
|
||||||
/// assert!( (3...5).contains(3));
|
/// assert!( (3..=5).contains(3));
|
||||||
/// assert!( (3...5).contains(4));
|
/// assert!( (3..=5).contains(4));
|
||||||
/// assert!( (3...5).contains(5));
|
/// assert!( (3..=5).contains(5));
|
||||||
/// assert!(!(3...5).contains(6));
|
/// assert!(!(3..=5).contains(6));
|
||||||
///
|
///
|
||||||
/// assert!( (3...3).contains(3));
|
/// assert!( (3..=3).contains(3));
|
||||||
/// assert!(!(3...2).contains(3));
|
/// assert!(!(3..=2).contains(3));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn contains(&self, item: Idx) -> bool {
|
pub fn contains(&self, item: Idx) -> bool {
|
||||||
self.start <= item && item <= self.end
|
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.
|
/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// The `...end` syntax is a `RangeToInclusive`:
|
/// The `..=end` syntax is a `RangeToInclusive`:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(inclusive_range,inclusive_range_syntax)]
|
/// #![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
|
/// 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}>:
|
/// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>:
|
||||||
/// // std::iter::Iterator` is not satisfied
|
/// // 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)]
|
/// #![feature(inclusive_range_syntax)]
|
||||||
///
|
///
|
||||||
/// let arr = [0, 1, 2, 3];
|
/// let arr = [0, 1, 2, 3];
|
||||||
/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive
|
/// assert_eq!(arr[ ..=2], [0,1,2 ]); // RangeToInclusive
|
||||||
/// assert_eq!(arr[1...2], [ 1,2 ]);
|
/// assert_eq!(arr[1..=2], [ 1,2 ]);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`IntoIterator`]: ../iter/trait.Iterator.html
|
/// [`IntoIterator`]: ../iter/trait.Iterator.html
|
||||||
@ -357,7 +357,7 @@ pub struct RangeToInclusive<Idx> {
|
|||||||
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
||||||
impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
|
impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
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)]
|
/// #![feature(range_contains,inclusive_range_syntax)]
|
||||||
///
|
///
|
||||||
/// assert!( (...5).contains(-1_000_000_000));
|
/// assert!( (..=5).contains(-1_000_000_000));
|
||||||
/// assert!( (...5).contains(5));
|
/// assert!( (..=5).contains(5));
|
||||||
/// assert!(!(...5).contains(6));
|
/// assert!(!(..=5).contains(6));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn contains(&self, item: Idx) -> bool {
|
pub fn contains(&self, item: Idx) -> bool {
|
||||||
(item <= self.end)
|
(item <= self.end)
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
|
// FIXME: after next stage0, change RangeInclusive { ... } back to ..=
|
||||||
|
use ops::RangeInclusive;
|
||||||
|
|
||||||
// How this module is organized.
|
// How this module is organized.
|
||||||
//
|
//
|
||||||
// The library infrastructure for slices is fairly messy. There's
|
// The library infrastructure for slices is fairly messy. There's
|
||||||
@ -1044,32 +1047,32 @@ impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(self, slice: &[T]) -> Option<&[T]> {
|
fn get(self, slice: &[T]) -> Option<&[T]> {
|
||||||
(0...self.end).get(slice)
|
(RangeInclusive { start: 0, end: self.end }).get(slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
|
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
|
||||||
(0...self.end).get_mut(slice)
|
(RangeInclusive { start: 0, end: self.end }).get_mut(slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
|
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
|
||||||
(0...self.end).get_unchecked(slice)
|
(RangeInclusive { start: 0, end: self.end }).get_unchecked(slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
|
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
|
||||||
(0...self.end).get_unchecked_mut(slice)
|
(RangeInclusive { start: 0, end: self.end }).get_unchecked_mut(slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(self, slice: &[T]) -> &[T] {
|
fn index(self, slice: &[T]) -> &[T] {
|
||||||
(0...self.end).index(slice)
|
(RangeInclusive { start: 0, end: self.end }).index(slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
|
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
|
||||||
(0...self.end).index_mut(slice)
|
(RangeInclusive { start: 0, end: self.end }).index_mut(slice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1094,21 +1094,21 @@ fn test_range() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_range_inclusive_exhaustion() {
|
fn test_range_inclusive_exhaustion() {
|
||||||
let mut r = 10...10;
|
let mut r = 10..=10;
|
||||||
assert_eq!(r.next(), Some(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.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.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.nth(5), None);
|
||||||
assert_eq!(r, 1...0);
|
assert_eq!(r, 1..=0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1145,20 +1145,20 @@ fn test_range_from_nth() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_range_inclusive_nth() {
|
fn test_range_inclusive_nth() {
|
||||||
assert_eq!((10...15).nth(0), Some(10));
|
assert_eq!((10..=15).nth(0), Some(10));
|
||||||
assert_eq!((10...15).nth(1), Some(11));
|
assert_eq!((10..=15).nth(1), Some(11));
|
||||||
assert_eq!((10...15).nth(5), Some(15));
|
assert_eq!((10..=15).nth(5), Some(15));
|
||||||
assert_eq!((10...15).nth(6), None);
|
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.nth(2), Some(12));
|
||||||
assert_eq!(r, 13...20);
|
assert_eq!(r, 13..=20);
|
||||||
assert_eq!(r.nth(2), Some(15));
|
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.is_empty(), false);
|
||||||
assert_eq!(r.nth(10), None);
|
assert_eq!(r.nth(10), None);
|
||||||
assert_eq!(r.is_empty(), true);
|
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]
|
#[test]
|
||||||
|
@ -509,6 +509,7 @@ impl TokenTree {
|
|||||||
Dot => op!('.'),
|
Dot => op!('.'),
|
||||||
DotDot => joint!('.', Dot),
|
DotDot => joint!('.', Dot),
|
||||||
DotDotDot => joint!('.', DotDot),
|
DotDotDot => joint!('.', DotDot),
|
||||||
|
DotDotEq => joint!('.', DotEq),
|
||||||
Comma => op!(','),
|
Comma => op!(','),
|
||||||
Semi => op!(';'),
|
Semi => op!(';'),
|
||||||
Colon => op!(':'),
|
Colon => op!(':'),
|
||||||
@ -531,6 +532,7 @@ impl TokenTree {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DotEq => unreachable!(),
|
||||||
OpenDelim(..) | CloseDelim(..) => unreachable!(),
|
OpenDelim(..) | CloseDelim(..) => unreachable!(),
|
||||||
Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
|
Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
|
||||||
};
|
};
|
||||||
|
@ -202,8 +202,8 @@ impl Quote for Token {
|
|||||||
|
|
||||||
gen_match! {
|
gen_match! {
|
||||||
Eq, Lt, Le, EqEq, Ne, Ge, Gt, AndAnd, OrOr, Not, Tilde, At, Dot, DotDot, DotDotDot,
|
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,
|
DotDotEq, Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar,
|
||||||
Underscore;
|
Question, Underscore;
|
||||||
|
|
||||||
Token::OpenDelim(delim) => quote!(rt::token::OpenDelim((quote delim))),
|
Token::OpenDelim(delim) => quote!(rt::token::OpenDelim((quote delim))),
|
||||||
Token::CloseDelim(delim) => quote!(rt::token::CloseDelim((quote delim))),
|
Token::CloseDelim(delim) => quote!(rt::token::CloseDelim((quote delim))),
|
||||||
|
@ -1864,7 +1864,7 @@ impl<'a> LoweringContext<'a> {
|
|||||||
|
|
||||||
fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
|
fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
|
||||||
match *e {
|
match *e {
|
||||||
RangeEnd::Included => hir::RangeEnd::Included,
|
RangeEnd::Included(_) => hir::RangeEnd::Included,
|
||||||
RangeEnd::Excluded => hir::RangeEnd::Excluded,
|
RangeEnd::Excluded => hir::RangeEnd::Excluded,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,6 +272,8 @@ fn hash_token<'gcx, W: StableHasherResult>(token: &token::Token,
|
|||||||
token::Token::Dot |
|
token::Token::Dot |
|
||||||
token::Token::DotDot |
|
token::Token::DotDot |
|
||||||
token::Token::DotDotDot |
|
token::Token::DotDotDot |
|
||||||
|
token::Token::DotDotEq |
|
||||||
|
token::Token::DotEq |
|
||||||
token::Token::Comma |
|
token::Token::Comma |
|
||||||
token::Token::Semi |
|
token::Token::Semi |
|
||||||
token::Token::Colon |
|
token::Token::Colon |
|
||||||
|
@ -249,8 +249,8 @@ impl<'a> Classifier<'a> {
|
|||||||
token::BinOpEq(..) | token::FatArrow => Class::Op,
|
token::BinOpEq(..) | token::FatArrow => Class::Op,
|
||||||
|
|
||||||
// Miscellaneous, no highlighting.
|
// Miscellaneous, no highlighting.
|
||||||
token::Dot | token::DotDot | token::DotDotDot | token::Comma | token::Semi |
|
token::Dot | token::DotDot | token::DotDotDot | token::DotDotEq | token::Comma |
|
||||||
token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) |
|
token::Semi | token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) |
|
||||||
token::CloseDelim(token::Brace) | token::CloseDelim(token::Paren) |
|
token::CloseDelim(token::Brace) | token::CloseDelim(token::Paren) |
|
||||||
token::CloseDelim(token::NoDelim) => Class::None,
|
token::CloseDelim(token::NoDelim) => Class::None,
|
||||||
|
|
||||||
@ -353,7 +353,7 @@ impl<'a> Classifier<'a> {
|
|||||||
token::Lifetime(..) => Class::Lifetime,
|
token::Lifetime(..) => Class::Lifetime,
|
||||||
|
|
||||||
token::Underscore | token::Eof | token::Interpolated(..) |
|
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
|
// Anything that didn't return above is the simple case where we the
|
||||||
|
@ -538,10 +538,16 @@ pub enum BindingMode {
|
|||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
pub enum RangeEnd {
|
pub enum RangeEnd {
|
||||||
Included,
|
Included(RangeSyntax),
|
||||||
Excluded,
|
Excluded,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
|
pub enum RangeSyntax {
|
||||||
|
DotDotDot,
|
||||||
|
DotDotEq,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
pub enum PatKind {
|
pub enum PatKind {
|
||||||
/// Represents a wildcard pattern (`_`)
|
/// Represents a wildcard pattern (`_`)
|
||||||
@ -578,7 +584,7 @@ pub enum PatKind {
|
|||||||
Ref(P<Pat>, Mutability),
|
Ref(P<Pat>, Mutability),
|
||||||
/// A literal
|
/// A literal
|
||||||
Lit(P<Expr>),
|
Lit(P<Expr>),
|
||||||
/// A range pattern, e.g. `1...2` or `1..2`
|
/// A range pattern, e.g. `1...2`, `1..=2` or `1..2`
|
||||||
Range(P<Expr>, P<Expr>, RangeEnd),
|
Range(P<Expr>, P<Expr>, RangeEnd),
|
||||||
/// `[a, b, ..i, y, z]` is represented as:
|
/// `[a, b, ..i, y, z]` is represented as:
|
||||||
/// `PatKind::Slice(box [a, b], Some(i), box [y, z])`
|
/// `PatKind::Slice(box [a, b], Some(i), box [y, z])`
|
||||||
|
@ -291,7 +291,7 @@ Erroneous code example:
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
|
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() {
|
fn main() {
|
||||||
let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
|
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::At => "At",
|
||||||
token::Dot => "Dot",
|
token::Dot => "Dot",
|
||||||
token::DotDot => "DotDot",
|
token::DotDot => "DotDot",
|
||||||
|
token::DotEq => "DotEq",
|
||||||
token::DotDotDot => "DotDotDot",
|
token::DotDotDot => "DotDotDot",
|
||||||
|
token::DotDotEq => "DotDotEq",
|
||||||
token::Comma => "Comma",
|
token::Comma => "Comma",
|
||||||
token::Semi => "Semi",
|
token::Semi => "Semi",
|
||||||
token::Colon => "Colon",
|
token::Colon => "Colon",
|
||||||
|
@ -26,7 +26,7 @@ use self::AttributeType::*;
|
|||||||
use self::AttributeGate::*;
|
use self::AttributeGate::*;
|
||||||
|
|
||||||
use abi::Abi;
|
use abi::Abi;
|
||||||
use ast::{self, NodeId, PatKind, RangeEnd};
|
use ast::{self, NodeId, PatKind, RangeEnd, RangeSyntax};
|
||||||
use attr;
|
use attr;
|
||||||
use codemap::Spanned;
|
use codemap::Spanned;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
@ -261,7 +261,7 @@ declare_features! (
|
|||||||
// rustc internal
|
// rustc internal
|
||||||
(active, abi_vectorcall, "1.7.0", None),
|
(active, abi_vectorcall, "1.7.0", None),
|
||||||
|
|
||||||
// a...b and ...b
|
// a..=b and ..=b
|
||||||
(active, inclusive_range_syntax, "1.7.0", Some(28237)),
|
(active, inclusive_range_syntax, "1.7.0", Some(28237)),
|
||||||
|
|
||||||
// X..Y patterns
|
// X..Y patterns
|
||||||
@ -392,6 +392,9 @@ declare_features! (
|
|||||||
|
|
||||||
// allow `'_` placeholder lifetimes
|
// allow `'_` placeholder lifetimes
|
||||||
(active, underscore_lifetimes, "1.22.0", Some(44524)),
|
(active, underscore_lifetimes, "1.22.0", Some(44524)),
|
||||||
|
|
||||||
|
// allow `..=` in patterns (RFC 1192)
|
||||||
|
(active, dotdoteq_in_patterns, "1.22.0", Some(28237)),
|
||||||
);
|
);
|
||||||
|
|
||||||
declare_features! (
|
declare_features! (
|
||||||
@ -1491,6 +1494,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
|
gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
|
||||||
"exclusive range pattern syntax is experimental");
|
"exclusive range pattern syntax is experimental");
|
||||||
}
|
}
|
||||||
|
PatKind::Range(_, _, RangeEnd::Included(RangeSyntax::DotDotEq)) => {
|
||||||
|
gate_feature_post!(&self, dotdoteq_in_patterns, pattern.span,
|
||||||
|
"`..=` syntax in patterns is experimental");
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
visit::walk_pat(self, pattern)
|
visit::walk_pat(self, pattern)
|
||||||
|
@ -1131,6 +1131,9 @@ impl<'a> StringReader<'a> {
|
|||||||
if self.ch_is('.') {
|
if self.ch_is('.') {
|
||||||
self.bump();
|
self.bump();
|
||||||
Ok(token::DotDotDot)
|
Ok(token::DotDotDot)
|
||||||
|
} else if self.ch_is('=') {
|
||||||
|
self.bump();
|
||||||
|
Ok(token::DotDotEq)
|
||||||
} else {
|
} else {
|
||||||
Ok(token::DotDot)
|
Ok(token::DotDot)
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds};
|
|||||||
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
|
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
|
||||||
use ast::{Visibility, WhereClause};
|
use ast::{Visibility, WhereClause};
|
||||||
use ast::{BinOpKind, UnOp};
|
use ast::{BinOpKind, UnOp};
|
||||||
use ast::RangeEnd;
|
use ast::{RangeEnd, RangeSyntax};
|
||||||
use {ast, attr};
|
use {ast, attr};
|
||||||
use codemap::{self, CodeMap, Spanned, respan};
|
use codemap::{self, CodeMap, Spanned, respan};
|
||||||
use syntax_pos::{self, Span, BytePos};
|
use syntax_pos::{self, Span, BytePos};
|
||||||
@ -432,7 +432,7 @@ impl Error {
|
|||||||
Error::InclusiveRangeWithNoEnd => {
|
Error::InclusiveRangeWithNoEnd => {
|
||||||
let mut err = struct_span_err!(handler, sp, E0586,
|
let mut err = struct_span_err!(handler, sp, E0586,
|
||||||
"inclusive range with no end");
|
"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
|
err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2710,7 +2710,7 @@ impl<'a> Parser<'a> {
|
|||||||
LhsExpr::AttributesParsed(attrs) => Some(attrs),
|
LhsExpr::AttributesParsed(attrs) => Some(attrs),
|
||||||
_ => None,
|
_ => 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);
|
return self.parse_prefix_range_expr(attrs);
|
||||||
} else {
|
} else {
|
||||||
self.parse_prefix_expr(attrs)?
|
self.parse_prefix_expr(attrs)?
|
||||||
@ -2744,6 +2744,10 @@ impl<'a> Parser<'a> {
|
|||||||
if op.precedence() < min_prec {
|
if op.precedence() < min_prec {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Warn about deprecated ... syntax (until SNAP)
|
||||||
|
if self.token == token::DotDotDot {
|
||||||
|
self.warn_dotdoteq(self.span);
|
||||||
|
}
|
||||||
self.bump();
|
self.bump();
|
||||||
if op.is_comparison() {
|
if op.is_comparison() {
|
||||||
self.check_no_chained_comparison(&lhs, &op);
|
self.check_no_chained_comparison(&lhs, &op);
|
||||||
@ -2770,12 +2774,13 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
continue
|
continue
|
||||||
} else if op == AssocOp::DotDot || op == AssocOp::DotDotDot {
|
} else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
|
||||||
// If we didn’t have to handle `x..`/`x...`, it would be pretty easy to
|
// If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to
|
||||||
// generalise it to the Fixity::None code.
|
// 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.
|
// 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() {
|
let rhs = if self.is_at_start_of_range_notation_rhs() {
|
||||||
Some(self.parse_assoc_expr_with(op.precedence() + 1,
|
Some(self.parse_assoc_expr_with(op.precedence() + 1,
|
||||||
LhsExpr::NotYetParsed)?)
|
LhsExpr::NotYetParsed)?)
|
||||||
@ -2852,8 +2857,8 @@ impl<'a> Parser<'a> {
|
|||||||
let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
|
let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
|
||||||
self.mk_expr(span, aopexpr, ThinVec::new())
|
self.mk_expr(span, aopexpr, ThinVec::new())
|
||||||
}
|
}
|
||||||
AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotDot => {
|
AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => {
|
||||||
self.bug("As, Colon, DotDot or DotDotDot branch reached")
|
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,
|
fn parse_prefix_range_expr(&mut self,
|
||||||
already_parsed_attrs: Option<ThinVec<Attribute>>)
|
already_parsed_attrs: Option<ThinVec<Attribute>>)
|
||||||
-> PResult<'a, P<Expr>> {
|
-> PResult<'a, P<Expr>> {
|
||||||
debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot,
|
// SNAP remove DotDotDot
|
||||||
"parse_prefix_range_expr: token {:?} is not DotDot or DotDotDot",
|
debug_assert!([token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token),
|
||||||
|
"parse_prefix_range_expr: token {:?} is not DotDot/DotDotDot/DotDotEq",
|
||||||
self.token);
|
self.token);
|
||||||
let tok = self.token.clone();
|
let tok = self.token.clone();
|
||||||
let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
|
let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
|
||||||
let lo = self.span;
|
let lo = self.span;
|
||||||
let mut hi = self.span;
|
let mut hi = self.span;
|
||||||
|
// Warn about deprecated ... syntax (until SNAP)
|
||||||
|
if tok == token::DotDotDot {
|
||||||
|
self.warn_dotdoteq(self.span);
|
||||||
|
}
|
||||||
self.bump();
|
self.bump();
|
||||||
let opt_end = if self.is_at_start_of_range_notation_rhs() {
|
let opt_end = if self.is_at_start_of_range_notation_rhs() {
|
||||||
// RHS must be parsed with more associativity than the dots.
|
// 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 {
|
fn parse_as_ident(&mut self) -> bool {
|
||||||
self.look_ahead(1, |t| match *t {
|
self.look_ahead(1, |t| match *t {
|
||||||
token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
|
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
|
// ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the
|
||||||
// range pattern branch
|
// range pattern branch
|
||||||
token::DotDot => None,
|
token::DotDot => None,
|
||||||
@ -3544,11 +3554,13 @@ impl<'a> Parser<'a> {
|
|||||||
let mac = respan(lo.to(self.prev_span), Mac_ { path: path, tts: tts });
|
let mac = respan(lo.to(self.prev_span), Mac_ { path: path, tts: tts });
|
||||||
pat = PatKind::Mac(mac);
|
pat = PatKind::Mac(mac);
|
||||||
}
|
}
|
||||||
token::DotDotDot | token::DotDot => {
|
token::DotDotDot | token::DotDotEq | token::DotDot => {
|
||||||
let end_kind = match self.token {
|
let end_kind = match self.token {
|
||||||
token::DotDot => RangeEnd::Excluded,
|
token::DotDot => RangeEnd::Excluded,
|
||||||
token::DotDotDot => RangeEnd::Included,
|
token::DotDotDot => RangeEnd::Included(RangeSyntax::DotDotDot),
|
||||||
_ => panic!("can only parse `..` or `...` for ranges (checked above)"),
|
token::DotDotEq => RangeEnd::Included(RangeSyntax::DotDotEq),
|
||||||
|
_ => panic!("can only parse `..`/`...`/`..=` for ranges \
|
||||||
|
(checked above)"),
|
||||||
};
|
};
|
||||||
// Parse range
|
// Parse range
|
||||||
let span = lo.to(self.prev_span);
|
let span = lo.to(self.prev_span);
|
||||||
@ -3589,7 +3601,12 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(begin) => {
|
Ok(begin) => {
|
||||||
if self.eat(&token::DotDotDot) {
|
if self.eat(&token::DotDotDot) {
|
||||||
let end = self.parse_pat_range_end()?;
|
let end = self.parse_pat_range_end()?;
|
||||||
pat = PatKind::Range(begin, end, RangeEnd::Included);
|
pat = PatKind::Range(begin, end,
|
||||||
|
RangeEnd::Included(RangeSyntax::DotDotDot));
|
||||||
|
} else if self.eat(&token::DotDotEq) {
|
||||||
|
let end = self.parse_pat_range_end()?;
|
||||||
|
pat = PatKind::Range(begin, end,
|
||||||
|
RangeEnd::Included(RangeSyntax::DotDotEq));
|
||||||
} else if self.eat(&token::DotDot) {
|
} else if self.eat(&token::DotDot) {
|
||||||
let end = self.parse_pat_range_end()?;
|
let end = self.parse_pat_range_end()?;
|
||||||
pat = PatKind::Range(begin, end, RangeEnd::Excluded);
|
pat = PatKind::Range(begin, end, RangeEnd::Excluded);
|
||||||
@ -3973,7 +3990,7 @@ impl<'a> Parser<'a> {
|
|||||||
token::BinOp(token::Minus) | token::BinOp(token::Star) |
|
token::BinOp(token::Minus) | token::BinOp(token::Star) |
|
||||||
token::BinOp(token::And) | token::BinOp(token::Or) |
|
token::BinOp(token::And) | token::BinOp(token::Or) |
|
||||||
token::AndAnd | token::OrOr |
|
token::AndAnd | token::OrOr |
|
||||||
token::DotDot | token::DotDotDot => false,
|
token::DotDot | token::DotDotDot | token::DotDotEq => false,
|
||||||
_ => true,
|
_ => true,
|
||||||
} {
|
} {
|
||||||
self.warn_missing_semicolon();
|
self.warn_missing_semicolon();
|
||||||
@ -4195,6 +4212,12 @@ impl<'a> Parser<'a> {
|
|||||||
}).emit();
|
}).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 `+`.
|
// Parse bounds of a type parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
|
||||||
// BOUND = TY_BOUND | LT_BOUND
|
// BOUND = TY_BOUND | LT_BOUND
|
||||||
// LT_BOUND = LIFETIME (e.g. `'a`)
|
// LT_BOUND = LIFETIME (e.g. `'a`)
|
||||||
|
@ -152,6 +152,8 @@ pub enum Token {
|
|||||||
Dot,
|
Dot,
|
||||||
DotDot,
|
DotDot,
|
||||||
DotDotDot,
|
DotDotDot,
|
||||||
|
DotDotEq,
|
||||||
|
DotEq, // HACK(durka42) never produced by the parser, only used for libproc_macro
|
||||||
Comma,
|
Comma,
|
||||||
Semi,
|
Semi,
|
||||||
Colon,
|
Colon,
|
||||||
@ -220,7 +222,8 @@ impl Token {
|
|||||||
BinOp(Or) | OrOr | // closure
|
BinOp(Or) | OrOr | // closure
|
||||||
BinOp(And) | // reference
|
BinOp(And) | // reference
|
||||||
AndAnd | // double reference
|
AndAnd | // double reference
|
||||||
DotDot | DotDotDot | // range notation
|
DotDot | DotDotDot | DotDotEq | // range notation
|
||||||
|
// SNAP remove DotDotDot
|
||||||
Lt | BinOp(Shl) | // associated path
|
Lt | BinOp(Shl) | // associated path
|
||||||
ModSep | // global path
|
ModSep | // global path
|
||||||
Pound => true, // expression attributes
|
Pound => true, // expression attributes
|
||||||
@ -402,10 +405,12 @@ impl Token {
|
|||||||
Dot => match joint {
|
Dot => match joint {
|
||||||
Dot => DotDot,
|
Dot => DotDot,
|
||||||
DotDot => DotDotDot,
|
DotDot => DotDotDot,
|
||||||
|
DotEq => DotDotEq,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
},
|
},
|
||||||
DotDot => match joint {
|
DotDot => match joint {
|
||||||
Dot => DotDotDot,
|
Dot => DotDotDot,
|
||||||
|
Eq => DotDotEq,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
},
|
},
|
||||||
Colon => match joint {
|
Colon => match joint {
|
||||||
@ -413,9 +418,9 @@ impl Token {
|
|||||||
_ => return None,
|
_ => return None,
|
||||||
},
|
},
|
||||||
|
|
||||||
Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | Comma |
|
Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | DotEq |
|
||||||
Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question |
|
DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
|
||||||
OpenDelim(..) | CloseDelim(..) | Underscore => return None,
|
Question | OpenDelim(..) | CloseDelim(..) | Underscore => return None,
|
||||||
|
|
||||||
Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
|
Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
|
||||||
Whitespace | Comment | Shebang(..) | Eof => return None,
|
Whitespace | Comment | Shebang(..) | Eof => return None,
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
pub use self::AnnNode::*;
|
pub use self::AnnNode::*;
|
||||||
|
|
||||||
use abi::{self, Abi};
|
use abi::{self, Abi};
|
||||||
use ast::{self, BlockCheckMode, PatKind, RangeEnd};
|
use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
|
||||||
use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
|
use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
|
||||||
use ast::Attribute;
|
use ast::Attribute;
|
||||||
use util::parser::{self, AssocOp, Fixity};
|
use util::parser::{self, AssocOp, Fixity};
|
||||||
@ -203,6 +203,8 @@ pub fn token_to_string(tok: &Token) -> String {
|
|||||||
token::Dot => ".".to_string(),
|
token::Dot => ".".to_string(),
|
||||||
token::DotDot => "..".to_string(),
|
token::DotDot => "..".to_string(),
|
||||||
token::DotDotDot => "...".to_string(),
|
token::DotDotDot => "...".to_string(),
|
||||||
|
token::DotDotEq => "..=".to_string(),
|
||||||
|
token::DotEq => ".=".to_string(),
|
||||||
token::Comma => ",".to_string(),
|
token::Comma => ",".to_string(),
|
||||||
token::Semi => ";".to_string(),
|
token::Semi => ";".to_string(),
|
||||||
token::Colon => ":".to_string(),
|
token::Colon => ":".to_string(),
|
||||||
@ -2588,7 +2590,8 @@ impl<'a> State<'a> {
|
|||||||
self.print_expr(begin)?;
|
self.print_expr(begin)?;
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
match *end_kind {
|
match *end_kind {
|
||||||
RangeEnd::Included => self.s.word("...")?,
|
RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("...")?,
|
||||||
|
RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..=")?,
|
||||||
RangeEnd::Excluded => self.s.word("..")?,
|
RangeEnd::Excluded => self.s.word("..")?,
|
||||||
}
|
}
|
||||||
self.print_expr(end)?;
|
self.print_expr(end)?;
|
||||||
|
@ -62,8 +62,8 @@ pub enum AssocOp {
|
|||||||
As,
|
As,
|
||||||
/// `..` range
|
/// `..` range
|
||||||
DotDot,
|
DotDot,
|
||||||
/// `...` range
|
/// `..=` range
|
||||||
DotDotDot,
|
DotDotEq,
|
||||||
/// `:`
|
/// `:`
|
||||||
Colon,
|
Colon,
|
||||||
}
|
}
|
||||||
@ -105,7 +105,8 @@ impl AssocOp {
|
|||||||
Token::AndAnd => Some(LAnd),
|
Token::AndAnd => Some(LAnd),
|
||||||
Token::OrOr => Some(LOr),
|
Token::OrOr => Some(LOr),
|
||||||
Token::DotDot => Some(DotDot),
|
Token::DotDot => Some(DotDot),
|
||||||
Token::DotDotDot => Some(DotDotDot),
|
Token::DotDotEq => Some(DotDotEq),
|
||||||
|
Token::DotDotDot => Some(DotDotEq), // remove this after SNAP
|
||||||
Token::Colon => Some(Colon),
|
Token::Colon => Some(Colon),
|
||||||
_ if t.is_keyword(keywords::As) => Some(As),
|
_ if t.is_keyword(keywords::As) => Some(As),
|
||||||
_ => None
|
_ => None
|
||||||
@ -151,7 +152,7 @@ impl AssocOp {
|
|||||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7,
|
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7,
|
||||||
LAnd => 6,
|
LAnd => 6,
|
||||||
LOr => 5,
|
LOr => 5,
|
||||||
DotDot | DotDotDot => 4,
|
DotDot | DotDotEq => 4,
|
||||||
Inplace => 3,
|
Inplace => 3,
|
||||||
Assign | AssignOp(_) => 2,
|
Assign | AssignOp(_) => 2,
|
||||||
}
|
}
|
||||||
@ -166,7 +167,7 @@ impl AssocOp {
|
|||||||
As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd |
|
As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd |
|
||||||
BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual |
|
BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual |
|
||||||
LAnd | LOr | Colon => Fixity::Left,
|
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,
|
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true,
|
||||||
Inplace | Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract |
|
Inplace | Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract |
|
||||||
ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr |
|
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,
|
Assign | AssignOp(_) | Inplace => true,
|
||||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide |
|
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide |
|
||||||
Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd |
|
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),
|
BitOr => Some(BinOpKind::BitOr),
|
||||||
LAnd => Some(BinOpKind::And),
|
LAnd => Some(BinOpKind::And),
|
||||||
LOr => Some(BinOpKind::Or),
|
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() {
|
fn main() {
|
||||||
let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
|
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
|
||||||
}
|
}
|
||||||
|
16
src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs
Normal file
16
src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
match 22 {
|
||||||
|
0 ..= 3 => {} //~ ERROR `..=` syntax in patterns is experimental
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
@ -18,12 +18,12 @@ pub fn main() {
|
|||||||
..1;
|
..1;
|
||||||
0..1;
|
0..1;
|
||||||
|
|
||||||
...; //~ERROR inclusive range with no end
|
..=; //~ERROR inclusive range with no end
|
||||||
//~^HELP bounded at the 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
|
//~^HELP bounded at the end
|
||||||
...1;
|
..=1;
|
||||||
0...1;
|
0..=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// #![feature(inclusive_range)]
|
// #![feature(inclusive_range)]
|
||||||
|
|
||||||
pub fn main() {
|
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 use of unstable library feature 'inclusive_range'
|
||||||
//~| ERROR core_intrinsics
|
//~| ERROR core_intrinsics
|
||||||
//~| 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="cfail2")]
|
||||||
#[rustc_metadata_clean(cfg="cfail3")]
|
#[rustc_metadata_clean(cfg="cfail3")]
|
||||||
fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
|
fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
|
||||||
&slice[3...7]
|
&slice[3..=7]
|
||||||
}
|
}
|
||||||
|
@ -11,5 +11,5 @@
|
|||||||
// Parsing of range patterns
|
// Parsing of range patterns
|
||||||
|
|
||||||
fn main() {
|
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
|
// Parsing of range patterns
|
||||||
|
|
||||||
fn main() {
|
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
|
// Parsing of range patterns
|
||||||
|
|
||||||
fn main() {
|
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
|
// Parsing of range patterns
|
||||||
|
|
||||||
fn main() {
|
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)]
|
#![feature(inclusive_range_syntax, inclusive_range)]
|
||||||
|
|
||||||
pub fn main() {
|
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
|
//~^HELP bounded at the end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,21 +15,21 @@
|
|||||||
// #![feature(inclusive_range_syntax, inclusive_range)]
|
// #![feature(inclusive_range_syntax, inclusive_range)]
|
||||||
|
|
||||||
macro_rules! m {
|
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)]
|
#[cfg(nope)]
|
||||||
fn f() {}
|
fn f() {}
|
||||||
#[cfg(not(nope))]
|
#[cfg(not(nope))]
|
||||||
fn f() {
|
fn f() {
|
||||||
for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental
|
for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(nope)]
|
#[cfg(nope)]
|
||||||
macro_rules! n { () => {} }
|
macro_rules! n { () => {} }
|
||||||
#[cfg(not(nope))]
|
#[cfg(not(nope))]
|
||||||
macro_rules! n {
|
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 {
|
macro_rules! o {
|
||||||
@ -38,7 +38,7 @@ macro_rules! o {
|
|||||||
fn g() {}
|
fn g() {}
|
||||||
#[cfg(not(nope))]
|
#[cfg(not(nope))]
|
||||||
fn g() {
|
fn g() {
|
||||||
for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental
|
for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental
|
||||||
}
|
}
|
||||||
|
|
||||||
g();
|
g();
|
||||||
@ -54,7 +54,7 @@ macro_rules! p {
|
|||||||
fn h() {}
|
fn h() {}
|
||||||
#[cfg(not(nope))]
|
#[cfg(not(nope))]
|
||||||
fn h() {
|
fn h() {
|
||||||
for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental
|
for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental
|
||||||
}
|
}
|
||||||
|
|
||||||
h();
|
h();
|
||||||
@ -62,8 +62,8 @@ macro_rules! p {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
for _ in 1...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
|
for _ in ..=10 {} //~ ERROR inclusive range syntax is experimental
|
||||||
|
|
||||||
f(); // not allowed in cfg'ed functions
|
f(); // not allowed in cfg'ed functions
|
||||||
|
|
||||||
|
22
src/test/run-pass/inc-range-pat.rs
Normal file
22
src/test/run-pass/inc-range-pat.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// 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.
|
||||||
|
#![feature(dotdoteq_in_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 }
|
fn foo() -> isize { 42 }
|
||||||
|
|
||||||
// Test that range syntax works in return statements
|
// 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() {
|
pub fn main() {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
for i in 0_usize...10 {
|
for i in 0_usize..=10 {
|
||||||
assert!(i >= 0 && i <= 10);
|
assert!(i >= 0 && i <= 10);
|
||||||
count += i;
|
count += i;
|
||||||
}
|
}
|
||||||
assert_eq!(count, 55);
|
assert_eq!(count, 55);
|
||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let mut range = 0_usize...10;
|
let mut range = 0_usize..=10;
|
||||||
for i in range {
|
for i in range {
|
||||||
assert!(i >= 0 && i <= 10);
|
assert!(i >= 0 && i <= 10);
|
||||||
count += i;
|
count += i;
|
||||||
@ -36,53 +36,53 @@ pub fn main() {
|
|||||||
assert_eq!(count, 55);
|
assert_eq!(count, 55);
|
||||||
|
|
||||||
let mut count = 0;
|
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);
|
assert!(i >= 0 && i <= 10 && i % 2 == 0);
|
||||||
count += i;
|
count += i;
|
||||||
}
|
}
|
||||||
assert_eq!(count, 30);
|
assert_eq!(count, 30);
|
||||||
|
|
||||||
let _ = 0_usize...4+4-3;
|
let _ = 0_usize..=4+4-3;
|
||||||
let _ = 0...foo();
|
let _ = 0..=foo();
|
||||||
|
|
||||||
let _ = { &42...&100 }; // references to literals are OK
|
let _ = { &42..=&100 }; // references to literals are OK
|
||||||
let _ = ...42_usize;
|
let _ = ..=42_usize;
|
||||||
|
|
||||||
// Test we can use two different types with a common supertype.
|
// Test we can use two different types with a common supertype.
|
||||||
let x = &42;
|
let x = &42;
|
||||||
{
|
{
|
||||||
let y = 42;
|
let y = 42;
|
||||||
let _ = x...&y;
|
let _ = x..=&y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// test collection indexing
|
// test collection indexing
|
||||||
let vec = (0...10).collect::<Vec<_>>();
|
let vec = (0..=10).collect::<Vec<_>>();
|
||||||
let slice: &[_] = &*vec;
|
let slice: &[_] = &*vec;
|
||||||
let string = String::from("hello world");
|
let string = String::from("hello world");
|
||||||
let stir = "hello world";
|
let stir = "hello world";
|
||||||
|
|
||||||
assert_eq!(&vec[3...6], &[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!(&vec[ ..=6], &[0, 1, 2, 3, 4, 5, 6]);
|
||||||
|
|
||||||
assert_eq!(&slice[3...6], &[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[ ..=6], &[0, 1, 2, 3, 4, 5, 6]);
|
||||||
|
|
||||||
assert_eq!(&string[3...6], "lo w");
|
assert_eq!(&string[3..=6], "lo w");
|
||||||
assert_eq!(&string[ ...6], "hello w");
|
assert_eq!(&string[ ..=6], "hello w");
|
||||||
|
|
||||||
assert_eq!(&stir[3...6], "lo w");
|
assert_eq!(&stir[3..=6], "lo w");
|
||||||
assert_eq!(&stir[ ...6], "hello w");
|
assert_eq!(&stir[ ..=6], "hello w");
|
||||||
|
|
||||||
// test the size hints and emptying
|
// test the size hints and emptying
|
||||||
let mut long = 0...255u8;
|
let mut long = 0..=255u8;
|
||||||
let mut short = 42...42u8;
|
let mut short = 42..=42u8;
|
||||||
assert_eq!(long.size_hint(), (256, Some(256)));
|
assert_eq!(long.size_hint(), (256, Some(256)));
|
||||||
assert_eq!(short.size_hint(), (1, Some(1)));
|
assert_eq!(short.size_hint(), (1, Some(1)));
|
||||||
long.next();
|
long.next();
|
||||||
short.next();
|
short.next();
|
||||||
assert_eq!(long.size_hint(), (255, Some(255)));
|
assert_eq!(long.size_hint(), (255, Some(255)));
|
||||||
assert_eq!(short.size_hint(), (0, Some(0)));
|
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!(long.len(), 255);
|
||||||
assert_eq!(short.len(), 0);
|
assert_eq!(short.len(), 0);
|
||||||
@ -94,31 +94,31 @@ pub fn main() {
|
|||||||
assert_eq!(long.next(), Some(1));
|
assert_eq!(long.next(), Some(1));
|
||||||
assert_eq!(long.next(), Some(2));
|
assert_eq!(long.next(), Some(2));
|
||||||
assert_eq!(long.next_back(), Some(252));
|
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.next(), Some(i));
|
||||||
}
|
}
|
||||||
assert_eq!(long, 1...0);
|
assert_eq!(long, 1..=0);
|
||||||
|
|
||||||
// check underflow
|
// check underflow
|
||||||
let mut narrow = 1...0;
|
let mut narrow = 1..=0;
|
||||||
assert_eq!(narrow.next_back(), None);
|
assert_eq!(narrow.next_back(), None);
|
||||||
assert_eq!(narrow, 1...0);
|
assert_eq!(narrow, 1..=0);
|
||||||
let mut zero = 0u8...0;
|
let mut zero = 0u8..=0;
|
||||||
assert_eq!(zero.next_back(), Some(0));
|
assert_eq!(zero.next_back(), Some(0));
|
||||||
assert_eq!(zero.next_back(), None);
|
assert_eq!(zero.next_back(), None);
|
||||||
assert_eq!(zero, 1...0);
|
assert_eq!(zero, 1..=0);
|
||||||
let mut high = 255u8...255;
|
let mut high = 255u8..=255;
|
||||||
assert_eq!(high.next_back(), Some(255));
|
assert_eq!(high.next_back(), Some(255));
|
||||||
assert_eq!(high.next_back(), None);
|
assert_eq!(high.next_back(), None);
|
||||||
assert_eq!(high, 1...0);
|
assert_eq!(high, 1..=0);
|
||||||
|
|
||||||
// what happens if you have a nonsense range?
|
// 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.next(), None);
|
||||||
assert_eq!(nonsense, 10...5);
|
assert_eq!(nonsense, 10..=5);
|
||||||
|
|
||||||
// output
|
// output
|
||||||
assert_eq!(format!("{:?}", 0...10), "0...10");
|
assert_eq!(format!("{:?}", 0..=10), "0..=10");
|
||||||
assert_eq!(format!("{:?}", ...10), "...10");
|
assert_eq!(format!("{:?}", ..=10), "..=10");
|
||||||
assert_eq!(format!("{:?}", long), "1...0");
|
assert_eq!(format!("{:?}", long), "1..=0");
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
for i in 0_usize...10 {
|
for i in 0_usize..=10 {
|
||||||
assert!(i >= 0 && i <= 10);
|
assert!(i >= 0 && i <= 10);
|
||||||
count += i;
|
count += i;
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit a1fd68da464fc51585f351c81fc2b867211c197e
|
Subproject commit 22eb5241c0ee5bb7eaf95e270a2b1500e82bf767
|
Loading…
Reference in New Issue
Block a user