My goal is to understand the difference between instances of structs themselves — a la rect1: Rectangle
— and "borrowed pointer" type instances — rect2: &Rectangle
. My understanding is that using a raw self
in into_area
will cause ownership to be transferred to "the struct," presumably away from main()
. It is this ownership transfer that I am trying to grok.
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn into_area(self) -> u32 {
self.width * self.height
}
}
fn main() {
let rect1: Rectangle = Rectangle {
width: 90,
height: 10,
};
let rect2: &Rectangle = &Rectangle {
width: 15,
height: 10,
};
let area1 = rect1.into_area();
println!("rect1 area1: {}", area1);
// E0382
let _temp1 = rect1;
// E0507
let area2 = rect2.into_area();
println!("rect2 area2: {}", area2);
// No error given by compiler.
let _temp2 = rect2;
}
When I call rect1.into_area()
, ownership is moved. An area is computed and returned to the caller, and the Rectangle
instance then gets freed. If I try to then make use of rect1
again in main()
, via _temp1
, then the compiler complains that ownership has moved. That much makes sense.
However, I suppose I do not understand who "owns" the borrowed pointer type of rect2
. I thought that main()
would own it, and that there would be similar behaviour as with rect1
, but that doesn't seem to be the case. Instead I get E0507 immediately upon calling rect2.into_area()
:
error[E0507]: cannot move out of `*rect2` which is behind a shared reference
--> src/main.rs:31:17
|
31 | let area2 = rect2.into_area();
| ^^^^^^-----------
| | |
| | `*rect2` moved due to this method call
| move occurs because `*rect2` has type `Rectangle`, which does not implement the `Copy` trait
|
note: `Rectangle::into_area` takes ownership of the receiver `self`, which moves `*rect2`
--> src/main.rs:7:18
|
7 | fn into_area(self) -> u32 {
| ^^^^
Why can't I transfer ownership of a shared reference in this case, like was done for rect1
? Presumably, there is only one "share" of the reference: the declaration of rect2
in main()
. Is it a matter of the compiler not being able to infer that? Am I simply "holding it wrong" by conjuring a silly usage of &
that isn't how it's usually done?
I've tried reading over section four of the Rust Book. I also investigated the particular error via rustc --explain E0507
, which has this to say:
To fix this error, you have three choices:
- Try to avoid moving the variable.
- Somehow reclaim the ownership.
- Implement the
Copy
trait on the type.
I suppose using raw self
in into_area
precludes the first option, leaving options two and three. Implementing the Copy
trait is simple enough, but what would "Somehow reclaim the ownership" look like in this scenario? I'm assuming that, once the area is computed and returned to the caller, that the instance is freed/destroyed, meaning it's not possible to "somehow reclaim the ownership."