How to solve this "does not live long enough"? - rust

There is some minimal example library code I would like to use:
struct MyR<'a> {
x: &'a str,
}
struct T {
x: &'static str,
}
impl T {
fn bar<'a>(&'a self) -> MyR {
MyR { x: self.x }
}
}
The following is my code:
trait A<R, F: FnMut(&R)> {
fn foo(&mut self, callback: &mut F);
}
impl<'a, F> A<MyR<'a>, F> for T
where F: FnMut(&MyR<'a>)
{
fn foo(&mut self, callback: &mut F) {
let t = T { x: "l" };
let r = t.bar(); // t does not live long enough (for 'a)
callback(&r);
println!("abc");
}
}
fn test() {
let mut t = T { x: "l" };
let mut i = 1;
t.foo(&mut |x| { i += x.x.len(); });
}
I would like to make a trait that is parametrized by the callback, but I struggled to make it right. If I don't use a trait, it works well:
impl T {
fn foo<F: FnMut(&MyR)>(&mut self, callback: &'a mut F) {
let t = T { x: "l" };
let r = t.bar();
callback(&r);
println!("abc");
}
}
But I cannot do this:
impl T {
fn foo<'a, F: FnMut(&MyR<'a>)>(&mut self, callback: &mut F) {
let t = T { x: "l" };
let r = t.bar();
callback(&r);
println!("abc");
}
}
I know the problem is that t must outlive 'a, but I don't know to bound 'a so that its lifetime is shorter than t.
I'm using rustc 1.19.0-nightly.

Read the error messages:
t does not live long enough — it lives until the end of the foo function.
borrowed value must be valid for the lifetime 'a — you have specified 'a:
impl<'a, F> A<MyR<'a>, F> for T
where F: FnMut(&MyR<'a>)
This says that for any possible lifetime, the trait will be implemented, so long as F implements the FnMut trait.
There's only one possible way to make that work — you have to have a MyR that is parameterized with the 'static lifetime. That's the only lifetime that is guaranteed to outlive any arbitrary lifetime.
Let's see where MyR comes from:
fn bar<'a>(&'a self) -> MyR {
MyR { x: self.x }
}
If you go back and reread The Rust Programming Language section on lifetime elision, you'll recognize that this lifetime specification provides no value. It defines a lifetime and uses it with self, but it's never tied to any output lifetimes. The code is the same as:
fn bar<'a, 'b>(&'a self) -> MyR<'b>
If you removed the lifetime, then you'd have
fn bar(&self) -> MyR
fn bar<'a>(&'a self) -> MyR<'a> // equivalent
However, neither of these is the 'static lifetime. Luckily for you, you know that that x is a &'static str, so you can just reflect that in your signature and the code will compile:
fn bar(&self) -> MyR<'static>

Spending hours trying different approaches, this seems to work
trait A<F> {
fn foo(&mut self, callback: &mut F);
}
impl<F> A<F> for T
where F: FnMut(&MyR)
{
fn foo(&mut self, callback: &mut F) {
let t = T { x: "l" };
let r = t.bar(); // t does not live long enough (for 'a)
callback(&r);
println!("abc");
}
}
fn main() {
let mut t = T { x: "l" };
let mut i = 1;
t.foo(&mut |x: &MyR| { i += x.x.len(); });
}
The main difference is:
I have to loose trait a bit so that it takes arbitrary types.
So that when I impl I don't have to specify lifetime at all.
I have to type annotate the closure when invoking the function.
Playground

Related

lifetime with closure captures in rust

