About ownership



Why doesn’t the compiler issue an error at Line 15 while I am trying to assign it’s field with a new value ? It did throw a message at Line 16 saying p was moved at Line 14 already.



This section in the documentation is describing what is happening https://doc.rust-lang.org/book/second-edition/ch04-01-what-is-ownership.html#ownership-and-functions

Also a small hint. You can post code here without using screenshots by writing the code within these blocks

Code goes here



In this section, The Book also states that :

If we tried to use s after the call to takes_ownership, Rust would throw a compile time error.

I wander that why the compiler complains at Line 16 , not Line 15. Both use the moved variable p. I reassign p’s field x at Line 15 and the compiler doesn’t give a warning or an error. For the user’s perspective, Line 15 is useless if so. My question is: what does the compiler do when it comes to Line 15 ?


The line 15 is a partial initialization. (Failing to find a doc link.) It isn’t used very often.


I think you can use the following mental model: moving is essentially memcpy-ing the struct to the called function stack. (usually it’s optimized out, but initially it’s there) Memory region of old p is still there on stack, but is marked as “moved”, which makes it unreadable, but it does not forbid you from writing into that memory. Same story applies to this example:

let mut p: Point;
// works
p.x = 5;
// compilation error
println!("{}", p.x)

The only difference is that memory region of p marked not as “moved”, but as “uninitialized”. Although I agree that your example is strange and ideally Rust should produce error for line 15 as well. (of course if I am not missing some obscure cases where such behaviour will be useful)


I have no idea what the use cases are; but IIRC if you assign all of the fields in this manner, Rust will consider the object to be fully initialized.

Just watch out for the terrifying soundness hole. (surprise, a feature that almost nobody uses has bugs!)


Nope, it does not work like this unfortunately. It could be a nice (but arguably rarely needed) feature if Rust could’ve tracked partial initialization and detect if type became fully initialized.


This is issue #21232.