Description
(this is related to #30018, but it is also a distinct problem in its own right.)
We appear to be creating copies of values that should be moved when doing slice literal construction.
The copies can be observed because double-drop (of the same abstract value) can occur when there is a break of control out of the slice literal during evaluation of one of the elements.
Here is an example (playpen):
struct D(&'static str);
impl Drop for D {
fn drop(&mut self) {
println!("Dropping D({})", self.0);
}
}
fn main() {
println!("Start");
loop {
let _r = &[D("1"),
D("2"),
{ let _tmp = D("3"); break; },
D("4")];
}
println!("Finis");
}
outputs (in release mode):
Start
Dropping D(3)
Dropping D(2)
Dropping D(1)
Dropping D(1)
Dropping D(2)
Finis
The crucial point is that we see double drops of D(1)
and D(2)
in the output above. This would correspond, at least in theory, to deallocating a backing buffer multiple times -- that is, it is wrong. (Types like Vec
probably defend themselves against such an attack since they currently use unsafe_no_drop_flag
and thus should have an embedded drop flag state that it is maintaining itself, but other types that implement Drop
do not necessary take that tack.)
(In debug mode there is a sigtrap at the end of that example; that is due to #30018, but again, that is not this ticket.)