@@ -20,19 +20,24 @@ use crate::{fmt, hash, intrinsics, mem, ptr};
20
20
/// as a discriminant -- `Option<NonNull<T>>` has the same size as `*mut T`.
21
21
/// However the pointer may still dangle if it isn't dereferenced.
22
22
///
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`.
28
26
///
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>`.
32
31
///
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
+ /// ```
36
41
///
37
42
/// Notice that `NonNull<T>` has a `From` instance for `&T`. However, this does
38
43
/// not change the fact that mutating through a (pointer derived from a) shared
0 commit comments