diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index 4c93fead17237..064606cb40dbb 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -13,12 +13,11 @@ use core::fmt::Debug; use core::hash::{Hash, Hasher}; use core::iter::{FromIterator, Peekable, FusedIterator}; use core::marker::PhantomData; -use core::ops::Index; +use core::ops::{Index, RangeBounds}; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::{fmt, intrinsics, mem, ptr}; use borrow::Borrow; -use Bound::{Excluded, Included, Unbounded}; -use range::RangeArgument; use super::node::{self, Handle, NodeRef, marker}; use super::search; @@ -783,18 +782,18 @@ impl BTreeMap { /// map.insert(3, "a"); /// map.insert(5, "b"); /// map.insert(8, "c"); - /// for (&key, &value) in map.range((Included(&4), Included(&8))) { + /// for (&key, &value) in map.range((Included(4), Included(8))) { /// println!("{}: {}", key, value); /// } /// assert_eq!(Some((&5, &"b")), map.range(4..).next()); /// ``` #[stable(feature = "btree_range", since = "1.17.0")] - pub fn range(&self, range: R) -> Range - where T: Ord, K: Borrow, R: RangeArgument + pub fn range(&self, range: R) -> Range + where T: Ord, K: Borrow, R: Into> { let root1 = self.root.as_ref(); let root2 = self.root.as_ref(); - let (f, b) = range_search(root1, root2, range); + let (f, b) = range_search(root1, root2, range.into()); Range { front: f, back: b} } @@ -829,12 +828,12 @@ impl BTreeMap { /// } /// ``` #[stable(feature = "btree_range", since = "1.17.0")] - pub fn range_mut(&mut self, range: R) -> RangeMut - where T: Ord, K: Borrow, R: RangeArgument + pub fn range_mut(&mut self, range: R) -> RangeMut + where T: Ord, K: Borrow, R: Into> { let root1 = self.root.as_mut(); let root2 = unsafe { ptr::read(&root1) }; - let (f, b) = range_search(root1, root2, range); + let (f, b) = range_search(root1, root2, range.into()); RangeMut { front: f, @@ -1780,21 +1779,21 @@ fn last_leaf_edge } } -fn range_search>( +fn range_search( root1: NodeRef, root2: NodeRef, - range: R + range: RangeBounds )-> (Handle, marker::Edge>, Handle, marker::Edge>) where Q: Ord, K: Borrow { - match (range.start(), range.end()) { - (Excluded(s), Excluded(e)) if s==e => + match (&range.start, &range.end) { + (&Excluded(ref s), &Excluded(ref e)) if *s == *e => panic!("range start and end are equal and excluded in BTreeMap"), - (Included(s), Included(e)) | - (Included(s), Excluded(e)) | - (Excluded(s), Included(e)) | - (Excluded(s), Excluded(e)) if s>e => + (&Included(ref s), &Included(ref e)) | + (&Included(ref s), &Excluded(ref e)) | + (&Excluded(ref s), &Included(ref e)) | + (&Excluded(ref s), &Excluded(ref e)) if *s > *e => panic!("range start is greater than range end in BTreeMap"), _ => {}, }; @@ -1806,32 +1805,32 @@ fn range_search>( let mut diverged = false; loop { - let min_edge = match (min_found, range.start()) { - (false, Included(key)) => match search::search_linear(&min_node, key) { + let min_edge = match (min_found, &range.start) { + (false, &Included(ref key)) => match search::search_linear(&min_node, key) { (i, true) => { min_found = true; i }, (i, false) => i, }, - (false, Excluded(key)) => match search::search_linear(&min_node, key) { + (false, &Excluded(ref key)) => match search::search_linear(&min_node, &key) { (i, true) => { min_found = true; i+1 }, (i, false) => i, }, - (_, Unbounded) => 0, - (true, Included(_)) => min_node.keys().len(), - (true, Excluded(_)) => 0, + (_, &Unbounded) => 0, + (true, &Included(_)) => min_node.keys().len(), + (true, &Excluded(_)) => 0, }; - let max_edge = match (max_found, range.end()) { - (false, Included(key)) => match search::search_linear(&max_node, key) { + let max_edge = match (max_found, &range.end) { + (false, &Included(ref key)) => match search::search_linear(&max_node, key) { (i, true) => { max_found = true; i+1 }, (i, false) => i, }, - (false, Excluded(key)) => match search::search_linear(&max_node, key) { + (false, &Excluded(ref key)) => match search::search_linear(&max_node, key) { (i, true) => { max_found = true; i }, (i, false) => i, }, - (_, Unbounded) => max_node.keys().len(), - (true, Included(_)) => 0, - (true, Excluded(_)) => max_node.keys().len(), + (_, &Unbounded) => max_node.keys().len(), + (true, &Included(_)) => 0, + (true, &Excluded(_)) => max_node.keys().len(), }; if !diverged { diff --git a/src/liballoc/btree/set.rs b/src/liballoc/btree/set.rs index d32460da93923..6ff5a09b1b7bc 100644 --- a/src/liballoc/btree/set.rs +++ b/src/liballoc/btree/set.rs @@ -16,12 +16,11 @@ use core::cmp::{min, max}; use core::fmt::Debug; use core::fmt; use core::iter::{Peekable, FromIterator, FusedIterator}; -use core::ops::{BitOr, BitAnd, BitXor, Sub}; +use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeBounds}; use borrow::Borrow; use btree_map::{BTreeMap, Keys}; use super::Recover; -use range::RangeArgument; // FIXME(conventions): implement bounded iterators @@ -282,16 +281,16 @@ impl BTreeSet { /// set.insert(3); /// set.insert(5); /// set.insert(8); - /// for &elem in set.range((Included(&4), Included(&8))) { + /// for &elem in set.range((Included(4), Included(8))) { /// println!("{}", elem); /// } /// assert_eq!(Some(&5), set.range(4..).next()); /// ``` #[stable(feature = "btree_range", since = "1.17.0")] - pub fn range(&self, range: R) -> Range - where K: Ord, T: Borrow, R: RangeArgument + pub fn range(&self, range: R) -> Range + where K: Ord, T: Borrow, R: Into> { - Range { iter: self.map.range(range) } + Range { iter: self.map.range(range.into()) } } } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 2845d349ae165..f27cedd4fd2f8 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -106,6 +106,7 @@ #![feature(pattern)] #![feature(placement_in_syntax)] #![feature(placement_new_protocol)] +#![feature(range_argument)] #![feature(rustc_attrs)] #![feature(shared)] #![feature(slice_get_slice)] @@ -171,7 +172,6 @@ mod btree; pub mod borrow; pub mod fmt; pub mod linked_list; -pub mod range; pub mod slice; pub mod str; pub mod string; @@ -197,57 +197,6 @@ mod std { pub use core::ops; // RangeFull } -/// An endpoint of a range of keys. -/// -/// # Examples -/// -/// `Bound`s are range endpoints: -/// -/// ``` -/// #![feature(collections_range)] -/// -/// use std::collections::range::RangeArgument; -/// use std::collections::Bound::*; -/// -/// assert_eq!((..100).start(), Unbounded); -/// assert_eq!((1..12).start(), Included(&1)); -/// assert_eq!((1..12).end(), Excluded(&12)); -/// ``` -/// -/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. -/// Note that in most cases, it's better to use range syntax (`1..5`) instead. -/// -/// ``` -/// use std::collections::BTreeMap; -/// use std::collections::Bound::{Excluded, Included, Unbounded}; -/// -/// let mut map = BTreeMap::new(); -/// map.insert(3, "a"); -/// map.insert(5, "b"); -/// map.insert(8, "c"); -/// -/// for (key, value) in map.range((Excluded(3), Included(8))) { -/// println!("{}: {}", key, value); -/// } -/// -/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); -/// ``` -/// -/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range -#[stable(feature = "collections_bound", since = "1.17.0")] -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -pub enum Bound { - /// An inclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Included(#[stable(feature = "collections_bound", since = "1.17.0")] T), - /// An exclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Excluded(#[stable(feature = "collections_bound", since = "1.17.0")] T), - /// An infinite endpoint. Indicates that there is no bound in this direction. - #[stable(feature = "collections_bound", since = "1.17.0")] - Unbounded, -} - /// An intermediate trait for specialization of `Extend`. #[doc(hidden)] trait SpecExtend { @@ -255,6 +204,10 @@ trait SpecExtend { fn spec_extend(&mut self, iter: I); } +#[rustc_deprecated(reason = "moved to core::ops", since = "1.22.0")] +#[unstable(feature = "range_argument", issue = "30877")] +pub use core::ops::Bound; + #[doc(no_inline)] pub use binary_heap::BinaryHeap; #[doc(no_inline)] diff --git a/src/liballoc/range.rs b/src/liballoc/range.rs deleted file mode 100644 index f862da0d61e01..0000000000000 --- a/src/liballoc/range.rs +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![unstable(feature = "collections_range", - reason = "waiting for dust to settle on inclusive ranges", - issue = "30877")] - -//! Range syntax. - -use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive, RangeToInclusive}; -use Bound::{self, Excluded, Included, Unbounded}; - -/// `RangeArgument` is implemented by Rust's built-in range types, produced -/// by range syntax like `..`, `a..`, `..b` or `c..d`. -pub trait RangeArgument { - /// Start index bound. - /// - /// Returns the start value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// #![feature(alloc)] - /// #![feature(collections_range)] - /// - /// extern crate alloc; - /// - /// # fn main() { - /// use alloc::range::RangeArgument; - /// use alloc::Bound::*; - /// - /// assert_eq!((..10).start(), Unbounded); - /// assert_eq!((3..10).start(), Included(&3)); - /// # } - /// ``` - fn start(&self) -> Bound<&T>; - - /// End index bound. - /// - /// Returns the end value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// #![feature(alloc)] - /// #![feature(collections_range)] - /// - /// extern crate alloc; - /// - /// # fn main() { - /// use alloc::range::RangeArgument; - /// use alloc::Bound::*; - /// - /// assert_eq!((3..).end(), Unbounded); - /// assert_eq!((3..10).end(), Excluded(&10)); - /// # } - /// ``` - fn end(&self) -> Bound<&T>; -} - -// FIXME add inclusive ranges to RangeArgument - -impl RangeArgument for RangeFull { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -impl RangeArgument for RangeFrom { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -impl RangeArgument for RangeTo { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -impl RangeArgument for Range { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeInclusive { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeToInclusive { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -impl RangeArgument for (Bound, Bound) { - fn start(&self) -> Bound<&T> { - match *self { - (Included(ref start), _) => Included(start), - (Excluded(ref start), _) => Excluded(start), - (Unbounded, _) => Unbounded, - } - } - - fn end(&self) -> Bound<&T> { - match *self { - (_, Included(ref end)) => Included(end), - (_, Excluded(ref end)) => Excluded(end), - (_, Unbounded) => Unbounded, - } - } -} - -impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { - fn start(&self) -> Bound<&T> { - self.0 - } - - fn end(&self) -> Bound<&T> { - self.1 - } -} diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 1708f3e398756..d57feaadd81e5 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -59,15 +59,14 @@ use core::fmt; use core::hash; use core::iter::{FromIterator, FusedIterator}; -use core::ops::{self, Add, AddAssign, Index, IndexMut}; +use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeBounds}; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ptr; use core::str::pattern::Pattern; use std_unicode::lossy; use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER}; use borrow::{Cow, ToOwned}; -use range::RangeArgument; -use Bound::{Excluded, Included, Unbounded}; use str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars}; use vec::Vec; use boxed::Box; @@ -1367,7 +1366,7 @@ impl String { /// ``` #[stable(feature = "drain", since = "1.6.0")] pub fn drain(&mut self, range: R) -> Drain - where R: RangeArgument + where R: Into> { // Memory safety // @@ -1376,14 +1375,15 @@ impl String { // Because the range removal happens in Drop, if the Drain iterator is leaked, // the removal will not happen. let len = self.len(); - let start = match range.start() { - Included(&n) => n, - Excluded(&n) => n + 1, + let range = range.into(); + let start = match range.start { + Included(n) => n, + Excluded(n) => n + 1, Unbounded => 0, }; - let end = match range.end() { - Included(&n) => n + 1, - Excluded(&n) => n, + let end = match range.end { + Included(n) => n + 1, + Excluded(n) => n, Unbounded => len, }; @@ -1430,22 +1430,23 @@ impl String { /// assert_eq!(s, "Α is capital alpha; β is beta"); /// ``` #[unstable(feature = "splice", reason = "recently added", issue = "32310")] - pub fn splice(&mut self, range: R, replace_with: &str) - where R: RangeArgument + pub fn splice<'a, 'b, R>(&'a mut self, range: R, replace_with: &'b str) + where R: Into> { // Memory safety // // The String version of Splice does not have the memory safety issues // of the vector version. The data is just plain bytes. - match range.start() { - Included(&n) => assert!(self.is_char_boundary(n)), - Excluded(&n) => assert!(self.is_char_boundary(n + 1)), + let range = range.into(); + match range.start { + Included(n) => assert!(self.is_char_boundary(n)), + Excluded(n) => assert!(self.is_char_boundary(n + 1)), Unbounded => {}, }; - match range.end() { - Included(&n) => assert!(self.is_char_boundary(n + 1)), - Excluded(&n) => assert!(self.is_char_boundary(n)), + match range.end { + Included(n) => assert!(self.is_char_boundary(n + 1)), + Excluded(n) => assert!(self.is_char_boundary(n)), Unbounded => {}, }; diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 2c899d96940ec..88384a689b3f9 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -9,8 +9,8 @@ // except according to those terms. use std::collections::BTreeMap; -use std::collections::Bound::{self, Excluded, Included, Unbounded}; use std::collections::btree_map::Entry::{Occupied, Vacant}; +use std::ops::Bound::{self, Excluded, Included, Unbounded}; use std::rc::Rc; use std::iter::FromIterator; @@ -262,7 +262,7 @@ fn test_range_1000() { let size = 1000; let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - fn test(map: &BTreeMap, size: u32, min: Bound<&u32>, max: Bound<&u32>) { + fn test(map: &BTreeMap, size: u32, min: Bound, max: Bound) { let mut kvs = map.range((min, max)).map(|(&k, &v)| (k, v)); let mut pairs = (0..size).map(|i| (i, i)); @@ -272,11 +272,11 @@ fn test_range_1000() { assert_eq!(kvs.next(), None); assert_eq!(pairs.next(), None); } - test(&map, size, Included(&0), Excluded(&size)); - test(&map, size, Unbounded, Excluded(&size)); - test(&map, size, Included(&0), Included(&(size - 1))); - test(&map, size, Unbounded, Included(&(size - 1))); - test(&map, size, Included(&0), Unbounded); + test(&map, size, Included(0), Excluded(size)); + test(&map, size, Unbounded, Excluded(size)); + test(&map, size, Included(0), Included(size - 1)); + test(&map, size, Unbounded, Included(size - 1)); + test(&map, size, Included(0), Unbounded); test(&map, size, Unbounded, Unbounded); } @@ -288,7 +288,7 @@ fn test_range_borrowed_key() { map.insert("coyote".to_string(), 3); map.insert("dingo".to_string(), 4); // NOTE: would like to use simply "b".."d" here... - let mut iter = map.range::((Included("b"),Excluded("d"))); + let mut iter = map.range::((Included("b".to_string()),Excluded("d".to_string()))); assert_eq!(iter.next(), Some((&"baboon".to_string(), &2))); assert_eq!(iter.next(), Some((&"coyote".to_string(), &3))); assert_eq!(iter.next(), None); @@ -301,7 +301,7 @@ fn test_range() { for i in 0..size { for j in i..size { - let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v)); + let mut kvs = map.range((Included(i), Included(j))).map(|(&k, &v)| (k, v)); let mut pairs = (i..j + 1).map(|i| (i, i)); for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { @@ -320,7 +320,7 @@ fn test_range_mut() { for i in 0..size { for j in i..size { - let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v)); + let mut kvs = map.range_mut((Included(i), Included(j))).map(|(&k, &mut v)| (k, v)); let mut pairs = (i..j + 1).map(|i| (i, i)); for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 8141851b8c9af..da55cc8dd46e9 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -74,7 +74,8 @@ use core::iter::{FromIterator, FusedIterator, TrustedLen}; use core::mem; #[cfg(not(test))] use core::num::Float; -use core::ops::{InPlace, Index, IndexMut, Place, Placer}; +use core::ops::{InPlace, Index, IndexMut, Place, Placer, RangeBounds}; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops; use core::ptr; use core::ptr::Shared; @@ -84,8 +85,6 @@ use borrow::ToOwned; use borrow::Cow; use boxed::Box; use raw_vec::RawVec; -use super::range::RangeArgument; -use Bound::{Excluded, Included, Unbounded}; /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// @@ -1089,7 +1088,7 @@ impl Vec { /// ``` #[stable(feature = "drain", since = "1.6.0")] pub fn drain(&mut self, range: R) -> Drain - where R: RangeArgument + where R: Into> { // Memory safety // @@ -1102,14 +1101,15 @@ impl Vec { // the hole, and the vector length is restored to the new length. // let len = self.len(); - let start = match range.start() { - Included(&n) => n, - Excluded(&n) => n + 1, + let range = range.into(); + let start = match range.start { + Included(n) => n, + Excluded(n) => n + 1, Unbounded => 0, }; - let end = match range.end() { - Included(&n) => n + 1, - Excluded(&n) => n, + let end = match range.end { + Included(n) => n + 1, + Excluded(n) => n, Unbounded => len, }; assert!(start <= end); @@ -1952,7 +1952,7 @@ impl Vec { #[inline] #[unstable(feature = "splice", reason = "recently added", issue = "32310")] pub fn splice(&mut self, range: R, replace_with: I) -> Splice - where R: RangeArgument, I: IntoIterator + where R: Into>, I: IntoIterator { Splice { drain: self.drain(range), diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 00def2a1eac49..31f0664a4696f 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -21,7 +21,8 @@ use core::cmp::Ordering; use core::fmt; use core::iter::{repeat, FromIterator, FusedIterator}; use core::mem; -use core::ops::{Index, IndexMut, Place, Placer, InPlace}; +use core::ops::{Index, IndexMut, Place, Placer, InPlace, RangeBounds}; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ptr; use core::ptr::Shared; use core::slice; @@ -31,8 +32,6 @@ use core::cmp; use raw_vec::RawVec; -use super::range::RangeArgument; -use Bound::{Excluded, Included, Unbounded}; use super::vec::Vec; const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 @@ -844,7 +843,7 @@ impl VecDeque { #[inline] #[stable(feature = "drain", since = "1.6.0")] pub fn drain(&mut self, range: R) -> Drain - where R: RangeArgument + where R: Into> { // Memory safety // @@ -857,14 +856,15 @@ impl VecDeque { // and the head/tail values will be restored correctly. // let len = self.len(); - let start = match range.start() { - Included(&n) => n, - Excluded(&n) => n + 1, + let range = range.into(); + let start = match range.start { + Included(n) => n, + Excluded(n) => n + 1, Unbounded => 0, }; - let end = match range.end() { - Included(&n) => n + 1, - Excluded(&n) => n, + let end = match range.end { + Included(n) => n + 1, + Excluded(n) => n, Unbounded => len, }; assert!(start <= end, "drain lower bound was too large"); diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 55316db3d5a43..d7c0a59abb256 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -24,7 +24,6 @@ #![deny(warnings)] #![feature(alloc)] -#![feature(collections_range)] #![feature(macro_reexport)] #![feature(staged_api)] @@ -36,13 +35,16 @@ #[macro_reexport(vec, format)] extern crate alloc; +#[rustc_deprecated(reason = "moved to core::ops", since = "1.22.0")] +#[unstable(feature = "range_argument", issue = "30877")] +pub mod range { } + pub use alloc::Bound; pub use alloc::binary_heap; pub use alloc::borrow; pub use alloc::fmt; pub use alloc::linked_list; -pub use alloc::range; pub use alloc::slice; pub use alloc::str; pub use alloc::string; diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index 8975b680ca7fa..dbab20ee0d85b 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -194,6 +194,12 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub use self::range::{RangeInclusive, RangeToInclusive}; +#[stable(feature = "collections_bound", since = "1.17.0")] +pub use self::range::Bound; + +#[unstable(feature = "range_argument", issue = "30877")] +pub use self::range::RangeBounds; + #[unstable(feature = "try_trait", issue = "42327")] pub use self::try::Try; diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 463a50491a866..a57aac6d88956 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -381,3 +381,129 @@ impl> RangeToInclusive { // RangeToInclusive cannot impl From> // because underflow would be possible with (..0).into() + +/// An endpoint of a range of keys. +/// +/// # Examples +/// +/// `Bound`s are range endpoints: +/// +/// ``` +/// # #![feature(range_argument)] +/// use std::ops::RangeBounds; +/// use std::ops::Bound::*; +/// +/// assert_eq!(Into::>::into((..100)).start, Unbounded); +/// assert_eq!(Into::>::into((1..12)).start, Included(1)); +/// assert_eq!(Into::>::into((1..12)).end, Excluded(12)); +/// ``` +/// +/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. +/// Note that in most cases, it's better to use range syntax (`1..5`) instead. +/// +/// ``` +/// use std::collections::BTreeMap; +/// use std::ops::Bound::{Excluded, Included, Unbounded}; +/// +/// let mut map = BTreeMap::new(); +/// map.insert(3, "a"); +/// map.insert(5, "b"); +/// map.insert(8, "c"); +/// +/// for (key, value) in map.range((Excluded(3), Included(8))) { +/// println!("{}: {}", key, value); +/// } +/// +/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); +/// ``` +/// +/// [`BTreeMap::range`]: +/// https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.range +#[stable(feature = "collections_bound", since = "1.17.0")] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum Bound { + /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Included( + #[stable(feature = "collections_bound", since = "1.17.0")] + T + ), + /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Excluded( + #[stable(feature = "collections_bound", since = "1.17.0")] + T + ), + /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] + Unbounded, +} +use self::Bound::{Included, Excluded, Unbounded}; + + +/// Rust's built-in range types can be converted to `RangeBounds`. +#[unstable(feature = "range_argument", issue = "30877")] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub struct RangeBounds { + /// The lower bound of the range. + pub start: Bound, + + /// The upper bound of the range. + pub end: Bound, +} +impl RangeBounds { + /// Constructs a pair of range bounds. + #[unstable(feature = "range_argument", issue = "30877")] + pub fn new(start: Bound, end: Bound) -> RangeBounds { + RangeBounds { start, end } + } +} + +#[unstable(feature = "range_argument", issue = "30877")] +impl From for RangeBounds { + fn from(_: RangeFull) -> RangeBounds { + RangeBounds::new(Unbounded, Unbounded) + } +} + +#[unstable(feature = "range_argument", issue = "30877")] +impl From> for RangeBounds { + fn from(range: RangeFrom) -> RangeBounds { + RangeBounds::new(Included(range.start), Unbounded) + } +} + +#[unstable(feature = "range_argument", issue = "30877")] +impl From> for RangeBounds { + fn from(range: RangeTo) -> RangeBounds { + RangeBounds::new(Unbounded, Excluded(range.end)) + } +} + +#[unstable(feature = "range_argument", issue = "30877")] +impl From> for RangeBounds { + fn from(range: Range) -> RangeBounds { + RangeBounds::new(Included(range.start), Excluded(range.end)) + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl From> for RangeBounds { + fn from(range: RangeInclusive) -> RangeBounds { + RangeBounds::new(Included(range.start), Included(range.end)) + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl From> for RangeBounds { + fn from(range: RangeToInclusive) -> RangeBounds { + RangeBounds::new(Unbounded, Included(range.end)) + } +} + +#[unstable(feature = "range_argument", issue = "30877")] +impl From<(Bound, Bound)> for RangeBounds { + fn from((start, end): (Bound, Bound)) -> RangeBounds { + RangeBounds::new(start, end) + } +} diff --git a/src/librustc_data_structures/accumulate_vec.rs b/src/librustc_data_structures/accumulate_vec.rs index 52306de74cb8b..47a730ee98ce8 100644 --- a/src/librustc_data_structures/accumulate_vec.rs +++ b/src/librustc_data_structures/accumulate_vec.rs @@ -15,11 +15,10 @@ //! //! The N above is determined by Array's implementor, by way of an associated constant. -use std::ops::{Deref, DerefMut}; +use std::ops::{Deref, DerefMut, RangeBounds}; use std::iter::{self, IntoIterator, FromIterator}; use std::slice; use std::vec; -use std::collections::range::RangeArgument; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; @@ -74,7 +73,7 @@ impl AccumulateVec { } pub fn drain(&mut self, range: R) -> Drain - where R: RangeArgument + where R: Into> { match *self { AccumulateVec::Array(ref mut v) => { diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index 1e67461e0556d..798c404248480 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -13,13 +13,12 @@ use std::marker::Unsize; use std::iter::Extend; use std::ptr::{self, drop_in_place, Shared}; -use std::ops::{Deref, DerefMut, Range}; +use std::ops::{Deref, DerefMut, Range, RangeBounds}; +use std::ops::Bound::{Excluded, Included, Unbounded}; use std::hash::{Hash, Hasher}; use std::slice; use std::fmt; use std::mem; -use std::collections::range::RangeArgument; -use std::collections::Bound::{Excluded, Included, Unbounded}; use std::mem::ManuallyDrop; pub unsafe trait Array { @@ -106,7 +105,7 @@ impl ArrayVec { } pub fn drain(&mut self, range: R) -> Drain - where R: RangeArgument + where R: Into> { // Memory safety // @@ -119,14 +118,15 @@ impl ArrayVec { // the hole, and the vector length is restored to the new length. // let len = self.len(); - let start = match range.start() { - Included(&n) => n, - Excluded(&n) => n + 1, + let range = range.into(); + let start = match range.start { + Included(n) => n, + Excluded(n) => n + 1, Unbounded => 0, }; - let end = match range.end() { - Included(&n) => n + 1, - Excluded(&n) => n, + let end = match range.end { + Included(n) => n + 1, + Excluded(n) => n, Unbounded => len, }; assert!(start <= end); diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 1d0e88ee32855..c483974c48967 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::range::RangeArgument; use std::fmt::Debug; use std::iter::{self, FromIterator}; use std::slice; use std::marker::PhantomData; -use std::ops::{Index, IndexMut, Range}; +use std::ops::{Index, IndexMut, Range, RangeBounds}; use std::fmt; use std::vec; use std::u32; @@ -147,13 +146,13 @@ impl IndexVec { } #[inline] - pub fn drain<'a, R: RangeArgument>( + pub fn drain<'a, R: Into>> ( &'a mut self, range: R) -> impl Iterator + 'a { self.raw.drain(range) } #[inline] - pub fn drain_enumerated<'a, R: RangeArgument>( + pub fn drain_enumerated<'a, R: Into>> ( &'a mut self, range: R) -> impl Iterator + 'a { self.raw.drain(range).enumerate().map(IntoIdx { _marker: PhantomData }) } diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 47061883425e2..9127ffeb42ba9 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -22,7 +22,6 @@ #![deny(warnings)] #![feature(shared)] -#![feature(collections_range)] #![feature(nonzero)] #![feature(unboxed_closures)] #![feature(fn_traits)] @@ -30,6 +29,7 @@ #![feature(i128_type)] #![feature(conservative_impl_trait)] #![feature(specialization)] +#![feature(range_argument)] #![cfg_attr(unix, feature(libc))] #![cfg_attr(test, feature(test))] diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index b8a6a66eaa65d..84d4434476fe9 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -435,8 +435,10 @@ pub use self::hash_map::HashMap; #[stable(feature = "rust1", since = "1.0.0")] pub use self::hash_set::HashSet; -#[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::range; +#[rustc_deprecated(reason = "moved to std::ops", since = "1.22.0")] +#[unstable(feature = "range_argument", issue = "30877")] +/// `RangeArgument` is deprecated and moved to std::ops +pub mod range { } mod hash; diff --git a/src/test/run-pass/sync-send-iterators-in-libcollections.rs b/src/test/run-pass/sync-send-iterators-in-libcollections.rs index 903532e9bc80a..11da6a5be78e3 100644 --- a/src/test/run-pass/sync-send-iterators-in-libcollections.rs +++ b/src/test/run-pass/sync-send-iterators-in-libcollections.rs @@ -50,11 +50,11 @@ fn main() { all_sync_send!(BinaryHeap::::new(), iter, drain, into_iter); all_sync_send!(BTreeMap::::new(), iter, iter_mut, into_iter, keys, values); - is_sync_send!(BTreeMap::::new(), range((Included(&0), Included(&9)))); - is_sync_send!(BTreeMap::::new(), range_mut((Included(&0), Included(&9)))); + is_sync_send!(BTreeMap::::new(), range((Included(0), Included(9)))); + is_sync_send!(BTreeMap::::new(), range_mut((Included(0), Included(9)))); all_sync_send!(BTreeSet::::new(), iter, into_iter); - is_sync_send!(BTreeSet::::new(), range((Included(&0), Included(&9)))); + is_sync_send!(BTreeSet::::new(), range((Included(0), Included(9)))); is_sync_send!(BTreeSet::::new(), difference(&BTreeSet::::new())); is_sync_send!(BTreeSet::::new(), symmetric_difference(&BTreeSet::::new())); is_sync_send!(BTreeSet::::new(), intersection(&BTreeSet::::new()));