How can I reduce the lifetime of a closure?
I was trying to make a method, which returns an iterator related to self. I didn't want to make new struct or something, so I just made it return filters and maps, and confronted some borrow checker errors.
The following code was my first try.
fn f<'b>(&'b self) -> impl Iterator<Item = u8> {
(0..self.some_number())
.filter(|&i| self.some_bool_function(i))
.map(|i| i as u8)
}
The following code replicates my question.
struct A(bool);
impl A {
fn f<'a>(&'a self) -> impl Iterator<Item = u8> + 'a {
(0..1).filter(|&i| self.0)
}
}
or even shorter,
fn g<'a>(t:&'a ()) -> impl 'a + FnMut() {
|| *t
}
This would not compile, because the closure may outlive self. I don't know how to make this work, without moving self.
If you return a closure, you must ensure that the closure has everything it needs - even after returning (i.e. after the (temporary) function parameters are popped from the stack).
Thus, I think you want to move the stuff you return into the closure:
impl A {
fn f<'a>(&'a self) -> impl Iterator<Item = u8> + 'a {
(0..1).filter(move |&i| self.0)
}
}
Resp.
fn g<'a>(t:&'a ()) -> impl 'a + FnMut() {
move || *t
}
Resp (extending your first example):
struct A(bool);
impl A {
fn some_number(&self) -> usize {
6
}
fn some_bool_function(&self, i: usize) -> bool {
i%2==0
}
fn f<'b>(&'b self) -> impl Iterator<Item = u8> + 'b {
(0..self.some_number())
.filter(move |&i| self.some_bool_function(i))
.map(|i| i as u8)
}
}

Strange behavior of HRTBs

I have this code:
use std::fmt::Debug;
struct S<A>
where
for<'a> A: Debug + 'a,
{
f: Box<Fn(A) -> i32>,
}
impl<A> S<A>
where
for<'a> A: Debug + 'a,
{
fn call(&self, a: A) {
println!("Return {:?}", (self.f)(a));
}
}
fn create<A>(f: Box<Fn(A) -> i32>) -> S<A>
where
for<'a> A: Debug + 'a,
{
S::<A> { f }
}
fn helper() {
let x = create::<&i32>(Box::new(|x: &i32| *x * 2));
let arg = 333;
x.call(&arg);
}
fn main() {
let x = helper();
}
It's failed to compile:
error[E0310]: the parameter type `A` may not live long enough
In code 2, I changed Fn(A) -> i32 to Fn(&A) -> i32, the code works.
...
f: Box<Fn(&A) -> i32>,
...
Since A is argument of Fn trait, it's a type that has Higher-Rank lifetime. It shouldn't be affected by the lifetime of struct S<A> .
But why can't code 1 be compiled?
How can I workaround it for borrow or non-borrow type A?
There is no easy way to make helper work in current Rust, even if you remove all the for<'a> A: Debug + 'a, bounds (which only further restricts what types A can be, whereas you want to allow more).
This is as simple as I can make your example:
struct S<A> {
f: Box<Fn(A) -> i32>,
}
impl<A> S<A> {
fn call(&self, a: A) {
println!("Return {:?}", (self.f)(a));
}
}
fn create<A>(f: Box<Fn(A) -> i32>) -> S<A> {
S { f }
}
fn helper() {
let x = create(Box::new(|x: &i32| *x * 2));
let arg = 333;
x.call(&arg);
}
fn main() {
helper();
}
The reason it doesn't work is that A "comes from the outside", and Rust can't infer that you want for<'a> S<&'a A>, it can't even talk about such a type.
Note that if let arg = 333; is placed above let x, this example does compile (because it infers a reference to arg specifically, not a for<'a>).
The closest you can get today is with an associated type on a trait with a lifetime parameter, e.g.:
// Emulating `type Type<'a>` by moving `'a` to the trait.
trait Apply<'a> {
type Type;
}
struct Plain<T>(std::marker::PhantomData<T>);
impl<'a, T> Apply<'a> for Plain<T> {
type Type = T;
}
struct Ref<T: ?Sized>(std::marker::PhantomData<T>);
impl<'a, T: ?Sized + 'a> Apply<'a> for Ref<T> {
type Type = &'a T;
}
struct S<A: for<'a> Apply<'a>> {
f: Box<for<'a> Fn(<A as Apply<'a>>::Type) -> i32>,
}
impl<A: for<'a> Apply<'a>> S<A> {
fn call<'a>(&self, a: <A as Apply<'a>>::Type) {
println!("Return {:?}", (self.f)(a));
}
}
fn create<A: for<'a> Apply<'a>>(
f: Box<for<'a> Fn(<A as Apply<'a>>::Type) -> i32>,
) -> S<A> {
S { f }
}
fn helper() {
let x = create::<Ref<i32>>(Box::new(|x: &i32| *x * 2));
let arg = 333;
x.call(&arg);
}
fn main() {
helper();
}
However, it turns out that this encoding hits https://github.com/rust-lang/rust/issues/52812, so it's not actually usable at the moment (and I'm not aware of an workaround).

