mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
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 rust-lang/rust#154998.
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,34 @@ fn eq(&self, other: &TestEq) -> bool {
|
||||
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>;
|
||||
|
||||
@@ -87,6 +87,34 @@ fn eq(&self, other: &TestEq) -> bool {
|
||||
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) {}
|
||||
|
||||
Reference in New Issue
Block a user