Skip to content

Commit 18c72d0

Browse files
committed
stabilize Strict Provenance and Exposed Provenance
This comes with a big docs rewrite. It's mostly just rewording, except: - I removed the discussion of how pointers also have an associated "address space" -- that is not actually tracked in the pointer value, it is tracked in the type, so IMO it just distracts from the core point of provenance. - I also adjusted the docs for with_exposed_provenance to make it clear that we cannot guarantee much about this function, it's all best-effort.
1 parent f9567d0 commit 18c72d0

File tree

4 files changed

+237
-309
lines changed

4 files changed

+237
-309
lines changed

library/core/src/ptr/const_ptr.rs

+37-42
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,11 @@ impl<T: ?Sized> *const T {
116116

117117
/// Gets the "address" portion of the pointer.
118118
///
119-
/// This is similar to `self as usize`, which semantically discards *provenance* and
120-
/// *address-space* information. However, unlike `self as usize`, casting the returned address
121-
/// back to a pointer yields a [pointer without provenance][without_provenance], which is undefined behavior to dereference. To
122-
/// properly restore the lost information and obtain a dereferenceable pointer, use
119+
/// This is similar to `self as usize`, except that the [provenance][crate::ptr#provenance] of
120+
/// the pointer is discarded and not [exposed][crate::ptr#exposed-provenance]. This means that
121+
/// casting the returned address back to a pointer yields a [pointer without
122+
/// provenance][without_provenance], which is undefined behavior to dereference. To properly
123+
/// restore the lost information and obtain a dereferenceable pointer, use
123124
/// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr].
124125
///
125126
/// If using those APIs is not possible because there is no way to preserve a pointer with the
@@ -134,67 +135,61 @@ impl<T: ?Sized> *const T {
134135
/// perform a change of representation to produce a value containing only the address
135136
/// portion of the pointer. What that means is up to the platform to define.
136137
///
137-
/// This API and its claimed semantics are part of the Strict Provenance experiment, and as such
138-
/// might change in the future (including possibly weakening this so it becomes wholly
139-
/// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details.
138+
/// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
140139
#[must_use]
141140
#[inline(always)]
142-
#[unstable(feature = "strict_provenance", issue = "95228")]
141+
#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
143142
pub fn addr(self) -> usize {
144-
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
143+
// A pointer-to-integer transmute has exactly the right semantics: it returns
144+
// the address without exposing the provenance.
145145
// SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the
146146
// provenance).
147147
unsafe { mem::transmute(self.cast::<()>()) }
148148
}
149149

150-
/// Exposes the "provenance" part of the pointer for future use in
151-
/// [`with_exposed_provenance`][] and returns the "address" portion.
150+
/// Exposes the ["provenance"][crate::ptr#provenance] part of the pointer for future use in
151+
/// [`with_exposed_provenance`] and returns the "address" portion.
152152
///
153-
/// This is equivalent to `self as usize`, which semantically discards *provenance* and
154-
/// *address-space* information. Furthermore, this (like the `as` cast) has the implicit
155-
/// side-effect of marking the provenance as 'exposed', so on platforms that support it you can
156-
/// later call [`with_exposed_provenance`][] to reconstitute the original pointer including its
157-
/// provenance. (Reconstructing address space information, if required, is your responsibility.)
153+
/// This is equivalent to `self as usize`, which semantically discards provenance information.
154+
/// Furthermore, this (like the `as` cast) has the implicit side-effect of marking the
155+
/// provenance as 'exposed', so on platforms that support it you can later call
156+
/// [`with_exposed_provenance`] to reconstitute the original pointer including its provenance.
158157
///
159-
/// Using this method means that code is *not* following [Strict
160-
/// Provenance][super#strict-provenance] rules. Supporting
161-
/// [`with_exposed_provenance`][] complicates specification and reasoning and may not be supported by
162-
/// tools that help you to stay conformant with the Rust memory model, so it is recommended to
163-
/// use [`addr`][pointer::addr] wherever possible.
158+
/// Due to its inherent ambiguity, [`with_exposed_provenance`] may not be supported by tools
159+
/// that help you to stay conformant with the Rust memory model. It is recommended to use
160+
/// [Strict Provenance][crate::ptr#strict-provenance] APIs such as [`with_addr`][pointer::with_addr]
161+
/// wherever possible, in which case [`addr`][pointer::addr] should be used instead of `expose_provenance`.
164162
///
165163
/// On most platforms this will produce a value with the same bytes as the original pointer,
166164
/// because all the bytes are dedicated to describing the address. Platforms which need to store
167165
/// additional information in the pointer may not support this operation, since the 'expose'
168-
/// side-effect which is required for [`with_exposed_provenance`][] to work is typically not
166+
/// side-effect which is required for [`with_exposed_provenance`] to work is typically not
169167
/// available.
170168
///
171-
/// It is unclear whether this method can be given a satisfying unambiguous specification. This
172-
/// API and its claimed semantics are part of [Exposed Provenance][super#exposed-provenance].
169+
/// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API.
173170
///
174171
/// [`with_exposed_provenance`]: with_exposed_provenance
175172
#[must_use]
176173
#[inline(always)]
177-
#[unstable(feature = "exposed_provenance", issue = "95228")]
174+
#[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")]
178175
pub fn expose_provenance(self) -> usize {
179-
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
180176
self.cast::<()>() as usize
181177
}
182178

183-
/// Creates a new pointer with the given address.
179+
/// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of
180+
/// `self`.
184181
///
185-
/// This performs the same operation as an `addr as ptr` cast, but copies
186-
/// the *address-space* and *provenance* of `self` to the new pointer.
187-
/// This allows us to dynamically preserve and propagate this important
188-
/// information in a way that is otherwise impossible with a unary cast.
182+
/// This is similar to a `addr as *const T` cast, but copies
183+
/// the *provenance* of `self` to the new pointer.
184+
/// This avoids the inherent ambiguity of the unary cast.
189185
///
190186
/// This is equivalent to using [`wrapping_offset`][pointer::wrapping_offset] to offset
191187
/// `self` to the given address, and therefore has all the same capabilities and restrictions.
192188
///
193-
/// This API and its claimed semantics are part of the Strict Provenance experiment,
194-
/// see the [module documentation][crate::ptr] for details.
189+
/// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
195190
#[must_use]
196191
#[inline]
197-
#[unstable(feature = "strict_provenance", issue = "95228")]
192+
#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
198193
pub fn with_addr(self, addr: usize) -> Self {
199194
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
200195
//
@@ -209,15 +204,15 @@ impl<T: ?Sized> *const T {
209204
self.wrapping_byte_offset(offset)
210205
}
211206

212-
/// Creates a new pointer by mapping `self`'s address to a new one.
207+
/// Creates a new pointer by mapping `self`'s address to a new one, preserving the
208+
/// [provenance][crate::ptr#provenance] of `self`.
213209
///
214210
/// This is a convenience for [`with_addr`][pointer::with_addr], see that method for details.
215211
///
216-
/// This API and its claimed semantics are part of the Strict Provenance experiment,
217-
/// see the [module documentation][crate::ptr] for details.
212+
/// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
218213
#[must_use]
219214
#[inline]
220-
#[unstable(feature = "strict_provenance", issue = "95228")]
215+
#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
221216
pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self {
222217
self.with_addr(f(self.addr()))
223218
}
@@ -357,7 +352,7 @@ impl<T: ?Sized> *const T {
357352
///
358353
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
359354
///
360-
/// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
355+
/// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
361356
/// [allocated object], and the entire memory range between `self` and the result must be in
362357
/// bounds of that allocated object. In particular, this range must not "wrap around" the edge
363358
/// of the address space.
@@ -561,7 +556,7 @@ impl<T: ?Sized> *const T {
561556
/// * `self` and `origin` must either
562557
///
563558
/// * point to the same address, or
564-
/// * both be *derived from* a pointer to the same [allocated object], and the memory range between
559+
/// * both be [derived from][crate::ptr#provenance] a pointer to the same [allocated object], and the memory range between
565560
/// the two pointers must be in bounds of that object. (See below for an example.)
566561
///
567562
/// * The distance between the pointers, in bytes, must be an exact multiple
@@ -818,7 +813,7 @@ impl<T: ?Sized> *const T {
818813
///
819814
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
820815
///
821-
/// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
816+
/// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
822817
/// [allocated object], and the entire memory range between `self` and the result must be in
823818
/// bounds of that allocated object. In particular, this range must not "wrap around" the edge
824819
/// of the address space.
@@ -892,7 +887,7 @@ impl<T: ?Sized> *const T {
892887
///
893888
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
894889
///
895-
/// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
890+
/// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
896891
/// [allocated object], and the entire memory range between `self` and the result must be in
897892
/// bounds of that allocated object. In particular, this range must not "wrap around" the edge
898893
/// of the address space.

0 commit comments

Comments
 (0)