/// the program has undefined behavior. In particular, the aliasing rules still apply: pointers
/// and references that have been invalidated due to aliasing accesses cannot be used any more,
/// even if they have been exposed!
+///
/// Note that there is no algorithm that decides which provenance will be used. You can think of this
/// as "guessing" the right provenance, and the guess will be "maximally in your favor", in the sense
/// that if there is any way to avoid undefined behavior (while upholding all aliasing requirements),
// SAFETY: the caller must guarantee that `x` and `y` are
// valid for writes and properly aligned.
unsafe {
- assert_unsafe_precondition!([T](x: *mut T, y: *mut T, count: usize) =>
+ assert_unsafe_precondition!(
+ "ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null \
+ and the specified memory ranges do not overlap",
+ [T](x: *mut T, y: *mut T, count: usize) =>
is_aligned_and_not_null(x)
&& is_aligned_and_not_null(y)
&& is_nonoverlapping(x, y, count)
// and cannot overlap `src` since `dst` must point to a distinct
// allocated object.
unsafe {
- assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst));
+ assert_unsafe_precondition!(
+ "ptr::replace requires that the pointer argument is aligned and non-null",
+ [T](dst: *mut T) => is_aligned_and_not_null(dst)
+ );
mem::swap(&mut *dst, &mut src); // cannot overlap
}
src
// Also, since we just wrote a valid value into `tmp`, it is guaranteed
// to be properly initialized.
unsafe {
- assert_unsafe_precondition!([T](src: *const T) => is_aligned_and_not_null(src));
+ assert_unsafe_precondition!(
+ "ptr::read requires that the pointer argument is aligned and non-null",
+ [T](src: *const T) => is_aligned_and_not_null(src)
+ );
copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
tmp.assume_init()
}
// `dst` cannot overlap `src` because the caller has mutable access
// to `dst` while `src` is owned by this function.
unsafe {
- assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst));
+ assert_unsafe_precondition!(
+ "ptr::write requires that the pointer argument is aligned and non-null",
+ [T](dst: *mut T) => is_aligned_and_not_null(dst)
+ );
copy_nonoverlapping(&src as *const T, dst, 1);
intrinsics::forget(src);
}
pub unsafe fn read_volatile<T>(src: *const T) -> T {
// SAFETY: the caller must uphold the safety contract for `volatile_load`.
unsafe {
- assert_unsafe_precondition!([T](src: *const T) => is_aligned_and_not_null(src));
+ assert_unsafe_precondition!(
+ "ptr::read_volatile requires that the pointer argument is aligned and non-null",
+ [T](src: *const T) => is_aligned_and_not_null(src)
+ );
intrinsics::volatile_load(src)
}
}
pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
// SAFETY: the caller must uphold the safety contract for `volatile_store`.
unsafe {
- assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst));
+ assert_unsafe_precondition!(
+ "ptr::write_volatile requires that the pointer argument is aligned and non-null",
+ [T](dst: *mut T) => is_aligned_and_not_null(dst)
+ );
intrinsics::volatile_store(dst, src);
}
}
/// by their address rather than comparing the values they point to
/// (which is what the `PartialEq for &T` implementation does).
///
+/// When comparing wide pointers, both the address and the metadata are tested for equality.
+/// However, note that comparing trait object pointers (`*const dyn Trait`) is unrealiable: pointers
+/// to values of the same underlying type can compare inequal (because vtables are duplicated in
+/// multiple codegen units), and pointers to values of *different* underlying type can compare equal
+/// (since identical vtables can be deduplicated within a codegen unit).
+///
/// # Examples
///
/// ```
/// assert!(!std::ptr::eq(&a[..2], &a[..3]));
/// assert!(!std::ptr::eq(&a[0..2], &a[1..3]));
/// ```
-///
-/// Traits are also compared by their implementation:
-///
-/// ```
-/// #[repr(transparent)]
-/// struct Wrapper { member: i32 }
-///
-/// trait Trait {}
-/// impl Trait for Wrapper {}
-/// impl Trait for i32 {}
-///
-/// let wrapper = Wrapper { member: 10 };
-///
-/// // Pointers have equal addresses.
-/// assert!(std::ptr::eq(
-/// &wrapper as *const Wrapper as *const u8,
-/// &wrapper.member as *const i32 as *const u8
-/// ));
-///
-/// // Objects have equal addresses, but `Trait` has different implementations.
-/// assert!(!std::ptr::eq(
-/// &wrapper as &dyn Trait,
-/// &wrapper.member as &dyn Trait,
-/// ));
-/// assert!(!std::ptr::eq(
-/// &wrapper as &dyn Trait as *const dyn Trait,
-/// &wrapper.member as &dyn Trait as *const dyn Trait,
-/// ));
-///
-/// // Converting the reference to a `*const u8` compares by address.
-/// assert!(std::ptr::eq(
-/// &wrapper as &dyn Trait as *const dyn Trait as *const u8,
-/// &wrapper.member as &dyn Trait as *const dyn Trait as *const u8,
-/// ));
-/// ```
#[stable(feature = "ptr_eq", since = "1.17.0")]
#[inline]
pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
fnptr_impls_safety_abi! { #[stable(feature = "fnptr_impls", since = "1.4.0")] $FnTy, $($Arg),* }
};
(@c_unwind $FnTy: ty, $($Arg: ident),*) => {
- #[cfg(not(bootstrap))]
fnptr_impls_safety_abi! { #[unstable(feature = "c_unwind", issue = "74990")] $FnTy, $($Arg),* }
};
(#[$meta:meta] $FnTy: ty, $($Arg: ident),*) => {