Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why writing through a pointer to a moved variable has not been decided as UB in Rust?

Tags:

I am investigating possible reasons that prevent the Rust compiler from optimizing certain code pieces. I found this comment in an issue in rust-lang that alerts me.

We must not optimize away storage of locals that are mutably borrowed, because as @matthewjasper notes in #61430, it isn't decided that the following is UB:

let mut x = String::new();
let p = &mut x as *mut String;
let y = x;
p.write(String::new());

I thought that the lifetime of x ends when it is moved to y. p is dangling while being .write() through. But why this is not decided as UB?

like image 318
Zhiyao Avatar asked May 13 '21 06:05

Zhiyao


1 Answers

In the same thread, a bit further, there is this other comment by cramertj that I think explains a bit this issue. The code exemplified in this other comment is:

let mut x = String::new();
let addr_x: *const String = reference_to_pointer(&x);
drop(x);
ptr::write(addr_x as *mut String, String::new());

The basic idea of this snippet is to be able to drop a local value to run its destructor and reuse its memory allocation to store a new value. This is a pattern that some think it may be useful, but others think it should be UB.

Remember that drop() is not a special function in any way, it just moves the x into its own scope that finishes immediately, so it is more or less equivalent to your original code. You could even use forget() or push the value into a container and the example still holds.

Note that this idiom is actually valid if you use allocated dynamic memory (it is what Vec does under the hood). The issue here is whether it is also valid for stack allocated automatic memory.

like image 166
rodrigo Avatar answered Oct 21 '22 02:10

rodrigo