|
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