[Solved] Ownership issue?


#1

Hello all,

First time Rust user here.

I have a strange question regarding ownership. The following code below results in a error. The issue is that the compiler for some reason seems to think the tripple send_response are actually a moves when in fact they do not move. Chancing the code to a single send_response removes the error, but its not the solution.

Or is my understanding of the ownership/borrowing wrong? In my head this code needs to be valid because the ownership only moves when one of the condition is met.

fn handle_client(stream: TcpStream) -> Result<()>
{
let mut reader = BufReader::new(stream);

Do some work here ( reading out the reader info) …

if action == "GET"
    {
        if url == "/hello"
            {
                send_response(reader.into_inner(), "HTTP/1.1 200 OK\n\n<html><body>Hello!</body></html>");
            }
        if url == "/world"
            {
                send_response(reader.into_inner(), "HTTP/1.1 200 OK\n\n<html><body>Hello, World!</body></html>");
            }
        if url == "/"
            {
                send_response(reader.into_inner(), "HTTP/1.0 400 Bad Request\nContent-Type: text/html; charset=utf-8\n\n");
            }
    }

–> src\main.rs:61:35
|
56 | send_response(reader.into_inner(), “HTTP/1.1 200 OK\n\nHello!”);
| ------ value moved here

61 | send_response(reader.into_inner(), “HTTP/1.1 200 OK\n\nHello, World!”);
| ^^^^^^ value used here after move
|
= note: move occurs because reader has type std::io::BufReader<std::net::TcpStream>, which does not implement the Copy trait

It makes no sense that the compiler hints about using a copy when there is no reason for a copy to happen.

Slowly starting to get my head around the memory management / ownership but this one stumped me.


#2

It’s telling you that reader.into_inner() consumed the reader by value, and since it couldn’t copy that value, it had to move it. Once moved, it’s no longer available to be used elsewhere.

The compiler isn’t smart enough to see that your three if url == "/..." tests are independent, but I think if you change the latter two to else if, it should work just fine. This way, the three blocks where reader might be moved are in independent parts of the control flow graph.


#3

Indeed. Just tested this and “if else” works. Good to know that the compiler can only see that logic. I assume that a switch will also work for the compiler.

Thanks :slight_smile: