|
|
|
@ -234,19 +234,7 @@ error: lifetime may not live long enough
|
|
|
|
|
|
|
|
|
|
真的是非常奇怪的错误,学过上一节的读者应该都记得这样一条生命周期消除规则:**如果函数参数中只有一个引用类型,那该引用的生命周期会被自动分配给所有的返回引用**。我们当前的情况完美符合, `function` 函数的顺利编译通过,就充分说明了问题。
|
|
|
|
|
|
|
|
|
|
**最好的解决方案**: 通过包装一层Fn Trait来解决。
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
fn main() {
|
|
|
|
|
let closure_slision = fun(|x: &i32| -> &i32 { x });
|
|
|
|
|
assert_eq!(*closure_slision(&45), 45);
|
|
|
|
|
// Passed !
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn fun<T, F: Fn(&T) -> &T>(f: F) -> F {
|
|
|
|
|
f
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
先给出一个结论:**这个问题,可能很难被解决,建议大家遇到后,还是老老实实用正常的函数,不要秀闭包了**。
|
|
|
|
|
|
|
|
|
|
对于函数的生命周期而言,它的消除规则之所以能生效是因为它的生命周期完全体现在签名的引用类型上,在函数体中无需任何体现:
|
|
|
|
|
|
|
|
|
@ -266,6 +254,21 @@ let closure_slision = |x: &i32| -> &i32 { x };
|
|
|
|
|
|
|
|
|
|
由于上述原因(当然,实际情况复杂的多),Rust 语言开发者目前其实是有意针对函数和闭包实现了两种不同的生命周期消除规则。
|
|
|
|
|
|
|
|
|
|
> **用 `Fn` 特征解决闭包生命周期**
|
|
|
|
|
>
|
|
|
|
|
> 之前我们提到了很难解决,但是并没有完全堵死(论文字的艺术- , -) 这不 @Ykong1337 同学就带了一个解决方法,为他点赞!
|
|
|
|
|
>
|
|
|
|
|
> ```rust
|
|
|
|
|
> fn main() {
|
|
|
|
|
> let closure_slision = fun(|x: &i32| -> &i32 { x });
|
|
|
|
|
> assert_eq!(*closure_slision(&45), 45);
|
|
|
|
|
> // Passed !
|
|
|
|
|
> }
|
|
|
|
|
>
|
|
|
|
|
> fn fun<T, F: Fn(&T) -> &T>(f: F) -> F {
|
|
|
|
|
> f
|
|
|
|
|
> }
|
|
|
|
|
> ```
|
|
|
|
|
## NLL (Non-Lexical Lifetime)
|
|
|
|
|
|
|
|
|
|
之前我们在[引用与借用](https://course.rs/basic/ownership/borrowing.html#NLL)那一章其实有讲到过这个概念,简单来说就是:**引用的生命周期正常来说应该从借用开始一直持续到作用域结束**,但是这种规则会让多引用共存的情况变得更复杂:
|
|
|
|
|