Skip to content

Commit 0e6f4cf

Browse files
committed
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
2 parents 1fd3a42 + 5102309 commit 0e6f4cf

38 files changed

+295
-199
lines changed

src/Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/doc/unstable-book/src/language-features/inclusive-range-syntax.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ The tracking issue for this feature is: [#28237]
77
------------------------
88

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

1212
```rust
1313
#![feature(inclusive_range_syntax)]
1414

1515
fn main() {
16-
for i in 0...10 {
16+
for i in 0..=10 {
1717
println!("{}", i);
1818
}
1919
}

src/liballoc/tests/btree/map.rs

+14-14
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ fn test_range_small() {
182182
fn test_range_inclusive() {
183183
let size = 500;
184184

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

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

196-
check(map.range(size + 1...size + 1), vec![]);
197-
check(map.range(size...size), vec![(&size, &size)]);
198-
check(map.range(size...size + 1), vec![(&size, &size)]);
199-
check(map.range(0...0), vec![(&0, &0)]);
200-
check(map.range(0...size - 1), map.range(..size));
201-
check(map.range(-1...-1), vec![]);
202-
check(map.range(-1...size), map.range(..));
203-
check(map.range(...size), map.range(..));
204-
check(map.range(...200), map.range(..201));
205-
check(map.range(5...8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
206-
check(map.range(-1...0), vec![(&0, &0)]);
207-
check(map.range(-1...2), vec![(&0, &0), (&1, &1), (&2, &2)]);
196+
check(map.range(size + 1..=size + 1), vec![]);
197+
check(map.range(size..=size), vec![(&size, &size)]);
198+
check(map.range(size..=size + 1), vec![(&size, &size)]);
199+
check(map.range(0..=0), vec![(&0, &0)]);
200+
check(map.range(0..=size - 1), map.range(..size));
201+
check(map.range(-1..=-1), vec![]);
202+
check(map.range(-1..=size), map.range(..));
203+
check(map.range(..=size), map.range(..));
204+
check(map.range(..=200), map.range(..201));
205+
check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
206+
check(map.range(-1..=0), vec![(&0, &0)]);
207+
check(map.range(-1..=2), vec![(&0, &0), (&1, &1), (&2, &2)]);
208208
}
209209

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

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

218218
#[test]

src/liballoc/tests/str.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -361,43 +361,43 @@ fn test_slice_fail() {
361361
#[test]
362362
#[should_panic]
363363
fn test_str_slice_rangetoinclusive_max_panics() {
364-
&"hello"[...usize::max_value()];
364+
&"hello"[..=usize::max_value()];
365365
}
366366

367367
#[test]
368368
#[should_panic]
369369
fn test_str_slice_rangeinclusive_max_panics() {
370-
&"hello"[1...usize::max_value()];
370+
&"hello"[1..=usize::max_value()];
371371
}
372372

373373
#[test]
374374
#[should_panic]
375375
fn test_str_slicemut_rangetoinclusive_max_panics() {
376376
let mut s = "hello".to_owned();
377377
let s: &mut str = &mut s;
378-
&mut s[...usize::max_value()];
378+
&mut s[..=usize::max_value()];
379379
}
380380

381381
#[test]
382382
#[should_panic]
383383
fn test_str_slicemut_rangeinclusive_max_panics() {
384384
let mut s = "hello".to_owned();
385385
let s: &mut str = &mut s;
386-
&mut s[1...usize::max_value()];
386+
&mut s[1..=usize::max_value()];
387387
}
388388

389389
#[test]
390390
fn test_str_get_maxinclusive() {
391391
let mut s = "hello".to_owned();
392392
{
393393
let s: &str = &s;
394-
assert_eq!(s.get(...usize::max_value()), None);
395-
assert_eq!(s.get(1...usize::max_value()), None);
394+
assert_eq!(s.get(..=usize::max_value()), None);
395+
assert_eq!(s.get(1..=usize::max_value()), None);
396396
}
397397
{
398398
let s: &mut str = &mut s;
399-
assert_eq!(s.get(...usize::max_value()), None);
400-
assert_eq!(s.get(1...usize::max_value()), None);
399+
assert_eq!(s.get(..=usize::max_value()), None);
400+
assert_eq!(s.get(1..=usize::max_value()), None);
401401
}
402402
}
403403

src/liballoc/tests/string.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -456,9 +456,9 @@ fn test_splice_char_boundary() {
456456
#[test]
457457
fn test_splice_inclusive_range() {
458458
let mut v = String::from("12345");
459-
v.splice(2...3, "789");
459+
v.splice(2..=3, "789");
460460
assert_eq!(v, "127895");
461-
v.splice(1...2, "A");
461+
v.splice(1..=2, "A");
462462
assert_eq!(v, "1A895");
463463
}
464464

@@ -473,7 +473,7 @@ fn test_splice_out_of_bounds() {
473473
#[should_panic]
474474
fn test_splice_inclusive_out_of_bounds() {
475475
let mut s = String::from("12345");
476-
s.splice(5...5, "789");
476+
s.splice(5..=5, "789");
477477
}
478478

479479
#[test]

src/liballoc/tests/vec.rs

+14-14
Original file line numberDiff line numberDiff line change
@@ -537,27 +537,27 @@ fn test_drain_range() {
537537
#[test]
538538
fn test_drain_inclusive_range() {
539539
let mut v = vec!['a', 'b', 'c', 'd', 'e'];
540-
for _ in v.drain(1...3) {
540+
for _ in v.drain(1..=3) {
541541
}
542542
assert_eq!(v, &['a', 'e']);
543543

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

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

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

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

573573
let mut v = Vec::<()>::with_capacity(usize::max_value());
574574
unsafe { v.set_len(usize::max_value()); }
575-
for _ in v.drain(usize::max_value() - 1...usize::max_value() - 1) {
575+
for _ in v.drain(usize::max_value() - 1..=usize::max_value() - 1) {
576576
}
577577
assert_eq!(v.len(), usize::max_value() - 1);
578578
}
@@ -581,7 +581,7 @@ fn test_drain_max_vec_size() {
581581
#[should_panic]
582582
fn test_drain_inclusive_out_of_bounds() {
583583
let mut v = vec![1, 2, 3, 4, 5];
584-
v.drain(5...5);
584+
v.drain(5..=5);
585585
}
586586

587587
#[test]
@@ -598,10 +598,10 @@ fn test_splice() {
598598
fn test_splice_inclusive_range() {
599599
let mut v = vec![1, 2, 3, 4, 5];
600600
let a = [10, 11, 12];
601-
let t1: Vec<_> = v.splice(2...3, a.iter().cloned()).collect();
601+
let t1: Vec<_> = v.splice(2..=3, a.iter().cloned()).collect();
602602
assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
603603
assert_eq!(t1, &[3, 4]);
604-
let t2: Vec<_> = v.splice(1...2, Some(20)).collect();
604+
let t2: Vec<_> = v.splice(1..=2, Some(20)).collect();
605605
assert_eq!(v, &[1, 20, 11, 12, 5]);
606606
assert_eq!(t2, &[2, 10]);
607607
}
@@ -619,7 +619,7 @@ fn test_splice_out_of_bounds() {
619619
fn test_splice_inclusive_out_of_bounds() {
620620
let mut v = vec![1, 2, 3, 4, 5];
621621
let a = [10, 11, 12];
622-
v.splice(5...5, a.iter().cloned());
622+
v.splice(5..=5, a.iter().cloned());
623623
}
624624

625625
#[test]

src/libcore/ops/range.rs

+25-25
Original file line numberDiff line numberDiff line change
@@ -241,22 +241,22 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
241241
}
242242
}
243243

244-
/// An range bounded inclusively below and above (`start...end`).
244+
/// An range bounded inclusively below and above (`start..=end`).
245245
///
246-
/// The `RangeInclusive` `start...end` contains all values with `x >= start`
246+
/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
247247
/// and `x <= end`.
248248
///
249249
/// # Examples
250250
///
251251
/// ```
252252
/// #![feature(inclusive_range,inclusive_range_syntax)]
253253
///
254-
/// assert_eq!((3...5), std::ops::RangeInclusive { start: 3, end: 5 });
255-
/// assert_eq!(3 + 4 + 5, (3...5).sum());
254+
/// assert_eq!((3..=5), std::ops::RangeInclusive { start: 3, end: 5 });
255+
/// assert_eq!(3 + 4 + 5, (3..=5).sum());
256256
///
257257
/// let arr = [0, 1, 2, 3];
258-
/// assert_eq!(arr[ ...2], [0,1,2 ]);
259-
/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive
258+
/// assert_eq!(arr[ ..=2], [0,1,2 ]);
259+
/// assert_eq!(arr[1..=2], [ 1,2 ]); // RangeInclusive
260260
/// ```
261261
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
262262
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
@@ -276,7 +276,7 @@ pub struct RangeInclusive<Idx> {
276276
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
277277
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
278278
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
279-
write!(fmt, "{:?}...{:?}", self.start, self.end)
279+
write!(fmt, "{:?}..={:?}", self.start, self.end)
280280
}
281281
}
282282

