]>
Commit | Line | Data |
---|---|---|
c295e0f8 XL |
1 | A lifetime of a returned value does not outlive the function call. |
2 | ||
3 | Erroneous code example: | |
4 | ||
5 | ```compile_fail,E0482 | |
6 | fn prefix<'a>( | |
7 | words: impl Iterator<Item = &'a str> | |
8 | ) -> impl Iterator<Item = String> { // error! | |
9 | words.map(|v| format!("foo-{}", v)) | |
10 | } | |
11 | ``` | |
12 | ||
13 | To fix this error, make the lifetime of the returned value explicit: | |
14 | ||
15 | ``` | |
16 | fn prefix<'a>( | |
17 | words: impl Iterator<Item = &'a str> + 'a | |
18 | ) -> impl Iterator<Item = String> + 'a { // ok! | |
19 | words.map(|v| format!("foo-{}", v)) | |
20 | } | |
21 | ``` | |
22 | ||
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 | ||
27 | The solution involves adding lifetime bound to both function argument and | |
28 | the return value to make sure that the values inside the iterator | |
29 | are not dropped when the function goes out of the scope. | |
30 | ||
31 | An alternative solution would be to guarantee that the `Item` references | |
32 | in the iterator are alive for the whole lifetime of the program. | |
33 | ||
34 | ``` | |
35 | fn prefix( | |
36 | words: impl Iterator<Item = &'static str> | |
37 | ) -> impl Iterator<Item = String> { // ok! | |
38 | words.map(|v| format!("foo-{}", v)) | |
39 | } | |
40 | ``` | |
41 | ||
42 | A similar lifetime problem might arise when returning closures: | |
43 | ||
44 | ```compile_fail,E0482 | |
45 | fn foo( | |
46 | x: &mut Vec<i32> | |
47 | ) -> impl FnMut(&mut Vec<i32>) -> &[i32] { // error! | |
48 | |y| { | |
49 | y.append(x); | |
50 | y | |
51 | } | |
52 | } | |
53 | ``` | |
54 | ||
55 | Analogically, a solution here is to use explicit return lifetime | |
56 | and move the ownership of the variable to the closure. | |
57 | ||
58 | ``` | |
59 | fn foo<'a>( | |
60 | x: &'a mut Vec<i32> | |
61 | ) -> impl FnMut(&mut Vec<i32>) -> &[i32] + 'a { // ok! | |
62 | move |y| { | |
63 | y.append(x); | |
64 | y | |
65 | } | |
66 | } | |
67 | ``` | |
68 | ||
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 |