Почему эта жизнь не может пережить закрытие? - PullRequest
0 голосов
/ 11 сентября 2018

Я гоняюсь ошибка компилятора и нашел следующий пример

trait Lt<'a> {
    type T;
}

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

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

fn main() {
    test();
}

Я ожидаю, что вышеприведенное скомпилируется, поскольку я дал подсказку, что Lt<'_> будет Lt<'static>, поэтому все должно быть в порядке, но я получаю следующую ошибку:

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 ()

Какова логика «во-первых, время жизни не может пережить анонимное время жизни №2»? Поскольку я смотрю на вариант ошибки, если причина не является твердой, мы можем попытаться ее исправить.

Рабочая вариация

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

1 Ответ

0 голосов
/ 11 сентября 2018

Фрагменты кода, приведенные ниже, являются иллюстрацией вашего случая, они помогли мне понять проблему с ошибкой компиляции при использовании в вашем коде объявления времени жизни 'static.

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() {}
...