diff options
| author | bors <bors@rust-lang.org> | 2018-12-19 10:16:05 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-12-19 10:16:05 +0000 |
| commit | 74ebf026fe927ffa99d541479454f45791806802 (patch) | |
| tree | d0759b9af29a848eed2b7c1feb10a4dcfe0e1ed4 /src/liballoc | |
| parent | e7b4bc35e99ee3c5b2b42a1b8b3f9cd6eca1f0b2 (diff) | |
| parent | d828c22bd6ff6059c75dfa63e024997619eb6e7c (diff) | |
| download | rust-74ebf026fe927ffa99d541479454f45791806802.tar.gz rust-74ebf026fe927ffa99d541479454f45791806802.zip | |
Auto merge of #56550 - chpio:rc-eq, r=alexcrichton
Short-circuit Rc/Arc equality checking on equal pointers where T: Eq based on #42965 Is the use of the private trait ok this way? Is there anything else needed for this to get pulled?
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/rc.rs | 46 | ||||
| -rw-r--r-- | src/liballoc/sync.rs | 44 | ||||
| -rw-r--r-- | src/liballoc/tests/arc.rs | 42 | ||||
| -rw-r--r-- | src/liballoc/tests/rc.rs | 42 |
4 files changed, 168 insertions, 6 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 52ad30c411a..6769a70ddbe 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -901,11 +901,46 @@ impl<T: Default> Default for Rc<T> { } #[stable(feature = "rust1", since = "1.0.0")] +trait RcEqIdent<T: ?Sized + PartialEq> { + fn eq(&self, other: &Rc<T>) -> bool; + fn ne(&self, other: &Rc<T>) -> bool; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<T: ?Sized + PartialEq> RcEqIdent<T> for Rc<T> { + #[inline] + default fn eq(&self, other: &Rc<T>) -> bool { + **self == **other + } + + #[inline] + default fn ne(&self, other: &Rc<T>) -> bool { + **self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<T: ?Sized + Eq> RcEqIdent<T> for Rc<T> { + #[inline] + fn eq(&self, other: &Rc<T>) -> bool { + Rc::ptr_eq(self, other) || **self == **other + } + + #[inline] + fn ne(&self, other: &Rc<T>) -> bool { + !Rc::ptr_eq(self, other) && **self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized + PartialEq> PartialEq for Rc<T> { /// Equality for two `Rc`s. /// /// Two `Rc`s are equal if their inner values are equal. /// + /// If `T` also implements `Eq`, two `Rc`s that point to the same value are + /// always equal. + /// /// # Examples /// /// ``` @@ -915,15 +950,18 @@ impl<T: ?Sized + PartialEq> PartialEq for Rc<T> { /// /// assert!(five == Rc::new(5)); /// ``` - #[inline(always)] + #[inline] fn eq(&self, other: &Rc<T>) -> bool { - **self == **other + RcEqIdent::eq(self, other) } /// Inequality for two `Rc`s. /// /// Two `Rc`s are unequal if their inner values are unequal. /// + /// If `T` also implements `Eq`, two `Rc`s that point to the same value are + /// never unequal. + /// /// # Examples /// /// ``` @@ -933,9 +971,9 @@ impl<T: ?Sized + PartialEq> PartialEq for Rc<T> { /// /// assert!(five != Rc::new(6)); /// ``` - #[inline(always)] + #[inline] fn ne(&self, other: &Rc<T>) -> bool { - **self != **other + RcEqIdent::ne(self, other) } } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 111459d12a4..e596694fb9d 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -1288,11 +1288,45 @@ impl<T: ?Sized> Drop for Weak<T> { } #[stable(feature = "rust1", since = "1.0.0")] +trait ArcEqIdent<T: ?Sized + PartialEq> { + fn eq(&self, other: &Arc<T>) -> bool; + fn ne(&self, other: &Arc<T>) -> bool; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<T: ?Sized + PartialEq> ArcEqIdent<T> for Arc<T> { + #[inline] + default fn eq(&self, other: &Arc<T>) -> bool { + **self == **other + } + #[inline] + default fn ne(&self, other: &Arc<T>) -> bool { + **self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<T: ?Sized + Eq> ArcEqIdent<T> for Arc<T> { + #[inline] + fn eq(&self, other: &Arc<T>) -> bool { + Arc::ptr_eq(self, other) || **self == **other + } + + #[inline] + fn ne(&self, other: &Arc<T>) -> bool { + !Arc::ptr_eq(self, other) && **self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized + PartialEq> PartialEq for Arc<T> { /// Equality for two `Arc`s. /// /// Two `Arc`s are equal if their inner values are equal. /// + /// If `T` also implements `Eq`, two `Arc`s that point to the same value are + /// always equal. + /// /// # Examples /// /// ``` @@ -1302,14 +1336,18 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> { /// /// assert!(five == Arc::new(5)); /// ``` + #[inline] fn eq(&self, other: &Arc<T>) -> bool { - *(*self) == *(*other) + ArcEqIdent::eq(self, other) } /// Inequality for two `Arc`s. /// /// Two `Arc`s are unequal if their inner values are unequal. /// + /// If `T` also implements `Eq`, two `Arc`s that point to the same value are + /// never unequal. + /// /// # Examples /// /// ``` @@ -1319,10 +1357,12 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> { /// /// assert!(five != Arc::new(6)); /// ``` + #[inline] fn ne(&self, other: &Arc<T>) -> bool { - *(*self) != *(*other) + ArcEqIdent::ne(self, other) } } + #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> { /// Partial comparison for two `Arc`s. diff --git a/src/liballoc/tests/arc.rs b/src/liballoc/tests/arc.rs index d90c22a3b18..ec589710216 100644 --- a/src/liballoc/tests/arc.rs +++ b/src/liballoc/tests/arc.rs @@ -10,6 +10,8 @@ use std::any::Any; use std::sync::{Arc, Weak}; +use std::cell::RefCell; +use std::cmp::PartialEq; #[test] fn uninhabited() { @@ -53,3 +55,43 @@ fn trait_object() { b = b.clone(); assert!(b.upgrade().is_none()); } + +#[test] +fn float_nan_ne() { + let x = Arc::new(std::f32::NAN); + assert!(x != x); + assert!(!(x == x)); +} + +#[test] +fn partial_eq() { + struct TestPEq (RefCell<usize>); + impl PartialEq for TestPEq { + fn eq(&self, other: &TestPEq) -> bool { + *self.0.borrow_mut() += 1; + *other.0.borrow_mut() += 1; + true + } + } + let x = Arc::new(TestPEq(RefCell::new(0))); + assert!(x == x); + assert!(!(x != x)); + assert_eq!(*x.0.borrow(), 4); +} + +#[test] +fn eq() { + #[derive(Eq)] + struct TestEq (RefCell<usize>); + impl PartialEq for TestEq { + fn eq(&self, other: &TestEq) -> bool { + *self.0.borrow_mut() += 1; + *other.0.borrow_mut() += 1; + true + } + } + let x = Arc::new(TestEq(RefCell::new(0))); + assert!(x == x); + assert!(!(x != x)); + assert_eq!(*x.0.borrow(), 0); +} diff --git a/src/liballoc/tests/rc.rs b/src/liballoc/tests/rc.rs index 9ec7c831444..02e1dfe13bb 100644 --- a/src/liballoc/tests/rc.rs +++ b/src/liballoc/tests/rc.rs @@ -10,6 +10,8 @@ use std::any::Any; use std::rc::{Rc, Weak}; +use std::cell::RefCell; +use std::cmp::PartialEq; #[test] fn uninhabited() { @@ -53,3 +55,43 @@ fn trait_object() { b = b.clone(); assert!(b.upgrade().is_none()); } + +#[test] +fn float_nan_ne() { + let x = Rc::new(std::f32::NAN); + assert!(x != x); + assert!(!(x == x)); +} + +#[test] +fn partial_eq() { + struct TestPEq (RefCell<usize>); + impl PartialEq for TestPEq { + fn eq(&self, other: &TestPEq) -> bool { + *self.0.borrow_mut() += 1; + *other.0.borrow_mut() += 1; + true + } + } + let x = Rc::new(TestPEq(RefCell::new(0))); + assert!(x == x); + assert!(!(x != x)); + assert_eq!(*x.0.borrow(), 4); +} + +#[test] +fn eq() { + #[derive(Eq)] + struct TestEq (RefCell<usize>); + impl PartialEq for TestEq { + fn eq(&self, other: &TestEq) -> bool { + *self.0.borrow_mut() += 1; + *other.0.borrow_mut() += 1; + true + } + } + let x = Rc::new(TestEq(RefCell::new(0))); + assert!(x == x); + assert!(!(x != x)); + assert_eq!(*x.0.borrow(), 0); +} |
