|
1 | | -A lifetime of return value does not outlive the function call. |
| 1 | +A lifetime of a returned value does not outlive the function call. |
2 | 2 |
|
3 | 3 | Erroneous code example: |
4 | 4 |
|
5 | 5 | ```compile_fail,E0482 |
6 | 6 | fn prefix<'a>( |
7 | 7 | words: impl Iterator<Item = &'a str> |
8 | | -) -> impl Iterator<Item = String> { |
| 8 | +) -> impl Iterator<Item = String> { // error! |
9 | 9 | words.map(|v| format!("foo-{}", v)) |
10 | 10 | } |
11 | 11 | ``` |
12 | 12 |
|
13 | | -To fix this error, make the lifetime of the returned value explicit. |
| 13 | +To fix this error, make the lifetime of the returned value explicit: |
14 | 14 |
|
15 | 15 | ``` |
16 | 16 | fn prefix<'a>( |
17 | 17 | words: impl Iterator<Item = &'a str> + 'a |
18 | | -) -> impl Iterator<Item = String> + 'a { |
| 18 | +) -> impl Iterator<Item = String> + 'a { // ok! |
19 | 19 | words.map(|v| format!("foo-{}", v)) |
20 | 20 | } |
21 | 21 | ``` |
22 | 22 |
|
23 | | -[`impl Trait`] feature in return type have implicit `'static` lifetime |
24 | | -restriction and the type implementing the `Iterator` passed to the function |
25 | | -lives just `'a`, so shorter time. |
| 23 | +The [`impl Trait`] feature in this example uses an implicit `'static` lifetime |
| 24 | +restriction in the returned type. However the type implementing the `Iterator` |
| 25 | +passed to the function lives just as long as `'a`, which is not long enough. |
26 | 26 |
|
27 | 27 | The solution involves adding lifetime bound to both function argument and |
28 | 28 | the return value to make sure that the values inside the iterator |
29 | 29 | are not dropped when the function goes out of the scope. |
30 | 30 |
|
31 | | -Alternative solution would be to guarantee that the `Item` references |
| 31 | +An alternative solution would be to guarantee that the `Item` references |
32 | 32 | in the iterator are alive for the whole lifetime of the program. |
33 | 33 |
|
34 | 34 | ``` |
35 | 35 | fn prefix( |
36 | 36 | words: impl Iterator<Item = &'static str> |
37 | | -) -> impl Iterator<Item = String> { |
| 37 | +) -> impl Iterator<Item = String> { // ok! |
38 | 38 | words.map(|v| format!("foo-{}", v)) |
39 | 39 | } |
40 | 40 | ``` |
41 | 41 |
|
42 | | -Similar lifetime problem might arise when returning closures. |
43 | | - |
44 | | -Erroneous code example: |
| 42 | +A similar lifetime problem might arise when returning closures: |
45 | 43 |
|
46 | 44 | ```compile_fail,E0482 |
47 | | -fn foo(x: &mut Vec<i32>) -> impl FnMut(&mut Vec<i32>) -> &[i32] { |
| 45 | +fn foo( |
| 46 | + x: &mut Vec<i32> |
| 47 | +) -> impl FnMut(&mut Vec<i32>) -> &[i32] { // error! |
48 | 48 | |y| { |
49 | 49 | y.append(x); |
50 | 50 | y |
51 | 51 | } |
52 | 52 | } |
53 | 53 | ``` |
54 | 54 |
|
55 | | -Analogically, solution here is to use explicit return lifetime |
| 55 | +Analogically, a solution here is to use explicit return lifetime |
56 | 56 | and move the ownership of the variable to the closure. |
57 | 57 |
|
58 | 58 | ``` |
59 | | -fn foo<'a>(x: &'a mut Vec<i32>) -> impl FnMut(&mut Vec<i32>) -> &[i32] + 'a { |
| 59 | +fn foo<'a>( |
| 60 | + x: &'a mut Vec<i32> |
| 61 | +) -> impl FnMut(&mut Vec<i32>) -> &[i32] + 'a { // ok! |
60 | 62 | move |y| { |
61 | 63 | y.append(x); |
62 | 64 | y |
63 | 65 | } |
64 | 66 | } |
65 | 67 | ``` |
66 | 68 |
|
67 | | -- [`impl Trait`]: https://doc.rust-lang.org/reference/types/impl-trait.html |
68 | | -- [RFC 1951]: https://rust-lang.github.io/rfcs/1951-expand-impl-trait.html |
| 69 | +To better understand the lifetime treatment in the [`impl Trait`], |
| 70 | +please see the [RFC 1951]. |
| 71 | + |
| 72 | +[`impl Trait`]: https://doc.rust-lang.org/reference/types/impl-trait.html |
| 73 | +[RFC 1951]: https://rust-lang.github.io/rfcs/1951-expand-impl-trait.html |
0 commit comments