Skip to content

Commit 7b420ae

Browse files
authored
Rollup merge of #70166 - CDirkx:range-inclusive-derives, r=cramertj
Derive PartialEq, Eq and Hash for RangeInclusive The manual implementation of `PartialEq`, `Eq` and `Hash` for `RangeInclusive` was functionally equivalent to a derived implementation. This change removes the manual implementation and adds the respective derives. A side effect of this change is that the derives also add implementations for `StructuralPartialEq` and `StructuralEq`, which enables `RangeInclusive` to be used in const generics, closing #70155. This change is enabled by #68835, which changed the field `is_empty: Option<bool>` to `exhausted: bool` removing the need for *semantic* equality instead of *structural* equality. ## PartialEq original [`PartialEq`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L353-L359) implementation: ```rust #[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 && self.exhausted == other.exhausted } } ``` expanded derive implementation (using `cargo expand ops::range`): ```rust #[stable(feature = "inclusive_range", since = "1.26.0")] impl<Idx> crate::marker::StructuralPartialEq for RangeInclusive<Idx> {} #[automatically_derived] #[allow(unused_qualifications)] #[stable(feature = "inclusive_range", since = "1.26.0")] impl<Idx: crate::cmp::PartialEq> crate::cmp::PartialEq for RangeInclusive<Idx> { #[inline] fn eq(&self, other: &RangeInclusive<Idx>) -> bool { match *other { RangeInclusive { start: ref __self_1_0,end: ref __self_1_1, exhausted: ref __self_1_2 } => match *self { RangeInclusive { start: ref __self_0_0, end: ref __self_0_1, exhausted: ref __self_0_2 } => { (*__self_0_0) == (*__self_1_0) && (*__self_0_1) == (*__self_1_1) && (*__self_0_2) == (*__self_1_2) } }, } } #[inline] fn ne(&self, other: &RangeInclusive<Idx>) -> bool { match *other { RangeInclusive { start: ref __self_1_0, end: ref __self_1_1, exhausted: ref __self_1_2 } => match *self { RangeInclusive { start: ref __self_0_0, end: ref __self_0_1exhausted: ref __self_0_2 } => { (*__self_0_0) != (*__self_1_0) || (*__self_0_1) != (*__self_1_1) || (*__self_0_2) != (*__self_1_2) } }, } } } ``` These implementations both test for *structural* equality, with the same order of field comparisons, and the bound `Idx: PartialEq` is the same. ## Eq original [`Eq`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L361-L362) implementation: ```rust #[stable(feature = "inclusive_range", since = "1.26.0")] impl<Idx: Eq> Eq for RangeInclusive<Idx> {} ``` expanded derive implementation (using `cargo expand ops::range`): ```rust #[stable(feature = "inclusive_range", since = "1.26.0")] impl<Idx> crate::marker::StructuralEq for RangeInclusive<Idx> {} #[automatically_derived] #[allow(unused_qualifications)] #[stable(feature = "inclusive_range", since = "1.26.0")] impl<Idx: crate::cmp::Eq> crate::cmp::Eq for RangeInclusive<Idx> { #[inline] #[doc(hidden)] fn assert_receiver_is_total_eq(&self) -> () { { let _: crate::cmp::AssertParamIsEq<Idx>; let _: crate::cmp::AssertParamIsEq<Idx>; let _: crate::cmp::AssertParamIsEq<bool>; } } } ``` These implementations are equivalent since `Eq` is just a marker trait and the bound `Idx: Eq` is the same. ## Hash original [`Hash`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L364-L371) implementation: ```rust #[stable(feature = "inclusive_range", since = "1.26.0")] impl<Idx: Hash> Hash for RangeInclusive<Idx> { fn hash<H: Hasher>(&self, state: &mut H) { self.start.hash(state); self.end.hash(state); self.exhausted.hash(state); } } ``` expanded derive implementation (using `cargo expand ops::range`): ```rust #[automatically_derived] #[allow(unused_qualifications)] #[stable(feature = "inclusive_range", since = "1.26.0")] impl<Idx: crate::hash::Hash> crate::hash::Hash for RangeInclusive<Idx> { fn hash<__H: crate::hash::Hasher>(&self, state: &mut __H) -> () { match *self { RangeInclusive { start: ref __self_0_0, end: ref __self_0_1, exhausted: ref __self_0_2 } => { crate::hash::Hash::hash(&(*__self_0_0), state); crate::hash::Hash::hash(&(*__self_0_1), state); crate::hash::Hash::hash(&(*__self_0_2), state) } } } } ``` These implementations are functionally equivalent, with the same order of field hashing, and the bound `Idx: Hash` is the same.
2 parents b24d168 + 6570e27 commit 7b420ae

File tree

1 file changed

+2
-22
lines changed

1 file changed

+2
-22
lines changed

src/libcore/ops/range.rs

+2-22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::fmt;
2-
use crate::hash::{Hash, Hasher};
2+
use crate::hash::Hash;
33

44
/// An unbounded range (`..`).
55
///
@@ -330,7 +330,7 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
330330
/// assert_eq!(arr[1..=3], [ 1,2,3 ]); // RangeInclusive
331331
/// ```
332332
#[doc(alias = "..=")]
333-
#[derive(Clone)] // not Copy -- see #27186
333+
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
334334
#[stable(feature = "inclusive_range", since = "1.26.0")]
335335
pub struct RangeInclusive<Idx> {
336336
// Note that the fields here are not public to allow changing the
@@ -350,26 +350,6 @@ pub struct RangeInclusive<Idx> {
350350
pub(crate) exhausted: bool,
351351
}
352352

353-
#[stable(feature = "inclusive_range", since = "1.26.0")]
354-
impl<Idx: PartialEq> PartialEq for RangeInclusive<Idx> {
355-
#[inline]
356-
fn eq(&self, other: &Self) -> bool {
357-
self.start == other.start && self.end == other.end && self.exhausted == other.exhausted
358-
}
359-
}
360-
361-
#[stable(feature = "inclusive_range", since = "1.26.0")]
362-
impl<Idx: Eq> Eq for RangeInclusive<Idx> {}
363-
364-
#[stable(feature = "inclusive_range", since = "1.26.0")]
365-
impl<Idx: Hash> Hash for RangeInclusive<Idx> {
366-
fn hash<H: Hasher>(&self, state: &mut H) {
367-
self.start.hash(state);
368-
self.end.hash(state);
369-
self.exhausted.hash(state);
370-
}
371-
}
372-
373353
impl<Idx> RangeInclusive<Idx> {
374354
/// Creates a new inclusive range. Equivalent to writing `start..=end`.
375355
///

0 commit comments

Comments
 (0)