1

I have the following code:

pub enum Direction {
    Up, Right, Down, Left, None
}

struct Point {
    y: i32,
    x: i32
}

pub struct Chain {
    segments: Vec<Point>,
    direction: Direction
}

and later I implement the following function:

fn turn (&mut self, dir: Direction) -> i32 {
    use std::num::SignedInt;

    if dir == self.direction { return 0; }
    else if SignedInt::abs(dir as i32 - self.direction as i32) == 2 { return -1; }
    else {
        self.direction = dir;
        return 1;
    }
}

I get the error:

error: cannot move out of borrowed content
foo.rs:45       else if SignedInt::abs(dir as i32 - self.direction as i32) == 2 { return 1; }
                                                        ^~~~
foo.rs:47:21: 47:24 error: use of moved value: `dir`
foo.rs:47           self.direction = dir;
                                         ^~~
foo.rs:45:26: 45:29 note: `dir` moved here because it has type `foo::Direction`, which is non-copyable
foo.rs:45       else if SignedInt::abs(dir as i32 - self.direction as i32) == 2 { return 1; }

I've read about Rust ownership and borrowing, but I still don't really understand them, therefore I cannot fix this code. Could someone give me a working variant of what I pasted?

c_spk
  • 169
  • 16
  • Please create an [MCVE](http://stackoverflow.com/help/mcve). This both helps you understand the problem better and lets other people comprehend the problem faster, making the all-around result better. – Shepmaster Feb 15 '15 at 15:40
  • 2
    Not related to the issue, but to your code: that function seems to assume that a difference of 2 between `self` direction and the given (perhaps new) direction always mean the same thing (1 or maybe a U-turn?), but my impression is that "`Down - None`" is not the same as "`Up - Down`", or is it? – didierc Feb 15 '15 at 15:44
  • @didierc: Yes, difference of two between these two directions indicate that they are opposite. The None value is used only on creation of a Chain object and can be deleted, I guess. – c_spk Feb 15 '15 at 15:48
  • 2
    Adding to @didierc's comment, you probably don't want to do math on enums, that's a very C-like paradigm. Also, you might want to not include `None` as part of your enum and just use `Option` instead. It also looks like you are trying to return a boolean from `turn`, so you should probably just do that. – Shepmaster Feb 15 '15 at 15:49
  • @Shepmaster: I made a mistake: the else-if branch should return -1. And yes, I'm learning Rust by porting a C program almost line-to-line. – c_spk Feb 15 '15 at 15:53
  • 2
    Gotcha. Once done porting, you may want to look into returning your own enum type to indicate the success, but I'd also suggest checking out `Result`, which is most commonly used for error-handling stuff. – Shepmaster Feb 15 '15 at 15:55
  • @Shepmaster: Yeah, I thought about a special return type too. Thanks. – c_spk Feb 15 '15 at 15:57

1 Answers1

3

As the error message says:

dir moved here because it has type foo::Direction, which is non-copyable

No type is copyable by default, the author has to opt into the marker trait Copy. You almost certainly want Direction to be copyable, so add #[derive(Copy)] to the definition. Point can probably be Copy as well.