Why can't I take a slice from an array?

#1

the code below won’t compile because of the part &buffer[..num_read] the compiler complains that it does not live long enough. Then how do I slice the array if it never lives long enough? From rust book what I understand 'static lifetimed things are never getting cleaned up so using 'static lifetime for the buffer is not an option I assume.

Also why it does not live long enough what for I just need it to live long enough to produce the string after that it can go to hell if the compiler pleases so

let mut buffer = [0; MAX_DATA_LEN];
let read = c.read(&mut buffer);
let num_read = if let Ok(n) = read { n } else { break };
if num_read == 0
{
    break;
}
let str_val = String::from_utf8_lossy(&buffer[..num_read]).trim_end();

EDIT1:
I have tried making a variable let tmp = &buffer[..num_read] and even let tmp = &buffer
it always fails but obviously they share the same lifetime as the buffer they are in the same scope i dont understand why it does not live long enoug

#2

You need a temporary binding to satisfy the borrow checker: playground

The error message even tells you how to solve this:

error[E0716]: temporary value dropped while borrowed
  --> src/main.rs:18:23
   |
18 |         let str_val = String::from_utf8_lossy(&buffer[..num_read]).trim_end();
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^           - temporary value is freed at the end of this statement
   |                       |
   |                       creates a temporary which is freed while still in use
19 |     
20 |         println!("{}", str_val);
   |                        ------- borrow used here, in later iteration of loop
   |
   = note: consider using a `let` binding to create a longer lived value

Lifetimes don’t do what you think they do. They just annotate code for the compiler’s understanding of programmer-intent; a lifetime will not extend the life of the annotated item. The lifetime annotations only provide relationships between references.

Here is a useful error reference page for things like this. Particularly, this provides some contextual information for the error, as well as the same “create a temporary binding” solution.

See also the answer to this stackoverflow question which describes why the lifetime of the temporary value cannot be extended; In this case, from_utf8_lossy() returns a Cow<'a, str>, and trim_end() returns a reference to … what exactly? In the working code, it’s a reference to the temp variable. In the one-liner, the temporary is dropped right after trim_end() returns. Which means you can’t actually do anything with the reference after the temporary is dropped. (E.g. I am not able to print the string value on the next line.)

If I comment out the use of the reference-to-nothing with the one-liner (comment out the println!) then the code compiles (thanks to NLL) but of course it really doesn’t do anything useful.

1 Like
#3

unfortunately thid does not work for me can this be a compiler bug where identical code refuses to compile for me ?
here is my entire function

fn handle_connection(c: UnixStream)
{
    let mut c = c;
    const MAX_DATA_LEN: usize = 1024; //max data size in bytes
    loop
    {
        let mut buffer = [0; MAX_DATA_LEN];
        let read = c.read(&mut buffer);
        let num_read = if let Ok(n) = read { n } else { break };
        if num_read == 0
        {
            break;
        }
        // let cmd: Result<Command, serde_json::Error> = serde_json::from_reader(c);
        let str_val = String::from_utf8_lossy(&buffer[..num_read]);
        let str_val = str_val.trim_end();
        let cmd = serde_json::from_str(str_val);

        let cmd: Command = if let Ok(cmd) = cmd { cmd } else { break };
        println!("{:?}", cmd);
    }
}

and the compiler error message is as follows

here buffer goes out of scope but theres no one trying to use it after that its simply the end everything else must be destroyed as well but they arent seems like @parasyte

#4

I think this is going to come down to your definition of the Command struct, which seems to have a 'static lifetime bound? It’s hard to say without seeing the full code, so this is just a guess.

1 Like
#5

Oh that makes total sense now thank you i think i should change &'static str to owned string in the command

1 Like
#6

It all comes to me now. Thank you so much. @parasyte

1 Like