about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/core/src/ops/mod.rs2
-rw-r--r--library/core/src/ops/range.rs82
-rw-r--r--library/core/src/range.rs28
3 files changed, 111 insertions, 1 deletions
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index 7b2ced2cc4b..627a875d9f7 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -182,6 +182,8 @@ pub use self::function::{Fn, FnMut, FnOnce};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::index::{Index, IndexMut};
 pub(crate) use self::index_range::IndexRange;
+#[unstable(feature = "range_into_bounds", issue = "136903")]
+pub use self::range::IntoBounds;
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
 #[unstable(feature = "one_sided_range", issue = "69780")]
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index 42e07a0e51d..5580faefacc 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -831,6 +831,30 @@ pub trait RangeBounds<T: ?Sized> {
     }
 }
 
+/// Used to convert a range into start and end bounds, consuming the
+/// range by value.
+///
+/// `IntoBounds` is implemented by Rust’s built-in range types, produced
+/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
+#[unstable(feature = "range_into_bounds", issue = "136903")]
+pub trait IntoBounds<T>: RangeBounds<T> {
+    /// Convert this range into the start and end bounds.
+    /// Returns `(start_bound, end_bound)`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(range_into_bounds)]
+    ///
+    /// use std::ops::Bound::*;
+    /// use std::ops::IntoBounds;
+    ///
+    /// assert_eq!((0..5).into_bounds(), (Included(0), Excluded(5)));
+    /// assert_eq!((..=7).into_bounds(), (Unbounded, Included(7)));
+    /// ```
+    fn into_bounds(self) -> (Bound<T>, Bound<T>);
+}
+
 use self::Bound::{Excluded, Included, Unbounded};
 
 #[stable(feature = "collections_range", since = "1.28.0")]
@@ -843,6 +867,13 @@ impl<T: ?Sized> RangeBounds<T> for RangeFull {
     }
 }
 
+#[unstable(feature = "range_into_bounds", issue = "136903")]
+impl<T> IntoBounds<T> for RangeFull {
+    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
+        (Unbounded, Unbounded)
+    }
+}
+
 #[stable(feature = "collections_range", since = "1.28.0")]
 impl<T> RangeBounds<T> for RangeFrom<T> {
     fn start_bound(&self) -> Bound<&T> {
@@ -853,6 +884,13 @@ impl<T> RangeBounds<T> for RangeFrom<T> {
     }
 }
 
+#[unstable(feature = "range_into_bounds", issue = "136903")]
+impl<T> IntoBounds<T> for RangeFrom<T> {
+    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
+        (Included(self.start), Unbounded)
+    }
+}
+
 #[stable(feature = "collections_range", since = "1.28.0")]
 impl<T> RangeBounds<T> for RangeTo<T> {
     fn start_bound(&self) -> Bound<&T> {
@@ -863,6 +901,13 @@ impl<T> RangeBounds<T> for RangeTo<T> {
     }
 }
 
+#[unstable(feature = "range_into_bounds", issue = "136903")]
+impl<T> IntoBounds<T> for RangeTo<T> {
+    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
+        (Unbounded, Excluded(self.end))
+    }
+}
+
 #[stable(feature = "collections_range", since = "1.28.0")]
 impl<T> RangeBounds<T> for Range<T> {
     fn start_bound(&self) -> Bound<&T> {
@@ -873,6 +918,13 @@ impl<T> RangeBounds<T> for Range<T> {
     }
 }
 
+#[unstable(feature = "range_into_bounds", issue = "136903")]
+impl<T> IntoBounds<T> for Range<T> {
+    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
+        (Included(self.start), Excluded(self.end))
+    }
+}
+
 #[stable(feature = "collections_range", since = "1.28.0")]
 impl<T> RangeBounds<T> for RangeInclusive<T> {
     fn start_bound(&self) -> Bound<&T> {
@@ -889,6 +941,22 @@ impl<T> RangeBounds<T> for RangeInclusive<T> {
     }
 }
 
+#[unstable(feature = "range_into_bounds", issue = "136903")]
+impl<T> IntoBounds<T> for RangeInclusive<T> {
+    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
+        (
+            Included(self.start),
+            if self.exhausted {
+                // When the iterator is exhausted, we usually have start == end,
+                // but we want the range to appear empty, containing nothing.
+                Excluded(self.end)
+            } else {
+                Included(self.end)
+            },
+        )
+    }
+}
+
 #[stable(feature = "collections_range", since = "1.28.0")]
 impl<T> RangeBounds<T> for RangeToInclusive<T> {
     fn start_bound(&self) -> Bound<&T> {
@@ -899,6 +967,13 @@ impl<T> RangeBounds<T> for RangeToInclusive<T> {
     }
 }
 
+#[unstable(feature = "range_into_bounds", issue = "136903")]
+impl<T> IntoBounds<T> for RangeToInclusive<T> {
+    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
+        (Unbounded, Included(self.end))
+    }
+}
+
 #[stable(feature = "collections_range", since = "1.28.0")]
 impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
     fn start_bound(&self) -> Bound<&T> {
@@ -918,6 +993,13 @@ impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
     }
 }
 
+#[unstable(feature = "range_into_bounds", issue = "136903")]
+impl<T> IntoBounds<T> for (Bound<T>, Bound<T>) {
+    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
+        self
+    }
+}
+
 #[stable(feature = "collections_range", since = "1.28.0")]
 impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
     fn start_bound(&self) -> Bound<&T> {
diff --git a/library/core/src/range.rs b/library/core/src/range.rs
index 6a62928873f..e94499065ac 100644
--- a/library/core/src/range.rs
+++ b/library/core/src/range.rs
@@ -31,7 +31,9 @@ pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive};
 #[doc(inline)]
 pub use crate::iter::Step;
 #[doc(inline)]
-pub use crate::ops::{Bound, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive};
+pub use crate::ops::{
+    Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive,
+};
 
 /// A (half-open) range bounded inclusively below and exclusively above
 /// (`start..end` in a future edition).
@@ -175,6 +177,14 @@ impl<T> RangeBounds<T> for Range<&T> {
     }
 }
 
+// #[unstable(feature = "range_into_bounds", issue = "136903")]
+#[unstable(feature = "new_range_api", issue = "125687")]
+impl<T> IntoBounds<T> for Range<T> {
+    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
+        (Included(self.start), Excluded(self.end))
+    }
+}
+
 #[unstable(feature = "new_range_api", issue = "125687")]
 impl<T> From<Range<T>> for legacy::Range<T> {
     #[inline]
@@ -343,6 +353,14 @@ impl<T> RangeBounds<T> for RangeInclusive<&T> {
     }
 }
 
+// #[unstable(feature = "range_into_bounds", issue = "136903")]
+#[unstable(feature = "new_range_api", issue = "125687")]
+impl<T> IntoBounds<T> for RangeInclusive<T> {
+    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
+        (Included(self.start), Included(self.end))
+    }
+}
+
 #[unstable(feature = "new_range_api", issue = "125687")]
 impl<T> From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
     #[inline]
@@ -479,6 +497,14 @@ impl<T> RangeBounds<T> for RangeFrom<&T> {
     }
 }
 
+// #[unstable(feature = "range_into_bounds", issue = "136903")]
+#[unstable(feature = "new_range_api", issue = "125687")]
+impl<T> IntoBounds<T> for RangeFrom<T> {
+    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
+        (Included(self.start), Unbounded)
+    }
+}
+
 #[unstable(feature = "new_range_api", issue = "125687")]
 impl<T> From<RangeFrom<T>> for legacy::RangeFrom<T> {
     #[inline]