Drop Elaboration
We know where drops may happen, so we now only need to decide which drops to run at each relevant program point.
Dropping happens in-place by running the compiler-generated core::ptr::drop_in_place function on
the place to be dropped.
Instead of calling that function directly we use the
drop_in_place!() built-in macro so that the borrow-checker can
tell that the place has been deinitialized.
In this step we’ll replace every ensure_dropped!($place) with a series of
appropriate calls to drop_in_place!($subplace).
For any subplace of $place that hasn’t been explicitly moved out, we insert a call to
drop_in_place!.
This can require adding extra booleans (“drop flags”) if different branches haven’t moved the same
places:
#![allow(unused)]
fn main() {
let x = Struct {
a: String::new(),
b: String::new(),
};
if foo() {
drop(move!(x.a));
} else {
drop(move!(x.b));
}
ensure_dropped!(x.a);
x.a = "some other string".to_owned();
ensure_dropped!(x);
scope_end!(x);
// becomes:
let a_is_initialized = true;
let b_is_initialized = true;
if foo() {
drop(move!(x.a));
a_is_initialized = false;
} else {
drop(move!(x.b));
b_is_initialized = false;
}
if a_is_initialized {
drop_in_place!(x.a);
}
x.a = "some other string".to_owned();
if b_is_initialized {
drop_in_place!(x.b);
}
drop_in_place!(x.a);
scope_end!(x);
}
(unwind paths omitted for legibility)
After this step, all the code involved in dropping values is explicit.
Backlinks