I've created the following Rust struct:
struct HTTPRequestHeader {
name: ~str,
data: ~str,
next: Option<~HTTPRequestHeader>
}
And the following code to print it:
fn print_headers(hdr: &HTTPRequestHeader) {
println(fmt!("%s: %s", (*hdr).name, (*hdr).data));
match (*hdr).next {
Some(next_hdr) => { print_headers(next_hdr); }
None => { }
}
}
Trying to compile this code, I get the following error:
> rustc http_parse.rs
http_parse.rs:37:7: 37:18 error: moving out of immutable field
http_parse.rs:37 match (*hdr).next {
^~~~~~~~~~~
error: aborting due to previous error
What does this mean? The line which contains (*hdr).name, (*hdr).data)
compiles without errors. The match
statement should not be attempting to mutate hdr.next
in any way, so I don't see how immutability comes into it. I attempted to write a modified version which doesn't take pointers:
fn print_headers(hdr: HTTPRequestHeader) {
println(fmt!("%s: %s", hdr.name, hdr.data));
match hdr.next {
Some(next_hdr) => { print_headers(*next_hdr); }
None => { }
}
}
This one gave me:
> rustc http_parse.rs
http_parse.rs:37:7: 37:15 error: moving out of immutable field
http_parse.rs:37 match hdr.next {
^~~~~~~~
http_parse.rs:38:36: 38:45 error: moving out of dereference of immutable ~ pointer
http_parse.rs:38 Some(next_hdr) => { print_headers(*next_hdr); }
^~~~~~~~~
error: aborting due to 2 previous errors
Please help me understand what's going on here! :)
While the error does tell you where you're trying to move the value from it doesn't indicate where you're trying to move it to which might help make it a bit clearer why it doesn't work.
The problem is that you have a unique pointer (Option<~HTTPRequestHeader>
) which means you either need to take a reference to it or make a copy. Since they can only have a single owner they are moved by default. Which is what is happening in the Some(next_hdr)
branch of your match.
So what you probably want is something like this:
fn print_headers(hdr: &HTTPRequestHeader) {
println(fmt!("%s: %s", hdr.name, hdr.data));
match hdr.next {
Some(ref next_hdr) => print_headers(*next_hdr),
None => {}
}
}
Also, a side note: if you want to access a field of some struct through a pointer you don't need to explicitly dereference it (i.e. just hdr.name
works as well as (*hdr).name
).