0

I'm trying to understand why Rust makes a type have 'static lifetime.

Please take a look at this code:

let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 128]);

VSCode tells me that the type of tcp_tx_buffer is

smoltcp::storage::RingBuffer<'static, u8>

but if we find the new method on RingBuffer:

pub fn new<S>(storage: S) -> RingBuffer<'a, T>
    where S: Into<ManagedSlice<'a, T>>,
{
    RingBuffer {
        storage: storage.into(),
        read_at: 0,
        length:  0,
    }
}

there's no 'static lifetime on the return. In fact the lifetime is the same as the input, 'a. If let tcp_tx_buffer were outside main, I'd guess it's static, but it has its own scope. Or does Rust consider main to have a 'static lifetime?

Teymour
  • 1,832
  • 1
  • 13
  • 34
Guerlando OCs
  • 1,886
  • 9
  • 61
  • 150
  • 1
    Because the lifetime is irrelevant, ManagedSlice is basically a Cow, the lifetime is there in case the value is a borrow (an actual slice). Since you're giving it an owned value there is no lifetime for which the object would be invalid, so it can get the "widest" possible lifetime, which is `'static`. – Masklinn May 11 '20 at 07:54
  • It's hard to answer your question because it doesn't include a [MRE]. We can't tell what crates (and their versions), types, traits, fields, etc. are present in the code. It would make it easier for us to help you if you try to reproduce your error on the [Rust Playground](https://play.rust-lang.org) if possible, otherwise in a brand new Cargo project, then [edit] your question to include the additional info. There are [Rust-specific MRE tips](//stackoverflow.com/tags/rust/info) you can use to reduce your original code for posting here. Thanks! – Shepmaster May 12 '20 at 20:32

1 Answers1

3

The signature on new says that it returns a RingBuffer which carries a specific lifetime; it is defined to be the same lifetime as the one carried by whatever the storage-parameter returns as part of ManagedSlice when Into<ManagedSlice> is called on it. That is, the storage-parameter gets to decide the lifetime carried by the RingBuffer-value.

You are passing an owned Vec into TcpSocketBuffer::new(). An owned Vec which does not contain reference-types is itself 'static. TcpSocketBuffer can (due to its implementation) Into<ManagedSlice>, where ManagedSlice carries the lifetime original Vec's lifetime 'static. This is where 'static comes from.

It may be helpful when thinking about 'static that this lifetime does not mean that the value has to live forever. It just means that the value can be made to live forever. This is true for all values which do not contain references that themselves have a lifetime shorter than 'static. For example, a String::new()is 'static because it can be made to live as long as we want (simply by not dropping it). A Foo<'a> { bar: &'a str } can only be made to live for as long as 'a, because Foo contains a reference which may be shorter than 'static.

From the moment of creation, your owned Vec can be made to live for as long as we want and this property is carried through to RingBuffer.

user2722968
  • 13,636
  • 2
  • 46
  • 67