Skip to content

Commit 61eff8f

Browse files
committed
Expand set_ptr_value / with_metadata_of docs
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.
1 parent 6b57e57 commit 61eff8f

File tree

2 files changed

+61
-20
lines changed

2 files changed

+61
-20
lines changed

core/src/ptr/const_ptr.rs

+31-10
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,22 @@ impl<T: ?Sized> *const T {
6363
self as _
6464
}
6565

66-
/// Uses the pointer value in a new pointer of another type.
66+
/// Uses the address value in a new pointer of another type.
6767
///
68-
/// In case `meta` is a (fat) pointer to an unsized type, this operation
69-
/// will ignore the pointer part, whereas for (thin) pointers to sized
70-
/// types, this has the same effect as a simple cast.
68+
/// This operation will ignore the address part of its `meta` operand and discard existing
69+
/// metadata of `self`. For pointers to a sized types (thin pointers), this has the same effect
70+
/// as a simple cast. For pointers to an unsized type (fat pointers) this recombines the address
71+
/// with new metadata such as slice lengths or `dyn`-vtable.
7172
///
72-
/// The resulting pointer will have provenance of `self`, i.e., for a fat
73-
/// pointer, this operation is semantically the same as creating a new
74-
/// fat pointer with the data pointer value of `self` but the metadata of
75-
/// `meta`.
73+
/// The resulting pointer will have provenance of `self`. This operation is semantically the
74+
/// same as creating a new pointer with the data pointer value of `self` but the metadata of
75+
/// `meta`, being fat or thing depending on the `meta` operand.
7676
///
7777
/// # Examples
7878
///
79-
/// This function is primarily useful for allowing byte-wise pointer
80-
/// arithmetic on potentially fat pointers:
79+
/// This function is primarily useful for enabling pointer arithmetic on potentially fat
80+
/// pointers. The pointer is cast to a sized pointee to utilize offset operations and then
81+
/// recombined with its own original metadata.
8182
///
8283
/// ```
8384
/// #![feature(set_ptr_value)]
@@ -91,6 +92,26 @@ impl<T: ?Sized> *const T {
9192
/// println!("{:?}", &*ptr); // will print "3"
9293
/// }
9394
/// ```
95+
///
96+
/// # *Incorrect* usage
97+
///
98+
/// The provenance from pointers is *not* combined. The result must only be used to refer to the
99+
/// address allowed by `self`.
100+
///
101+
/// ```rust,no_run
102+
/// #![feature(set_ptr_value)]
103+
/// let x = 0u32;
104+
/// let y = 1u32;
105+
///
106+
/// let x = (&x) as *const u32;
107+
/// let y = (&y) as *const u32;
108+
///
109+
/// let offset = (x as usize - y as usize) / 4;
110+
/// let bad = x.wrapping_add(offset).with_metadata_of(y);
111+
///
112+
/// // This dereference is UB. The pointer only has provenance for `x` but points to `y`.
113+
/// println!("{:?}", unsafe { &*bad });
114+
/// ```
94115
#[unstable(feature = "set_ptr_value", issue = "75091")]
95116
#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")]
96117
#[must_use = "returns a new pointer rather than modifying its argument"]

core/src/ptr/mut_ptr.rs

+30-10
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,22 @@ impl<T: ?Sized> *mut T {
4545
self as _
4646
}
4747

48-
/// Uses the pointer value in a new pointer of another type.
48+
/// Uses the address value in a new pointer of another type.
4949
///
50-
/// In case `meta` is a (fat) pointer to an unsized type, this operation
51-
/// will ignore the pointer part, whereas for (thin) pointers to sized
52-
/// types, this has the same effect as a simple cast.
50+
/// This operation will ignore the address part of its `meta` operand and discard existing
51+
/// metadata of `self`. For pointers to a sized types (thin pointers), this has the same effect
52+
/// as a simple cast. For pointers to an unsized type (fat pointers) this recombines the address
53+
/// with new metadata such as slice lengths or `dyn`-vtable.
5354
///
54-
/// The resulting pointer will have provenance of `self`, i.e., for a fat
55-
/// pointer, this operation is semantically the same as creating a new
56-
/// fat pointer with the data pointer value of `self` but the metadata of
57-
/// `meta`.
55+
/// The resulting pointer will have provenance of `self`. This operation is semantically the
56+
/// same as creating a new pointer with the data pointer value of `self` but the metadata of
57+
/// `meta`, being fat or thing depending on the `meta` operand.
5858
///
5959
/// # Examples
6060
///
61-
/// This function is primarily useful for allowing byte-wise pointer
62-
/// arithmetic on potentially fat pointers:
61+
/// This function is primarily useful for enabling pointer arithmetic on potentially fat
62+
/// pointers. The pointer is cast to a sized pointee to utilize offset operations and then
63+
/// recombined with its own original metadata.
6364
///
6465
/// ```
6566
/// #![feature(set_ptr_value)]
@@ -73,6 +74,25 @@ impl<T: ?Sized> *mut T {
7374
/// println!("{:?}", &*ptr); // will print "3"
7475
/// }
7576
/// ```
77+
///
78+
/// # *Incorrect* usage
79+
///
80+
/// The provenance from pointers is *not* combined. The result must only be used to refer to the
81+
/// address allowed by `self`.
82+
///
83+
/// ```rust,no_run
84+
/// #![feature(set_ptr_value)]
85+
/// let mut x = 0u32;
86+
/// let mut y = 1u32;
87+
///
88+
/// let x = (&mut x) as *mut u32;
89+
/// let y = (&mut y) as *mut u32;
90+
///
91+
/// let offset = (x as usize - y as usize) / 4;
92+
/// let bad = x.wrapping_add(offset).with_metadata_of(y);
93+
///
94+
/// // This dereference is UB. The pointer only has provenance for `x` but points to `y`.
95+
/// println!("{:?}", unsafe { &*bad });
7696
#[unstable(feature = "set_ptr_value", issue = "75091")]
7797
#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")]
7898
#[must_use = "returns a new pointer rather than modifying its argument"]

0 commit comments

Comments
 (0)