How to return an array belonging to me from a function?

I'm new to Rust trying to understand a language while playing with it. I hit some problems when trying to return an array from a function:

struct Widget { thingies: ~[int] } impl Widget { fn new() -> Widget { Widget { thingies: ~[4, 8, 15, 16, 23, 42] } } fn somethings(&self) -> ~[int] { self.thingies } } fn main() { let widget = Widget::new(); let wotsits = widget.somethings(); } 

This, of course, does not allow compilation with this error:

 pointers.rs:11:8: 11:21 error: cannot move out of dereference of & pointer pointers.rs:11 self.thingies 

If this code example does not look like it, all I am trying to do is to deduce the array from the implemented structure. The borrowed pointer is not important, this is exactly how I am trying to save the data.

Any tips on how to properly extract your array?

Btw, I am using Rust 0.8

+7
arrays rust
source share
3 answers

The reason your code does not compile is because the unique pointer ~ can only have one owner. The compiler is stopping you from writing error-prone code. You can either decide to return a copy of objects, links to objects, or a piece of objects (this is a link to vector data or its segment).

Copy solution

 struct Widget { thingies: ~[int] } impl Widget { fn new() -> Widget { Widget { thingies: ~[4, 8, 15, 16, 23, 42] } } fn somethings(&self) -> ~[int] { self.thingies.clone() } } 

Reference Solution

 struct Widget { thingies: ~[int] } impl Widget { fn new() -> Widget { Widget { thingies: ~[4, 8, 15, 16, 23, 42] } } fn somethings<'a>(&'a self) -> &'a~[int] { &self.thingies } } 

Slice Solution

 struct Widget { thingies: ~[int] } impl Widget { fn new() -> Widget { Widget { thingies: ~[4, 8, 15, 16, 23, 42] } } fn somethings<'a>(&'a self) -> &'a[int] { self.thingies.as_slice() } } 

In order to understand the solutions of links and slices, you need to understand what 'a means: it indicates the lifetime, and &'a is a way to tell the compiler that the link should never survive the object that it refers to, which in this case is a widget.

These solutions also have some limitations: you cannot change the object that you are currently referencing, because it makes reference reversal impossible.

You can, of course, change thingies if you return a volatile link. Changed link over time will be recorded &'a mut T

 struct Widget { thingies: ~[int] } impl Widget { fn new() -> Widget { Widget { thingies: ~[4, 8, 15, 16, 23, 42] } } fn somethings<'a>(&'a mut self) -> &'a mut ~[int] { &mut self.thingies } } 

Note I believe that in Rust 0.8 you need to write &'self instead of &'a , because lifetimes with user names have not yet been supported. I also wrote this in 0.9.

Edit: Removed redundant life expectancy ads.

+8
source share

=== EDIT ===

in Rust 1 stable, ~[T] became Vec<T> , but (aside syntax) the same problem applies, since Vec still has a unique owner. In short, somethings only has a link to self and (via the link), it cannot become the owner of thingies . The link to the playing field for Rust 1 is here: https://play.rust-lang.org/?gist=50ec1acdc684e53fd5f9&version=stable .

The Rust ownership model is quite important for the language, so for more information I would suggest looking at the large official documentation on ownership and borrowing

=== END EDIT ===

In Rust,. after self , auto-dereferences self , so this is the dereference of & pointer that the error mentions.

Now the thingies owner is that you cannot move out of dereference:

  let widget = Widget::new(); // widget owns the unique pointer to self let wotsits = widget.somethings(); // if this worked, ownership of // unique pointer to thingies would be // moved to wotsits 

Instead, you could take a link to things:

 fn somethings<'a>(&'a self) -> &'a~[int] { &self.thingies } 

or explicitly return a copy of thingies

 fn somethings(&self) -> ~[int] { self.thingies.clone() } 
+4
source share

You cannot exit the borrowed index, as explained in other answers. But you can pass self by value or by the pointer that is in the property, then you can return your own vector:

 struct Widget { thingies: ~[int] } impl Widget { fn somethings(self) -> ~[int] { self.thingies } } 
+2
source share

All Articles