Skip to content

Commit 0ef85a6

Browse files
committed
Auto merge of #38610 - djzin:master, r=sfackler
Implementation of plan in issue #27787 for btree_range Still some ergonomics to be worked on, the ::<str,_> is particularly unsightly
2 parents c21f73e + bd04c30 commit 0ef85a6

File tree

10 files changed

+190
-77
lines changed

10 files changed

+190
-77
lines changed

src/libcollections/btree/map.rs

+27-25
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ use core::ops::Index;
1717
use core::{fmt, intrinsics, mem, ptr};
1818

1919
use borrow::Borrow;
20-
use Bound::{self, Excluded, Included, Unbounded};
20+
use Bound::{Excluded, Included, Unbounded};
21+
use range::RangeArgument;
2122

2223
use super::node::{self, Handle, NodeRef, marker};
2324
use super::search;
@@ -654,10 +655,12 @@ impl<K: Ord, V> BTreeMap<K, V> {
654655
self.fix_right_edge();
655656
}
656657

657-
/// Constructs a double-ended iterator over a sub-range of elements in the map, starting
658-
/// at min, and ending at max. If min is `Unbounded`, then it will be treated as "negative
659-
/// infinity", and if max is `Unbounded`, then it will be treated as "positive infinity".
660-
/// Thus range(Unbounded, Unbounded) will yield the whole collection.
658+
/// Constructs a double-ended iterator over a sub-range of elements in the map.
659+
/// The simplest way is to use the range synax `min..max`, thus `range(min..max)` will
660+
/// yield elements from min (inclusive) to max (exclusive).
661+
/// The range may also be entered as `(Bound<T>, Bound<T>)`, so for example
662+
/// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive
663+
/// range from 4 to 10.
661664
///
662665
/// # Examples
663666
///
@@ -667,26 +670,25 @@ impl<K: Ord, V> BTreeMap<K, V> {
667670
/// #![feature(btree_range, collections_bound)]
668671
///
669672
/// use std::collections::BTreeMap;
670-
/// use std::collections::Bound::{Included, Unbounded};
673+
/// use std::collections::Bound::Included;
671674
///
672675
/// let mut map = BTreeMap::new();
673676
/// map.insert(3, "a");
674677
/// map.insert(5, "b");
675678
/// map.insert(8, "c");
676-
/// for (&key, &value) in map.range(Included(&4), Included(&8)) {
679+
/// for (&key, &value) in map.range((Included(&4), Included(&8))) {
677680
/// println!("{}: {}", key, value);
678681
/// }
679-
/// assert_eq!(Some((&5, &"b")), map.range(Included(&4), Unbounded).next());
682+
/// assert_eq!(Some((&5, &"b")), map.range(4..).next());
680683
/// ```
681684
#[unstable(feature = "btree_range",
682685
reason = "matches collection reform specification, waiting for dust to settle",
683686
issue = "27787")]
684-
pub fn range<Min: ?Sized + Ord, Max: ?Sized + Ord>(&self,
685-
min: Bound<&Min>,
686-
max: Bound<&Max>)
687-
-> Range<K, V>
688-
where K: Borrow<Min> + Borrow<Max>
687+
pub fn range<T: ?Sized, R>(&self, range: R) -> Range<K, V>
688+
where T: Ord, K: Borrow<T>, R: RangeArgument<T>
689689
{
690+
let min = range.start();
691+
let max = range.end();
690692
let front = match min {
691693
Included(key) => {
692694
match search::search_tree(self.root.as_ref(), key) {
@@ -745,25 +747,26 @@ impl<K: Ord, V> BTreeMap<K, V> {
745747
}
746748
}
747749

748-
/// Constructs a mutable double-ended iterator over a sub-range of elements in the map, starting
749-
/// at min, and ending at max. If min is `Unbounded`, then it will be treated as "negative
750-
/// infinity", and if max is `Unbounded`, then it will be treated as "positive infinity".
751-
/// Thus range(Unbounded, Unbounded) will yield the whole collection.
750+
/// Constructs a mutable double-ended iterator over a sub-range of elements in the map.
751+
/// The simplest way is to use the range synax `min..max`, thus `range(min..max)` will
752+
/// yield elements from min (inclusive) to max (exclusive).
753+
/// The range may also be entered as `(Bound<T>, Bound<T>)`, so for example
754+
/// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive
755+
/// range from 4 to 10.
752756
///
753757
/// # Examples
754758
///
755759
/// Basic usage:
756760
///
757761
/// ```
758-
/// #![feature(btree_range, collections_bound)]
762+
/// #![feature(btree_range)]
759763
///
760764
/// use std::collections::BTreeMap;
761-
/// use std::collections::Bound::{Included, Excluded};
762765
///
763766
/// let mut map: BTreeMap<&str, i32> = ["Alice", "Bob", "Carol", "Cheryl"].iter()
764767
/// .map(|&s| (s, 0))
765768
/// .collect();
766-
/// for (_, balance) in map.range_mut(Included("B"), Excluded("Cheryl")) {
769+
/// for (_, balance) in map.range_mut("B".."Cheryl") {
767770
/// *balance += 100;
768771
/// }
769772
/// for (name, balance) in &map {
@@ -773,12 +776,11 @@ impl<K: Ord, V> BTreeMap<K, V> {
773776
#[unstable(feature = "btree_range",
774777
reason = "matches collection reform specification, waiting for dust to settle",
775778
issue = "27787")]
776-
pub fn range_mut<Min: ?Sized + Ord, Max: ?Sized + Ord>(&mut self,
777-
min: Bound<&Min>,
778-
max: Bound<&Max>)
779-
-> RangeMut<K, V>
780-
where K: Borrow<Min> + Borrow<Max>
779+
pub fn range_mut<T: ?Sized, R>(&mut self, range: R) -> RangeMut<K, V>
780+
where T: Ord, K: Borrow<T>, R: RangeArgument<T>
781781
{
782+
let min = range.start();
783+
let max = range.end();
782784
let root1 = self.root.as_mut();
783785
let root2 = unsafe { ptr::read(&root1) };
784786

src/libcollections/btree/set.rs

+13-14
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use core::ops::{BitOr, BitAnd, BitXor, Sub};
2121
use borrow::Borrow;
2222
use btree_map::{BTreeMap, Keys};
2323
use super::Recover;
24-
use Bound;
24+
use range::RangeArgument;
2525

2626
// FIXME(conventions): implement bounded iterators
2727

@@ -207,38 +207,37 @@ impl<T> BTreeSet<T> {
207207
}
208208

209209
impl<T: Ord> BTreeSet<T> {
210-
/// Constructs a double-ended iterator over a sub-range of elements in the set, starting
211-
/// at min, and ending at max. If min is `Unbounded`, then it will be treated as "negative
212-
/// infinity", and if max is `Unbounded`, then it will be treated as "positive infinity".
213-
/// Thus range(Unbounded, Unbounded) will yield the whole collection.
210+
/// Constructs a double-ended iterator over a sub-range of elements in the set.
211+
/// The simplest way is to use the range synax `min..max`, thus `range(min..max)` will
212+
/// yield elements from min (inclusive) to max (exclusive).
213+
/// The range may also be entered as `(Bound<T>, Bound<T>)`, so for example
214+
/// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive
215+
/// range from 4 to 10.
214216
///
215217
/// # Examples
216218
///
217219
/// ```
218220
/// #![feature(btree_range, collections_bound)]
219221
///
220222
/// use std::collections::BTreeSet;
221-
/// use std::collections::Bound::{Included, Unbounded};
223+
/// use std::collections::Bound::Included;
222224
///
223225
/// let mut set = BTreeSet::new();
224226
/// set.insert(3);
225227
/// set.insert(5);
226228
/// set.insert(8);
227-
/// for &elem in set.range(Included(&4), Included(&8)) {
229+
/// for &elem in set.range((Included(&4), Included(&8))) {
228230
/// println!("{}", elem);
229231
/// }
230-
/// assert_eq!(Some(&5), set.range(Included(&4), Unbounded).next());
232+
/// assert_eq!(Some(&5), set.range(4..).next());
231233
/// ```
232234
#[unstable(feature = "btree_range",
233235
reason = "matches collection reform specification, waiting for dust to settle",
234236
issue = "27787")]
235-
pub fn range<'a, Min: ?Sized + Ord, Max: ?Sized + Ord>(&'a self,
236-
min: Bound<&Min>,
237-
max: Bound<&Max>)
238-
-> Range<'a, T>
239-
where T: Borrow<Min> + Borrow<Max>
237+
pub fn range<K: ?Sized, R>(&self, range: R) -> Range<T>
238+
where K: Ord, T: Borrow<K>, R: RangeArgument<K>
240239
{
241-
Range { iter: self.map.range(min, max) }
240+
Range { iter: self.map.range(range) }
242241
}
243242
}
244243

