Explicit Drop Locations
This step makes explicit where drops may happen, using the ensure_dropped!
macro.
We add ensure_dropped! statements in two locations: at end of scopes and before variable
assignments.
#![allow(unused)] fn main() { scope_end!($local); // becomes: ensure_dropped!($local); scope_end!($local); }
#![allow(unused)] fn main() { $place = $expr; // becomes: ensure_dropped!($place); $place = $expr; }
One tricky case is assignment through a mutable reference:
#![allow(unused)] fn main() { let a: &mut String = ...; *a = String::new(); // this drops the previous string // becomes: ensure_dropped!(*a); // this drops the previous string *a = String::new(); // borrowck knows there's no previous string to drop }
This is not allowed in today's Rust, but is legal for us thanks to the Moving Out Of
&mut feature.
After this step, all assignments are to statically uninitialized places (hence won't cause implicit
drops), and scope_end never needs to drop anything.