@ -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>`
couldn't be used where an `&Vec<&'a str>` was expected. More importantly, it
will give incorrect ownership information to the drop checker, as it will
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.
couldn't be used where an `&Vec<&'a str>` was expected. See [the chapter
on ownership and lifetimes][ownership] for all the details on variance.
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,
@ -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:
* 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
* 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
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
over `T` and is declared to never be null. By adding a `PhantomData<T>` (for drop
check) and implementing Send/Sync if `T` is, we get the same results as using
`Unique<T>` :
over `T` and is declared to never be null. By implementing Send/Sync if `T` is,
we get the same results as using `Unique<T>` :
```rust
use std::ptr::NonNull;
@ -49,7 +46,6 @@ pub struct Vec<T> {
ptr: NonNull< T > ,
cap: usize,
len: usize,
_marker: PhantomData< T > ,
}
unsafe impl< T: Send > Send for Vec< T > {}
@ -58,4 +54,5 @@ unsafe impl<T: Sync> Sync for Vec<T> {}
```
[ownership]: ../ownership.html
[phantom-data]: ../phantom-data.md
[NonNull]: ../../std/ptr/struct.NonNull.html