pull/10/head
Alexis Beingessner 10 years ago committed by Manish Goregaokar
parent d1e5cf6da5
commit ff08e31903

@ -474,16 +474,9 @@ struct Foo<'a, 'b, A, B, C, D, E, F, G, H> {
## Dropck
TODO
## PhantomData
However when working with unsafe code, we can often end up in a situation where
When working with unsafe code, we can often end up in a situation where
types or lifetimes are logically associated with a struct, but not actually
part of a field. This most commonly occurs with lifetimes. For instance, the `Iter`
for `&'a [T]` is (approximately) defined as follows:
@ -498,7 +491,8 @@ pub struct Iter<'a, T: 'a> {
However because `'a` is unused within the struct's body, it's *unbound*.
Because of the troubles this has historically caused, unbound lifetimes and
types are *illegal* in struct definitions. Therefore we must somehow refer
to these types in the body.
to these types in the body. Correctly doing this is necessary to have
correct variance and drop checking.
We do this using *PhantomData*, which is a special marker type. PhantomData
consumes no space, but simulates a field of the given type for the purpose of
@ -516,8 +510,50 @@ pub struct Iter<'a, T: 'a> {
}
```
However PhantomData is also necessary to signal important information to
*dropck*. (TODO)
## Dropck
When a type is going out of scope, Rust will try to Drop it. Drop executes
arbitrary code, and in fact allows us to "smuggle" arbitrary code execution
into many places. As such additional soundness checks (dropck) are necessary to
ensure that a type T can be safely instantiated and dropped. It turns out that we
*really* don't need to care about dropck in practice, as it often "just works".
However the one exception is with PhantomData. Given a struct like Vec:
```
struct Vec<T> {
data: *const T, // *const for covariance!
len: usize,
cap: usize,
}
```
dropck will generously determine that Vec<T> does not contain any values of
type T. This will unfortunately allow people to construct unsound Drop
implementations that access data that has already been dropped. In order to
tell dropck that we *do* own values of type T and may call destructors of that
type, we must add extra PhantomData:
```
struct Vec<T> {
data: *const T, // *const for covariance!
len: usize,
cap: usize,
_marker: marker::PhantomData<T>,
}
```
Raw pointers that own an allocation is such a pervasive pattern that the
standard library made a utility for itself called `Unique<T>` which:
* wraps a `*const T`,
* includes a PhantomData<T>,
* auto-derives Send/Sync as if T was contained
* marks the pointer as NonZero for the null-pointer optimization

Loading…
Cancel
Save