fn pointer coercion fails for method on type with lifetime

27b27d9
Opened by Henrique M. D. at 2023-03-16 10:24:29

The following code does not infer the type of the method correctly:

/*
<anon>:12:31: 12:45 error: mismatched types:
 expected `fn(MyStruct<'_>)`,
    found `fn(MyStruct<'_>) {MyStruct<'a>::func}`
(expected concrete lifetime,
    found bound lifetime parameter ) [E0308]
<anon>:12     let fails: fn(MyStruct) = MyStruct::func; // ERROR: mismatched types
                                        ^~~~~~~~~~~~~~
<anon>:12:31: 12:45 help: see the detailed explanation for E0308
*/
struct MyStruct<'a> {
    y: &'a u32,
}

impl<'a> MyStruct<'a> {
    pub fn func(self) {}
}

fn wrapper<'a>(x: MyStruct<'a>) { x.func() }

fn main() {
    let fails: fn(MyStruct) = MyStruct::func; // ERROR: mismatched types
    let works: fn(MyStruct) = wrapper;
}

As one can see in the error message (found fn(MyStruct<'_>) {MyStruct<'a>::func}), it seems that the compiler is getting confused when inferring the type of the expression.

If the lifetime from MyStruct is removed, the code compiles fine.

PS: Thanks to huon for simplifying the example demonstrating the issue

  1. The issue is early vs. late-bound lifetimes.

    Ariel Ben-Yehuda at 2016-03-02 20:45:11

  2. Triage: no change

    Steve Klabnik at 2019-12-25 17:03:34

  3. Current error output:

    error[[E0308]](https://doc.rust-lang.org/stable/error_codes/E0308.html): mismatched types
      --> src/main.rs:12:31
       |
    12 |     let fails: fn(MyStruct) = MyStruct::func; // ERROR: mismatched types
       |                               ^^^^^^^^^^^^^^ one type is more general than the other
       |
       = note: expected fn pointer `for<'a> fn(MyStruct<'a>)`
                     found fn item `fn(MyStruct<'_>) {MyStruct::<'_>::func}`
    

    Dylan DPC at 2023-03-16 10:24:29