@@ -289,32 +289,32 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
289289
/// ```
290290
/// #![feature(range_contains,inclusive_range_syntax)]
291291
///
292-
/// assert!(!(3...5).contains(2));
293-
/// assert!( (3...5).contains(3));
294-
/// assert!( (3...5).contains(4));
295-
/// assert!( (3...5).contains(5));
296-
/// assert!(!(3...5).contains(6));
292+
/// assert!(!(3..=5).contains(2));
293+
/// assert!( (3..=5).contains(3));
294+
/// assert!( (3..=5).contains(4));
295+
/// assert!( (3..=5).contains(5));
296+
/// assert!(!(3..=5).contains(6));
297297
///
298-
/// assert!( (3...3).contains(3));
299-
/// assert!(!(3...2).contains(3));
298+
/// assert!( (3..=3).contains(3));
299+
/// assert!(!(3..=2).contains(3));
300300
/// ```
301301
pub fn contains(&self, item: Idx) -> bool {
302302
self.start <= item && item <= self.end
303303
}
304304
}
305305

306-
/// A range only bounded inclusively above (`...end`).
306+
/// A range only bounded inclusively above (`..=end`).
307307
///
308-
/// The `RangeToInclusive` `...end` contains all values with `x <= end`.
308+
/// The `RangeToInclusive` `..=end` contains all values with `x <= end`.
309309
/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
310310
///
311311
/// # Examples
312312
///
313-
/// The `...end` syntax is a `RangeToInclusive`:
313+
/// The `..=end` syntax is a `RangeToInclusive`:
314314
///
315315
/// ```
316316
/// #![feature(inclusive_range,inclusive_range_syntax)]
317-
/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 });
317+
/// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 });
318318
/// ```
319319
///
320320
/// 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> {
325325
///
326326
/// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>:
327327
/// // std::iter::Iterator` is not satisfied
328-
/// for i in ...5 {
328+
/// for i in ..=5 {
329329
/// // ...
330330
/// }
331331
/// ```
@@ -337,8 +337,8 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
337337
/// #![feature(inclusive_range_syntax)]
338338
///
339339
/// let arr = [0, 1, 2, 3];
340-
/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive
341-
/// assert_eq!(arr[1...2], [ 1,2 ]);
340+
/// assert_eq!(arr[ ..=2], [0,1,2 ]); // RangeToInclusive
341+
/// assert_eq!(arr[1..=2], [ 1,2 ]);
342342
/// ```
343343
///
344344
/// [`IntoIterator`]: ../iter/trait.Iterator.html
@@ -357,7 +357,7 @@ pub struct RangeToInclusive<Idx> {
357357
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
358358
impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
359359
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
360-
write!(fmt, "...{:?}", self.end)
360+
write!(fmt, "..={:?}", self.end)
361361
}
362362
}
363363

@@ -370,9 +370,9 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
370370
/// ```
371371
/// #![feature(range_contains,inclusive_range_syntax)]
372372
///
373-
/// assert!( (...5).contains(-1_000_000_000));
374-
/// assert!( (...5).contains(5));
375-
/// assert!(!(...5).contains(6));
373+
/// assert!( (..=5).contains(-1_000_000_000));
374+
/// assert!( (..=5).contains(5));
375+
/// assert!(!(..=5).contains(6));
376376
/// ```
377377
pub fn contains(&self, item: Idx) -> bool {
378378
(item <= self.end)

0 commit comments

Comments
 (0)