2

I'm new to Rust and toying a bit with it. It's my first program, and it seems I've already encountered the dreaded borrow checker. :)

pub struct Foo<T> {
    memory:  Vec<T>
}

impl<T> Foo<T> { {
    pub fn set(&mut self, value: T) {
        self.memory.push(value);
    }

    pub fn get(&self, index: usize) -> Option<&T> {
        Some(&self.memory[index])
    }
}

It compiles just fine but I want to return value not reference from get function.

If I do

pub fn get(&self, index: usize) -> Option<T> {
    Some(*&self.memory[index])
}

Which fails with:

error: cannot move out of borrowed content [E0507] Some(*&self.memory[index])

I just have no idea why the borrow checker behaves this way.

How can I return the value? Can anyone enlighten me?

Rem: It's not duplicate question. I don't ask someone explain what "indexed content" means but how to return value with no cannot move out of borrowed content error.

LeMoussel
  • 5,290
  • 12
  • 69
  • 122

1 Answers1

3

You need to clone the object you want to return in order for that to be possible. This also means T needs to be Cloneable. Consider the following code:

pub struct Foo<T: Clone> {
    memory: Vec<T>
}

impl<T> Foo<T> where T:Clone {
    pub fn set(&mut self, value: T) {
        self.memory.push(value);
    }

    pub fn get(&self, index: usize) -> Option<T> {
        Some(self.memory[index].clone())
    }
}

If this concerned an object that could be returned in full (unlike an element of a vector), you could create a method that moves the object, like so:

pub struct Foo<T> {
    memory: T
}

impl<T> Foo<T> {
    pub fn get(self) -> Option<T> {
        Some(self.memory)
    }
}

Note that this time the argument is not &self, but just self, so the ownership will be moved.

You can also consider implementing Copy for T. In this case it will be passed to functions as value instead of reference like a primitive type, e.g. i32:

pub struct Foo<T: Copy> {
    memory: Vec<T>
}

impl<T> Foo<T> where T:Copy {
    pub fn set(&mut self, value: T) {
        self.memory.push(value);
    }

    pub fn get(&self, index: usize) -> Option<T> {
        Some(self.memory[index].clone())
    }
}

I would not recomment this, however, for memory-heavy objects or those whose ownership should for any reason be preserved/secured.

ljedrz
  • 20,316
  • 4
  • 69
  • 97