Skip to content

Commit 9efcd99

Browse files
committed
Add even more details to top-level pointer docs
1 parent 7514d76 commit 9efcd99

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

library/core/src/ptr/mod.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,8 @@
153153
//! integers is very useful, so what can we do?
154154
//!
155155
//! Strict Provenance attempts to square this circle by decoupling Rust's traditional conflation
156-
//! of pointers and `usize` (and `isize`), defining a pointer to semantically contain the following
157-
//! information:
156+
//! of pointers and `usize` (and `isize`), and defining a pointer to semantically contain the
157+
//! following information:
158158
//!
159159
//! * The **address-space** it is part of.
160160
//! * The **address** it points to, which can be represented by a `usize`.
@@ -235,6 +235,10 @@
235235
//! }
236236
//! ```
237237
//!
238+
//! (Yes, if you've been using AtomicUsize for pointers in concurrent datastructures, you should
239+
//! be using AtomicPtr instead. If that messes up the way you atomically manipulate pointers,
240+
//! we would like to know why, and what needs to be done to fix it.)
241+
//!
238242
//! Something more complicated and just generally *evil* like a XOR-List requires more significant
239243
//! changes like allocating all nodes in a pre-allocated Vec or Arena and using a pointer
240244
//! to the whole allocation to reconstitute the XORed addresses.
@@ -258,11 +262,13 @@
258262
//!
259263
//! * Create an invalid pointer from just an address (see [`ptr::invalid`][]). This can
260264
//! be used for sentinel values like `null` *or* to represent a tagged pointer that will
261-
//! never be dereferencable.
265+
//! never be dereferencable. In general, it is always sound for an integer to pretend
266+
//! to be a pointer "for fun" as long as you don't use operations on it which require
267+
//! it to be valid (offset, read, write, etc).
262268
//!
263269
//! * Forge an allocation of size zero at any sufficiently aligned non-null address.
264270
//! i.e. the usual "ZSTs are fake, do what you want" rules apply *but* this only applies
265-
//! for actual forgery (integers cast to pointers). If you borrow some structs subfield
271+
//! for actual forgery (integers cast to pointers). If you borrow some struct's field
266272
//! that *happens* to be zero-sized, the resulting pointer will have provenance tied to
267273
//! that allocation and it will still get invalidated if the allocation gets deallocated.
268274
//! In the future we may introduce an API to make such a forged allocation explicit.
@@ -277,6 +283,16 @@
277283
//! and based on alignment, but the buffer on either side of the pointer's range is pretty
278284
//! generous (think kilobytes, not bytes).
279285
//!
286+
//! * Compare arbitrary pointers by address. Addresses *are* just integers and so there is
287+
//! always a coherent answer, even if the pointers are invalid or from different
288+
//! address-spaces/provenances. Of course, comparing addresses from different address-spaces
289+
//! is generally going to be *meaningless*, but so is comparing Kilograms to Meters, and Rust
290+
//! doesn't prevent that either. Similarly, if you get "lucky" and notice that a pointer
291+
//! one-past-the-end is the "same" address as the start of an unrelated allocation, anything
292+
//! you do with that fact is *probably* going to be gibberish. The scope of that gibberish
293+
//! is kept under control by the fact that the two pointers *still* aren't allowed to access
294+
//! the other's allocation (bytes), because they still have different provenance.
295+
//!
280296
//! * Perform pointer tagging tricks. This falls out of [`wrapping_offset`] but is worth
281297
//! mentioning in more detail because of the limitations of [CHERI][]. Low-bit tagging
282298
//! is very robust, and often doesn't even go out of bounds because types have a

0 commit comments

Comments
 (0)