How to simplify lifetime constraints?

I have the following simple MWE:

// A does not implement copy.
struct TempFile<'a> {
    i: &'a i64,
}

impl TempFile<'_> {
    fn persist_to(&mut self, i: i64) -> i64 { self.i + i } // Cannot change this signature.
}

// Understanding a closure.
// Here simulated with a type:
struct C<'a, 'b: 'a> {
    i: &'a mut TempFile<'b>,
}

impl C<'_, '_> {
    fn call(&mut self) { 
        self.i.persist_to(8);
    }
}

fn store<'a,'b: 'a>(a: &'a mut TempFile<'b>) {
    let mut c = C{i: a};
    c.call();
}

fn main() {
    let v = 3;
    let mut a = TempFile { i: &v };
    
    store(&mut a)
}

The question resolves around C as a local object (simulating something like a closure FnMut which captures a).

I needed to introduce <'a, 'b: 'a> to C and store.

  • Why cant I remove the contstraint: <'a, 'b> or <'a,'b> and let the compiler figure things out?
  • How can I simplify this code, is it possible to use some to me magical '_ placeholder?

Example: Rust Playground

No, this code is not correct.

struct C<'b, 'a: 'b> {
    i: &'a mut TempFile<'b>,
}

this struct will be almost entirely unusable, the same goes for the store function.

&'a mut TempFile<'b>

with 'a: 'b (“'a outlives 'b”) also has an implicit 'b: 'a bound, and together restricts 'a and 'b to be the same lifetime.

&'a mut TempFile<'a>

such types are a clear anti-pattern and almost always unwanted. They come up commonly when one doesn’t pay attention too closely to the meaning of the lifetimes involved and blindly applies outlives constraints the compiler says are necessary/violated; typically for example in cases where data is stored in self-referencing-struct kind of manners.


Regarding your concrete example, the code seems to be perhaps overly simplified? You claim

but in the playground you’ve given, there’s no apparent problem with simply removing those constraints.

1 Like

I thought removing also <'a,'b> all together and let the compiler figure things out. But that does not compile, why?

I assume you mean the struct is unusable because I accidentially wrote 'a >= 'b or a outlives b which is weird because the inner reference should live for sure longer so the correct thing would have been 'b: 'a, right?

Yes. If that was just a typo, then I might have focused on the wrong thing.

This one doesn’t compile because struct C still features the 'a: 'b constraint.

My example was not a typo, I also understood liftime bounds the otherway around, sorry, I updated the question to be more specific what I wanted to head at.

Ah in fact we can remove lifetimes on store. I think your answer was right, I over bounded the struct C with <'a> and &'a mut TempFile<'a> which made problems, so you were right I got mislead by the compiler, but was not pointed towards relaxing the lifetimes in C to C<'a, 'b: 'a>. Thanks for the answer !

The final working example here: