PhantomData<T>inside Vec<T>(contained indirectly through Unique<T>inside RawVec<T>) tells the compiler that the vector can have instances T, and therefore the vector can trigger destructors for Twhen the vector is discarded.
Deep immersion: there are several factors:
We have one Vec<T>that has impl Drop(i.e. a destructor implementation).
RFC 1238 Vec<T> , T, , T .
Vec<T> ( Vec<T>) (. RFC 1238 RFC 1327). , . ; , , (, , ), .
: , , , . T , T . , , , .
, : , S, , S impl Drop for S ( , S ). S , dropck. ( , , S #[may_dangle].)
Vec<T>, ( RawVec<T>/Unique<T>) T, *const T. *const T; S S T , , S T ( , dropck).
, Vec<T> a *const T, T, , #[may_dangle] T , ( , T ).
: Vec<T> *const T. PhantomData<T>, ", (- #[may_dangle] T), Vec T, drop, , - T T ."
: Vec<T>, T , ( , , , , ). T ( , - ), , , , , ( , T - ).
, , , #[may_dangle] PhantomData.
, , :
extern crate alloc;
use alloc::heap;
use std::fmt;
use std::marker::PhantomData;
use std::mem;
use std::ptr;
enum State { INVALID, Valid }
struct PrintOnDrop<T: fmt::Debug>(&'static str, T, State);
impl<T: fmt::Debug> PrintOnDrop<T> {
fn new(name: &'static str, t: T) -> Self {
PrintOnDrop(name, t, State::Valid)
}
}
impl<T: fmt::Debug> Drop for PrintOnDrop<T> {
fn drop(&mut self) {
println!("drop PrintOnDrop({}, {:?}, {:?})",
self.0,
self.1,
self.2);
self.2 = State::INVALID;
}
}
struct MyBox1<T> {
v: Box<T>,
}
impl<T> MyBox1<T> {
fn new(t: T) -> Self {
MyBox1 { v: Box::new(t) }
}
}
struct MyBox2<T> {
v: *const T,
}
impl<T> MyBox2<T> {
fn new(t: T) -> Self {
unsafe {
let p = heap::allocate(mem::size_of::<T>(), mem::align_of::<T>());
let p = p as *mut T;
ptr::write(p, t);
MyBox2 { v: p }
}
}
}
unsafe impl<
fn drop(&mut self) {
unsafe {
ptr::read(self.v);
heap::deallocate(self.v as *mut u8,
mem::size_of::<T>(),
mem::align_of::<T>());
}
}
}
struct MyBox3<T> {
v: *const T,
_pd: PhantomData<T>,
}
impl<T> MyBox3<T> {
fn new(t: T) -> Self {
unsafe {
let p = heap::allocate(mem::size_of::<T>(), mem::align_of::<T>());
let p = p as *mut T;
ptr::write(p, t);
MyBox3 { v: p, _pd: Default::default() }
}
}
}
unsafe impl<
fn drop(&mut self) {
unsafe {
ptr::read(self.v);
heap::deallocate(self.v as *mut u8,
mem::size_of::<T>(),
mem::align_of::<T>());
}
}
}
fn f1() {
let v1; let _mb1;
v1 = PrintOnDrop::new("v1", 13);
_mb1 = MyBox1::new(PrintOnDrop::new("mb1", &v1));
}
fn f2() {
{
let (v2a, _mb2a);
v2a = PrintOnDrop::new("v2a", 13);
_mb2a = MyBox2::new(PrintOnDrop::new("mb2a", &v2a));
}
{
let (_mb2b, v2b);
v2b = PrintOnDrop::new("v2b", 13);
_mb2b = MyBox2::new(PrintOnDrop::new("mb2b", &v2b));
}
}
fn f3() {
let v3; let _mb3;
v3 = PrintOnDrop::new("v3", 13);
_mb3 = MyBox3::new(PrintOnDrop::new("mb3", &v3));
}
fn main() {
f1(); f2(); f3();
}