1
votes

I am chasing a compiler bug and found the following example

trait Lt<'a> {
    type T;
}

impl<'a> Lt<'a> for () {
    type T = &'a ();
}

fn test() {
    let _: fn(<() as Lt<'_>>::T) = |_: &'static ()| {};
}

fn main() {
    test();
}

I expect the above to compile as I gave a hint for Lt<'_> to be Lt<'static> and so everything should be fine, but I get the following error:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src/main.rs:10:53
   |
10 |     let _: fn(<() as Lt<'_>>::T) = |_: &'static ()| {};
   |                                                     ^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 10:36...
  --> src/main.rs:10:36
   |
10 |     let _: fn(<() as Lt<'_>>::T) = |_: &'static ()| {};
   |                                    ^^^^^^^^^^^^^^^^^^^
   = note: ...so that the types are compatible:
           expected Lt<'_>
              found Lt<'_>
   = note: but, the lifetime must be valid for the static lifetime...
   = note: ...so that the types are compatible:
           expected &()
              found &'static ()

What is the logic behind "first, the lifetime cannot outlive the anonymous lifetime #2"? As I am looking at a variation of a bug, if the reason is not solid we can attempt to fix it.

Working variation

fn test() {
    let _: fn(<() as Lt<'static>>::T) = |_: &'_ ()| {};
}
1

1 Answers

1
votes

The code fragments below are a semplification of your case, it helped me to understand the issue about the compilation error when using the 'static lifetime declaration in your code.

struct Foo {
}

fn _test_ok() {

    // myf is declared as a function pointer that accepts
    // a reference with some generic lifetime  
    let myf: fn(&'_ Foo);

    // with this definition ...
    myf = |_arg: &'_ Foo| {};

    // this local value works as expected
    let local_foo: Foo = Foo {};

    myf(&local_foo);
}

fn _test_static_fail() {

    let myf: fn(&'_ Foo);

    // suppose this myf() definition ...
    myf = |_arg: &'static Foo| {};

    // this local value is compatible with myf() declaration ...
    let local_foo: Foo = Foo {};

    // so theoretically it is usable here: 
    myf(&local_foo);

    // but this is clearly not possible because the anomymous lifetime region where 
    // local_foo lives does not outlive the 'static lifetime required
    // when defining myf()   
}


static FOO: Foo = Foo {};

fn _test_static_flipped() {

    // As you have already discovered
    let myf: fn(&'static Foo) = |arg: &'_ Foo| {};

    // this works because ...
    // 1. FOO is a static value and it is compatible with myf() definition and
    // 2. 'static lifetime outlives every other lifetime  
    myf(&FOO);
}

fn main() {}