The code below gives the error "cannot move out of borrowed content". I know that there are already a lot of questions on here about this. I think that everyone using Rust finds themselves here at one point, trying to figure out exactly what is going on with ownership. I think I know what's going on here and how to fix it, I just don't know how to use a reference in this particular case. If there is a more idiomatic way to accomplish what I am trying, please let me know in the comments.
I can see where I'm trying to take ownership, but I'm unsure how to use a reference instead.
Let's look at a somewhat minimal example:
/* I define two shape structs. The main point here is that they
are not default copyable, unlike most primitive types */
struct Circle {
center_x: f64,
center_y: f64,
r: f64,
}
struct Square {
center_x: f64,
center_y: f64,
length: f64,
}
/* this enum will be a container for shapes because we don't know
which shape we might need. */
enum Shape {
// these are scoped differently, so it's okay.
Circle(Circle),
Square(Square),
}
/* I'm making cookies, each cookie has a shape */
struct Cookie {
shape: Shape,
}
/* All of the above was setup, here is where we find errors */
impl Cookie {
/* checks if two cookies have the same radius. squares -> false */
fn has_same_radius(&self, other_cookie: &Cookie) -> bool {
// fn has_same_radius(self, other_cookie: Cookie) -> bool {
/* swapping the above two lines will remedy the error,
but I don't want this function to take ownership of either */
match self.shape {
/* As soon as I declare c1, I'm taking ownership of self.shape
and therefore self as well. This is in spite of the fact
that I never plan to alter anything.
How can I simply use a reference to c1> */
Shape::Circle(c1) => match other_cookie.shape {
/* same thing here with c2 */
Shape::Circle(c2) => {
if c2.r == c1.r {
return true;
}
}
Shape::Square(_) => return false,
},
Shape::Square(_) => return false,
}
return false;
}
}
When I match on the Shape enum, I only want to reference the parameter encapsulated in Shape, but since I am not using a reference, I am trying to take ownership of the entire Cookie struct.
Change
....
Shape::Circle(c1) => ...
....
Shape::Circle(c2) => ...
....
to
....
Shape::Circle(ref c1) => ...
....
Shape::Circle(ref c2) => ...
....
Playground
let ref x = y; is basically the pattern matching version of let x = &y;.
As pointed by WiSaGan, you must use ref pattern to create a reference to the contained value. You can also simplify the code matching against the two shapes simultaneously:
impl Cookie {
fn has_same_radius(&self, other: &Cookie) -> bool {
match (&self.shape, &other.shape) {
(&Shape::Circle(ref c1), &Shape::Circle(ref c2)) => c1.r == c2.r,
_ => false,
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With