I am having trouble understanding why the following code compiles.
struct Wrapper<'a, T> {
inner: &'a mut T
}
fn get<'a, T>(w: &'a mut Wrapper<'a, T>) -> &'a mut T {
w.inner
}
According to the language reference, field expressions (like w.inner
) are place expressions, and using a place expression in a value expression context (like the return value of a function) should move the value. Since mutable references don't implement Copy
, this would result in a compiler error about moving out of w
. Indeed, we can get such an error if we modify get
slightly:
fn get<'a, T>(w: &'a mut Wrapper<'a, T>) -> &'a mut T {
let x = w.inner;
x
}
error[E0507]: cannot move out of `w.inner` which is behind a mutable reference
--> src/lib.rs:6:13
|
6 | let x = w.inner;
| ^^^^^^^
| |
| move occurs because `w.inner` has type `&mut T`, which does not implement the `Copy` trait
| help: consider borrowing here: `&w.inner`
However, when we return w.inner
directly, the language apparently implicitly reborrows it for us. Furthermore, the example above will also compile if we give x
an explicit type annotation as &mut T
. I know that function returns and annotated let statements are coercion sites whereas unannotated let statements are not, so I assume this is due to some kind of coercion? But I don't see how coercion can result in an implicit borrow like this.
(To be clear, I'm aware that there's nothing conceptually wrong with this code. If we just explicitly borrow w.inner
before returning it then it all makes perfect sense to me. I'm just confused about what aspect of the language semantics allows us to omit that explicit borrow.)