0

The following code:

trait Passable: Sized { fn call<F: Fn(Self)>(f: F); } impl Passable for &[i32] { fn call<F: Fn(Self)>(f: F) { let vec = vec![1, 2, 3]; f(&vec); } } 

gives the error

error[E0597]: `vec` does not live long enough --> src/main.rs:8:11 | 8 | f(&vec); | ^^^^ borrowed value does not live long enough 9 | } | - `vec` dropped here while still borrowed 

By contrast, if I write the same thing but with a fixed type of &[i32] instead of Self, it compiles:

trait Passable: Sized { fn call<F: Fn(&[i32])>(f: F); } impl Passable for &[i32] { fn call<F: Fn(&[i32])>(f: F) { let vec = vec![1, 2, 3]; f(&vec); } } 

Why does the first code fail but not the second? And can the first code be changed so that it does compile?

1 Answer 1

2

Because of lifetime elision. Your first example (with Self) is equivalent to this code:

trait Passable: Sized { fn call<F: Fn(Self)>(f: F); } impl<'a> Passable for &'a [i32] { fn call<F: Fn(&'a [i32])>(f: F) { let vec = vec![1, 2, 3]; f(&vec); } } 

Note that here f takes an argument with the same lifetime as Self but vec has a smaller lifetime.

On the other hand, your second example is equivalent to this code:

trait Passable: Sized { fn call<'b, F: Fn(&'b [i32])>(f: F); } impl<'a> Passable for &'a [i32] { fn call<'b, F: Fn(&'b [i32])>(f: F) { let vec = vec![1, 2, 3]; f(&vec); } } 

which uses different lifetimes for Self and the argument of f.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.