Skip to content

Inconsistent lifetime checks between function and field access. #141481

Open
@konnorandrews

Description

@konnorandrews

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions