]> git.lizzy.rs Git - rust.git/blobdiff - src/libcore/ops/range.rs
parser: move `ban_async_in_2015` to `fn` parsing & improve it.
[rust.git] / src / libcore / ops / range.rs
index be6d8edb99f594f8df9b306df75bec2455581870..8ffad82b69d7c688816b15d7157586701f9ede7b 100644 (file)
@@ -333,43 +333,28 @@ pub fn contains<U>(&self, item: &U) -> bool
 #[derive(Clone)] // not Copy -- see #27186
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub struct RangeInclusive<Idx> {
+    // Note that the fields here are not public to allow changing the
+    // representation in the future; in particular, while we could plausibly
+    // expose start/end, modifying them without changing (future/current)
+    // private fields may lead to incorrect behavior, so we don't want to
+    // support that mode.
     pub(crate) start: Idx,
     pub(crate) end: Idx,
-    pub(crate) is_empty: Option<bool>,
-    // This field is:
-    //  - `None` when next() or next_back() was never called
-    //  - `Some(false)` when `start <= end` assuming no overflow
-    //  - `Some(true)` otherwise
-    // The field cannot be a simple `bool` because the `..=` constructor can
-    // accept non-PartialOrd types, also we want the constructor to be const.
-}
-
-trait RangeInclusiveEquality: Sized {
-    fn canonicalized_is_empty(range: &RangeInclusive<Self>) -> bool;
-}
-
-impl<T> RangeInclusiveEquality for T {
-    #[inline]
-    default fn canonicalized_is_empty(range: &RangeInclusive<Self>) -> bool {
-        range.is_empty.unwrap_or_default()
-    }
-}
 
-impl<T: PartialOrd> RangeInclusiveEquality for T {
-    #[inline]
-    fn canonicalized_is_empty(range: &RangeInclusive<Self>) -> bool {
-        range.is_empty()
-    }
+    // This field is:
+    //  - `false` upon construction
+    //  - `false` when iteration has yielded an element and the iterator is not exhausted
+    //  - `true` when iteration has been used to exhaust the iterator
+    //
+    // This is required to support PartialEq and Hash without a PartialOrd bound or specialization.
+    pub(crate) exhausted: bool,
 }
 
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 impl<Idx: PartialEq> PartialEq for RangeInclusive<Idx> {
     #[inline]
     fn eq(&self, other: &Self) -> bool {
-        self.start == other.start
-            && self.end == other.end
-            && RangeInclusiveEquality::canonicalized_is_empty(self)
-                == RangeInclusiveEquality::canonicalized_is_empty(other)
+        self.start == other.start && self.end == other.end && self.exhausted == other.exhausted
     }
 }
 
@@ -381,7 +366,7 @@ impl<Idx: Hash> Hash for RangeInclusive<Idx> {
     fn hash<H: Hasher>(&self, state: &mut H) {
         self.start.hash(state);
         self.end.hash(state);
-        RangeInclusiveEquality::canonicalized_is_empty(self).hash(state);
+        self.exhausted.hash(state);
     }
 }
 
@@ -400,7 +385,7 @@ impl<Idx> RangeInclusive<Idx> {
     #[rustc_promotable]
     #[rustc_const_stable(feature = "const_range_new", since = "1.32.0")]
     pub const fn new(start: Idx, end: Idx) -> Self {
-        Self { start, end, is_empty: None }
+        Self { start, end, exhausted: false }
     }
 
     /// Returns the lower bound of the range (inclusive).
@@ -476,6 +461,9 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.start.fmt(fmt)?;
         write!(fmt, "..=")?;
         self.end.fmt(fmt)?;
+        if self.exhausted {
+            write!(fmt, " (exhausted)")?;
+        }
         Ok(())
     }
 }
@@ -547,15 +535,7 @@ pub fn contains<U>(&self, item: &U) -> bool
     #[unstable(feature = "range_is_empty", reason = "recently added", issue = "48111")]
     #[inline]
     pub fn is_empty(&self) -> bool {
-        self.is_empty.unwrap_or_else(|| !(self.start <= self.end))
-    }
-
-    // If this range's `is_empty` is field is unknown (`None`), update it to be a concrete value.
-    #[inline]
-    pub(crate) fn compute_is_empty(&mut self) {
-        if self.is_empty.is_none() {
-            self.is_empty = Some(!(self.start <= self.end));
-        }
+        self.exhausted || !(self.start <= self.end)
     }
 }