What is the difference between '&self' and '&'a self'?

I recently had an error which was simply resolved by changing
impl<'a> Foo<'a> {
fn foo(&'a self, path: &str) -> Boo<'a> { /* */ }
}
to
impl<'a> Foo<'a> {
fn foo(&self, path: &str) -> Boo { /* */ }
}
which did not make sense according to my understanding, as I thought that the second version is exactly the same as the first with applied lifetime elision.
In case we introduce a new lifetime for the method this seems to be the case according this example from the nomicon.
fn get_mut(&mut self) -> &mut T; // elided
fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
So what are the differences between this and my first code snipped.
Lifetime 'a in fn foo(&'a self, ...) ... is defined for impl<'a>, that is it is the same for all foo calls.
Lifetime 'a in fn get_mut<'a>(&'a mut self) ... is defined for the function. Different calls of get_mut can have different values for 'a.
Your code
impl<'a> Foo<'a> {
fn foo(&'a self, path: &str) -> Boo<'a> { /* */ }
}
is not the expansion of elided lifetime. This code ties lifetime of borrow &'a self to the lifetime of structure Foo<'a>. If Foo<'a> is invariant over 'a, then self should remain borrowed as long as 'a.
Correct expansion of elided lifetime is
impl<'a> Foo<'a> {
fn foo<'b>(&'b self, path: &str) -> Boo<'b> { /* */ }
}
This code doesn't depend on variance of structure Foo to be able to borrow self for shorter lifetimes.
Example of differences between variant and invariant structures.
use std::cell::Cell;
struct Variant<'a>(&'a u32);
struct Invariant<'a>(Cell<&'a u32>);
impl<'a> Variant<'a> {
fn foo(&'a self) -> &'a u32 {
self.0
}
}
impl<'a> Invariant<'a> {
fn foo(&'a self) -> &'a u32 {
self.0.get()
}
}
fn main() {
let val = 0;
let mut variant = Variant(&val);// variant: Variant<'long>
let mut invariant = Invariant(Cell::new(&val));// invariant: Invariant<'long>
{
let r = variant.foo();
// Pseudocode to explain what happens here
// let r: &'short u32 = Variant::<'short>::foo(&'short variant);
// Borrow of `variant` ends here, as it was borrowed for `'short` lifetime
// Compiler can do this conversion, because `Variant<'long>` is
// subtype of Variant<'short> and `&T` is variant over `T`
// thus `variant` of type `Variant<'long>` can be passed into the function
// Variant::<'short>::foo(&'short Variant<'short>)
}
// variant is not borrowed here
variant = Variant(&val);
{
let r = invariant.foo();
// compiler can't shorten lifetime of `Invariant`
// thus `invariant` is borrowed for `'long` lifetime
}
// Error. invariant is still borrowed here
//invariant = Invariant(Cell::new(&val));
}
Playground link

Reference lifetime conflicts with same lifetime range

I am trying to store and use an optional callback handle in Rust which works like a method to the structure I am storing it in. It works as long as I do not pass a reference to itself to the callback. But doing so gives me a lifetime error for the used object references (E0312). The lifetime seems to be the same and I cannot figure out what to change to get this working.
type Callback<'a> = Fn(&'a mut Func, i32) -> i32;
struct Func<'a> {
val: i32,
func: Option<Box<Callback<'a>>>,
}
impl<'a, 'b> Func<'b> {
fn exec(&'a mut self, val: i32) -> i32 {
if let Some(ref f) = self.func {
return f(self, val);
};
0i32
}
}
fn main() {
let mut a32 = Func{
val: 10i32,
func: Some(Box::new(|ref mut s, val: i32| -> i32 {
let v = s.val;
s.val += 1;
val * 32 + v
}))
};
println!("a32(4) = {}", a32.exec(4i32));
println!("a32(4) = {}", a32.exec(4i32));
}
Is there a way to fix this or did I come across a compiler bug?
Using rustc 1.15.0 (10893a9a3 2017-01-19).
See also on Rust playground.
I also tried the same without explicit lifetimes but then I run into the problem that I cannot alias references in Rust (E0502).
I know that Rust tries to prevent this to avoid data races but would this mean that I always need to create a copy of my object in these cases?
The following does not work either giving me an error, that borrowed content cannot be moved out (E0507).
impl Func {
fn exec(&mut self, val: i32) -> i32 {
if self.func.is_some() {
return self.func.unwrap()(self, val);
};
0i32
}
}
But I could not find a way to clone the boxed function...
You have a borrow issue here:
You are borrowing self.func immutably
You are attempting to borrow self mutably at the same time
This is not allowed, because it could allow you to change func while using it, which heralds troubles.
You could attempt to change Callback to only pass in &mut i32 instead, but then you would hit lifetime unification issues:
if you specify that exec takes &'a mut self, then you anchor the object, borrowing it for the rest of its lifetime,
on the other hand, if you specify a fresh lifetime, then by definition it's less than 'a, and you required 'a in the signature of Callback.
Neither situation works.
The solution, thus, is to avoid the lifetime in the first place.
It's also easier (on borrowing) NOT to pass an instance of self but just to pass a reference to self.val so I present that first:
type Callback = Fn(&mut i32, i32) -> i32;
struct Func {
val: i32,
func: Option<Box<Callback>>,
}
impl Func {
fn exec(&mut self, val: i32) -> i32 {
if let Some(ref f) = self.func {
return f(&mut self.val, val);
};
0i32
}
}
fn main() {
let mut a32 = Func{
val: 10i32,
func: Some(Box::new(|s: &mut i32, val: i32| -> i32 {
let v = *s;
*s += 1;
val * 32 + v
}))
};
println!("a32(4) = {}", a32.exec(4i32));
println!("a32(4) = {}", a32.exec(4i32));
}
If you want to really pass Func, you need to "option dance":
impl Func {
fn exec(&mut self, val: i32) -> i32 {
let func = self.func.take();
let res = if let Some(ref f) = func {
f(self, val)
} else {
0i32
};
self.func = func;
res
}
}
And be aware that self.func is empty in the callback.

