Skip to content

Commit 26ad51f

Browse files
author
Yuki Okushi
authored
Rollup merge of #103567 - RalfJung:ptr-eq-dyn-trait, r=dtolnay
ptr::eq: clarify that comparing dyn Trait is fragile Also remove the dyn trait example from `ptr::eq` since those tests are not actually guaranteed to pass due to how unstable vtable comparison is. Cc ``@rust-lang/libs-api`` Cc discussion following #80505
2 parents 3bfe39e + 1946a18 commit 26ad51f

File tree

3 files changed

+16
-45
lines changed

3 files changed

+16
-45
lines changed

library/alloc/src/rc.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1110,8 +1110,8 @@ impl<T: ?Sized> Rc<T> {
11101110

11111111
#[inline]
11121112
#[stable(feature = "ptr_eq", since = "1.17.0")]
1113-
/// Returns `true` if the two `Rc`s point to the same allocation
1114-
/// (in a vein similar to [`ptr::eq`]).
1113+
/// Returns `true` if the two `Rc`s point to the same allocation in a vein similar to
1114+
/// [`ptr::eq`]. See [that function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers.
11151115
///
11161116
/// # Examples
11171117
///
@@ -2419,9 +2419,9 @@ impl<T: ?Sized> Weak<T> {
24192419
}
24202420
}
24212421

2422-
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
2423-
/// [`ptr::eq`]), or if both don't point to any allocation
2424-
/// (because they were created with `Weak::new()`).
2422+
/// Returns `true` if the two `Weak`s point to the same allocation similar to [`ptr::eq`], or if
2423+
/// both don't point to any allocation (because they were created with `Weak::new()`). See [that
2424+
/// function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers.
24252425
///
24262426
/// # Notes
24272427
///

library/alloc/src/sync.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1117,8 +1117,8 @@ impl<T: ?Sized> Arc<T> {
11171117
drop(Weak { ptr: self.ptr });
11181118
}
11191119

1120-
/// Returns `true` if the two `Arc`s point to the same allocation
1121-
/// (in a vein similar to [`ptr::eq`]).
1120+
/// Returns `true` if the two `Arc`s point to the same allocation in a vein similar to
1121+
/// [`ptr::eq`]. See [that function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers.
11221122
///
11231123
/// # Examples
11241124
///
@@ -2069,9 +2069,9 @@ impl<T: ?Sized> Weak<T> {
20692069
}
20702070
}
20712071

2072-
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
2073-
/// [`ptr::eq`]), or if both don't point to any allocation
2074-
/// (because they were created with `Weak::new()`).
2072+
/// Returns `true` if the two `Weak`s point to the same allocation similar to [`ptr::eq`], or if
2073+
/// both don't point to any allocation (because they were created with `Weak::new()`). See [that
2074+
/// function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers.
20752075
///
20762076
/// # Notes
20772077
///

library/core/src/ptr/mod.rs

+6-35
Original file line numberDiff line numberDiff line change
@@ -1733,6 +1733,12 @@ pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
17331733
/// by their address rather than comparing the values they point to
17341734
/// (which is what the `PartialEq for &T` implementation does).
17351735
///
1736+
/// When comparing wide pointers, both the address and the metadata are tested for equality.
1737+
/// However, note that comparing trait object pointers (`*const dyn Trait`) is unrealiable: pointers
1738+
/// to values of the same underlying type can compare inequal (because vtables are duplicated in
1739+
/// multiple codegen units), and pointers to values of *different* underlying type can compare equal
1740+
/// (since identical vtables can be deduplicated within a codegen unit).
1741+
///
17361742
/// # Examples
17371743
///
17381744
/// ```
@@ -1759,41 +1765,6 @@ pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
17591765
/// assert!(!std::ptr::eq(&a[..2], &a[..3]));
17601766
/// assert!(!std::ptr::eq(&a[0..2], &a[1..3]));
17611767
/// ```
1762-
///
1763-
/// Traits are also compared by their implementation:
1764-
///
1765-
/// ```
1766-
/// #[repr(transparent)]
1767-
/// struct Wrapper { member: i32 }
1768-
///
1769-
/// trait Trait {}
1770-
/// impl Trait for Wrapper {}
1771-
/// impl Trait for i32 {}
1772-
///
1773-
/// let wrapper = Wrapper { member: 10 };
1774-
///
1775-
/// // Pointers have equal addresses.
1776-
/// assert!(std::ptr::eq(
1777-
/// &wrapper as *const Wrapper as *const u8,
1778-
/// &wrapper.member as *const i32 as *const u8
1779-
/// ));
1780-
///
1781-
/// // Objects have equal addresses, but `Trait` has different implementations.
1782-
/// assert!(!std::ptr::eq(
1783-
/// &wrapper as &dyn Trait,
1784-
/// &wrapper.member as &dyn Trait,
1785-
/// ));
1786-
/// assert!(!std::ptr::eq(
1787-
/// &wrapper as &dyn Trait as *const dyn Trait,
1788-
/// &wrapper.member as &dyn Trait as *const dyn Trait,
1789-
/// ));
1790-
///
1791-
/// // Converting the reference to a `*const u8` compares by address.
1792-
/// assert!(std::ptr::eq(
1793-
/// &wrapper as &dyn Trait as *const dyn Trait as *const u8,
1794-
/// &wrapper.member as &dyn Trait as *const dyn Trait as *const u8,
1795-
/// ));
1796-
/// ```
17971768
#[stable(feature = "ptr_eq", since = "1.17.0")]
17981769
#[inline]
17991770
pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {

0 commit comments

Comments
 (0)