Stop mentioning dropck and `PhantomData<T>` in the vec chapter

The usage of `PhantomData<T>` in this chapter is wrong and useless.
It's only needed when you have an unstable `#[may_dangle` on `Drop`.
Since the `phantom-data` chapter talks about this extensively, link
to it for more info and stop using `PhantomData<T>` for dropck in the
vec chapter.
pull/381/head
Nilstrieb 3 years ago
parent 9c73283775
commit d7d11b01df
No known key found for this signature in database

@ -28,7 +28,6 @@ impl<T> Vec<T> {
ptr: NonNull::dangling(),
len: 0,
cap: 0,
_marker: PhantomData,
}
}
}

@ -10,7 +10,6 @@ use std::ptr::{self, NonNull};
struct RawVec<T> {
ptr: NonNull<T>,
cap: usize,
_marker: PhantomData<T>,
}
unsafe impl<T: Send> Send for RawVec<T> {}
@ -25,7 +24,6 @@ impl<T> RawVec<T> {
RawVec {
ptr: NonNull::dangling(),
cap: cap,
_marker: PhantomData,
}
}

@ -49,7 +49,6 @@ pub struct IntoIter<T> {
cap: usize,
start: *const T,
end: *const T,
_marker: PhantomData<T>,
}
```
@ -80,7 +79,6 @@ impl<T> IntoIterator for Vec<T> {
} else {
ptr.as_ptr().add(len)
},
_marker: PhantomData,
}
}
}

@ -15,13 +15,10 @@ pub struct Vec<T> {
}
```
And indeed this would compile. Unfortunately, it would be incorrect. First, the
And indeed this would compile. Unfortunately, it would be too strict. The
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

@ -13,7 +13,6 @@ allocating, growing, and freeing:
struct RawVec<T> {
ptr: NonNull<T>,
cap: usize,
_marker: PhantomData<T>,
}
unsafe impl<T: Send> Send for RawVec<T> {}
@ -25,7 +24,6 @@ impl<T> RawVec<T> {
RawVec {
ptr: NonNull::dangling(),
cap: 0,
_marker: PhantomData,
}
}

@ -33,14 +33,13 @@ method of `RawVec`.
```rust,ignore
impl<T> RawVec<T> {
fn new() -> Self {
// !0 is usize::MAX. This branch should be stripped at compile time.
let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
// This branch should be stripped at compile time.
let cap = if mem::size_of::<T>() == 0 { usize::MAX } else { 0 };
// `NonNull::dangling()` doubles as "unallocated" and "zero-sized allocation"
RawVec {
ptr: NonNull::dangling(),
cap: cap,
_marker: PhantomData,
}
}

Loading…
Cancel
Save