Clarify the error descriptions
This commit is contained in:
parent
14aae67bbc
commit
0fde6f672f
1 changed files with 22 additions and 17 deletions
|
@ -1,50 +1,50 @@
|
|||
A lifetime of return value does not outlive the function call.
|
||||
A lifetime of a returned value does not outlive the function call.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0482
|
||||
fn prefix<'a>(
|
||||
words: impl Iterator<Item = &'a str>
|
||||
) -> impl Iterator<Item = String> {
|
||||
) -> impl Iterator<Item = String> { // error!
|
||||
words.map(|v| format!("foo-{}", v))
|
||||
}
|
||||
```
|
||||
|
||||
To fix this error, make the lifetime of the returned value explicit.
|
||||
To fix this error, make the lifetime of the returned value explicit:
|
||||
|
||||
```
|
||||
fn prefix<'a>(
|
||||
words: impl Iterator<Item = &'a str> + 'a
|
||||
) -> impl Iterator<Item = String> + 'a {
|
||||
) -> impl Iterator<Item = String> + 'a { // ok!
|
||||
words.map(|v| format!("foo-{}", v))
|
||||
}
|
||||
```
|
||||
|
||||
[`impl Trait`] feature in return type have implicit `'static` lifetime
|
||||
restriction and the type implementing the `Iterator` passed to the function
|
||||
lives just `'a`, so shorter time.
|
||||
The [`impl Trait`] feature in this example uses an implicit `'static` lifetime
|
||||
restriction in the returned type. However the type implementing the `Iterator`
|
||||
passed to the function lives just as long as `'a`, which is not long enough.
|
||||
|
||||
The solution involves adding lifetime bound to both function argument and
|
||||
the return value to make sure that the values inside the iterator
|
||||
are not dropped when the function goes out of the scope.
|
||||
|
||||
Alternative solution would be to guarantee that the `Item` references
|
||||
An alternative solution would be to guarantee that the `Item` references
|
||||
in the iterator are alive for the whole lifetime of the program.
|
||||
|
||||
```
|
||||
fn prefix(
|
||||
words: impl Iterator<Item = &'static str>
|
||||
) -> impl Iterator<Item = String> {
|
||||
) -> impl Iterator<Item = String> { // ok!
|
||||
words.map(|v| format!("foo-{}", v))
|
||||
}
|
||||
```
|
||||
|
||||
Similar lifetime problem might arise when returning closures.
|
||||
|
||||
Erroneous code example:
|
||||
A similar lifetime problem might arise when returning closures:
|
||||
|
||||
```compile_fail,E0482
|
||||
fn foo(x: &mut Vec<i32>) -> impl FnMut(&mut Vec<i32>) -> &[i32] {
|
||||
fn foo(
|
||||
x: &mut Vec<i32>
|
||||
) -> impl FnMut(&mut Vec<i32>) -> &[i32] { // error!
|
||||
|y| {
|
||||
y.append(x);
|
||||
y
|
||||
|
@ -52,11 +52,13 @@ fn foo(x: &mut Vec<i32>) -> impl FnMut(&mut Vec<i32>) -> &[i32] {
|
|||
}
|
||||
```
|
||||
|
||||
Analogically, solution here is to use explicit return lifetime
|
||||
Analogically, a solution here is to use explicit return lifetime
|
||||
and move the ownership of the variable to the closure.
|
||||
|
||||
```
|
||||
fn foo<'a>(x: &'a mut Vec<i32>) -> impl FnMut(&mut Vec<i32>) -> &[i32] + 'a {
|
||||
fn foo<'a>(
|
||||
x: &'a mut Vec<i32>
|
||||
) -> impl FnMut(&mut Vec<i32>) -> &[i32] + 'a { // ok!
|
||||
move |y| {
|
||||
y.append(x);
|
||||
y
|
||||
|
@ -64,5 +66,8 @@ fn foo<'a>(x: &'a mut Vec<i32>) -> impl FnMut(&mut Vec<i32>) -> &[i32] + 'a {
|
|||
}
|
||||
```
|
||||
|
||||
- [`impl Trait`]: https://doc.rust-lang.org/reference/types/impl-trait.html
|
||||
- [RFC 1951]: https://rust-lang.github.io/rfcs/1951-expand-impl-trait.html
|
||||
To better understand the lifetime treatment in the [`impl Trait`],
|
||||
please see the [RFC 1951].
|
||||
|
||||
[`impl Trait`]: https://doc.rust-lang.org/reference/types/impl-trait.html
|
||||
[RFC 1951]: https://rust-lang.github.io/rfcs/1951-expand-impl-trait.html
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue