我正在追逐a compiler bug并发现以下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();
}
我希望上面编译,因为我给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) = |_: &'_ ()| {};
}
下面的代码片段是对您的案例的简化,它帮助我理解了在代码中使用'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() {}