1

I am trying to run the following code. It was straightforward to understand that the lifetime of the returned value of inner() was not compatible with the 'static lifetime, but how can I make this work without changing the main() function?

struct Wrapper<'a>(&'a str);

impl<'a> Wrapper<'a> {
    fn inner(&self) -> &str {
        self.0
    }
}

pub fn main() {
    let x = "hello";
    let wrapper = Wrapper(&x);
    let _: &'static str = wrapper.inner();
}
error[E0597]: `wrapper` does not live long enough
  --> src/main.rs:12:27
   |
12 |     let _: &'static str = wrapper.inner();
   |                           ^^^^^^^ borrowed value does not live long enough
13 | }
   | - borrowed value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

I came across this as a example from a course I am following but I am kind of stuck with understanding how to make this work.

1 Answer 1

3

All you have to do is change the signature of inner so that the return type matches the type of the Wrapper's field:

impl<'a> Wrapper<'a> {
    fn inner(&self) -> &'a str {
        //              ^^ 'a added here
        self.0
    }
}

When you initialize the variable wrapper with Wrapper(&x), the compiler infers that its type is Wrapper<'static>, because x has the 'static lifetime (all literal strings have the 'static lifetime). Thus, when you call inner on a Wrapper<'static>, the return type is &'static str.

If we don't add 'a to the signature, then the lifetime of the returned value is the lifetime of the Wrapper itself. This is more apparent if we write out the lifetimes in full:

impl<'a> Wrapper<'a> {
    fn inner<'b>(&'b self) -> &'b str {
        self.0
    }
}

Your Wrapper doesn't have the 'static lifetime because it lives in a local variable; its life will end when the function returns — main isn't special when it comes to lifetimes. Therefore, the returned string slice doesn't have the 'static lifetime either.

Now, maybe you're wondering, "If the original string has the 'static lifetime, why is it valid to return it with a different lifetime?". It's important to understand that lifetimes don't have to be exact; they can be shortened if necessary. The goal of lifetimes is to ensure you don't use a reference after its referent has been dropped; if you claim that a value has a lifetime shorter than it's actually is, it's totally safe, it just (perhaps unnecessarily) restricts how long the reference can be used.

1
  • Thanks Francis, this makes things more clear for me.
    – pradeep
    Commented Feb 17, 2018 at 6:03

Not the answer you're looking for? Browse other questions tagged or ask your own question.