Description
Currently, the only way for a library to run a destructor on a value is to let it fall out of scope while on the stack, that is, types wrapping raw pointers (like Vec
and Rc
) have to call ptr::read
and let the resulting value drop to destroy their contents. This moves values in memory, and thus makes it literally impossible to use Vec
or Rc
(or any other library defined container type) for types with destructors that depend on the location of the value in memory.
This could be avoid we had a destroy_directly(&mut T)
intrinsic that destroyed that memory location, and so what is currently written ptr::read(x)
(or drop(ptr::read(x))
) would be written destroy_directly(&mut *x)
and (for types with Drop
impls) effectively be just calling (&mut *x).drop()
.
e.g.
rust/src/libcollections/vec.rs
Line 1539 in 795f6ae
ptr::read
s for a similar purpose in this file, and in other low-level code).
As a real-world example, putting a series of std::comm::Handle
into a preallocated Vec
(to satisfy the requirement that they must not move in memory after calling .add
) will still break, because the destructors asserts that the memory address is the same as it was and thus Vec
moving things in memory upsets it. The value being location dependent is bad, but it seems very reasonable to just destroy things in place to allow it to mostly work (it's probably more efficient too, since I believe LLVM can't optimise away the memcpy
out of the Vec
in all situations).
(NB. one can currently work-around this by box
-ing everything, because the compiler-magic of the Box
type means its destructor destroys things in-place.)