Mutable versus immutable lifetime

I have a program that I'm not sure how to reason about. I have a concrete lifetime defined on a trait A, and A is parameterized by a type T : A. One of the trait functions refine of A takes a &'a mut self parameter and returns a Vec<T>.
Suppose I have two structs U and V, such that V has a field with type &'a U, and U has a refine defined as:
fn refine(&'a mut self) -> Vec<V<'a>>
If I construct a V directly in the body of U's implementation of refine, the compiler tells me that self doesn't live long enough. However, if I construct a V within an implementation function of U, let's call it make_v, whose signature is:
fn make_v<'a>(&'a self) -> V<'a>
It seems to work OK. I'm confused about how the lifetime requirements of the two are different. I have a rust playground working example, and here it is again for posterity:
trait A<'a, T : A<'a> = Self> {
fn refine(&'a mut self) -> Vec<T>;
}
#[derive(Clone, Debug)]
struct V<'a> {
u: &'a U,
id: usize
}
#[derive(Debug)]
struct U {
id: u64
}
impl U {
fn make_v<'a>(&'a self, i: usize) -> V<'a> {
V { u: &self, id: i }
}
}
impl<'a> A<'a> for V<'a> {
fn refine(&'a mut self) -> Vec<V<'a>> {
vec![self.clone(), self.clone(), self.clone()]
}
}
impl<'a> A<'a, V<'a>> for U {
fn refine(&'a mut self) -> Vec<V<'a>> {
let mut v = Vec::new();
for i in 0..3 {
// This doesn't compile
// v.push(V { u: &self, id: i });
// This does compile...?
v.push(self.make_v(i));
}
v
}
}
fn main() {
let mut u = U { id: 0 };
println!("{:?}", u.refine());
}
v.push(V { u: &self, id: i });
is invoking auto-deref, so ends up as
v.push(V { u: *&self, id: i });
&self is a &'k &'a mut T where 'k is the scope of the &mut pointer (not the pointed-to object). This means that borrows into this are at times restricted.
The self.make_ref version does this differently; as a reborrow. This looks like &*self. In this case the outer reference is into an object with lifetime 'a, so can be of lifetime 'a.
Just writing self in this case will have this handled automatically.
Credit goes to to #fjh for his comment, which clarified things nicely.

Resources