src/libcollections/range.rs

+66-24
Original file line numberDiff line numberDiff line change
@@ -15,78 +15,120 @@
1515
//! Range syntax.
1616
1717
use core::ops::{RangeFull, Range, RangeTo, RangeFrom};
18+
use Bound::{self, Excluded, Included, Unbounded};
1819

1920
/// **RangeArgument** is implemented by Rust's built-in range types, produced
2021
/// by range syntax like `..`, `a..`, `..b` or `c..d`.
21-
pub trait RangeArgument<T> {
22-
/// Start index (inclusive)
22+
pub trait RangeArgument<T: ?Sized> {
23+
/// Start index bound
2324
///
24-
/// Return start value if present, else `None`.
25+
/// Return start value as a `Bound`
2526
///
2627
/// # Examples
2728
///
2829
/// ```
2930
/// #![feature(collections)]
3031
/// #![feature(collections_range)]
32+
/// #![feature(collections_bound)]
3133
///
3234
/// extern crate collections;
3335
///
3436
/// # fn main() {
3537
/// use collections::range::RangeArgument;
38+
/// use collections::Bound::*;
3639
///
37-
/// assert_eq!((..10).start(), None);
38-
/// assert_eq!((3..10).start(), Some(&3));
40+
/// assert_eq!((..10).start(), Unbounded);
41+
/// assert_eq!((3..10).start(), Included(&3));
3942
/// # }
4043
/// ```
41-
fn start(&self) -> Option<&T> {
42-
None
43-
}
44+
fn start(&self) -> Bound<&T>;
4445

45-
/// End index (exclusive)
46+
/// End index bound
4647
///
47-
/// Return end value if present, else `None`.
48+
/// Return end value as a `Bound`
4849
///
4950
/// # Examples
5051
///
5152
/// ```
5253
/// #![feature(collections)]
5354
/// #![feature(collections_range)]
55+
/// #![feature(collections_bound)]
5456
///
5557
/// extern crate collections;
5658
///
5759
/// # fn main() {
5860
/// use collections::range::RangeArgument;
61+
/// use collections::Bound::*;
5962
///
60-
/// assert_eq!((3..).end(), None);
61-
/// assert_eq!((3..10).end(), Some(&10));
63+
/// assert_eq!((3..).end(), Unbounded);
64+
/// assert_eq!((3..10).end(), Excluded(&10));
6265
/// # }
6366
/// ```
64-
fn end(&self) -> Option<&T> {
65-
None
66-
}
67+
fn end(&self) -> Bound<&T>;
6768
}
6869

6970
// FIXME add inclusive ranges to RangeArgument
7071

71-
impl<T> RangeArgument<T> for RangeFull {}
72+
impl<T: ?Sized> RangeArgument<T> for RangeFull {
73+
fn start(&self) -> Bound<&T> {
74+
Unbounded
75+
}
76+
fn end(&self) -> Bound<&T> {
77+
Unbounded
78+
}
79+
}
7280

7381
impl<T> RangeArgument<T> for RangeFrom<T> {
74-
fn start(&self) -> Option<&T> {
75-
Some(&self.start)
82+
fn start(&self) -> Bound<&T> {
83+
Included(&self.start)
84+
}
85+
fn end(&self) -> Bound<&T> {
86+
Unbounded
7687
}
7788
}
7889

7990
impl<T> RangeArgument<T> for RangeTo<T> {
80-
fn end(&self) -> Option<&T> {
81-
Some(&self.end)
91+
fn start(&self) -> Bound<&T> {
92+
Unbounded
93+
}
94+
fn end(&self) -> Bound<&T> {
95+
Excluded(&self.end)
8296
}
8397
}
8498

8599
impl<T> RangeArgument<T> for Range<T> {
86-
fn start(&self) -> Option<&T> {
87-
Some(&self.start)
100+
fn start(&self) -> Bound<&T> {
101+
Included(&self.start)
88102
}
89-
fn end(&self) -> Option<&T> {
90-
Some(&self.end)
103+
fn end(&self) -> Bound<&T> {
104+
Excluded(&self.end)
105+
}
106+
}
107+
108+
impl<T> RangeArgument<T> for (Bound<T>, Bound<T>) {
109+
fn start(&self) -> Bound<&T> {
110+
match *self {
111+
(Included(ref start), _) => Included(start),
112+
(Excluded(ref start), _) => Excluded(start),
113+
(Unbounded, _) => Unbounded,
114+
}
115+
}
116+
117+
fn end(&self) -> Bound<&T> {
118+
match *self {
119+
(_, Included(ref end)) => Included(end),
120+
(_, Excluded(ref end)) => Excluded(end),
121+
(_, Unbounded) => Unbounded,
122+
}
123+
}
124+
}
125+
126+
impl<'a, T: ?Sized + 'a> RangeArgument<T> for (Bound<&'a T>, Bound<&'a T>) {
127+
fn start(&self) -> Bound<&T> {
128+
self.0
129+
}
130+
131+
fn end(&self) -> Bound<&T> {
132+
self.1
91133
}
92134
}

src/libcollections/string.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ use std_unicode::str as unicode_str;
6868

6969
use borrow::{Cow, ToOwned};
7070
use range::RangeArgument;
71+
use Bound::{Excluded, Included, Unbounded};
7172
use str::{self, FromStr, Utf8Error, Chars};
7273
use vec::Vec;
7374
use boxed::Box;
@@ -1350,8 +1351,16 @@ impl String {
13501351
// Because the range removal happens in Drop, if the Drain iterator is leaked,
13511352
// the removal will not happen.
13521353
let len = self.len();
1353-
let start = *range.start().unwrap_or(&0);
1354-
let end = *range.end().unwrap_or(&len);
1354+
let start = match range.start() {
1355+
Included(&n) => n,
1356+
Excluded(&n) => n + 1,
1357+
Unbounded => 0,
1358+
};
1359+
let end = match range.end() {
1360+
Included(&n) => n + 1,
1361+
Excluded(&n) => n,
1362+
Unbounded => len,
1363+
};
13551364

13561365
// Take out two simultaneous borrows. The &mut String won't be accessed
13571366
// until iteration is over, in Drop.

src/libcollections/vec.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ use core::ptr::Shared;
8484
use core::slice;
8585

8686
use super::range::RangeArgument;
87+
use Bound::{Excluded, Included, Unbounded};
8788

8889
/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
8990
///
@@ -1060,8 +1061,16 @@ impl<T> Vec<T> {
10601061
// the hole, and the vector length is restored to the new length.
10611062
//
10621063
let len = self.len();
1063-
let start = *range.start().unwrap_or(&0);
1064-
let end = *range.end().unwrap_or(&len);
1064+
let start = match range.start() {
1065+
Included(&n) => n,
1066+
Excluded(&n) => n + 1,
1067+
Unbounded => 0,
1068+
};
1069+
let end = match range.end() {
1070+
Included(&n) => n + 1,
1071+
Excluded(&n) => n,
1072+
Unbounded => len,
1073+
};
10651074
assert!(start <= end);
10661075
assert!(end <= len);
10671076

src/libcollections/vec_deque.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use core::cmp;
3333
use alloc::raw_vec::RawVec;
3434

3535
use super::range::RangeArgument;
36+
use Bound::{Excluded, Included, Unbounded};
3637
use super::vec::Vec;
3738

3839
const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
@@ -852,8 +853,16 @@ impl<T> VecDeque<T> {
852853
// and the head/tail values will be restored correctly.
853854
//
854855
let len = self.len();
855-
let start = *range.start().unwrap_or(&0);
856-
let end = *range.end().unwrap_or(&len);
856+
let start = match range.start() {
857+
Included(&n) => n,
858+
Excluded(&n) => n + 1,
859+
Unbounded => 0,
860+
};
861+
let end = match range.end() {
862+
Included(&n) => n + 1,
863+
Excluded(&n) => n,
864+
Unbounded => len,
865+
};
857866
assert!(start <= end, "drain lower bound was too large");
858867
assert!(end <= len, "drain upper bound was too large");
859868

0 commit comments

Comments
 (0)