eyelash
eyelash

Reputation: 3720

mismatched types between method and lifetime-generic parameter

I expect the following Rust code to work

struct Expression<'a> {
    s: &'a str,
}

impl<'a> Expression<'a> {
    fn foo(e: Expression<'a>, _: Expression<'a>) -> Expression<'a> {
        e
    }
}

fn accept(_: for<'a> fn(Expression<'a>, Expression<'a>) -> Expression<'a>) {
    
}

fn main() {
    accept(Expression::foo)
}

but I get an error message:

error[E0308]: mismatched types
  --> src/main.rs:16:12
   |
16 |     accept(Expression::foo)
   |            ^^^^^^^^^^^^^^^ one type is more general than the other
   |
   = note: expected fn pointer `for<'a> fn(Expression<'a>, Expression<'a>) -> Expression<'a>`
              found fn pointer `fn(Expression<'_>, Expression<'_>) -> Expression<'_>`

For more information about this error, try `rustc --explain E0308`.

The error can be fixed by introducing another lifetime 'b

impl<'a> Expression<'a> {
    fn foo<'b>(e: Expression<'b>, _: Expression<'b>) -> Expression<'b> {
        e
    }
}

Can someone explain to me why this is necessary? Isn't 'a already generic?

Upvotes: 0

Views: 63

Answers (1)

Chayim Friedman
Chayim Friedman

Reputation: 70980

Another instance of the late-bound vs. early-bound lifetimes.

A similar problem is in Using HRTBs to automate getter method unit tests. The problem is that while it foo is generic over 'a, it is not late-bound but early-bound, meaning that it is fixed when we specify the name of the function and we cannot create a generic function pointer (for<'a>) from it.

Upvotes: 1

Related Questions