diff --git a/src/advance/lifetime/advance.md b/src/advance/lifetime/advance.md index 37f5e126..d0372024 100644 --- a/src/advance/lifetime/advance.md +++ b/src/advance/lifetime/advance.md @@ -234,7 +234,7 @@ error: lifetime may not live long enough 真的是非常奇怪的错误,学过上一节的读者应该都记得这样一条生命周期消除规则:**如果函数参数中只有一个引用类型,那该引用的生命周期会被自动分配给所有的返回引用**。我们当前的情况完美符合, `function` 函数的顺利编译通过,就充分说明了问题。 -首先给出一个结论:**这个问题,可能很难被解决,建议大家遇到后,还是老老实实用正常的函数,不要秀闭包了**。 +先给出一个结论:**这个问题,可能很难被解决,建议大家遇到后,还是老老实实用正常的函数,不要秀闭包了**。 对于函数的生命周期而言,它的消除规则之所以能生效是因为它的生命周期完全体现在签名的引用类型上,在函数体中无需任何体现: @@ -254,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: F) -> F { +> f +> } +> ``` ## NLL (Non-Lexical Lifetime) 之前我们在[引用与借用](https://course.rs/basic/ownership/borrowing.html#NLL)那一章其实有讲到过这个概念,简单来说就是:**引用的生命周期正常来说应该从借用开始一直持续到作用域结束**,但是这种规则会让多引用共存的情况变得更复杂: diff --git a/src/basic/comment.md b/src/basic/comment.md index 81d58871..6c36707d 100644 --- a/src/basic/comment.md +++ b/src/basic/comment.md @@ -45,7 +45,7 @@ fn main() { S u n - ... 淦,好长! + ... 哎,好长! */ let name = "sunface"; let age = "???"; // 今年其实。。。挺大了 diff --git a/src/basic/ownership/borrowing.md b/src/basic/ownership/borrowing.md index f36bf184..40a394bb 100644 --- a/src/basic/ownership/borrowing.md +++ b/src/basic/ownership/borrowing.md @@ -148,7 +148,7 @@ error[E0499]: cannot borrow `s` as mutable more than once at a time 同一时间 | -- first borrow later used here 第一个借用在这里使用 ``` -这段代码出错的原因在于,第一个可变借用 `r1` 必须要持续到最后一次使用的位置 `println!`,在 `r1` 创建和最后一次使用之间,我们又尝试创建第二个可变引用 `r2`。 +这段代码出错的原因在于,第一个可变借用 `r1` 必须要持续到最后一次使用的位置 `println!`,在 `r1` 创建和最后一次使用之间,我们又尝试创建第二个可变借用 `r2`。 对于新手来说,这个特性绝对是一大拦路虎,也是新人们谈之色变的编译器 `borrow checker` 特性之一,不过各行各业都一样,限制往往是出于安全的考虑,Rust 也一样。 diff --git a/src/too-many-lists/intro.md b/src/too-many-lists/intro.md index 7a0eff02..4d5d27da 100644 --- a/src/too-many-lists/intro.md +++ b/src/too-many-lists/intro.md @@ -5,7 +5,7 @@ > Rust 语言: 兄弟,语言精通了吗?来写一个链表证明你已经精通了 Rust! -上面的对话非常真实,我们在之前的章节也讲过[初学者学习 Rust 应该避免的坑](https://course.rs/sth-you-should-not-do.html#千万别从链表或图开始练手),其中最重要的就是 - 不要写链表或者类似的数据结构! +上面的对话非常真实,我们在之前的章节也讲过[避免从入门到放弃](https://course.rs/first-try/sth-you-should-not-do.html#千万别从链表或图开始练手),其中最重要的就是 - 不要写链表或者类似的数据结构! 而本章,你就将见识到何为真正的深坑,看完后,就知道没有提早跳进去是一个多么幸运的事。总之,在专题中,你将学会如何使用 Rust 来实现链表。 diff --git a/src/too-many-lists/unsafe-queue/extra-junk.md b/src/too-many-lists/unsafe-queue/extra-junk.md index 62dadac2..8ba0fa85 100644 --- a/src/too-many-lists/unsafe-queue/extra-junk.md +++ b/src/too-many-lists/unsafe-queue/extra-junk.md @@ -141,10 +141,12 @@ impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T; fn next(&mut self) -> Option { - self.next.map(|node| { - self.next = node.next.as_deref(); - &node.elem - }) + unsafe { + self.next.map(|node| { + self.next = node.next.as_ref(); + &node.elem + }) + } } } @@ -152,10 +154,12 @@ impl<'a, T> Iterator for IterMut<'a, T> { type Item = &'a mut T; fn next(&mut self) -> Option { - self.next.take().map(|node| { - self.next = node.next.as_deref_mut(); - &mut node.elem - }) + unsafe { + self.next.take().map(|node| { + self.next = node.next.as_mut(); + &mut node.elem + }) + } } } ```