Reputation: 547
I have a structure which contains a Vector of structs, e.g.
fn main() {
let x: Vec<Item> = Vec::new();
// assume x is filled with stuff
do_things_with(x);
}
struct Item {
value: String,
}
struct Context {
x: Vec<Item>,
}
impl Context {
fn get(&mut self, at: usize) -> Item {
self.x[at]
}
}
fn do_things_with(x: Vec<Item>) {
let mut ctx = Context{
x: x,
};
ctx.get(5);
}
I have a Vec of stuff, and I pass this to some function which creates a context and stores the passed value in that structure. I then want to look at the items in this Vec so I have some helper functions, e.g. 'get' which will get the item at the index specified.
This seems all good, and in C or whatever language it would be fine, however Rust complains:
'cannot move out of borrowed content'
For the function 'get' where we try to access the item in the vector.
What am I doing wrong here?
Upvotes: 1
Views: 493
Reputation: 6017
The problem here is that the Vec
has ownership of the Item
s it contains, but Context.get
is trying to return the Item
directly (and take ownership of it).
If Context.get
just needs to let callers peek at the contents of the vector, it should return a reference to an Item instead of an Item:
impl Context {
fn get(&mut self, at: usize) -> &Item {
&self.x[at]
}
}
In the above case, Context.get
can take an immutable reference to self
since it is not changing anything. Further, if you want to allow callers of Context.get
to modify the referenced Item, you would return &mut Item
instead of &Item
:
impl Context {
fn get(&mut self, at: usize) -> &mut Item {
&mut self.x[at]
}
}
Edit: As @apemanzilla helpfully notes in the comments, you could also have Item implement the Clone
trait if you want Context.get to return a separate copy of the Item at at
:
#[derive(Clone)]
struct Item {
value: String,
}
impl Context {
fn get(&mut self, at: usize) -> Item {
self.x[at].clone()
}
Changing the returned Item will not modify the one contained in self.x though; this may or may not be what you intended.
Upvotes: 2