1

Trying to refactor and cleanup our code we ran into a lifetime compile error. Compiling the following code:

fn create_ping_packet<'a>(sequence_number: u16) -> echo_request::MutableEchoRequestPacket<'a> {
    let mut packet_contents = [0; 48];
    let mut ping_packet = echo_request::MutableEchoRequestPacket::new(&mut packet_contents[20..]).unwrap();
    ping_packet.set_icmp_type(IcmpTypes::EchoRequest);
    ping_packet.set_icmp_code(echo_request::IcmpCodes::NoCode);
    ping_packet.set_identifier(902);
    ping_packet.set_sequence_number(sequence_number);
    ping_packet.set_payload(b"Ring ring");
    ping_packet
}

fn main() {
    // ...
    let mut sequence_number = 0;
    loop {
        let packet = create_ping_packet(sequence_number);
        // ...
    }
}

Gives us :

error: `packet_contents` does not live long enough
  --> src/main.rs:15:76
   |
15 |     let mut ping_packet =     echo_request::MutableEchoRequestPacket::new(&mut     packet_contents[20..]).unwrap();
   |                                                                                ^^^^^^^^^^^^^^^ does not live long enough
...
22 | }
   | - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on     the body at 13:94...
  --> src/main.rs:13:95
   |
13 |   fn create_ping_packet<'a>(sequence_number: u16) ->     echo_request::MutableEchoRequestPacket<'a> {
   |      __________________________________________________________________________    _____________________^
14 | |     let mut packet_contents = [0; 48];
15 | |     let mut ping_packet =         echo_request::MutableEchoRequestPacket::new(&mut             packet_contents[20..]).unwrap();
16 | |     ping_packet.set_icmp_type(IcmpTypes::EchoRequest);
...  |
21 | |     ping_packet
22 | | }
   | |_^

We understand the problem is that packet_contents is allocated on the stack and goes out of scope at the end of the function. Is there a way to allocate packet_contents inside and give it a lifetime of 'a?

Lukas Kalbertodt
  • 79,749
  • 26
  • 255
  • 305
SlavGradev
  • 11
  • 1
  • 1
    I'm pretty sure this question is a duplicate, but I can't find a good dupe-question right now. In short, the answer to your question is: No, you can't just do it. Lifetime-annotations are not magic and they can't actually change lifetimes. The actual lifetimes are completely determined by your function body (and thus one lifetime is too short). [The book](https://doc.rust-lang.org/book/first-edition/lifetimes.html) says: "lifetime annotations are *descriptive*, not *prescriptive*". I don't know your application, but the solution is to think of another API/function signature. – Lukas Kalbertodt Jul 16 '17 at 12:08
  • It is a slight variation of https://stackoverflow.com/q/44643430/2731452 – red75prime Jul 16 '17 at 14:17
  • *another API/function signature* — specifically, you can accept the result of `&mut packet_contents[20..]` or you can embed the array inside of `MutableEchoRequestPacket`. – Shepmaster Jul 17 '17 at 01:31

0 Answers0