Skip to content

Commit

Permalink
Rollup merge of #131339 - HeroicKatora:set_ptr_value-documentation, r…
Browse files Browse the repository at this point in the history
…=Mark-Simulacrum

Expand set_ptr_value / with_metadata_of docs

In preparation of a potential FCP, intends to clean up and expand the documentation of this operation.

Rewrite these blobs to explicitly mention the case of a sized operand. The previous made that seem wrong instead of emphasizing it is nothing but a simple cast. Instead, the explanation now emphasizes that the address portion of the argument, together with its provenance, is discarded which previously had to be inferred by the reader. Then an example demonstrates a simple line of incorrect usage based on this idea of provenance.

Tracking issue: #75091
  • Loading branch information
matthiaskrgr authored Oct 15, 2024
2 parents bb2f970 + c128b4c commit 09103f2
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 20 deletions.
41 changes: 31 additions & 10 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,22 @@ impl<T: ?Sized> *const T {
self as _
}

/// Uses the pointer value in a new pointer of another type.
/// Uses the address value in a new pointer of another type.
///
/// In case `meta` is a (fat) pointer to an unsized type, this operation
/// will ignore the pointer part, whereas for (thin) pointers to sized
/// types, this has the same effect as a simple cast.
/// This operation will ignore the address part of its `meta` operand and discard existing
/// metadata of `self`. For pointers to a sized types (thin pointers), this has the same effect
/// as a simple cast. For pointers to an unsized type (fat pointers) this recombines the address
/// with new metadata such as slice lengths or `dyn`-vtable.
///
/// The resulting pointer will have provenance of `self`, i.e., for a fat
/// pointer, this operation is semantically the same as creating a new
/// fat pointer with the data pointer value of `self` but the metadata of
/// `meta`.
/// The resulting pointer will have provenance of `self`. This operation is semantically the
/// same as creating a new pointer with the data pointer value of `self` but the metadata of
/// `meta`, being fat or thin depending on the `meta` operand.
///
/// # Examples
///
/// This function is primarily useful for allowing byte-wise pointer
/// arithmetic on potentially fat pointers:
/// This function is primarily useful for enabling pointer arithmetic on potentially fat
/// pointers. The pointer is cast to a sized pointee to utilize offset operations and then
/// recombined with its own original metadata.
///
/// ```
/// #![feature(set_ptr_value)]
Expand All @@ -91,6 +92,26 @@ impl<T: ?Sized> *const T {
/// println!("{:?}", &*ptr); // will print "3"
/// }
/// ```
///
/// # *Incorrect* usage
///
/// The provenance from pointers is *not* combined. The result must only be used to refer to the
/// address allowed by `self`.
///
/// ```rust,no_run
/// #![feature(set_ptr_value)]
/// let x = 0u32;
/// let y = 1u32;
///
/// let x = (&x) as *const u32;
/// let y = (&y) as *const u32;
///
/// let offset = (x as usize - y as usize) / 4;
/// let bad = x.wrapping_add(offset).with_metadata_of(y);
///
/// // This dereference is UB. The pointer only has provenance for `x` but points to `y`.
/// println!("{:?}", unsafe { &*bad });
/// ```
#[unstable(feature = "set_ptr_value", issue = "75091")]
#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "returns a new pointer rather than modifying its argument"]
Expand Down
40 changes: 30 additions & 10 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,22 @@ impl<T: ?Sized> *mut T {
self as _
}

/// Uses the pointer value in a new pointer of another type.
/// Uses the address value in a new pointer of another type.
///
/// In case `meta` is a (fat) pointer to an unsized type, this operation
/// will ignore the pointer part, whereas for (thin) pointers to sized
/// types, this has the same effect as a simple cast.
/// This operation will ignore the address part of its `meta` operand and discard existing
/// metadata of `self`. For pointers to a sized types (thin pointers), this has the same effect
/// as a simple cast. For pointers to an unsized type (fat pointers) this recombines the address
/// with new metadata such as slice lengths or `dyn`-vtable.
///
/// The resulting pointer will have provenance of `self`, i.e., for a fat
/// pointer, this operation is semantically the same as creating a new
/// fat pointer with the data pointer value of `self` but the metadata of
/// `meta`.
/// The resulting pointer will have provenance of `self`. This operation is semantically the
/// same as creating a new pointer with the data pointer value of `self` but the metadata of
/// `meta`, being fat or thin depending on the `meta` operand.
///
/// # Examples
///
/// This function is primarily useful for allowing byte-wise pointer
/// arithmetic on potentially fat pointers:
/// This function is primarily useful for enabling pointer arithmetic on potentially fat
/// pointers. The pointer is cast to a sized pointee to utilize offset operations and then
/// recombined with its own original metadata.
///
/// ```
/// #![feature(set_ptr_value)]
Expand All @@ -73,6 +74,25 @@ impl<T: ?Sized> *mut T {
/// println!("{:?}", &*ptr); // will print "3"
/// }
/// ```
///
/// # *Incorrect* usage
///
/// The provenance from pointers is *not* combined. The result must only be used to refer to the
/// address allowed by `self`.
///
/// ```rust,no_run
/// #![feature(set_ptr_value)]
/// let mut x = 0u32;
/// let mut y = 1u32;
///
/// let x = (&mut x) as *mut u32;
/// let y = (&mut y) as *mut u32;
///
/// let offset = (x as usize - y as usize) / 4;
/// let bad = x.wrapping_add(offset).with_metadata_of(y);
///
/// // This dereference is UB. The pointer only has provenance for `x` but points to `y`.
/// println!("{:?}", unsafe { &*bad });
#[unstable(feature = "set_ptr_value", issue = "75091")]
#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "returns a new pointer rather than modifying its argument"]
Expand Down

0 comments on commit 09103f2

Please sign in to comment.