Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2615,7 +2615,7 @@ impl<T: ?Sized + PartialEq, A: Allocator> RcEqIdent<T, A> for Rc<T, A> {
#[rustc_unsafe_specialization_marker]
pub(crate) trait MarkerEq: PartialEq<Self> {}

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

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

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

Expand Down
4 changes: 2 additions & 2 deletions library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3549,12 +3549,12 @@ impl<T: ?Sized + PartialEq, A: Allocator> ArcEqIdent<T, A> for Arc<T, A> {
impl<T: ?Sized + crate::rc::MarkerEq, A: Allocator> ArcEqIdent<T, A> for Arc<T, A> {
#[inline]
fn eq(&self, other: &Arc<T, A>) -> bool {
Arc::ptr_eq(self, other) || **self == **other
ptr::eq(self.ptr.as_ptr(), other.ptr.as_ptr()) || **self == **other
}

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

Expand Down
28 changes: 28 additions & 0 deletions library/alloctests/tests/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,34 @@ fn eq() {
assert_eq!(*x.0.borrow(), 0);
}

#[test]
fn eq_unsized() {
#[derive(Eq)]
struct TestEq<T: ?Sized>(RefCell<usize>, T);
impl<T: ?Sized> PartialEq for TestEq<T> {
fn eq(&self, other: &TestEq<T>) -> bool {
*self.0.borrow_mut() += 1;
*other.0.borrow_mut() += 1;
true
}
}
let x = Arc::<TestEq<[u8; 3]>>::new(TestEq(RefCell::new(0), [0, 1, 2])) as Arc<TestEq<[u8]>>;
assert!(x == x);
assert!(!(x != x));
assert_eq!(*x.0.borrow(), 0);
}

#[test]
fn eq_unsized_slice() {
let a: Arc<[()]> = Arc::new([(); 3]);
let ptr: *const () = Arc::into_raw(a.clone()).cast();
let b: Arc<[()]> = unsafe { Arc::from_raw(core::ptr::slice_from_raw_parts(ptr, 42)) };
assert!(a == a);
assert!(!(a != a));
assert!(a != b);
assert!(!(a == b));
}

// The test code below is identical to that in `rc.rs`.
// For better maintainability we therefore define this type alias.
type Rc<T, A = std::alloc::Global> = Arc<T, A>;
Expand Down
28 changes: 28 additions & 0 deletions library/alloctests/tests/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,34 @@ fn eq() {
assert_eq!(*x.0.borrow(), 0);
}

#[test]
fn eq_unsized() {
#[derive(Eq)]
struct TestEq<T: ?Sized>(RefCell<usize>, T);
impl<T: ?Sized> PartialEq for TestEq<T> {
fn eq(&self, other: &TestEq<T>) -> bool {
*self.0.borrow_mut() += 1;
*other.0.borrow_mut() += 1;
true
}
}
let x = Rc::<TestEq<[u8; 3]>>::new(TestEq(RefCell::new(0), [0, 1, 2])) as Rc<TestEq<[u8]>>;
assert!(x == x);
assert!(!(x != x));
assert_eq!(*x.0.borrow(), 0);
}

#[test]
fn eq_unsized_slice() {
let a: Rc<[()]> = Rc::new([(); 3]);
let ptr: *const () = Rc::into_raw(a.clone()).cast();
let b: Rc<[()]> = unsafe { Rc::from_raw(core::ptr::slice_from_raw_parts(ptr, 42)) };
assert!(a == a);
assert!(!(a != a));
assert!(a != b);
assert!(!(a == b));
}

const SHARED_ITER_MAX: u16 = 100;

fn assert_trusted_len<I: TrustedLen>(_: &I) {}
Expand Down
Loading