about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-03-29 11:34:17 +0000
committerbors <bors@rust-lang.org>2018-03-29 11:34:17 +0000
commitae544ee1c90afc0f939753014dc5e884cb2749a0 (patch)
treed07caa9ff970a3127f3530bc78460b81fe727ca7
parent409744bcb91f4efa35b8fcc9e7033523a86b90c2 (diff)
parent6c9b3cccbcef8918829e173a2ea9c5d975cd2777 (diff)
downloadrust-ae544ee1c90afc0f939753014dc5e884cb2749a0.tar.gz
rust-ae544ee1c90afc0f939753014dc5e884cb2749a0.zip
Auto merge of #49163 - SimonSapin:range-bounds, r=alexcrichton
Rename RangeArgument to RangeBounds, move it and Bound to libcore

As proposed in the tracking issue: https://github.com/rust-lang/rust/issues/30877

Changes to *stable* items:

* `core::ops::Bound` / `std::ops::Bound` is new
* `std::collections::Bound` is a deprecated reexport of it (does this actually cause a warning?)

Changes to *unstable* items

* `alloc::Bound` is gone
* `alloc::range::RangeArgument` is moved to `core::ops::RangeBounds` / `std::ops::RangeBounds`
* `alloc::range` is gone
* `std::collections::range::RangeArgument` is deprecated reexport, to be removed later
* `std::collections::range` is deprecated, to be removed later
* `impl RangeBounds<T> for Range{,From,To,Inclusive,ToInclusive}<&T>` are added

The idea of replacing this trait with a type to be used with `Into<_>` is left for future consideration / work.

