From a53a404fb83e1a1c30ba52ee68c71f284c13f7cb Mon Sep 17 00:00:00 2001 From: husharp Date: Mon, 12 Dec 2022 20:44:32 +0800 Subject: [PATCH 1/7] update fifth-extras Signed-off-by: husharp --- src/too-many-lists/unsafe-queue/extra-junk.md | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) 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 + }) + } } } ``` From 8da054261212f0480323e930db5ff43df0b06771 Mon Sep 17 00:00:00 2001 From: unlsycn Date: Sat, 17 Dec 2022 11:19:00 +0800 Subject: [PATCH 2/7] fix broken link --- src/too-many-lists/intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 来实现链表。 From a774b953364a7b8a1bba2dc0a18fcac1a5fdfbbc Mon Sep 17 00:00:00 2001 From: riba2534 Date: Sat, 17 Dec 2022 19:27:45 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8F=8F=E8=BF=B0?= =?UTF-8?q?=E4=BD=BF=E4=B8=8A=E4=B8=8B=E5=8F=A5=E7=94=A8=E5=90=8C=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E8=AF=8D=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/basic/ownership/borrowing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/ownership/borrowing.md b/src/basic/ownership/borrowing.md index f36bf184..5d09fed7 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 也一样。 From 07c033c8003dd74a3760537b714f981ece64813d Mon Sep 17 00:00:00 2001 From: Ykong <66518156+Ykong1337@users.noreply.github.com> Date: Wed, 21 Dec 2022 14:04:57 +0800 Subject: [PATCH 4/7] Update advance.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 解决闭包不遵循生命周期消除规则问题 --- src/advance/lifetime/advance.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/advance/lifetime/advance.md b/src/advance/lifetime/advance.md index 37f5e126..2c759bc5 100644 --- a/src/advance/lifetime/advance.md +++ b/src/advance/lifetime/advance.md @@ -234,7 +234,19 @@ 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: F) -> F { + f +} +``` 对于函数的生命周期而言,它的消除规则之所以能生效是因为它的生命周期完全体现在签名的引用类型上,在函数体中无需任何体现: From 548d9054cce6ce55a0c4db53ec537e4e13e15377 Mon Sep 17 00:00:00 2001 From: Sunface Date: Sun, 25 Dec 2022 12:21:05 +0800 Subject: [PATCH 5/7] Update src/basic/ownership/borrowing.md --- src/basic/ownership/borrowing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/ownership/borrowing.md b/src/basic/ownership/borrowing.md index 5d09fed7..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 也一样。 From f68cc76bff263968130795043fd31138d7c3c8ee Mon Sep 17 00:00:00 2001 From: sunface Date: Sun, 25 Dec 2022 13:19:22 +0800 Subject: [PATCH 6/7] fix #1085 --- src/basic/comment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 = "???"; // 今年其实。。。挺大了 From 0491ea124473b2d294b9414bae6ee58661d38f11 Mon Sep 17 00:00:00 2001 From: sunface Date: Sun, 25 Dec 2022 13:26:27 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E5=9F=BA=E4=BA=8E@Ykong1337=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E7=9A=84PR=E5=AE=8C=E5=96=84=E4=B8=8B=E6=96=87?= =?UTF-8?q?=E5=AD=97=E7=BB=84=E7=BB=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/advance/lifetime/advance.md | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/advance/lifetime/advance.md b/src/advance/lifetime/advance.md index 2c759bc5..d0372024 100644 --- a/src/advance/lifetime/advance.md +++ b/src/advance/lifetime/advance.md @@ -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: 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: F) -> F { +> f +> } +> ``` ## NLL (Non-Lexical Lifetime) 之前我们在[引用与借用](https://course.rs/basic/ownership/borrowing.html#NLL)那一章其实有讲到过这个概念,简单来说就是:**引用的生命周期正常来说应该从借用开始一直持续到作用域结束**,但是这种规则会让多引用共存的情况变得更复杂: