@@ -11,36 +11,23 @@ use crate::{fmt, hash, intrinsics, mem, ptr};
11
11
12
12
/// `*mut T` but non-zero and [covariant].
13
13
///
14
- /// This is often the correct thing to use when building data structures using
15
- /// raw pointers, but is ultimately more dangerous to use because of its additional
16
- /// properties. If you're not sure if you should use `NonNull<T>`, just use `*mut T`!
14
+ /// `NonNull<T>` is a non-null raw pointer, commonly used for building data structures with raw pointers.
15
+ /// It is **covariant** over `T`, which is the correct choice for most safe abstractions (such as `Box`, `Rc`, `Arc`, `Vec`, etc).
17
16
///
18
- /// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
19
- /// is never dereferenced. This is so that enums may use this forbidden value
20
- /// as a discriminant -- `Option<NonNull<T>>` has the same size as `*mut T`.
21
- /// However the pointer may still dangle if it isn't dereferenced.
17
+ /// If you need **invariance** (for example, when implementing types like `Cell<T>`), you can add a marker field to your type:
22
18
///
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.)
28
- ///
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.
19
+ /// ```rust
20
+ /// use std::marker::PhantomData;
21
+ /// use std::cell::Cell;
22
+ /// use std::ptr::NonNull;
32
23
///
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>`.
24
+ /// struct MyCell<T> {
25
+ /// ptr: NonNull<T>,
26
+ /// _invariant: PhantomData<Cell<T>>,
27
+ /// }
28
+ /// ```
36
29
///
37
- /// Notice that `NonNull<T>` has a `From` instance for `&T`. However, this does
38
- /// not change the fact that mutating through a (pointer derived from a) shared
39
- /// reference is undefined behavior unless the mutation happens inside an
40
- /// [`UnsafeCell<T>`]. The same goes for creating a mutable reference from a shared
41
- /// reference. When using this `From` instance without an `UnsafeCell<T>`,
42
- /// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr`
43
- /// is never used for mutation.
30
+ /// In most cases, you should use `NonNull<T>` when you want a non-null pointer. If you are unsure, using a raw pointer (`*mut T`) is also fine.
44
31
///
45
32
/// # Representation
46
33
///
0 commit comments