4

I've implemented a simple linked list as a struct thusly

struct List {

    data : String,
    cons : Option<Box<List>>
}

I have another struct which has a member of this type, defined below

pub struct Context {

    head : Option<Box<List>>
}

In a function of this struct, run, I have this code

let mut temp_head = &mut self.head;
let mut full_msg = "".to_string();
while temp_head.is_some() {
       let temp_node = temp_head.unwrap();
       full_msg.push_str(temp_node.data.as_slice());
       temp_head = temp_node.cons;
}

To iterate through the linked list and assemble a string of their data. However, the line which sets the value of temp_node produces the following error: cannot move out of dereference of &mut-pointer, and the compiler also complains that the value I'm trying to put into temp_head at the end doesn't live past the block.

I've tried cloning temp_head on the first line or temp_node.cons on the last line to get versions with the lifespan that I want, but that just produces additional errors, and the real problem seems to be that I just don't understand why the first version doesn't work. Can someone explain what I'm doing wrong, and/or link me to the Rust docs which explain this?

Ben Pious
  • 4,765
  • 2
  • 22
  • 34

1 Answers1

4

You need to be very careful with references in your code, the problem is that first you indeed attempt to move the content of temp_head out of it's container, when using unwrap(). This content being moved would be destroyed at the end of the while block, leaving temp_head referring to deleted content.

You need to use references all the way, and for this pattern-matching is more appropriate than using unwrap() and is_some(), like this :

let mut temp_head = &self.head;
let mut full_msg = "".to_string();
while match temp_head {
    &Some(ref temp_node) => { // get a reference to the content of node
        full_msg.push_str(temp_node.data.as_slice()); // copy string content
        temp_head = &temp_node.cons; // update reference
        true // continue looping
    },
    &None => false // we reached the end, stop looping
} { /* body of while, nothing to do */ }
Levans
  • 14,196
  • 3
  • 49
  • 53