Skip to content

Commit 74ebf02

Browse files
committed
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?
2 parents e7b4bc3 + d828c22 commit 74ebf02

File tree

4 files changed

+168
-6
lines changed

4 files changed

+168
-6
lines changed

src/liballoc/rc.rs

+42-4
Original file line numberDiff line numberDiff line change
@@ -900,12 +900,47 @@ impl<T: Default> Default for Rc<T> {
900900
}
901901
}
902902

903+
#[stable(feature = "rust1", since = "1.0.0")]
904+
trait RcEqIdent<T: ?Sized + PartialEq> {
905+
fn eq(&self, other: &Rc<T>) -> bool;
906+
fn ne(&self, other: &Rc<T>) -> bool;
907+
}
908+
909+
#[stable(feature = "rust1", since = "1.0.0")]
910+
impl<T: ?Sized + PartialEq> RcEqIdent<T> for Rc<T> {
911+
#[inline]
912+
default fn eq(&self, other: &Rc<T>) -> bool {
913+
**self == **other
914+
}
915+
916+
#[inline]
917+
default fn ne(&self, other: &Rc<T>) -> bool {
918+
**self != **other
919+
}
920+
}
921+
922+
#[stable(feature = "rust1", since = "1.0.0")]
923+
impl<T: ?Sized + Eq> RcEqIdent<T> for Rc<T> {
924+
#[inline]
925+
fn eq(&self, other: &Rc<T>) -> bool {
926+
Rc::ptr_eq(self, other) || **self == **other
927+
}
928+
929+
#[inline]
930+
fn ne(&self, other: &Rc<T>) -> bool {
931+
!Rc::ptr_eq(self, other) && **self != **other
932+
}
933+
}
934+
903935
#[stable(feature = "rust1", since = "1.0.0")]
904936
impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
905937
/// Equality for two `Rc`s.
906938
///
907939
/// Two `Rc`s are equal if their inner values are equal.
908940
///
941+
/// If `T` also implements `Eq`, two `Rc`s that point to the same value are
942+
/// always equal.
943+
///
909944
/// # Examples
910945
///
911946
/// ```
@@ -915,15 +950,18 @@ impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
915950
///
916951
/// assert!(five == Rc::new(5));
917952
/// ```
918-
#[inline(always)]
953+
#[inline]
919954
fn eq(&self, other: &Rc<T>) -> bool {
920-
**self == **other
955+
RcEqIdent::eq(self, other)
921956
}
922957

923958
/// Inequality for two `Rc`s.
924959
///
925960
/// Two `Rc`s are unequal if their inner values are unequal.
926961
///
962+
/// If `T` also implements `Eq`, two `Rc`s that point to the same value are
963+
/// never unequal.
964+
///
927965
/// # Examples
928966
///
929967
/// ```
@@ -933,9 +971,9 @@ impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
933971
///
934972
/// assert!(five != Rc::new(6));
935973
/// ```
936-
#[inline(always)]
974+
#[inline]
937975
fn ne(&self, other: &Rc<T>) -> bool {
938-
**self != **other
976+
RcEqIdent::ne(self, other)
939977
}
940978
}
941979

src/liballoc/sync.rs

+42-2
Original file line numberDiff line numberDiff line change
@@ -1287,12 +1287,46 @@ impl<T: ?Sized> Drop for Weak<T> {
12871287
}
12881288
}
12891289

1290+
#[stable(feature = "rust1", since = "1.0.0")]
1291+
trait ArcEqIdent<T: ?Sized + PartialEq> {
1292+
fn eq(&self, other: &Arc<T>) -> bool;
1293+
fn ne(&self, other: &Arc<T>) -> bool;
1294+
}
1295+
1296+
#[stable(feature = "rust1", since = "1.0.0")]
1297+
impl<T: ?Sized + PartialEq> ArcEqIdent<T> for Arc<T> {
1298+
#[inline]
1299+
default fn eq(&self, other: &Arc<T>) -> bool {
1300+
**self == **other
1301+
}
1302+
#[inline]
1303+
default fn ne(&self, other: &Arc<T>) -> bool {
1304+
**self != **other
1305+
}
1306+
}
1307+
1308+
#[stable(feature = "rust1", since = "1.0.0")]
1309+
impl<T: ?Sized + Eq> ArcEqIdent<T> for Arc<T> {
1310+
#[inline]
1311+
fn eq(&self, other: &Arc<T>) -> bool {
1312+
Arc::ptr_eq(self, other) || **self == **other
1313+
}
1314+
1315+
#[inline]
1316+
fn ne(&self, other: &Arc<T>) -> bool {
1317+
!Arc::ptr_eq(self, other) && **self != **other
1318+
}
1319+
}
1320+
12901321
#[stable(feature = "rust1", since = "1.0.0")]
12911322
impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
12921323
/// Equality for two `Arc`s.
12931324
///
12941325
/// Two `Arc`s are equal if their inner values are equal.
12951326
///
1327+
/// If `T` also implements `Eq`, two `Arc`s that point to the same value are
1328+
/// always equal.
1329+
///
12961330
/// # Examples
12971331
///
12981332
/// ```
@@ -1302,14 +1336,18 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
13021336
///
13031337
/// assert!(five == Arc::new(5));
13041338
/// ```
1339+
#[inline]
13051340
fn eq(&self, other: &Arc<T>) -> bool {
1306-
*(*self) == *(*other)
1341+
ArcEqIdent::eq(self, other)
13071342
}
13081343

13091344
/// Inequality for two `Arc`s.
13101345
///
13111346
/// Two `Arc`s are unequal if their inner values are unequal.
13121347
///
1348+
/// If `T` also implements `Eq`, two `Arc`s that point to the same value are
1349+
/// never unequal.
1350+
///
13131351
/// # Examples
13141352
///
13151353
/// ```
@@ -1319,10 +1357,12 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
13191357
///
13201358
/// assert!(five != Arc::new(6));
13211359
/// ```
1360+
#[inline]
13221361
fn ne(&self, other: &Arc<T>) -> bool {
1323-
*(*self) != *(*other)
1362+
ArcEqIdent::ne(self, other)
13241363
}
13251364
}
1365+
13261366
#[stable(feature = "rust1", since = "1.0.0")]
13271367
impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
13281368
/// Partial comparison for two `Arc`s.

src/liballoc/tests/arc.rs

+42
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
use std::any::Any;
1212
use std::sync::{Arc, Weak};
13+
use std::cell::RefCell;
14+
use std::cmp::PartialEq;
1315

1416
#[test]
1517
fn uninhabited() {
@@ -53,3 +55,43 @@ fn trait_object() {
5355
b = b.clone();
5456
assert!(b.upgrade().is_none());
5557
}
58+
59+
#[test]
60+
fn float_nan_ne() {
61+
let x = Arc::new(std::f32::NAN);
62+
assert!(x != x);
63+
assert!(!(x == x));
64+
}
65+
66+
#[test]
67+
fn partial_eq() {
68+
struct TestPEq (RefCell<usize>);
69+
impl PartialEq for TestPEq {
70+
fn eq(&self, other: &TestPEq) -> bool {
71+
*self.0.borrow_mut() += 1;
72+
*other.0.borrow_mut() += 1;
73+
true
74+
}
75+
}
76+
let x = Arc::new(TestPEq(RefCell::new(0)));
77+
assert!(x == x);
78+
assert!(!(x != x));
79+
assert_eq!(*x.0.borrow(), 4);
80+
}
81+
82+
#[test]
83+
fn eq() {
84+
#[derive(Eq)]
85+
struct TestEq (RefCell<usize>);
86+
impl PartialEq for TestEq {
87+
fn eq(&self, other: &TestEq) -> bool {
88+
*self.0.borrow_mut() += 1;
89+
*other.0.borrow_mut() += 1;
90+
true
91+
}
92+
}
93+
let x = Arc::new(TestEq(RefCell::new(0)));
94+
assert!(x == x);
95+
assert!(!(x != x));
96+
assert_eq!(*x.0.borrow(), 0);
97+
}

src/liballoc/tests/rc.rs

+42
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
use std::any::Any;
1212
use std::rc::{Rc, Weak};
13+
use std::cell::RefCell;
14+
use std::cmp::PartialEq;
1315

1416
#[test]
1517
fn uninhabited() {
@@ -53,3 +55,43 @@ fn trait_object() {
5355
b = b.clone();
5456
assert!(b.upgrade().is_none());
5557
}
58+
59+
#[test]
60+
fn float_nan_ne() {
61+
let x = Rc::new(std::f32::NAN);
62+
assert!(x != x);
63+
assert!(!(x == x));
64+
}
65+
66+
#[test]
67+
fn partial_eq() {
68+
struct TestPEq (RefCell<usize>);
69+
impl PartialEq for TestPEq {
70+
fn eq(&self, other: &TestPEq) -> bool {
71+
*self.0.borrow_mut() += 1;
72+
*other.0.borrow_mut() += 1;
73+
true
74+
}
75+
}
76+
let x = Rc::new(TestPEq(RefCell::new(0)));
77+
assert!(x == x);
78+
assert!(!(x != x));
79+
assert_eq!(*x.0.borrow(), 4);
80+
}
81+
82+
#[test]
83+
fn eq() {
84+
#[derive(Eq)]
85+
struct TestEq (RefCell<usize>);
86+
impl PartialEq for TestEq {
87+
fn eq(&self, other: &TestEq) -> bool {
88+
*self.0.borrow_mut() += 1;
89+
*other.0.borrow_mut() += 1;
90+
true
91+
}
92+
}
93+
let x = Rc::new(TestEq(RefCell::new(0)));
94+
assert!(x == x);
95+
assert!(!(x != x));
96+
assert_eq!(*x.0.borrow(), 0);
97+
}

0 commit comments

Comments
 (0)