Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move an owned pointer

Tags:

rust

For reference, I'm using Rust 0.7.

I'm trying to create a stack implementation using an owned linked list and I'm running into trouble.

trait Stack<T> {
    fn push(&mut self, item : T);
    fn pop(&mut self) -> Option<T>;
}

enum Chain<T> {
    Link(T, ~Chain<T>),
    Break
}

impl<T> Stack<T> for ~Chain<T> {
    fn push(&mut self, item : T) {
        *self = ~Link(item, *self);
    }
    fn pop(&mut self) -> Option<T> {
        None
    }
}

When I try to rustc stack.rs I get the following error:

stack.rs:13:28: 13:34 error: cannot move out of dereference of & pointer
stack.rs:13         *self = ~Link(item, *self);
                                        ^~~~~~

I don't know how I could overcome this or what I could do differently to allow this. It seems like I should be able to create this data structure without using managed pointers, but I haven't seen a lot of documentation on this sort of thing.

like image 418
Kyle Sletten Avatar asked Jul 08 '13 20:07

Kyle Sletten


1 Answers

Either assignment from self (which I think includes constructing a new thing out of it, as in the case of Link(item, *self) implies a move. This means that in the process of constructing the new Link that self becomes unusable, because:

"After a value has been moved, it can no longer be used from the source location and will not be destroyed there."

The Right Way™ is probably best documented by what's done in this example in the stdlib. It's a doubly linked list, and it is managed, but it's mutable, and I hope copy free. There's also list of useful container types, too.

I did manage to get this immutable version of your datastructure working, however.

trait Stack<T> {
    fn push(self, item : T) -> Self;
    fn pop(self)            -> Option<(T, Self)>;
    fn new()                -> Self;
}

#[deriving(Eq, ToStr)]
enum Chain<T> {
    Link(T, ~Chain<T>),
    Break
}

impl<T> Stack<T> for Chain<T> {
    fn push(self, item : T) -> Chain<T> {
        Link(item, ~self)
    }
    fn pop(self)            -> Option<(T, Chain<T>)> {
        match self {
            Link(item, ~new_self) => Some((item, new_self)),
            Break                 => None
        }
    }
    fn new()                -> Chain<T> {
        Break
    }
}

fn main() {
    let b : ~Chain<int> = ~Stack::new();
    println(b.push(1).push(2).push(3).to_str());
}
like image 87
heartpunk Avatar answered Oct 21 '22 23:10

heartpunk