Merge pull request #928 from zongzi531/hotfix/deque

fix: typo shell symbol in cargo script and etc
pull/934/head
Sunface 2 years ago committed by GitHub
commit e9f435d083
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -432,6 +432,7 @@ fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
```shell ```shell
$ cargo run $ cargo run
Running `target/debug/hello_macro` Running `target/debug/hello_macro`
Hello, Macro! My name is Sunfei! Hello, Macro! My name is Sunfei!
Hello, Macro! My name is Sunface! Hello, Macro! My name is Sunface!

@ -11,7 +11,7 @@ $ rustup update stable
## 基于源码的代码覆盖 ## 基于源码的代码覆盖
rustc 新增了基于 LLVM 的代码覆盖率测量,想要测试的同学可以通过以下方式重新构建你的项目: rustc 新增了基于 LLVM 的代码覆盖率测量,想要测试的同学可以通过以下方式重新构建你的项目:
```shell ```shell
RUSTFLAGS="-C instrument-coverage" cargo build $ RUSTFLAGS="-C instrument-coverage" cargo build
``` ```
运行新生成的可执行文件将在当前目录下产生一个 `default.profraw` 文件( 路径和文件名可以通过环境变量进行[覆盖](https://doc.rust-lang.org/stable/rustc/instrument-coverage.html#running-the-instrumented-binary-to-generate-raw-coverage-profiling-data) )。 运行新生成的可执行文件将在当前目录下产生一个 `default.profraw` 文件( 路径和文件名可以通过环境变量进行[覆盖](https://doc.rust-lang.org/stable/rustc/instrument-coverage.html#running-the-instrumented-binary-to-generate-raw-coverage-profiling-data) )。

@ -46,7 +46,7 @@ lto = true
然后在构建时使用 `--profile` 来指定想要选择的自定义 profile 然后在构建时使用 `--profile` 来指定想要选择的自定义 profile
```shell ```shell
cargo build --profile release-lto $ cargo build --profile release-lto
``` ```
与默认的 profile 相同,自定义 profile 的编译结果也存放在 [`target/`](https://course.rs/cargo/guide/build-cache.html) 下的同名目录中,例如 `--profile release-lto` 的输出结果存储在 `target/release-lto` 中。 与默认的 profile 相同,自定义 profile 的编译结果也存放在 [`target/`](https://course.rs/cargo/guide/build-cache.html) 下的同名目录中,例如 `--profile release-lto` 的输出结果存储在 `target/release-lto` 中。

@ -501,7 +501,8 @@ test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; fini
其中还有一点值得注意,那就是测试模块 `tests` 的名称也出现在了最终结果中:`tests::add_two_and_two`,这是非常贴心的细节,也意味着我们可以通过**模块名称来过滤测试** 其中还有一点值得注意,那就是测试模块 `tests` 的名称也出现在了最终结果中:`tests::add_two_and_two`,这是非常贴心的细节,也意味着我们可以通过**模块名称来过滤测试**
```shell ```shell
cargo test tests $ cargo test tests
running 3 tests running 3 tests
test tests::add_two_and_two ... ok test tests::add_two_and_two ... ok
test tests::add_three_and_two ... ok test tests::add_three_and_two ... ok

@ -189,7 +189,7 @@ mod test {
``` ```
```shell ```shell
> cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a

@ -85,7 +85,7 @@ mod test {
} }
``` ```
```shell ```shell
> cargo test $ cargo test
running 18 tests running 18 tests
test fifth::test::into_iter ... ok test fifth::test::into_iter ... ok
@ -149,7 +149,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
``` ```
```shell ```shell
> cargo test $ cargo test
error[E0521]: borrowed data escapes outside of closure error[E0521]: borrowed data escapes outside of closure
--> src\silly2.rs:47:32 --> src\silly2.rs:47:32
@ -194,7 +194,7 @@ fn elegance() {
``` ```
```shell ```shell
> cargo test $ cargo test
error[E0521]: borrowed data escapes outside of closure error[E0521]: borrowed data escapes outside of closure
--> src\silly2.rs:46:17 --> src\silly2.rs:46:17
@ -296,7 +296,7 @@ fn cell() {
``` ```
```shell ```shell
> cargo test $ cargo test
running 19 tests running 19 tests
test fifth::test::into_iter ... ok test fifth::test::into_iter ... ok

@ -170,7 +170,7 @@ pub fn pop(&mut self) -> Option<i32> {
以上代码果不其然又报错了: 以上代码果不其然又报错了:
```shell ```shell
> cargo build $ cargo build
error[E0507]: cannot move out of borrowed content error[E0507]: cannot move out of borrowed content
--> src/first.rs:28:15 --> src/first.rs:28:15

@ -43,7 +43,7 @@ mod test {
`src/first.rs` 中添加以上测试模块,然后使用 `cargo test` 运行相关的测试用例: `src/first.rs` 中添加以上测试模块,然后使用 `cargo test` 运行相关的测试用例:
```shell ```shell
> cargo test $ cargo test
error[E0433]: failed to resolve: use of undeclared type or module `List` error[E0433]: failed to resolve: use of undeclared type or module `List`
--> src/first.rs:43:24 --> src/first.rs:43:24
@ -150,7 +150,7 @@ impl Drop for List {
测试下上面的实现以及之前的长链表例子: 测试下上面的实现以及之前的长链表例子:
```shell ```shell
> cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a

@ -48,7 +48,7 @@ pub enum List {
``` ```
```shell ```shell
> cargo build $ cargo build
Finished dev [unoptimized + debuginfo] target(s) in 0.22s Finished dev [unoptimized + debuginfo] target(s) in 0.22s
``` ```

@ -51,7 +51,7 @@ fn into_iter() {
``` ```
```shell ```shell
cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a
@ -84,7 +84,7 @@ impl<T> List<T> {
``` ```
```shell ```shell
> cargo build $ cargo build
``` ```
迄今为止一切运行正常,接下来的 `next` 实现起来会有些麻烦: 迄今为止一切运行正常,接下来的 `next` 实现起来会有些麻烦:
@ -101,7 +101,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
``` ```
```shell ```shell
cargo build $ cargo build
error[E0521]: borrowed data escapes outside of closure error[E0521]: borrowed data escapes outside of closure
--> src/fourth.rs:155:13 --> src/fourth.rs:155:13
@ -157,7 +157,8 @@ fn next(&mut self) -> Option<Self::Item> {
``` ```
```shell ```shell
cargo build $ cargo build
Compiling lists v0.1.0 (/Users/ABeingessner/dev/temp/lists) Compiling lists v0.1.0 (/Users/ABeingessner/dev/temp/lists)
error[E0521]: borrowed data escapes outside of closure error[E0521]: borrowed data escapes outside of closure
--> src/fourth.rs:159:13 --> src/fourth.rs:159:13

@ -57,7 +57,7 @@ impl<T> List<T> {
除此之外,我们还需要处理一些关于空链表的边界问题:对于绝大部分操作而言,可能只需要使用 `head``tail` 指针,但是对于空链表,则需要同时使用它们。 除此之外,我们还需要处理一些关于空链表的边界问题:对于绝大部分操作而言,可能只需要使用 `head``tail` 指针,但是对于空链表,则需要同时使用它们。
一个验证方法 `methods` 是否有效的办法就是看它是否能保持不变性, 每个节点都应该有两个指针指向它: 中间的节点被它前后的节点所指向,而头部的节点除了被它后面的节点所指向外,还会被链表本身所指向,尾部的节点亦是如此。 一个验证方法 `methods` 是否有效的办法就是看它是否能保持不变性, 每个节点都应该有两个指针指向它: 中间的节点被它前后的节点所指向,而头部的节点除了被它后面的节点所指向外,还会被链表本身所指向,尾部的节点亦是如此。
```rust ```rust
pub fn push_front(&mut self, elem: T) { pub fn push_front(&mut self, elem: T) {
@ -79,7 +79,7 @@ pub fn push_front(&mut self, elem: T) {
``` ```
```rust ```rust
cargo build > cargo build
error[E0609]: no field `prev` on type `std::rc::Rc<std::cell::RefCell<fourth::Node<T>>>` error[E0609]: no field `prev` on type `std::rc::Rc<std::cell::RefCell<fourth::Node<T>>>`
--> src/fourth.rs:39:26 --> src/fourth.rs:39:26
@ -115,7 +115,7 @@ pub fn push_front(&mut self, elem: T) {
``` ```
```shell ```shell
> cargo build $ cargo build
warning: field is never used: `elem` warning: field is never used: `elem`
--> src/fourth.rs:12:5 --> src/fourth.rs:12:5
@ -152,7 +152,7 @@ pub fn pop_front(&mut self) -> Option<T> {
``` ```
```shell ```shell
> cargo build $ cargo build
error[E0609]: no field `elem` on type `std::rc::Rc<std::cell::RefCell<fourth::Node<T>>>` error[E0609]: no field `elem` on type `std::rc::Rc<std::cell::RefCell<fourth::Node<T>>>`
--> src/fourth.rs:64:22 --> src/fourth.rs:64:22
@ -180,7 +180,7 @@ pub fn pop_front(&mut self) -> Option<T> {
``` ```
```shell ```shell
cargo build $ cargo build
error[E0507]: cannot move out of borrowed content error[E0507]: cannot move out of borrowed content
--> src/fourth.rs:64:13 --> src/fourth.rs:64:13
@ -203,7 +203,7 @@ old_head.into_inner().elem
``` ```
```shell ```shell
> cargo build $ cargo build
error[E0507]: cannot move out of an `Rc` error[E0507]: cannot move out of an `Rc`
--> src/fourth.rs:64:13 --> src/fourth.rs:64:13
@ -222,7 +222,7 @@ Rc::try_unwrap(old_head).unwrap().into_inner().elem
`Rc::try_unwrap` 返回一个 `Result`,由于我们不关心 `Err` 的情况( 如果代码合理,这里不会是 `Err` ),直接使用 `unwrap` 即可。 `Rc::try_unwrap` 返回一个 `Result`,由于我们不关心 `Err` 的情况( 如果代码合理,这里不会是 `Err` ),直接使用 `unwrap` 即可。
```shell ```shell
> cargo build $ cargo build
error[E0599]: no method named `unwrap` found for type `std::result::Result<std::cell::RefCell<fourth::Node<T>>, std::rc::Rc<std::cell::RefCell<fourth::Node<T>>>>` in the current scope error[E0599]: no method named `unwrap` found for type `std::result::Result<std::cell::RefCell<fourth::Node<T>>, std::rc::Rc<std::cell::RefCell<fourth::Node<T>>>>` in the current scope
--> src/fourth.rs:64:38 --> src/fourth.rs:64:38
@ -242,7 +242,7 @@ Rc::try_unwrap(old_head).ok().unwrap().into_inner().elem
``` ```
```shell ```shell
cargo build $ cargo build
``` ```
终于成功的运行了,下面依然是惯例 - 写几个测试用例 : 终于成功的运行了,下面依然是惯例 - 写几个测试用例 :
@ -283,7 +283,7 @@ mod test {
``` ```
```shell ```shell
cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a
@ -302,7 +302,7 @@ test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured
``` ```
## Drop ## Drop
在[循环引用章节](),我们介绍过 `Rc` 最怕的就是引用形成循环,而双向链表恰恰如此。因此,当使用默认的实现来 `drop` 我们的链表时,两个节点会将各自的引用计数减少到 1 然后就不会继续减少,最终造成内存泄漏。 在[循环引用章节](),我们介绍过 `Rc` 最怕的就是引用形成循环,而双向链表恰恰如此。因此,当使用默认的实现来 `drop` 我们的链表时,两个节点会将各自的引用计数减少到 1 然后就不会继续减少,最终造成内存泄漏。
所以,这里最好的实现就是将每个节点 `pop` 出去,直到获得 `None`: 所以,这里最好的实现就是将每个节点 `pop` 出去,直到获得 `None`:
```rust ```rust

@ -20,7 +20,7 @@ pub fn peek_front(&self) -> Option<&T> {
``` ```
```shell ```shell
cargo build $ cargo build
error[E0515]: cannot return value referencing temporary value error[E0515]: cannot return value referencing temporary value
--> src/fourth.rs:66:13 --> src/fourth.rs:66:13
@ -58,7 +58,7 @@ pub fn peek_front(&self) -> Option<Ref<T>> {
``` ```
```shell ```shell
> cargo build $ cargo build
error[E0308]: mismatched types error[E0308]: mismatched types
--> src/fourth.rs:64:9 --> src/fourth.rs:64:9
@ -94,7 +94,7 @@ pub fn peek_front(&self) -> Option<Ref<T>> {
``` ```
```shell ```shell
> cargo build $ cargo build
``` ```
Gooood! 本章节的编译错误可以说是多个链表中最难解决的之一,依然被我们成功搞定了! Gooood! 本章节的编译错误可以说是多个链表中最难解决的之一,依然被我们成功搞定了!
@ -114,7 +114,7 @@ fn peek() {
``` ```
```shell ```shell
> cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a

@ -139,7 +139,7 @@ fn peek() {
什么?你问我这里的测试用例全吗?只能说如果测试全部的组合情况,这一章节会被撑爆。至于现在,能不出错就谢天谢地了 :( 什么?你问我这里的测试用例全吗?只能说如果测试全部的组合情况,这一章节会被撑爆。至于现在,能不出错就谢天谢地了 :(
```shell ```shell
> cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a

@ -18,8 +18,8 @@
#### 创建一个项目 #### 创建一个项目
在开始前,先来创建一个项目专门用于链表学习: 在开始前,先来创建一个项目专门用于链表学习:
```shell ```shell
> cargo new --lib lists $ cargo new --lib lists
> cd lists $ cd lists
``` ```
之后,我们会将每个一个链表放入单独的文件中,需要注意的是我们会尽量模拟真实的 Rust 开发场景:你写了一段代码,然后编译器开始跳出试图教你做事,只有这样才能真正学会 Rust温室环境是无法培养出强大的 Rustacean 的。 之后,我们会将每个一个链表放入单独的文件中,需要注意的是我们会尽量模拟真实的 Rust 开发场景:你写了一段代码,然后编译器开始跳出试图教你做事,只有这样才能真正学会 Rust温室环境是无法培养出强大的 Rustacean 的。

@ -55,7 +55,7 @@ fn into_iter() {
``` ```
```shell ```shell
> cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a
@ -97,7 +97,7 @@ impl<T> Iterator for Iter<T> {
``` ```
```shell ```shell
> cargo build $ cargo build
error[E0106]: missing lifetime specifier error[E0106]: missing lifetime specifier
--> src/second.rs:72:18 --> src/second.rs:72:18
@ -122,7 +122,7 @@ pub struct Iter<'a, T> {
``` ```
```shell ```shell
> cargo build $ cargo build
error[E0106]: missing lifetime specifier error[E0106]: missing lifetime specifier
--> src/second.rs:83:22 --> src/second.rs:83:22
@ -163,7 +163,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
``` ```
```shell ```shell
> cargo build $ cargo build
error: expected `:`, found `node` error: expected `:`, found `node`
--> src/second.rs:77:47 --> src/second.rs:77:47
@ -217,7 +217,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
现在,我们也许可以自信的编译下试试了: 现在,我们也许可以自信的编译下试试了:
```shell ```shell
> cargo build $ cargo build
error[E0308]: mismatched types error[E0308]: mismatched types
--> src/second.rs:77:22 --> src/second.rs:77:22
@ -260,7 +260,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
``` ```
```shell ```shell
> cargo build $ cargo build
Compiling lists v0.1.0 (/Users/ABeingessner/dev/temp/lists) Compiling lists v0.1.0 (/Users/ABeingessner/dev/temp/lists)
error[E0515]: cannot return reference to local data `*node` error[E0515]: cannot return reference to local data `*node`
@ -315,7 +315,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
``` ```
```shell ```shell
> cargo build $ cargo build
Compiling lists v0.1.0 (/Users/ABeingessner/dev/temp/lists) Compiling lists v0.1.0 (/Users/ABeingessner/dev/temp/lists)
error[E0308]: mismatched types error[E0308]: mismatched types
@ -364,7 +364,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
``` ```
```shell ```shell
> cargo build $ cargo build
``` ```
🎉 🎉 🎉 🎉 🎉 🎉
@ -402,7 +402,7 @@ fn iter() {
``` ```
```shell ```shell
> cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a

@ -57,7 +57,7 @@ impl<'a, T> Iterator for IterMut<'a, T> {
``` ```
```shell ```shell
> cargo build $ cargo build
error[E0596]: cannot borrow `self.head` as mutable, as it is behind a `&` reference error[E0596]: cannot borrow `self.head` as mutable, as it is behind a `&` reference
--> src/second.rs:95:25 --> src/second.rs:95:25
@ -96,7 +96,7 @@ fn next(&mut self) -> Option<Self::Item> {
``` ```
```shell ```shell
> cargo build $ cargo build
``` ```
老规矩,来测试下: 老规矩,来测试下:
@ -114,7 +114,7 @@ fn iter_mut() {
``` ```
```shell ```shell
> cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a

@ -12,7 +12,7 @@ pub fn peek(&self) -> Option<&T> {
``` ```
```shell ```shell
> cargo build $ cargo build
error[E0515]: cannot return reference to local data `node.elem` error[E0515]: cannot return reference to local data `node.elem`
--> src/second.rs:37:13 --> src/second.rs:37:13
@ -46,7 +46,7 @@ pub fn peek(&self) -> Option<&T> {
``` ```
```shell ```shell
> cargo build $ cargo build
Finished dev [unoptimized + debuginfo] target(s) in 0.32s Finished dev [unoptimized + debuginfo] target(s) in 0.32s
``` ```
@ -81,7 +81,7 @@ fn peek() {
``` ```
```shell ```shell
> cargo test $ cargo test
error[E0384]: cannot assign twice to immutable variable `value` error[E0384]: cannot assign twice to immutable variable `value`
--> src/second.rs:100:13 --> src/second.rs:100:13
@ -124,7 +124,7 @@ fn peek() {
这次我们直接匹配出来可变引用 `value`,然后对其修改即可。 这次我们直接匹配出来可变引用 `value`,然后对其修改即可。
```shell ```shell
> cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a

@ -126,7 +126,7 @@ pub fn pop(&mut self) -> Option<i32> {
不错,看上去简洁了很多,下面运行下测试代码确保链表依然可以正常运行(这就是 TDD 的优点!) : 不错,看上去简洁了很多,下面运行下测试代码确保链表依然可以正常运行(这就是 TDD 的优点!) :
```shell ```shell
> cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a
@ -188,7 +188,7 @@ impl<T> Drop for List<T> {
大家在修改了 `List` 的定义后,别忘了将 `impl` 中的 `List` 修改为 `List<T>`,切记**泛型参数也是类型定义的一部分**。 大家在修改了 `List` 的定义后,别忘了将 `impl` 中的 `List` 修改为 `List<T>`,切记**泛型参数也是类型定义的一部分**。
```shell ```shell
> cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a

@ -49,7 +49,8 @@ list3 -> X ---+
测试下新的代码: 测试下新的代码:
```shell ```shell
cargo test $ cargo test
Compiling lists v0.1.0 (/Users/ABeingessner/dev/too-many-lists/lists) Compiling lists v0.1.0 (/Users/ABeingessner/dev/too-many-lists/lists)
Finished dev [unoptimized + debuginfo] target(s) in 1.10s Finished dev [unoptimized + debuginfo] target(s) in 1.10s
Running /Users/ABeingessner/dev/too-many-lists/lists/target/debug/deps/lists-86544f1d97438f1f Running /Users/ABeingessner/dev/too-many-lists/lists/target/debug/deps/lists-86544f1d97438f1f

@ -74,7 +74,7 @@ pub fn prepend(&self, elem: T) -> List<T> {
运行下试试: 运行下试试:
```shell ```shell
> cargo build $ cargo build
warning: field is never used: `elem` warning: field is never used: `elem`
--> src/third.rs:10:5 --> src/third.rs:10:5
@ -101,7 +101,7 @@ pub fn tail(&self) -> List<T> {
``` ```
```shell ```shell
cargo build $ cargo build
error[E0308]: mismatched types error[E0308]: mismatched types
--> src/third.rs:27:22 --> src/third.rs:27:22
@ -159,7 +159,7 @@ mod test {
``` ```
```shell ```shell
> cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a
@ -211,7 +211,7 @@ fn iter() {
``` ```
```shell ```shell
cargo test $ cargo test
Running target/debug/lists-5c71138492ad4b4a Running target/debug/lists-5c71138492ad4b4a

@ -13,7 +13,7 @@ impl<T> List<T> {
但是我们不再在 `tail` 中使用 `Option`: 但是我们不再在 `tail` 中使用 `Option`:
```shell ```shell
> cargo build $ cargo build
error[E0308]: mismatched types error[E0308]: mismatched types
--> src/fifth.rs:15:34 --> src/fifth.rs:15:34
@ -73,7 +73,7 @@ pub fn push(&mut self, elem: T) {
``` ```
```shell ```shell
> cargo build $ cargo build
error[E0609]: no field `next` on type `*mut fifth::Node<T>` error[E0609]: no field `next` on type `*mut fifth::Node<T>`
--> src/fifth.rs:31:23 --> src/fifth.rs:31:23
@ -91,7 +91,7 @@ error[E0609]: no field `next` on type `*mut fifth::Node<T>`
``` ```
```shell ```shell
> cargo build $ cargo build
error[E0609]: no field `next` on type `*mut fifth::Node<T>` error[E0609]: no field `next` on type `*mut fifth::Node<T>`
--> src/fifth.rs:31:23 --> src/fifth.rs:31:23
@ -109,7 +109,7 @@ error[E0609]: no field `next` on type `*mut fifth::Node<T>`
``` ```
```shell ```shell
> cargo build $ cargo build
error[E0133]: dereference of raw pointer is unsafe and requires error[E0133]: dereference of raw pointer is unsafe and requires
unsafe function or block unsafe function or block
@ -149,7 +149,7 @@ pub fn push(&mut self, elem: T) {
``` ```
```shell ```shell
> cargo build $ cargo build
warning: field is never used: `elem` warning: field is never used: `elem`
--> src/fifth.rs:11:5 --> src/fifth.rs:11:5
| |
@ -225,7 +225,7 @@ mod test {
摊牌了,我们偷懒了,这些测试就是从之前的栈链表赋值过来的,但是依然做了些改变,例如在末尾增加了几个步骤以确保在 `pop` 中不会发生尾指针损坏( tail-pointer corruption )的情况。 摊牌了,我们偷懒了,这些测试就是从之前的栈链表赋值过来的,但是依然做了些改变,例如在末尾增加了几个步骤以确保在 `pop` 中不会发生尾指针损坏( tail-pointer corruption )的情况。
```shell ```shell
cargo test $ cargo test
running 12 tests running 12 tests
test fifth::test::basics ... ok test fifth::test::basics ... ok

@ -82,7 +82,7 @@ impl<T> List<T> {
但是如果你担心不再能看到错误,那就纯属多余了: 但是如果你担心不再能看到错误,那就纯属多余了:
```shell ```shell
> cargo build $ cargo build
error[E0382]: use of moved value: `new_tail` error[E0382]: use of moved value: `new_tail`
--> src/fifth.rs:38:38 --> src/fifth.rs:38:38
@ -139,7 +139,7 @@ impl<T> List<T> {
``` ```
```shell ```shell
> cargo build $ cargo build
error[E0106]: missing lifetime specifier error[E0106]: missing lifetime specifier
--> src/fifth.rs:3:18 --> src/fifth.rs:3:18
@ -190,7 +190,7 @@ impl<'a, T> List<'a, T> {
``` ```
```shell ```shell
cargo build $ cargo build
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/fifth.rs:35:27 --> src/fifth.rs:35:27
@ -235,7 +235,7 @@ pub fn push(&'a mut self, elem: T) {
当当当当,成功通过编译: 当当当当,成功通过编译:
```shell ```shell
cargo build $ cargo build
warning: field is never used: `elem` warning: field is never used: `elem`
--> src/fifth.rs:9:5 --> src/fifth.rs:9:5
@ -297,7 +297,7 @@ mod test {
} }
``` ```
```shell ```shell
cargo test $ cargo test
error[E0499]: cannot borrow `list` as mutable more than once at a time error[E0499]: cannot borrow `list` as mutable more than once at a time
--> src/fifth.rs:68:9 --> src/fifth.rs:68:9

@ -196,7 +196,7 @@ mod test {
``` ```
```shell ```shell
cargo test $ cargo test
running 12 tests running 12 tests
test fifth::test::basics ... ok test fifth::test::basics ... ok

@ -36,7 +36,7 @@ info: installing component 'miri'
> + 是一种临时性的规则运用,如果你不想每次都使用 `+nightly-2022-01-21`,可以使用 [`rustup override set`](https://course.rs/appendix/rust-version.html#rustup-和-rust-nightly-的职责) 命令对当前项目的 Rust 版本进行覆盖 > + 是一种临时性的规则运用,如果你不想每次都使用 `+nightly-2022-01-21`,可以使用 [`rustup override set`](https://course.rs/appendix/rust-version.html#rustup-和-rust-nightly-的职责) 命令对当前项目的 Rust 版本进行覆盖
```shell ```shell
> cargo +nightly-2022-01-21 miri test $ cargo +nightly-2022-01-21 miri test
I will run `"cargo.exe" "install" "xargo"` to install I will run `"cargo.exe" "install" "xargo"` to install
a recent enough xargo. Proceed? [Y/n] a recent enough xargo. Proceed? [Y/n]
@ -146,7 +146,7 @@ UB 检测是必须的,因为它发生在运行时,因此很难发现,如
总之,`miri` 的使用很简单: 总之,`miri` 的使用很简单:
```shell ```shell
> cargo +nightly-2022-01-21 miri test $ cargo +nightly-2022-01-21 miri test
``` ```
下面来看看具体的错误: 下面来看看具体的错误:

@ -50,7 +50,8 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
Compiling miri-sandbox v0.1.0 Compiling miri-sandbox v0.1.0
Finished dev [unoptimized + debuginfo] target(s) in 0.71s Finished dev [unoptimized + debuginfo] target(s) in 0.71s
Running `target\debug\miri-sandbox.exe` Running `target\debug\miri-sandbox.exe`
@ -101,7 +102,8 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
22 22
``` ```
@ -141,7 +143,8 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
20 20
MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run
@ -172,7 +175,8 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
[3, 3, 0, 0, 0, 0, 0, 0, 0, 0] [3, 3, 0, 0, 0, 0, 0, 0, 0, 0]
``` ```
@ -206,7 +210,8 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
[6, 0, 0, 0, 0, 0, 0, 0, 0, 0] [6, 0, 0, 0, 0, 0, 0, 0, 0, 0]
MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run
@ -238,7 +243,7 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
[20, 0, 0, 0, 0, 0, 0, 0, 0, 0] [20, 0, 0, 0, 0, 0, 0, 0, 0, 0]
MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run
@ -310,7 +315,7 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
[10, 12, 0, 0, 0, 0, 0, 0, 0, 0] [10, 12, 0, 0, 0, 0, 0, 0, 0, 0]
MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run
@ -353,7 +358,7 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
[8, 12, 4, 6, 8, 10, 12, 14, 16, 18] [8, 12, 4, 6, 8, 10, 12, 14, 16, 18]
MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run
@ -393,7 +398,7 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
warning: unnecessary `unsafe` block warning: unnecessary `unsafe` block
--> src\main.rs:6:1 --> src\main.rs:6:1
@ -436,7 +441,7 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
error[E0606]: casting `&i32` as `*mut i32` is invalid error[E0606]: casting `&i32` as `*mut i32` is invalid
--> src/main.rs:11:20 --> src/main.rs:11:20
@ -454,7 +459,7 @@ let ptr4 = sref3 as *const i32 as *mut i32;
如上,先将不可变引用转换成不可变的裸指针,然后再转换成可变的裸指针。 如上,先将不可变引用转换成不可变的裸指针,然后再转换成可变的裸指针。
```shell ```shell
cargo run $ cargo run
14 14
17 17
@ -502,7 +507,8 @@ unsafe {
可以看到,我们其实可以创建一个可变的裸指针,只要不去使用写操作,而是只使用读操作。 可以看到,我们其实可以创建一个可变的裸指针,只要不去使用写操作,而是只使用读操作。
```shell ```shell
cargo run $ cargo run
10 10
10 10
13 13
@ -534,7 +540,8 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
12 12
13 13
@ -578,7 +585,8 @@ unsafe {
地狱一般的代码,就等着 miri 来优化你吧。 地狱一般的代码,就等着 miri 来优化你吧。
```shell ```shell
cargo run $ cargo run
16 16
MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run
@ -624,7 +632,8 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
12 12
16 16
@ -666,7 +675,8 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
13 13
16 16
@ -694,7 +704,8 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
21 21
MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run
@ -726,7 +737,8 @@ unsafe {
``` ```
```shell ```shell
cargo run $ cargo run
21 21
MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo +nightly-2022-01-21 miri run

Loading…
Cancel
Save