diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index ee03f15eece3f..8f1531eccafcc 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1002,7 +1002,9 @@ impl Rc { /// /// [`ptr::eq`]: core::ptr::eq pub fn ptr_eq(this: &Self, other: &Self) -> bool { - this.ptr.as_ptr() == other.ptr.as_ptr() + // The *const u8 cast discards the vtable to work around + // https://github.com/rust-lang/rust/issues/46139 + this.ptr.as_ptr() as *const u8 == other.ptr.as_ptr() as *const u8 } } @@ -2136,7 +2138,9 @@ impl Weak { #[inline] #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { - self.ptr.as_ptr() == other.ptr.as_ptr() + // The *const u8 cast discards the vtable to work around + // https://github.com/rust-lang/rust/issues/46139 + self.ptr.as_ptr() as *const u8 == other.ptr.as_ptr() as *const u8 } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index c0d684fbb4573..0889bf5519894 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1066,7 +1066,9 @@ impl Arc { /// /// [`ptr::eq`]: core::ptr::eq pub fn ptr_eq(this: &Self, other: &Self) -> bool { - this.ptr.as_ptr() == other.ptr.as_ptr() + // The *const u8 cast discards the vtable to work around + // https://github.com/rust-lang/rust/issues/46139 + this.ptr.as_ptr() as *const u8 == other.ptr.as_ptr() as *const u8 } } @@ -1936,7 +1938,9 @@ impl Weak { #[inline] #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { - self.ptr.as_ptr() == other.ptr.as_ptr() + // The *const u8 cast discards the vtable to work around + // https://github.com/rust-lang/rust/issues/46139 + self.ptr.as_ptr() as *const u8 == other.ptr.as_ptr() as *const u8 } } diff --git a/library/alloc/tests/arc.rs b/library/alloc/tests/arc.rs index c02ba267056d6..8a498f305c621 100644 --- a/library/alloc/tests/arc.rs +++ b/library/alloc/tests/arc.rs @@ -195,3 +195,20 @@ fn shared_from_iter_trustedlen_no_fuse() { assert_trusted_len(&iter); assert_eq!(&[Box::new(42), Box::new(24)], &*iter.collect::>()); } + +mod other_mod { + use std::sync::Arc; + + pub fn cast(r: Arc<()>) -> Arc { + r + } +} + +#[test] +fn ptr_eq_ignores_duplicated_vtable() { + let a = Arc::new(()); + let b = other_mod::cast(Arc::clone(&a)); + let c: Arc = a; + assert!(Arc::ptr_eq(&b, &c)); + assert!(Weak::ptr_eq(&Arc::downgrade(&b), &Arc::downgrade(&c))); +} diff --git a/library/alloc/tests/rc.rs b/library/alloc/tests/rc.rs index 501b4f0f816be..3e7e7298f0701 100644 --- a/library/alloc/tests/rc.rs +++ b/library/alloc/tests/rc.rs @@ -191,3 +191,20 @@ fn shared_from_iter_trustedlen_no_fuse() { assert_trusted_len(&iter); assert_eq!(&[Box::new(42), Box::new(24)], &*iter.collect::>()); } + +mod other_mod { + use std::rc::Rc; + + pub fn cast(r: Rc<()>) -> Rc { + r + } +} + +#[test] +fn ptr_eq_ignores_duplicated_vtable() { + let a = Rc::new(()); + let b = other_mod::cast(Rc::clone(&a)); + let c: Rc = a; + assert!(Rc::ptr_eq(&b, &c)); + assert!(Weak::ptr_eq(&Rc::downgrade(&b), &Rc::downgrade(&c))); +}