Cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements

As a rust beginner I'm struggling with lifetimes.

I've simplified my problem to this snippet of code (also in the rust playground here: Rust Playground)

pub struct Token<'a>
{
    pub string_data: &'a String,
}

impl<'a> Token<'a>
{
    pub fn string_token(s: &String) -> Token<'a>
    {
        Token { string_data: s }
    }
}

fn main()
{
    let s = "data".to_string();
    let t = Token::string_token(&s);
}

But I am getting errors that:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a due to conflicting requirements
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 10:4...
note: but, the lifetime must be valid for the lifetime 'a as defined on the body at 10:4...

I don't really understand the error as both parts point at the same line of code?

2 Likes

You have to add the lifetime to the argument as well:

impl<'a> Token<'a>
{
    pub fn string_token(s: &'a String) -> Token<'a>
    {
        Token { string_data: s }
    }
}

that connects the lifetime of the reference passed in as argument to the returned type.

The error might point to the same line because the creation of the return type and the expression generating the reference are on the same line, but I'm not sure about that.

4 Likes

Or you can make use of lifetime elision feature by defining less lifetimes. This would also work, as Rust will automatically figure out correct lifetimes (in that specific case). Generally it's a good idea to not specify lifetimes in functions, unless actually needed.

pub fn string_token(s: &String) -> Token {
    ...
}

Your provided function says that it takes a reference to String with any lifetime, and returns Token with 'a lifetime (specified by function user). However, that any lifetime doesn't need to be anyhow compatible with 'a, which is why Rust complains.

(also, you probably should accept &str instead of &String, as it's easier to obtain &str, and &str does practically the same thing as &String)

2 Likes

As @phaylon mentioned, you need to specify the same lifetime for the argument. Keep in mind that your string_token function's signature is really fn string_token<'__elided>(s: &'__elided String) -> Token<'a>. As you can see, the two lifetimes (the elided one and 'a) are completely unrelated, as far as the signature is concerned.

Also, you may want to consider taking a &str rather than an immutable String reference. This would, for example, allow caller to hand you a &'static str (or more generally, a string slice they already have available), whereas with the current scheme they'd need to allocate a String.

3 Likes

Thanks, adding the lifetime to the variable worked.

I originally left out the lifetime from the function and it worked in the simplified version, but when I try to use it from my full program I need to specify it otherwise I get errors from the calling point.