I need to reduce lifetimes with each subsequent calls. Here is a simple example what I want:
struct Stack<'a>(PhantomData<&'a mut ()>);
impl<'a> Stack<'a> {
fn push<'b, T, F>(self, f: F) -> (Stack<'b>, &'b mut T)
where
'a: 'b,
T: 'b,
F: FnOnce() -> T,
{
todo!()
}
}
fn example(stack: Stack) {
let (stack, value0) = stack.push(|| 13);
let (stack, value1) = stack.push(|| Vec::<&mut i32>::new());
let (stack, value2) = stack.push(|| 42);
value1.push(value0);
value1.push(value2);
}
How I understand it:
'a >= 'b
, so Stack<'a> >= Stack<'b>
- value0 is
'1
- value1 is
'2
- value2 is
'3
'1 >= '2 >= '3
- value1 should be able to store value0 (value0 outlives value1)
- value1 should not be able to store value2 (value1 outlives value2)
But this example does compile. I can limit lifecycle with closures but this will make Stack
unusable.
Can anyone help with this? What am I doing wrong? Is this some kind of hidden inference magic I'm not aware of?
I think you may have over-reduced your example; it compiles just fine.
That said, it will be very hard to replace the todo!
with anything useful as you'll run into variance issues quite easily— When the exclusive borrow ends, the original buffer must still contain valid data to prevent UB, which means storing a value scoped to 'b
would be unsound.
I know it compiles, I want it to not compile 
I don't see a way: In the third push
call, 42
is 'static
, so 'a == 'b
is a valid solution to the given bounds. So '2 == '3
, which means that value1.push(value2)
is also valid.
As far as I can tell, what you'd need to make this work is a strictly-less-than lifetime bound instead of the less-or-equal bound, but that doesn't currently exist.
1 Like
I probably need to add more context.
This stack implementation is just for example to show what I want from lifetimes. Internally it can have unsafe
code to help with manipulating lifetimes. In general we can think it has a *const ()
pointer inside it and does unsafe magic in push
.
Now the question here is what I need to add to make lifetimes work. For example push
can return StackEntry<'b, T>: DerefMut
and have some phantoms inside it for inference things.
I just don't understant what I need to add where to make lifetimes work as I described above.
yes, this is what I want, to have '2 > '3
, not '2 >= '3
.
PS: I actually wrote it in the title 
As they said, a strictly-outlives (cannot be equal) bound does not exist.