Skip to content

Commit b31745b

Browse files
authored
Unrolled build for #155579
Rollup merge of #155579 - Gaming32:fix-154998, r=Mark-Simulacrum Make Rcs and Arcs use pointer comparison for unsized types `Rc` and `Arc`s have an `Eq` implementation that first attempt to compare the pointers as an optimization. This, however, was not extended to DSTs, which is what this PR fixes. Fixes #154998.
2 parents ca9a134 + 6f28cd5 commit b31745b

4 files changed

Lines changed: 61 additions & 5 deletions

File tree

library/alloc/src/rc.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2615,7 +2615,7 @@ impl<T: ?Sized + PartialEq, A: Allocator> RcEqIdent<T, A> for Rc<T, A> {
26152615
#[rustc_unsafe_specialization_marker]
26162616
pub(crate) trait MarkerEq: PartialEq<Self> {}
26172617

2618-
impl<T: Eq> MarkerEq for T {}
2618+
impl<T: ?Sized + Eq> MarkerEq for T {}
26192619

26202620
/// We're doing this specialization here, and not as a more general optimization on `&T`, because it
26212621
/// would otherwise add a cost to all equality checks on refs. We assume that `Rc`s are used to
@@ -2628,12 +2628,12 @@ impl<T: Eq> MarkerEq for T {}
26282628
impl<T: ?Sized + MarkerEq, A: Allocator> RcEqIdent<T, A> for Rc<T, A> {
26292629
#[inline]
26302630
fn eq(&self, other: &Rc<T, A>) -> bool {
2631-
Rc::ptr_eq(self, other) || **self == **other
2631+
ptr::eq(self.ptr.as_ptr(), other.ptr.as_ptr()) || **self == **other
26322632
}
26332633

26342634
#[inline]
26352635
fn ne(&self, other: &Rc<T, A>) -> bool {
2636-
!Rc::ptr_eq(self, other) && **self != **other
2636+
!ptr::eq(self.ptr.as_ptr(), other.ptr.as_ptr()) && **self != **other
26372637
}
26382638
}
26392639

library/alloc/src/sync.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3549,12 +3549,12 @@ impl<T: ?Sized + PartialEq, A: Allocator> ArcEqIdent<T, A> for Arc<T, A> {
35493549
impl<T: ?Sized + crate::rc::MarkerEq, A: Allocator> ArcEqIdent<T, A> for Arc<T, A> {
35503550
#[inline]
35513551
fn eq(&self, other: &Arc<T, A>) -> bool {
3552-
Arc::ptr_eq(self, other) || **self == **other
3552+
ptr::eq(self.ptr.as_ptr(), other.ptr.as_ptr()) || **self == **other
35533553
}
35543554

35553555
#[inline]
35563556
fn ne(&self, other: &Arc<T, A>) -> bool {
3557-
!Arc::ptr_eq(self, other) && **self != **other
3557+
!ptr::eq(self.ptr.as_ptr(), other.ptr.as_ptr()) && **self != **other
35583558
}
35593559
}
35603560

library/alloctests/tests/arc.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,34 @@ fn eq() {
8686
assert_eq!(*x.0.borrow(), 0);
8787
}
8888

89+
#[test]
90+
fn eq_unsized() {
91+
#[derive(Eq)]
92+
struct TestEq<T: ?Sized>(RefCell<usize>, T);
93+
impl<T: ?Sized> PartialEq for TestEq<T> {
94+
fn eq(&self, other: &TestEq<T>) -> bool {
95+
*self.0.borrow_mut() += 1;
96+
*other.0.borrow_mut() += 1;
97+
true
98+
}
99+
}
100+
let x = Arc::<TestEq<[u8; 3]>>::new(TestEq(RefCell::new(0), [0, 1, 2])) as Arc<TestEq<[u8]>>;
101+
assert!(x == x);
102+
assert!(!(x != x));
103+
assert_eq!(*x.0.borrow(), 0);
104+
}
105+
106+
#[test]
107+
fn eq_unsized_slice() {
108+
let a: Arc<[()]> = Arc::new([(); 3]);
109+
let ptr: *const () = Arc::into_raw(a.clone()).cast();
110+
let b: Arc<[()]> = unsafe { Arc::from_raw(core::ptr::slice_from_raw_parts(ptr, 42)) };
111+
assert!(a == a);
112+
assert!(!(a != a));
113+
assert!(a != b);
114+
assert!(!(a == b));
115+
}
116+
89117
// The test code below is identical to that in `rc.rs`.
90118
// For better maintainability we therefore define this type alias.
91119
type Rc<T, A = std::alloc::Global> = Arc<T, A>;

library/alloctests/tests/rc.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,34 @@ fn eq() {
8787
assert_eq!(*x.0.borrow(), 0);
8888
}
8989

90+
#[test]
91+
fn eq_unsized() {
92+
#[derive(Eq)]
93+
struct TestEq<T: ?Sized>(RefCell<usize>, T);
94+
impl<T: ?Sized> PartialEq for TestEq<T> {
95+
fn eq(&self, other: &TestEq<T>) -> bool {
96+
*self.0.borrow_mut() += 1;
97+
*other.0.borrow_mut() += 1;
98+
true
99+
}
100+
}
101+
let x = Rc::<TestEq<[u8; 3]>>::new(TestEq(RefCell::new(0), [0, 1, 2])) as Rc<TestEq<[u8]>>;
102+
assert!(x == x);
103+
assert!(!(x != x));
104+
assert_eq!(*x.0.borrow(), 0);
105+
}
106+
107+
#[test]
108+
fn eq_unsized_slice() {
109+
let a: Rc<[()]> = Rc::new([(); 3]);
110+
let ptr: *const () = Rc::into_raw(a.clone()).cast();
111+
let b: Rc<[()]> = unsafe { Rc::from_raw(core::ptr::slice_from_raw_parts(ptr, 42)) };
112+
assert!(a == a);
113+
assert!(!(a != a));
114+
assert!(a != b);
115+
assert!(!(a == b));
116+
}
117+
90118
const SHARED_ITER_MAX: u16 = 100;
91119

92120
fn assert_trusted_len<I: TrustedLen>(_: &I) {}

0 commit comments

Comments
 (0)