Hello! I encountered this behavior of the Rust compiler (see code), which seems to be a bit inconsistent (but perhaps is intended):
The compiler accepts access to field of self.y if it's done in a simple case like assignment to variable aa , but returns a move error message for the case of bb . (cannot move out of self.y which is behind a shared reference).
While it makes sense that return from an if triggers a move generally, the two assignments are semantically equivalent, and if-statement could be potentially optimized away.
My question is, is the latter case caused by how move rules are defined for Rust, or is it really some sort of inconsistency?
Thank you
struct SomeStruct2 {
z : i32,
}
struct SomeStruct {
y : SomeStruct2,
}
impl SomeStruct {
fn some_method(&self) {
let aa : i32 = (self.y).z; // <--- this is accepted by the compiler
let bb : i32 = (if true {
self.y
}
else {
SomeStruct2 {z : 42}
}).z; // <--- this is rejected by the compiler
}
}
I doubt the compiler optimizes things like this away before checking the program for correctness. Optimizations usually happen much later, mostly in LLVM backend.
More importantly, it would be horrible if something only compiled due to an optimization, since a change to the optimizer could result in a compiler error later on.
It's not the same. The if expression has it's own block. If you introduce a block in the first example it doesn't work either. I think you kind of tried to do so by using parentheses around (self.y).z but these don't have any meaning. The code is the same without them. If you want to introduce a block you need to use curly braces {}.
struct SomeStruct2 {
z : i32,
}
struct SomeStruct {
y : SomeStruct2,
}
impl SomeStruct {
fn some_method(&self) {
let aa : i32 = {self.y}.z; // <--- now this is rejected
let bb : i32 = if true {
self.y.z
}
else {
42
}; // <--- now this works
}
}
As to why a "return value" of a block needs to be a move, I am not a 100% sure. But I guess it would be super complicated if the compiler needed to track if a value ever actualy got used or was just used to refer to something else within the value. As to why it works without the block, that's just the place expression that @SkiFire13 mentioned.