Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference to parameters within an enum

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.

like image 396
Liam Avatar asked Sep 28 '26 14:09

Liam


2 Answers

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;.

like image 115
WiSaGaN Avatar answered Sep 30 '26 13:09

WiSaGaN


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,
        }
    }
}
like image 20
malbarbo Avatar answered Sep 30 '26 15:09

malbarbo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!