Description
The following code (based on #67911 (comment)):
fn g<'a, T: 'a>(t: &T) -> &'a i32 {
&0
}
fn f<'a, 'b, T: 'a + 'b>(x: T) -> (&'a i32, &'b i32) { // compare with returning (&'a i32, &'a i32)
let y = g(&x);
(y, y)
}
produces the following error message as of rustc 1.46.0-nightly (ff5b446d2 2020-06-23)
:
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:6:13
|
5 | fn f<'a, 'b, T: 'a + 'b>(x: T) -> (&'a i32, &'b i32) { // compare with returning (&'a i32, &'a i32)
| -- help: consider adding an explicit lifetime bound...: `T: 'static +`
6 | let y = g(&x);
| ^
|
note: ...so that the type `T` will meet its required lifetime bounds
--> src/lib.rs:6:13
|
6 | let y = g(&x);
| ^
with -Z borrowck=mir
:
error[E0309]: the parameter type `T` may not live long enough
--> contrived.rs:6:13
|
6 | let y = g(&x);
| ^^^^^
|
= help: consider adding an explicit lifetime bound `T: 'a`...
However, this should actually be able to compile. If we infer y
to the equivalent of &('a + 'b) i32
, then
(&('a + 'b) i32, &('a + 'b) i32) <: (&'a i32, &'b i32)
We have that T: 'a
and T: 'b
from the generic parameter T: 'a + 'b
, so we should be able to determine that T
lives long enough.
However, the current TypeTest
code (if I understand it correctly) attempts to prove that a type lives long enough by applying each of the lifetime bounds individually (e.g. splitting T: 'a + 'b
into T: 'a
and T: 'b
). However, neither T: 'a
nor T: 'a
alone is sufficient to prove that T: 'a + 'b
, so this check fails.
I suspect that this will never actually matter in practice, so the additional complexity needed to make this code compile might not be worth it. However, I didn't see an open issue for this, so I opened this issue for future reference.