/// Therefore, two pointers that are null may still not compare equal to
/// each other.
///
+ /// ## Behavior during const evaluation
+ ///
+ /// When this function is used during const evaluation, it may return `false` for pointers
+ /// that turn out to be null at runtime. Specifically, when a pointer to some memory
+ /// is offset beyond its bounds in such a way that the resulting pointer is null,
+ /// the function will still return `false`. There is no way for CTFE to know
+ /// the absolute position of that memory, so we cannot tell if the pointer is
+ /// null or not.
+ ///
/// # Examples
///
/// Basic usage:
/// assert!(!ptr.is_null());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
#[inline]
- pub fn is_null(self) -> bool {
+ pub const fn is_null(self) -> bool {
// Compare via a cast to a thin pointer, so fat pointers are only
// considering their "data" part for null-ness.
- (self as *mut u8) == null_mut()
+ (self as *mut u8).guaranteed_eq(null_mut())
}
/// Casts to a pointer of another type.
/// byte past the end of the same allocated object. Note that in Rust,
/// every (stack-allocated) variable is considered a separate allocated object.
///
+ /// * Both pointers must be *derived from* a pointer to the same object.
+ /// (See below for an example.)
+ ///
/// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
///
/// * The distance between the pointers, in bytes, must be an exact multiple
/// assert_eq!(ptr2.offset(-2), ptr1);
/// }
/// ```
- #[unstable(feature = "ptr_offset_from", issue = "41079")]
- #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
- #[inline]
- pub const unsafe fn offset_from(self, origin: *const T) -> isize
- where
- T: Sized,
- {
- // SAFETY: the caller must uphold the safety contract for `offset_from`.
- unsafe { (self as *const T).offset_from(origin) }
- }
-
- /// Calculates the distance between two pointers. The returned value is in
- /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
- ///
- /// If the address different between the two pointers is not a multiple of
- /// `mem::size_of::<T>()` then the result of the division is rounded towards
- /// zero.
- ///
- /// Though this method is safe for any two pointers, note that its result
- /// will be mostly useless if the two pointers aren't into the same allocated
- /// object, for example if they point to two different local variables.
- ///
- /// # Panics
///
- /// This function panics if `T` is a zero-sized type.
+ /// *Incorrect* usage:
///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// #![feature(ptr_wrapping_offset_from)]
+ /// ```rust,no_run
+ /// #![feature(ptr_offset_from)]
///
- /// let mut a = [0; 5];
- /// let ptr1: *mut i32 = &mut a[1];
- /// let ptr2: *mut i32 = &mut a[3];
- /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
- /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
- /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
- /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
- ///
- /// let ptr1: *mut i32 = 3 as _;
- /// let ptr2: *mut i32 = 13 as _;
- /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
+ /// let ptr1 = Box::into_raw(Box::new(0u8));
+ /// let ptr2 = Box::into_raw(Box::new(1u8));
+ /// let diff = (ptr2 as isize).wrapping_sub(ptr1 as isize);
+ /// // Make ptr2_other an "alias" of ptr2, but derived from ptr1.
+ /// let ptr2_other = (ptr1 as *mut u8).wrapping_offset(diff);
+ /// assert_eq!(ptr2 as usize, ptr2_other as usize);
+ /// // Since ptr2_other and ptr2 are derived from pointers to different objects,
+ /// // computing their offset is undefined behavior, even though
+ /// // they point to the same address!
+ /// unsafe {
+ /// let zero = ptr2_other.offset_from(ptr2); // Undefined Behavior
+ /// }
/// ```
- #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
- #[rustc_deprecated(
- since = "1.46.0",
- reason = "Pointer distances across allocation \
- boundaries are not typically meaningful. \
- Use integer subtraction if you really need this."
- )]
+ #[stable(feature = "ptr_offset_from", since = "1.46.0")]
+ #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
#[inline]
- pub fn wrapping_offset_from(self, origin: *const T) -> isize
+ pub const unsafe fn offset_from(self, origin: *const T) -> isize
where
T: Sized,
{
- #[allow(deprecated_in_future, deprecated)]
- (self as *const T).wrapping_offset_from(origin)
+ // SAFETY: the caller must uphold the safety contract for `offset_from`.
+ unsafe { (self as *const T).offset_from(origin) }
}
/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
/// will only affect the pointer part, whereas for (thin) pointers to
/// sized types, this has the same effect as a simple assignment.
///
+ /// The resulting pointer will have provenance of `val`, i.e., for a fat
+ /// pointer, this operation is semantically the same as creating a new
+ /// fat pointer with the data pointer value of `val` but the metadata of
+ /// `self`.
+ ///
/// # Examples
///
/// This function is primarily useful for allowing byte-wise pointer
/// let mut arr: [i32; 3] = [1, 2, 3];
/// let mut ptr = &mut arr[0] as *mut dyn Debug;
/// let thin = ptr as *mut u8;
- /// ptr = ptr.set_ptr_value(unsafe { thin.add(8).cast() });
- /// assert_eq!(unsafe { *(ptr as *mut i32) }, 3);
+ /// unsafe {
+ /// ptr = ptr.set_ptr_value(thin.add(8));
+ /// # assert_eq!(*(ptr as *mut i32), 3);
+ /// println!("{:?}", &*ptr); // will print "3"
+ /// }
/// ```
#[unstable(feature = "set_ptr_value", issue = "75091")]
+ #[must_use = "returns a new pointer rather than modifying its argument"]
#[inline]
- pub fn set_ptr_value(mut self, val: *mut ()) -> Self {
- let thin = &mut self as *mut *mut T as *mut *mut ();
+ pub fn set_ptr_value(mut self, val: *mut u8) -> Self {
+ let thin = &mut self as *mut *mut T as *mut *mut u8;
// SAFETY: In case of a thin pointer, this operations is identical
// to a simple assignment. In case of a fat pointer, with the current
// fat pointer layout implementation, the first field of such a