Open
Description
I tried this code (minimized from a real usage):
fn demo<'a, 'b, 'c, T>(x: &'b T, y: Wrap<'c, L2<'a, 'b>>) {
callback(y, |y| {
// Doesn't work
take_both(x, Wrap::new(y.into_inner()));
// Works
//take_both(x, Wrap::new(y.0));
});
}
trait Bad<T> {}
struct L2<'a, 'b>(&'a (), &'b ());
struct Wrap<'want, T>(&'want mut dyn Bad<T>);
impl<'want, T> Wrap<'want, T> {
fn new(_x: &'want mut dyn Bad<T>) -> Self {
loop {}
}
fn into_inner(self) -> &'want mut dyn Bad<T> {
self.0
}
}
fn callback<'a, 'b, 'c>(
_x: Wrap<'c, L2<'a, 'b>>,
_f: impl for<'w> FnOnce(Wrap<'w, L2<'a, 'b>>),
) {
}
fn take_both<'a, 'b, 'c, T>(_x: &'c T, _y: Wrap<'a, L2<'b, 'c>>) {}
I expected for both the into_inner
function and the field access to behave the same.
Instead, the into_inner
function causes a lifetime error that doesn't make any sense.
error: lifetime may not live long enough
--> src/main.rs:4:5
|
3 | fn demo<'a, 'b, 'c, T>(x: &'b T, y: Wrap<'c, L2<'a, 'b>>) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
4 | / callback(y, |y| {
5 | | // Doesn't work
6 | | take_both(x, Wrap::new(y.into_inner()));
... |
10 | | });
| |______^ argument requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of the type `Wrap<'_, L2<'_, '_>>`, which makes the generic argument `'_` invariant
= note: the struct `Wrap<'r, T>` is invariant over the parameter `'r`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
This did work pre 1.37.0. In 1.37.0 it appears as a warning and 1.40.0 made it a hard error.
Meta
rustc --version --verbose
:
rustc 1.87.0 (17067e9ac 2025-05-09)
binary: rustc
commit-hash: 17067e9ac6d7ecb70e50f92c1944e545188d2359
commit-date: 2025-05-09
host: x86_64-unknown-linux-gnu
release: 1.87.0
LLVM version: 20.1.1