@ -15,13 +15,10 @@ pub struct Vec<T> {
}
}
```
```
And indeed this would compile. Unfortunately, it would be incorrect. First, t he
And indeed this would compile. Unfortunately, it would be too strict. T he
compiler will give us too strict variance. So a `&Vec<&'static str>`
compiler will give us too strict variance. So a `&Vec<&'static str>`
couldn't be used where an `&Vec<&'a str>` was expected. More importantly, it
couldn't be used where an `&Vec<&'a str>` was expected. See [the chapter
will give incorrect ownership information to the drop checker, as it will
on ownership and lifetimes][ownership] for all the details on variance.
conservatively assume we don't own any values of type `T` . See [the chapter
on ownership and lifetimes][ownership] for all the details on variance and
drop check.
As we saw in the ownership chapter, the standard library uses `Unique<T>` in place of
As we saw in the ownership chapter, the standard library uses `Unique<T>` in place of
`*mut T` when it has a raw pointer to an allocation that it owns. Unique is unstable,
`*mut T` when it has a raw pointer to an allocation that it owns. Unique is unstable,
@ -30,16 +27,16 @@ so we'd like to not use it if possible, though.
As a recap, Unique is a wrapper around a raw pointer that declares that:
As a recap, Unique is a wrapper around a raw pointer that declares that:
* We are covariant over `T`
* We are covariant over `T`
* We may own a value of type `T` (for drop check)
* We may own a value of type `T` (this is not relevant for our example here, but see
[the chapter on PhantomData][phantom-data] on why the real `std::vec::Vec<T>` needs this)
* We are Send/Sync if `T` is Send/Sync
* We are Send/Sync if `T` is Send/Sync
* Our pointer is never null (so `Option<Vec<T>>` is null-pointer-optimized)
* Our pointer is never null (so `Option<Vec<T>>` is null-pointer-optimized)
We can implement all of the above requirements in stable Rust. To do this, instead
We can implement all of the above requirements in stable Rust. To do this, instead
of using `Unique<T>` we will use [`NonNull< T > `][NonNull], another wrapper around a
of using `Unique<T>` we will use [`NonNull< T > `][NonNull], another wrapper around a
raw pointer, which gives us two of the above properties, namely it is covariant
raw pointer, which gives us two of the above properties, namely it is covariant
over `T` and is declared to never be null. By adding a `PhantomData<T>` (for drop
over `T` and is declared to never be null. By implementing Send/Sync if `T` is,
check) and implementing Send/Sync if `T` is, we get the same results as using
we get the same results as using `Unique<T>` :
`Unique<T>` :
```rust
```rust
use std::ptr::NonNull;
use std::ptr::NonNull;
@ -49,7 +46,6 @@ pub struct Vec<T> {
ptr: NonNull< T > ,
ptr: NonNull< T > ,
cap: usize,
cap: usize,
len: usize,
len: usize,
_marker: PhantomData< T > ,
}
}
unsafe impl< T: Send > Send for Vec< T > {}
unsafe impl< T: Send > Send for Vec< T > {}
@ -58,4 +54,5 @@ unsafe impl<T: Sync> Sync for Vec<T> {}
```
```
[ownership]: ../ownership.html
[ownership]: ../ownership.html
[phantom-data]: ../phantom-data.md
[NonNull]: ../../std/ptr/struct.NonNull.html
[NonNull]: ../../std/ptr/struct.NonNull.html