(Fixes https://github.com/rust-lang-nursery/rust-clippy/issues/2552.)
-rw-r--r--src/liballoc/btree/map.rs12
-rw-r--r--src/liballoc/btree/set.rs7
-rw-r--r--src/liballoc/lib.rs53
-rw-r--r--src/liballoc/range.rs152
-rw-r--r--src/liballoc/string.rs9
-rw-r--r--src/liballoc/tests/btree/map.rs2
-rw-r--r--src/liballoc/vec.rs9
-rw-r--r--src/liballoc/vec_deque.rs7
-rw-r--r--src/libcore/ops/mod.rs2
-rw-r--r--src/libcore/ops/range.rs264
-rw-r--r--src/librustc_data_structures/accumulate_vec.rs5
-rw-r--r--src/librustc_data_structures/array_vec.rs6
-rw-r--r--src/librustc_data_structures/indexed_vec.rs7
-rw-r--r--src/libstd/collections/mod.rs13
-rw-r--r--src/test/run-pass/sync-send-iterators-in-libcollections.rs2
m---------src/tools/clippy24
16 files changed, 311 insertions, 263 deletions
diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs
index cada190032a..c604df7049e 100644
--- a/src/liballoc/btree/map.rs
+++ b/src/liballoc/btree/map.rs
@@ -13,12 +13,12 @@ use core::fmt::Debug;
 use core::hash::{Hash, Hasher};
 use core::iter::{FromIterator, Peekable, FusedIterator};
 use core::marker::PhantomData;
+use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ops::Index;
+use core::ops::RangeBounds;
 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;
@@ -804,7 +804,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     ///
     /// ```
     /// use std::collections::BTreeMap;
-    /// use std::collections::Bound::Included;
+    /// use std::ops::Bound::Included;
     ///
     /// let mut map = BTreeMap::new();
     /// map.insert(3, "a");
@@ -817,7 +817,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// ```
     #[stable(feature = "btree_range", since = "1.17.0")]
     pub fn range<T: ?Sized, R>(&self, range: R) -> Range<K, V>
-        where T: Ord, K: Borrow<T>, R: RangeArgument<T>
+        where T: Ord, K: Borrow<T>, R: RangeBounds<T>
     {
         let root1 = self.root.as_ref();
         let root2 = self.root.as_ref();
@@ -857,7 +857,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// ```
     #[stable(feature = "btree_range", since = "1.17.0")]
     pub fn range_mut<T: ?Sized, R>(&mut self, range: R) -> RangeMut<K, V>
-        where T: Ord, K: Borrow<T>, R: RangeArgument<T>
+        where T: Ord, K: Borrow<T>, R: RangeBounds<T>
     {
         let root1 = self.root.as_mut();
         let root2 = unsafe { ptr::read(&root1) };
@@ -1812,7 +1812,7 @@ fn last_leaf_edge<BorrowType, K, V>
     }
 }
 
-fn range_search<BorrowType, K, V, Q: ?Sized, R: RangeArgument<Q>>(
+fn range_search<BorrowType, K, V, Q: ?Sized, R: RangeBounds<Q>>(
     root1: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
     root2: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
     range: R
diff --git a/src/liballoc/btree/set.rs b/src/liballoc/btree/set.rs
index 2e3157147a0..2aad476d315 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
 
@@ -240,7 +239,7 @@ impl<T: Ord> BTreeSet<T> {
     ///
     /// ```
     /// use std::collections::BTreeSet;
-    /// use std::collections::Bound::Included;
+    /// use std::ops::Bound::Included;
     ///
     /// let mut set = BTreeSet::new();
     /// set.insert(3);
@@ -253,7 +252,7 @@ impl<T: Ord> BTreeSet<T> {
     /// ```
     #[stable(feature = "btree_range", since = "1.17.0")]
     pub fn range<K: ?Sized, R>(&self, range: R) -> Range<T>
-        where K: Ord, T: Borrow<K>, R: RangeArgument<K>
+        where K: Ord, T: Borrow<K>, R: RangeBounds<K>
     {
         Range { iter: self.map.range(range) }
     }
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 19d64d8fea9..e98b58994bf 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -88,6 +88,7 @@
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
 #![feature(coerce_unsized)]
+#![feature(collections_range)]
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(custom_attribute)]
@@ -178,7 +179,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;
@@ -204,57 +204,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<T> {
-    /// 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<I: IntoIterator> {
diff --git a/src/liballoc/range.rs b/src/liballoc/range.rs
deleted file mode 100644
index b03abc85180..00000000000
--- 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 <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.
-
-#![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<T: ?Sized> {
-    /// 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<T: ?Sized> RangeArgument<T> for RangeFull {
-    fn start(&self) -> Bound<&T> {
-        Unbounded
-    }
-    fn end(&self) -> Bound<&T> {
-        Unbounded
-    }
-}
-
-impl<T> RangeArgument<T> for RangeFrom<T> {
-    fn start(&self) -> Bound<&T> {
-        Included(&self.start)
-    }
-    fn end(&self) -> Bound<&T> {
-        Unbounded
-    }
-}
-
-impl<T> RangeArgument<T> for RangeTo<T> {
-    fn start(&self) -> Bound<&T> {
-        Unbounded
-    }
-    fn end(&self) -> Bound<&T> {
-        Excluded(&self.end)
-    }
-}
-
-impl<T> RangeArgument<T> for Range<T> {
-    fn start(&self) -> Bound<&T> {
-        Included(&self.start)
-    }
-    fn end(&self) -> Bound<&T> {
-        Excluded(&self.end)
-    }
-}
-
-#[stable(feature = "inclusive_range", since = "1.26.0")]
-impl<T> RangeArgument<T> for RangeInclusive<T> {
-    fn start(&self) -> Bound<&T> {
-        Included(&self.start)
-    }
-    fn end(&self) -> Bound<&T> {
-        Included(&self.end)
-    }
-}
-
-#[stable(feature = "inclusive_range", since = "1.26.0")]
-impl<T> RangeArgument<T> for RangeToInclusive<T> {
-    fn start(&self) -> Bound<&T> {
-        Unbounded
-    }
-    fn end(&self) -> Bound<&T> {
-        Included(&self.end)
-    }
-}
-
-impl<T> RangeArgument<T> for (Bound<T>, Bound<T>) {
-    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<T> 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 23c12bef3aa..aa202e23628 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::Bound::{Excluded, Included, Unbounded};
+use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeBounds};
 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;
@@ -1484,7 +1483,7 @@ impl String {
     /// ```
     #[stable(feature = "drain", since = "1.6.0")]
     pub fn drain<R>(&mut self, range: R) -> Drain
-        where R: RangeArgument<usize>
+        where R: RangeBounds<usize>
     {
         // Memory safety
         //
@@ -1548,7 +1547,7 @@ impl String {
     /// ```
     #[unstable(feature = "splice", reason = "recently added", issue = "44643")]
     pub fn splice<R>(&mut self, range: R, replace_with: &str)
-        where R: RangeArgument<usize>
+        where R: RangeBounds<usize>
     {
         // Memory safety
         //
diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs
index 2393101040d..6ebdb86cc4a 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;
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index bcc999d7386..df08e46fe25 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -75,7 +75,8 @@ use core::marker::PhantomData;
 use core::mem;
 #[cfg(not(test))]
 use core::num::Float;
-use core::ops::{InPlace, Index, IndexMut, Place, Placer};
+use core::ops::Bound::{Excluded, Included, Unbounded};
+use core::ops::{InPlace, Index, IndexMut, Place, Placer, RangeBounds};
 use core::ops;
 use core::ptr;
 use core::ptr::NonNull;
@@ -85,9 +86,7 @@ use borrow::ToOwned;
 use borrow::Cow;
 use boxed::Box;
 use raw_vec::RawVec;
-use super::range::RangeArgument;
 use super::allocator::CollectionAllocErr;
-use Bound::{Excluded, Included, Unbounded};
 
 /// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
 ///
@@ -1176,7 +1175,7 @@ impl<T> Vec<T> {
     /// ```
     #[stable(feature = "drain", since = "1.6.0")]
     pub fn drain<R>(&mut self, range: R) -> Drain<T>
-        where R: RangeArgument<usize>
+        where R: RangeBounds<usize>
     {
         // Memory safety
         //
@@ -1950,7 +1949,7 @@ impl<T> Vec<T> {
     #[inline]
     #[stable(feature = "vec_splice", since = "1.21.0")]
     pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<I::IntoIter>
-        where R: RangeArgument<usize>, I: IntoIterator<Item=T>
+        where R: RangeBounds<usize>, I: IntoIterator<Item=T>
     {
         Splice {
             drain: self.drain(range),
diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs
index be6e8d0f22f..94d042a45aa 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::Bound::{Excluded, Included, Unbounded};
+use core::ops::{Index, IndexMut, Place, Placer, InPlace, RangeBounds};
 use core::ptr;
 use core::ptr::NonNull;
 use core::slice;
@@ -32,8 +33,6 @@ use core::cmp;
 use raw_vec::RawVec;
 
 use super::allocator::CollectionAllocErr;
-use super::range::RangeArgument;
-use Bound::{Excluded, Included, Unbounded};
 use super::vec::Vec;
 
 const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
@@ -969,7 +968,7 @@ impl<T> VecDeque<T> {
     #[inline]
     #[stable(feature = "drain", since = "1.6.0")]
     pub fn drain<R>(&mut self, range: R) -> Drain<T>
-        where R: RangeArgument<usize>
+        where R: RangeBounds<usize>
     {
         // Memory safety
         //
diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs
index 234970a81fa..0b480b618fc 100644
--- a/src/libcore/ops/mod.rs
+++ b/src/libcore/ops/mod.rs
@@ -192,7 +192,7 @@ pub use self::index::{Index, IndexMut};
 pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
 
 #[stable(feature = "inclusive_range", since = "1.26.0")]
-pub use self::range::{RangeInclusive, RangeToInclusive};
+pub use self::range::{RangeInclusive, RangeToInclusive, RangeBounds, Bound};
 
 #[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 be51f5239b0..3f667407125 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -442,3 +442,267 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
 
 // RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
 // because underflow would be possible with (..0).into()
+
+/// An endpoint of a range of keys.
+///
+/// # Examples
+///
+/// `Bound`s are range endpoints:
+///
+/// ```
+/// #![feature(collections_range)]
+///
+/// use std::ops::Bound::*;
+/// use std::ops::RangeBounds;
+///
+/// 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::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`]: ../../std/collections/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<T> {
+    /// 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,
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+/// `RangeBounds` is implemented by Rust's built-in range types, produced
+/// by range syntax like `..`, `a..`, `..b` or `c..d`.
+pub trait RangeBounds<T: ?Sized> {
+    /// Start index bound.
+    ///
+    /// Returns the start value as a `Bound`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(collections_range)]
+    ///
+    /// # fn main() {
+    /// use std::ops::Bound::*;
+    /// use std::ops::RangeBounds;
+    ///
+    /// 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(collections_range)]
+    ///
+    /// # fn main() {
+    /// use std::ops::Bound::*;
+    /// use std::ops::RangeBounds;
+    ///
+    /// assert_eq!((3..).end(), Unbounded);
+    /// assert_eq!((3..10).end(), Excluded(&10));
+    /// # }
+    /// ```
+    fn end(&self) -> Bound<&T>;
+}
+
+use self::Bound::{Excluded, Included, Unbounded};
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<T: ?Sized> RangeBounds<T> for RangeFull {
+    fn start(&self) -> Bound<&T> {
+        Unbounded
+    }
+    fn end(&self) -> Bound<&T> {
+        Unbounded
+    }
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<T> RangeBounds<T> for RangeFrom<T> {
+    fn start(&self) -> Bound<&T> {
+        Included(&self.start)
+    }
+    fn end(&self) -> Bound<&T> {
+        Unbounded
+    }
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<T> RangeBounds<T> for RangeTo<T> {
+    fn start(&self) -> Bound<&T> {
+        Unbounded
+    }
+    fn end(&self) -> Bound<&T> {
+        Excluded(&self.end)
+    }
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<T> RangeBounds<T> for Range<T> {
+    fn start(&self) -> Bound<&T> {
+        Included(&self.start)
+    }
+    fn end(&self) -> Bound<&T> {
+        Excluded(&self.end)
+    }
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<T> RangeBounds<T> for RangeInclusive<T> {
+    fn start(&self) -> Bound<&T> {
+        Included(&self.start)
+    }
+    fn end(&self) -> Bound<&T> {
+        Included(&self.end)
+    }
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<T> RangeBounds<T> for RangeToInclusive<T> {
+    fn start(&self) -> Bound<&T> {
+        Unbounded
+    }
+    fn end(&self) -> Bound<&T> {
+        Included(&self.end)
+    }
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
+    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,
+        }
+    }
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
+    fn start(&self) -> Bound<&T> {
+        self.0
+    }
+
+    fn end(&self) -> Bound<&T> {
+        self.1
+    }
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<'a, T> RangeBounds<T> for RangeFrom<&'a T> {
+    fn start(&self) -> Bound<&T> {
+        Included(self.start)
+    }
+    fn end(&self) -> Bound<&T> {
+        Unbounded
+    }
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<'a, T> RangeBounds<T> for RangeTo<&'a T> {
+    fn start(&self) -> Bound<&T> {
+        Unbounded
+    }
+    fn end(&self) -> Bound<&T> {
+        Excluded(self.end)
+    }
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<'a, T> RangeBounds<T> for Range<&'a T> {
+    fn start(&self) -> Bound<&T> {
+        Included(self.start)
+    }
+    fn end(&self) -> Bound<&T> {
+        Excluded(self.end)
+    }
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<'a, T> RangeBounds<T> for RangeInclusive<&'a T> {
+    fn start(&self) -> Bound<&T> {
+        Included(self.start)
+    }
+    fn end(&self) -> Bound<&T> {
+        Included(self.end)
+    }
+}
+
+#[unstable(feature = "collections_range",
+           reason = "might be replaced with `Into<_>` and a type containing two `Bound` values",
+           issue = "30877")]
+impl<'a, T> RangeBounds<T> for RangeToInclusive<&'a T> {
+    fn start(&self) -> Bound<&T> {
+        Unbounded
+    }
+    fn end(&self) -> Bound<&T> {
+        Included(self.end)
+    }
+}
diff --git a/src/librustc_data_structures/accumulate_vec.rs b/src/librustc_data_structures/accumulate_vec.rs
index 52306de74cb..f50b8cadf15 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<A: Array> AccumulateVec<A> {
     }
 
     pub fn drain<R>(&mut self, range: R) -> Drain<A>
-        where R: RangeArgument<usize>
+        where R: RangeBounds<usize>
     {
         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 511c407d45a..db1cfb5c767 100644
--- a/src/librustc_data_structures/array_vec.rs
+++ b/src/librustc_data_structures/array_vec.rs
@@ -18,9 +18,9 @@ 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;
+use std::ops::Bound::{Excluded, Included, Unbounded};
+use std::ops::RangeBounds;
 
 pub unsafe trait Array {
     type Element;
@@ -106,7 +106,7 @@ impl<A: Array> ArrayVec<A> {
     }
 
     pub fn drain<R>(&mut self, range: R) -> Drain<A>
-        where R: RangeArgument<usize>
+        where R: RangeBounds<usize>
     {
         // Memory safety
         //
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index cbb3ff51715..1fb63afc72f 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;
@@ -448,13 +447,13 @@ impl<I: Idx, T> IndexVec<I, T> {
     }
 
     #[inline]
-    pub fn drain<'a, R: RangeArgument<usize>>(
+    pub fn drain<'a, R: RangeBounds<usize>>(
         &'a mut self, range: R) -> impl Iterator<Item=T> + 'a {
         self.raw.drain(range)
     }
 
     #[inline]
-    pub fn drain_enumerated<'a, R: RangeArgument<usize>>(
+    pub fn drain_enumerated<'a, R: RangeBounds<usize>>(
         &'a mut self, range: R) -> impl Iterator<Item=(I, T)> + 'a {
         self.raw.drain(range).enumerate().map(IntoIdx { _marker: PhantomData })
     }
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index be88f4e268a..c7ad27d8d26 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -420,7 +420,9 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::Bound;
+#[rustc_deprecated(reason = "moved to `std::ops::Bound`", since = "1.26.0")]
+#[doc(hidden)]
+pub use ops::Bound;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use alloc::{BinaryHeap, BTreeMap, BTreeSet};
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -435,8 +437,13 @@ 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;
+#[unstable(feature = "collections_range", issue = "30877")]
+#[rustc_deprecated(reason = "renamed and moved to `std::ops::RangeBounds`", since = "1.26.0")]
+#[doc(hidden)]
+/// Range syntax
+pub mod range {
+    pub use ops::RangeBounds as RangeArgument;
+}
 
 #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
 pub use alloc::allocator::CollectionAllocErr;
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 903532e9bc8..e096fb3bbae 100644
--- a/src/test/run-pass/sync-send-iterators-in-libcollections.rs
+++ b/src/test/run-pass/sync-send-iterators-in-libcollections.rs
@@ -18,8 +18,8 @@ use std::collections::VecDeque;
 use std::collections::HashMap;
 use std::collections::HashSet;
 
-use std::collections::Bound::Included;
 use std::mem;
+use std::ops::Bound::Included;
 
 fn is_sync<T>(_: T) where T: Sync {}
 fn is_send<T>(_: T) where T: Send {}
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject eafd09010815da43302ac947afee45b0f5219e6
+Subproject b75618206cec71bd87ff7b07f0a8698ee854a2d