about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/liballoc/lib.rs2
-rw-r--r--src/liballoc/tests/lib.rs2
-rw-r--r--src/libcore/ops/range.rs60
-rw-r--r--src/libcore/tests/lib.rs2
-rw-r--r--src/librustc/hir/lowering.rs16
-rw-r--r--src/librustc_trans/lib.rs2
6 files changed, 78 insertions, 6 deletions
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 021395d0c82..c94fe2a2f83 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -122,7 +122,7 @@
 #![feature(on_unimplemented)]
 #![feature(exact_chunks)]
 #![feature(pointer_methods)]
-#![feature(inclusive_range_fields)]
+#![feature(inclusive_range_methods)]
 #![cfg_attr(stage0, feature(generic_param_attrs))]
 
 #![cfg_attr(not(test), feature(fn_traits, i128))]
diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs
index 32272169307..1c8ff316e55 100644
--- a/src/liballoc/tests/lib.rs
+++ b/src/liballoc/tests/lib.rs
@@ -25,7 +25,7 @@
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
 #![feature(exact_chunks)]
-#![feature(inclusive_range_fields)]
+#![feature(inclusive_range_methods)]
 
 extern crate alloc_system;
 extern crate core;
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index d70f7ae66f9..c1bd1ef2d1d 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -320,7 +320,7 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
 /// ```
 /// #![feature(inclusive_range_fields)]
 ///
-/// assert_eq!((3..=5), std::ops::RangeInclusive { start: 3, end: 5 });
+/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5));
 /// assert_eq!(3 + 4 + 5, (3..=5).sum());
 ///
 /// let arr = [0, 1, 2, 3];
@@ -331,14 +331,72 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub struct RangeInclusive<Idx> {
+    // FIXME: The current representation follows RFC 1980,
+    // but it is known that LLVM is not able to optimize loops following that RFC.
+    // Consider adding an extra `bool` field to indicate emptiness of the range.
+    // See #45222 for performance test cases.
+    #[cfg(not(stage0))]
+    pub(crate) start: Idx,
+    #[cfg(not(stage0))]
+    pub(crate) end: Idx,
     /// The lower bound of the range (inclusive).
+    #[cfg(stage0)]
     #[unstable(feature = "inclusive_range_fields", issue = "49022")]
     pub start: Idx,
     /// The upper bound of the range (inclusive).
+    #[cfg(stage0)]
     #[unstable(feature = "inclusive_range_fields", issue = "49022")]
     pub end: Idx,
 }
 
+impl<Idx> RangeInclusive<Idx> {
+    /// Creates a new inclusive range. Equivalent to writing `start..=end`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(inclusive_range_methods)]
+    /// use std::ops::RangeInclusive;
+    ///
+    /// assert_eq!(3..=5, RangeInclusive::new(3, 5));
+    /// ```
+    #[unstable(feature = "inclusive_range_methods", issue = "49022")]
+    #[inline]
+    pub fn new(start: Idx, end: Idx) -> Self {
+        Self { start, end }
+    }
+
+    /// Returns the lower bound of the range (inclusive).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(inclusive_range_methods)]
+    ///
+    /// assert_eq!((3..=5).start(), &3);
+    /// ```
+    #[unstable(feature = "inclusive_range_methods", issue = "49022")]
+    #[inline]
+    pub fn start(&self) -> &Idx {
+        &self.start
+    }
+
+    /// Returns the upper bound of the range (inclusive).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(inclusive_range_methods)]
+    ///
+    /// assert_eq!((3..=5).end(), &5);
+    /// ```
+    #[unstable(feature = "inclusive_range_methods", issue = "49022")]
+    #[inline]
+    pub fn end(&self) -> &Idx {
+        &self.end
+    }
+}
+
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index e4d27717938..f6750c590b3 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -44,7 +44,7 @@
 #![feature(exact_chunks)]
 #![cfg_attr(stage0, feature(atomic_nand))]
 #![feature(reverse_bits)]
-#![feature(inclusive_range_fields)]
+#![feature(inclusive_range_methods)]
 #![feature(iterator_find_map)]
 
 extern crate core;
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index e4b9fc1385d..196f7879980 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -3119,6 +3119,20 @@ impl<'a> LoweringContext<'a> {
             ExprKind::Index(ref el, ref er) => {
                 hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
             }
+            // Desugar `<start>..=<end>` to `std::ops::RangeInclusive::new(<start>, <end>)`
+            ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => {
+                // FIXME: Use head_sp directly after RangeInclusive::new() is stabilized in stage0.
+                let span = self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span);
+                let id = self.lower_node_id(e.id);
+                let e1 = self.lower_expr(e1);
+                let e2 = self.lower_expr(e2);
+                let ty_path = P(self.std_path(span, &["ops", "RangeInclusive"], false));
+                let ty = self.ty_path(id, span, hir::QPath::Resolved(None, ty_path));
+                let new_seg = P(hir::PathSegment::from_name(Symbol::intern("new")));
+                let new_path = hir::QPath::TypeRelative(ty, new_seg);
+                let new = P(self.expr(span, hir::ExprPath(new_path), ThinVec::new()));
+                hir::ExprCall(new, hir_vec![e1, e2])
+            }
             ExprKind::Range(ref e1, ref e2, lims) => {
                 use syntax::ast::RangeLimits::*;
 
@@ -3128,7 +3142,7 @@ impl<'a> LoweringContext<'a> {
                     (&None, &Some(..), HalfOpen) => "RangeTo",
                     (&Some(..), &Some(..), HalfOpen) => "Range",
                     (&None, &Some(..), Closed) => "RangeToInclusive",
-                    (&Some(..), &Some(..), Closed) => "RangeInclusive",
+                    (&Some(..), &Some(..), Closed) => unreachable!(),
                     (_, &None, Closed) => self.diagnostic()
                         .span_fatal(e.span, "inclusive range with no end")
                         .raise(),
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 96a10e8b99d..9259fef279f 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -29,7 +29,7 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(optin_builtin_traits)]
-#![feature(inclusive_range_fields)]
+#![feature(inclusive_range_methods)]
 
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;