Skip to content

Inferred struct lifetime bounds result in rejection of valid lifetimes #91942

Open
@davidhalter

Description

@davidhalter

I have skimmed about 100+ "similar" issues here and could find one that matches this issue, so apologies if this was already reported. The issue that seems most similar is this one: #87241.

I have tried to reduce this lifetime issue as much as possible to the essentials, but it's unfortunately still a bit of code:

fn main() {
}

struct Impl<'db> {
    some_trait: &'db dyn Trait<'db>,
}

impl<'db> Trait<'db> for Impl<'db> {
    fn foo(&self, s: &mut State<'db, '_>) {
        Car::new(s).debug(s, &mut |s| {
            self.some_trait.foo(s);
        });
    }
}

trait Trait<'db> {
    fn foo(&self, s: &mut State<'db, '_>);
}

struct State<'db, 'a> {
    car: &'a Car<'db>,
}

struct Car<'db> {
    foo: &'db u128,
}

impl<'db> Car<'db> {
    fn new(s: &mut State<'db, '_>) -> Self {
        todo!()
    }

    fn debug(
        &self,
        s: &mut State<'db, '_>,
        callable: &mut impl Fn(&mut State<'db, '_>),
    ) {
        todo!()
    }
}

I expected this to pass the borrow checker (cannot infer an appropriate lifetime...; see below). The problem could be that 'db: 'a is inferred for struct State, because if you rewrite that struct into this piece of code:

struct State<'db, 'a> {
    car: &'db Car<'db>,
    bar: &'a Car<'a>,
}

the borrow checker is happy. However the borrow checker is also happy if I'm using some_trait: &'db Impl<'db>, so it feels like this is really an issue and not me misunderstanding lifetimes. I have tried various approaches like using HRTBs and a lot of complicated where: with explicit lifetimes, but nothing helped.

I run a lot of similar code that passes, but this one doesn't, because the closure is using self.some_trait and not something given by the closure (in which case everything would work great!).

So again, sorry for the "long" code piece, but I have tried to reduce it for hours and couldn't really get further. I hope I do not waste your time with this.


The actual long-form error:

$ RUST_BACKTRACE=1 ca
rgo build
   Compiling zuban_python v0.1.0 (/home/dave/source/rust/issues/lifetimev4/zuban_python)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> zuban_python/src/lib.rs:11:29
   |
11 |             self.some_trait.foo(s);
   |                             ^^^
   |
note: first, the lifetime cannot outlive the lifetime `'db` as defined on the impl at 8:6...
  --> zuban_python/src/lib.rs:8:6
   |
8  | impl<'db> Trait<'db> for Impl<'db> {
   |      ^^^
note: ...so that the declared lifetime parameter bounds are satisfied
  --> zuban_python/src/lib.rs:11:29
   |
11 |             self.some_trait.foo(s);
   |                             ^^^
note: but, the lifetime must be valid for the anonymous lifetime #2 defined on the body at 10:35...
  --> zuban_python/src/lib.rs:10:35
   |
10 |           Car::new(s).debug(s, &mut |s| {
   |  ___________________________________^
11 | |             self.some_trait.foo(s);
12 | |         });
   | |_________^
note: ...so that the expression is assignable
  --> zuban_python/src/lib.rs:11:33
   |
11 |             self.some_trait.foo(s);
   |                                 ^
   = note: expected `&mut State<'db, '_>`
              found `&mut State<'_, '_>`

For more information about this error, try `rustc --explain E0495`.
error: could not compile `zuban_python` due to previous error

Meta

rustc --version --verbose:

rustc 1.56.0 (09c42c458 2021-10-18)
binary: rustc
commit-hash: 09c42c45858d5f3aedfa670698275303a3d19afa
commit-date: 2021-10-18
host: x86_64-unknown-linux-gnu
release: 1.56.0
LLVM version: 13.0.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lifetimesArea: Lifetimes / regionsA-varianceArea: Variance (https://doc.rust-lang.org/nomicon/subtyping.html)C-bugCategory: This is a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions