Lifetime elision with only the return type elided

I am surprised that the following code compiles, because the return type of new has the lifetime elided (while the input variable are explicit).

struct Lexer;

struct LexerIter<'a> {
    lexer: &'a Lexer,
}

impl<'a> LexerIter<'a> {
    pub fn new(lexer: &'a Lexer) -> LexerIter {
        LexerIter {
            lexer: lexer,
        }
    }
}

fn main() { }

I don’t see why this should compile. The naive equivalent (adding lifetime parameters) would have me go pub fn new<'b>(lexer: &'a Lexer) -> LexerIter<'b>, which is a type error. Am I missing something, or what is this strange case?

This is a bit subtle, but, fn new(_: &Lexer) is not “elision” or at least not the same kind as that found in the return type.

Instead, missing lifetimes in argument types get substituted with anonymous (late-bound) lifetime parameters, so these are all equivalent:

fn foo(_: &i32) -> R {...}
fn foo<'a>(_: &'a i32) -> R {...}
fn foo<'b>(_: &'b i32) -> R {...}

The return type lifetime elision, however, looks for more or less (self is a bit special) one lifetime in the argument types, and uses that lifetime in all locations where a lifetime is missing. That is, R above can have any number of lifetime parameters and they all get the same lifetime from the reference to i32.

Thanks for elaborating! I had completely missed that it could be only partway explicit in where a parameter is used. It allows us to write Rust that is extra confusing:

fn pos<'x>(&'x self) -> &usize;

I wouldn’t say that’s particularly confusing. Since the lifetime needs to be bound to an input (unless explicitly 'static) there’s really only one lifetime it could be here.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.