Skip to content

Commit 94ce4b5

Browse files
Rollup merge of #141946 - xizheyin:141933, r=jhpratt
std: refactor explanation of `NonNull` Fixes #141933 I cut out the excessive explanation and used an example to explain how to maintain invariance, but I think what is quoted in the *rust reference* in the document needs to be added with a more layman's explanation and example. (I'm not sure if I deleted too much) r? `@workingjubilee`
2 parents 346adce + 8713973 commit 94ce4b5

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

library/core/src/ptr/non_null.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,24 @@ use crate::{fmt, hash, intrinsics, mem, ptr};
2020
/// as a discriminant -- `Option<NonNull<T>>` has the same size as `*mut T`.
2121
/// However the pointer may still dangle if it isn't dereferenced.
2222
///
23-
/// Unlike `*mut T`, `NonNull<T>` was chosen to be covariant over `T`. This makes it
24-
/// possible to use `NonNull<T>` when building covariant types, but introduces the
25-
/// risk of unsoundness if used in a type that shouldn't actually be covariant.
26-
/// (The opposite choice was made for `*mut T` even though technically the unsoundness
27-
/// could only be caused by calling unsafe functions.)
23+
/// Unlike `*mut T`, `NonNull<T>` is covariant over `T`. This is usually the correct
24+
/// choice for most data structures and safe abstractions, such as `Box`, `Rc`, `Arc`, `Vec`,
25+
/// and `LinkedList`.
2826
///
29-
/// Covariance is correct for most safe abstractions, such as `Box`, `Rc`, `Arc`, `Vec`,
30-
/// and `LinkedList`. This is the case because they provide a public API that follows the
31-
/// normal shared XOR mutable rules of Rust.
27+
/// In rare cases, if your type exposes a way to mutate the value of `T` through a `NonNull<T>`,
28+
/// and you need to prevent unsoundness from variance (for example, if `T` could be a reference
29+
/// with a shorter lifetime), you should add a field to make your type invariant, such as
30+
/// `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
3231
///
33-
/// If your type cannot safely be covariant, you must ensure it contains some
34-
/// additional field to provide invariance. Often this field will be a [`PhantomData`]
35-
/// type like `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
32+
/// Example of a type that must be invariant:
33+
/// ```rust
34+
/// use std::cell::Cell;
35+
/// use std::marker::PhantomData;
36+
/// struct Invariant<T> {
37+
/// ptr: std::ptr::NonNull<T>,
38+
/// _invariant: PhantomData<Cell<T>>,
39+
/// }
40+
/// ```
3641
///
3742
/// Notice that `NonNull<T>` has a `From` instance for `&T`. However, this does
3843
/// not change the fact that mutating through a (pointer derived from a) shared

0 commit comments

Comments
 (0)