]> git.proxmox.com Git - rustc.git/blame - src/doc/nomicon/src/phantom-data.md
New upstream version 1.55.0+dfsg1
[rustc.git] / src / doc / nomicon / src / phantom-data.md
CommitLineData
8bb4bdeb 1# PhantomData
c1a9b12d
SL
2
3When working with unsafe code, we can often end up in a situation where
4types or lifetimes are logically associated with a struct, but not actually
5part of a field. This most commonly occurs with lifetimes. For instance, the
6`Iter` for `&'a [T]` is (approximately) defined as follows:
7
48663c56 8```rust,compile_fail
c1a9b12d
SL
9struct Iter<'a, T: 'a> {
10 ptr: *const T,
11 end: *const T,
12}
13```
14
15However because `'a` is unused within the struct's body, it's *unbounded*.
136023e0
XL
16[Because of the troubles this has historically caused][unused-param],
17unbounded lifetimes and types are *forbidden* in struct definitions.
18Therefore we must somehow refer to these types in the body.
19Correctly doing this is necessary to have correct variance and drop checking.
20
21[unused-param]: https://rust-lang.github.io/rfcs/0738-variance.html#the-corner-case-unused-parameters-and-parameters-that-are-only-used-unsafely
c1a9b12d
SL
22
23We do this using `PhantomData`, which is a special marker type. `PhantomData`
24consumes no space, but simulates a field of the given type for the purpose of
25static analysis. This was deemed to be less error-prone than explicitly telling
26the type-system the kind of variance that you want, while also providing other
48663c56 27useful things such as the information needed by drop check.
c1a9b12d
SL
28
29Iter logically contains a bunch of `&'a T`s, so this is exactly what we tell
136023e0 30the `PhantomData` to simulate:
c1a9b12d 31
450edc1f 32```rust
c1a9b12d
SL
33use std::marker;
34
35struct Iter<'a, T: 'a> {
36 ptr: *const T,
37 end: *const T,
38 _marker: marker::PhantomData<&'a T>,
39}
40```
41
42and that's it. The lifetime will be bounded, and your iterator will be variant
43over `'a` and `T`. Everything Just Works.
44
45Another important example is Vec, which is (approximately) defined as follows:
46
450edc1f 47```rust
c1a9b12d
SL
48struct Vec<T> {
49 data: *const T, // *const for variance!
50 len: usize,
51 cap: usize,
52}
53```
54
5bcae85e
SL
55Unlike the previous example, it *appears* that everything is exactly as we
56want. Every generic argument to Vec shows up in at least one field.
c1a9b12d
SL
57Good to go!
58
59Nope.
60
5bcae85e 61The drop checker will generously determine that `Vec<T>` does not own any values
c1a9b12d
SL
62of type T. This will in turn make it conclude that it doesn't need to worry
63about Vec dropping any T's in its destructor for determining drop check
64soundness. This will in turn allow people to create unsoundness using
65Vec's destructor.
66
67In order to tell dropck that we *do* own values of type T, and therefore may
136023e0 68drop some T's when *we* drop, we must add an extra `PhantomData` saying exactly
c1a9b12d
SL
69that:
70
450edc1f 71```rust
c1a9b12d
SL
72use std::marker;
73
74struct Vec<T> {
0531ce1d 75 data: *const T, // *const for variance!
c1a9b12d
SL
76 len: usize,
77 cap: usize,
78 _marker: marker::PhantomData<T>,
79}
80```
81
82Raw pointers that own an allocation is such a pervasive pattern that the
83standard library made a utility for itself called `Unique<T>` which:
84
85* wraps a `*const T` for variance
5bcae85e 86* includes a `PhantomData<T>`
8bb4bdeb
XL
87* auto-derives `Send`/`Sync` as if T was contained
88* marks the pointer as `NonZero` for the null-pointer optimization
89
90## Table of `PhantomData` patterns
91
92Here’s a table of all the wonderful ways `PhantomData` could be used:
93
94| Phantom type | `'a` | `T` |
95|-----------------------------|-----------|---------------------------|
29967ef6
XL
96| `PhantomData<T>` | - | covariant (with drop check) |
97| `PhantomData<&'a T>` | covariant | covariant |
98| `PhantomData<&'a mut T>` | covariant | invariant |
99| `PhantomData<*const T>` | - | covariant |
8bb4bdeb 100| `PhantomData<*mut T>` | - | invariant |
dfeec247 101| `PhantomData<fn(T)>` | - | contravariant |
29967ef6 102| `PhantomData<fn() -> T>` | - | covariant |
8bb4bdeb
XL
103| `PhantomData<fn(T) -> T>` | - | invariant |
104| `PhantomData<Cell<&'a ()>>` | invariant | - |