Skip to content

Instantly share code, notes, and snippets.

@JakubKoralewski
Last active March 15, 2020 12:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JakubKoralewski/ead81de516dfb3218857dabc38122c63 to your computer and use it in GitHub Desktop.
Save JakubKoralewski/ead81de516dfb3218857dabc38122c63 to your computer and use it in GitHub Desktop.
zrobiłem diff tego repo z commita [94308a2](https://github.com/paytchoo/book-pl/commit/94308a22e7bcd089a806e8e6eb11d9294667eb66) i [rust-lang/book 6fb3705e](https://github.com/rust-lang/book/commit/6fb3705e5230311b096d47f7e2c91f9ce24393d0) komendą `git diff --no-index --name-only book-original/src book-pl-en/src > diff-to-new.txt`. Wynik zamiesz…
diff --git a/book-original/src/SUMMARY.md b/book-pl-en/src/SUMMARY.md
index a9b8feb..4139eb0 100644
--- a/book-original/src/SUMMARY.md
+++ b/book-pl-en/src/SUMMARY.md
@@ -1,6 +1,5 @@
# The Rust Programming Language
-[The Rust Programming Language](title-page.md)
[Foreword](foreword.md)
[Introduction](ch00-00-introduction.md)
@@ -37,12 +36,9 @@
## Basic Rust Literacy
-- [Managing Growing Projects with Packages, Crates, and Modules](ch07-00-managing-growing-projects-with-packages-crates-and-modules.md)
- - [Packages and Crates](ch07-01-packages-and-crates.md)
- - [Defining Modules to Control Scope and Privacy](ch07-02-defining-modules-to-control-scope-and-privacy.md)
- - [Paths for Referring to an Item in the Module Tree](ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md)
- - [Bringing Paths Into Scope with the `use` Keyword](ch07-04-bringing-paths-into-scope-with-the-use-keyword.md)
- - [Separating Modules into Different Files](ch07-05-separating-modules-into-different-files.md)
+- [Packages, Crates, and Modules](ch07-00-packages-crates-and-modules.md)
+ - [Packages and Crates for Making Libraries and Executables](ch07-01-packages-and-crates-for-making-libraries-and-executables.md)
+ - [The Module System to Control Scope and Privacy](ch07-02-modules-and-use-to-control-scope-and-privacy.md)
- [Common Collections](ch08-00-common-collections.md)
- [Storing Lists of Values with Vectors](ch08-01-vectors.md)
@@ -115,6 +111,7 @@
- [Advanced Features](ch19-00-advanced-features.md)
- [Unsafe Rust](ch19-01-unsafe-rust.md)
+ - [Advanced Lifetimes](ch19-02-advanced-lifetimes.md)
- [Advanced Traits](ch19-03-advanced-traits.md)
- [Advanced Types](ch19-04-advanced-types.md)
- [Advanced Functions and Closures](ch19-05-advanced-functions-and-closures.md)
diff --git a/book-original/src/appendix-01-keywords.md b/book-pl-en/src/appendix-01-keywords.md
index c19b8a1..e9439ee 100644
--- a/book-original/src/appendix-01-keywords.md
+++ b/book-pl-en/src/appendix-01-keywords.md
@@ -1,13 +1,10 @@
## Appendix A: Keywords
The following list contains keywords that are reserved for current or future
-use by the Rust language. As such, they cannot be used as identifiers (except
-as raw identifiers as we’ll discuss in the “[Raw
-Identifiers][raw-identifiers]<!-- ignore -->” section), including names of
-functions, variables, parameters, struct fields, modules, crates, constants,
-macros, static values, attributes, types, traits, or lifetimes.
-
-[raw-identifiers]: #raw-identifiers
+use by the Rust language. As such, they cannot be used as identifiers (except as
+[raw identifiers][raw-identifiers]), including names of functions, variables,
+parameters, struct fields, modules, crates, constants, macros, static values,
+attributes, types, traits, or lifetimes.
### Keywords Currently in Use
@@ -15,8 +12,6 @@ The following keywords currently have the functionality described.
* `as` - perform primitive casting, disambiguate the specific trait containing
an item, or rename items in `use` and `extern crate` statements
-* `async` - return a `Future` instead of blocking the current thread
-* `await` - suspend execution until the result of a `Future` is ready
* `break` - exit a loop immediately
* `const` - define constant items or constant raw pointers
* `continue` - continue to the next loop iteration
@@ -42,7 +37,7 @@ The following keywords currently have the functionality described.
* `pub` - denote public visibility in struct fields, `impl` blocks, or modules
* `ref` - bind by reference
* `return` - return from function
-* `Self` - a type alias for the type we are defining or implementing
+* `Self` - a type alias for the type implementing a trait
* `self` - method subject or current module
* `static` - global variable or lifetime lasting the entire program execution
* `struct` - define a structure
@@ -61,6 +56,7 @@ The following keywords do not have any functionality but are reserved by Rust
for potential future use.
* `abstract`
+* `async`
* `become`
* `box`
* `do`
@@ -74,23 +70,21 @@ for potential future use.
* `virtual`
* `yield`
-### Raw Identifiers
-
-*Raw identifiers* are the syntax that lets you use keywords where they wouldn’t
-normally be allowed. You use a raw identifier by prefixing a keyword with `r#`.
+### Raw identifiers
+[raw-identifiers]: #raw-identifiers
-For example, `match` is a keyword. If you try to compile the following function
-that uses `match` as its name:
+Raw identifiers let you use keywords where they would not normally be allowed by
+prefixing them with `r#`.
-<span class="filename">Filename: src/main.rs</span>
+For example, `match` is a keyword. If you try to compile this function:
-```rust,ignore,does_not_compile
+```rust,ignore
fn match(needle: &str, haystack: &str) -> bool {
haystack.contains(needle)
}
```
-you’ll get this error:
+You’ll get this error:
```text
error: expected identifier, found keyword `match`
@@ -100,11 +94,7 @@ error: expected identifier, found keyword `match`
| ^^^^^ expected identifier, found keyword
```
-The error shows that you can’t use the keyword `match` as the function
-identifier. To use `match` as a function name, you need to use the raw
-identifier syntax, like this:
-
-<span class="filename">Filename: src/main.rs</span>
+You can write this with a raw identifier:
```rust
fn r#match(needle: &str, haystack: &str) -> bool {
@@ -116,16 +106,12 @@ fn main() {
}
```
-This code will compile without any errors. Note the `r#` prefix on the function
-name in its definition as well as where the function is called in `main`.
+Note the `r#` prefix on both the function name as well as the call.
-Raw identifiers allow you to use any word you choose as an identifier, even if
-that word happens to be a reserved keyword. In addition, raw identifiers allow
-you to use libraries written in a different Rust edition than your crate uses.
-For example, `try` isn’t a keyword in the 2015 edition but is in the 2018
-edition. If you depend on a library that’s written using the 2015 edition and
-has a `try` function, you’ll need to use the raw identifier syntax, `r#try` in
-this case, to call that function from your 2018 edition code. See [Appendix
-E][appendix-e]<!-- ignore --> for more information on editions.
+#### Motivation
-[appendix-e]: appendix-05-editions.html
+This feature is useful for a few reasons, but the primary motivation was
+inter-edition situations. For example, `try` is not a keyword in the 2015
+edition, but is in the 2018 edition. So if you have a library that is written
+in Rust 2015 and has a `try` function, to call it in Rust 2018, you’ll need
+to use the raw identifier.
diff --git a/book-original/src/appendix-02-operators.md b/book-pl-en/src/appendix-02-operators.md
index e70cc73..41077ba 100644
--- a/book-original/src/appendix-02-operators.md
+++ b/book-pl-en/src/appendix-02-operators.md
@@ -36,7 +36,7 @@ overload that operator is listed.
| `-` | `- expr` | Arithmetic negation | `Neg` |
| `-` | `expr - expr` | Arithmetic subtraction | `Sub` |
| `-=` | `var -= expr` | Arithmetic subtraction and assignment | `SubAssign` |
-| `->` | `fn(...) -> type`, <code>&vert;...&vert; -> type</code> | Function and closure return type | |
+| `->` | `fn(...) -> type`, <code>\|...\| -> type</code> | Function and closure return type | |
| `.` | `expr.ident` | Member access | |
| `..` | `..`, `expr..`, `..expr`, `expr..expr` | Right-exclusive range literal | |
| `..=` | `..=expr`, `expr..=expr` | Right-inclusive range literal | |
@@ -64,10 +64,10 @@ overload that operator is listed.
| `@` | `ident @ pat` | Pattern binding | |
| `^` | `expr ^ expr` | Bitwise exclusive OR | `BitXor` |
| `^=` | `var ^= expr` | Bitwise exclusive OR and assignment | `BitXorAssign` |
-| <code>&vert;</code> | <code>pat &vert; pat</code> | Pattern alternatives | |
-| <code>&vert;</code> | <code>expr &vert; expr</code> | Bitwise OR | `BitOr` |
-| <code>&vert;=</code> | <code>var &vert;= expr</code> | Bitwise OR and assignment | `BitOrAssign` |
-| <code>&vert;&vert;</code> | <code>expr &vert;&vert; expr</code> | Logical OR | |
+| <code>\|</code> | <code>pat \| pat</code> | Pattern alternatives | |
+| <code>\|</code> | <code>expr \| expr</code> | Bitwise OR | `BitOr` |
+| <code>\|=</code> | <code>var \|= expr</code> | Bitwise OR and assignment | `BitOrAssign` |
+| <code>\|\|</code> | <code>expr \|\| expr</code> | Logical OR | |
| `?` | `expr?` | Error propagation | |
### Non-operator Symbols
@@ -90,7 +90,7 @@ locations.
| `br"..."`, `br#"..."#`, `br##"..."##`, etc. | Raw byte string literal, combination of raw and byte string literal |
| `'...'` | Character literal |
| `b'...'` | ASCII byte literal |
-| <code>&vert;...&vert; expr</code> | Closure |
+| <code>\|...\| expr</code> | Closure |
| `!` | Always empty bottom type for diverging functions |
| `_` | “Ignored” pattern binding; also used to make integer literals readable |
@@ -153,7 +153,6 @@ macros and specifying attributes on an item.
| `$ident` | Macro substitution |
| `$ident:kind` | Macro capture |
| `$(…)…` | Macro repetition |
-| `ident!(...)`, `ident!{...}`, `ident![...]` | Macro invocation |
Table B-7 shows symbols that create comments.
@@ -181,6 +180,7 @@ Table B-8 shows symbols that appear in the context of using tuples.
| `(expr, ...)` | Tuple expression |
| `(type, ...)` | Tuple type |
| `expr(expr, ...)` | Function call expression; also used to initialize tuple `struct`s and tuple `enum` variants |
+| `ident!(...)`, `ident!{...}`, `ident![...]` | Macro invocation |
| `expr.0`, `expr.1`, etc. | Tuple indexing |
Table B-9 shows the contexts in which curly braces are used.
diff --git a/book-original/src/appendix-03-derivable-traits.md b/book-pl-en/src/appendix-03-derivable-traits.md
index eb49b30..a8a862c 100644
--- a/book-original/src/appendix-03-derivable-traits.md
+++ b/book-pl-en/src/appendix-03-derivable-traits.md
@@ -14,7 +14,7 @@ library that you can use with `derive`. Each section covers:
* The conditions in which you’re allowed or not allowed to implement the trait
* Examples of operations that require the trait
-If you want different behavior from that provided by the `derive` attribute,
+If you want different behavior than that provided by the `derive` attribute,
consult the [standard library documentation](../std/index.html)<!-- ignore -->
for each trait for details of how to manually implement them.
@@ -125,9 +125,9 @@ returned from `to_vec` will need to own its instances, so `to_vec` calls
`clone` on each item. Thus, the type stored in the slice must implement `Clone`.
The `Copy` trait allows you to duplicate a value by only copying bits stored on
-the stack; no arbitrary code is necessary. See the [“Stack-Only Data:
-Copy”][stack-only-data-copy]<!-- ignore --> section in Chapter 4 for more
-information on `Copy`.
+the stack; no arbitrary code is necessary. See the [“Stack-Only Data: Copy”]
+[stack-only-data-copy]<!-- ignore --> section in Chapter 4 for more information
+on `Copy`.
The `Copy` trait doesn’t define any methods to prevent programmers from
overloading those methods and violating the assumption that no arbitrary code
@@ -167,9 +167,9 @@ derive `Default`.
The `Default::default` function is commonly used in combination with the struct
update syntax discussed in the [“Creating Instances From Other Instances With
-Struct Update
-Syntax”][creating-instances-from-other-instances-with-struct-update-syntax]<!-- ignore -->
-section in Chapter 5. You can customize a few fields of a struct and then
+Struct Update Syntax”]
+[creating-instances-from-other-instances-with-struct-update-syntax]<!-- ignore
+--> section in Chapter 5. You can customize a few fields of a struct and then
set and use a default value for the rest of the fields by using
`..Default::default()`.
diff --git a/book-original/src/appendix-04-useful-development-tools.md b/book-pl-en/src/appendix-04-useful-development-tools.md
index 33929bc..4c099de 100644
--- a/book-original/src/appendix-04-useful-development-tools.md
+++ b/book-pl-en/src/appendix-04-useful-development-tools.md
@@ -1,39 +1,41 @@
-## Appendix D - Useful Development Tools
+# Appendix D - Useful Development Tools
-In this appendix, we talk about some useful development tools that the Rust
-project provides. We’ll look at automatic formatting, quick ways to apply
-warning fixes, a linter, and integrating with IDEs.
+In this appendix, we’ll talk about tools provided by the Rust project that are
+useful when developing Rust code.
-### Automatic Formatting with `rustfmt`
+## Automatic Formatting with `rustfmt`
-The `rustfmt` tool reformats your code according to the community code style.
-Many collaborative projects use `rustfmt` to prevent arguments about which
-style to use when writing Rust: everyone formats their code using the tool.
+The tool `rustfmt` reformats your code according to the community code style.
+Many projects use `rustfmt` to prevent arguments about which style to use when
+writing Rust: everyone formats their code with the tool!
-To install `rustfmt`, enter the following:
+The `rustfmt` tool is not yet at the quality of a version 1.0 release, but
+a preview is available for you to use in the meantime. Please give it a try and
+let us know how it goes!
+
+To install `rustfmt`:
```text
-$ rustup component add rustfmt
+$ rustup component add rustfmt-preview
```
-This command gives you `rustfmt` and `cargo-fmt`, similar to how Rust gives you
-both `rustc` and `cargo`. To format any Cargo project, enter the following:
+This will give you both `rustfmt` and `cargo-fmt`, similar to how Rust gives
+you both `rustc` and `cargo`. To take any Cargo project and format it:
```text
$ cargo fmt
```
-Running this command reformats all the Rust code in the current crate. This
-should only change the code style, not the code semantics. For more information
-on `rustfmt`, see [its documentation][rustfmt].
+Running this command will reformat all of the Rust code in the current crate.
+This should only change the code style, not the code semantics. For more
+information on `rustfmt`, see [its documentation][rustfmt].
-[rustfmt]: https://github.com/rust-lang/rustfmt
+[rustfmt]: https://github.com/rust-lang-nursery/rustfmt
-### Fix Your Code with `rustfix`
+## Fix Up Your Code with `rustfix`
-The rustfix tool is included with Rust installations and can automatically fix
-some compiler warnings. If you’ve written code in Rust, you’ve probably seen
-compiler warnings. For example, consider this code:
+If you’ve written code in Rust, you’ve probably seen compiler warnings. For
+example, consider this code:
<span class="filename">Filename: src/main.rs</span>
@@ -76,7 +78,7 @@ $ cargo fix
Finished dev [unoptimized + debuginfo] target(s) in 0.59s
```
-When we look at *src/main.rs* again, we’ll see that `cargo fix` has changed the
+If we look at *src/main.rs* again, we’ll see that `cargo fix` has changed the
code:
<span class="filename">Filename: src/main.rs</span>
@@ -91,30 +93,35 @@ fn main() {
}
```
-The `for` loop variable is now named `_i`, and the warning no longer appears.
+The `for` loop variable is now named `_i`, and the warning will no longer
+appear.
+
+The `cargo fix` command can also be used to transition your code between
+different editions of Rust. Editions are covered in Appendix E.
-You can also use the `cargo fix` command to transition your code between
-different Rust editions. Editions are covered in Appendix E.
+## More Lints with `clippy`
-### More Lints with Clippy
+The `clippy` tool is a collection of lints to catch common mistakes and improve
+your Rust code.
-The Clippy tool is a collection of lints to analyze your code so you can catch
-common mistakes and improve your Rust code.
+The `clippy` tool is not yet at the quality of a version 1.0 release, but a
+preview is available for you to use in the meantime. Please give it a try and
+let us know how it goes!
-To install Clippy, enter the following:
+To install `clippy`:
```text
-$ rustup component add clippy
+$ rustup component add clippy-preview
```
-To run Clippy’s lints on any Cargo project, enter the following:
+To take any Cargo project and run clippy’s lints on it:
```text
$ cargo clippy
```
-For example, say you write a program that uses an approximation of a
-mathematical constant, such as pi, as this program does:
+For example, if you write a program that uses an approximation of a
+mathematical constant such as pi, as this program does:
<span class="filename">Filename: src/main.rs</span>
@@ -126,7 +133,7 @@ fn main() {
}
```
-Running `cargo clippy` on this project results in this error:
+Running `cargo clippy` on this project will result in this error:
```text
error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
@@ -136,13 +143,12 @@ error: approximate value of `f{32, 64}::consts::PI` found. Consider using it dir
| ^^^^^^
|
= note: #[deny(clippy::approx_constant)] on by default
- = help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/master/index.html#approx_constant
+ = help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.212/index.html#approx_constant
```
-This error lets you know that Rust has this constant defined more precisely and
-that your program would be more correct if you used the constant instead. You
-would then change your code to use the `PI` constant. The following code
-doesn’t result in any errors or warnings from Clippy:
+This lets you know that Rust has this constant defined more precisely, and that
+your program would be more correct if you used the constant instead. This code
+doesn’t result in any errors or warnings from `clippy`:
<span class="filename">Filename: src/main.rs</span>
@@ -154,30 +160,34 @@ fn main() {
}
```
-For more information on Clippy, see [its documentation][clippy].
+For more information on `clippy`, see [its documentation][clippy].
-[clippy]: https://github.com/rust-lang/rust-clippy
+[clippy]: https://github.com/rust-lang-nursery/rust-clippy
-### IDE Integration Using the Rust Language Server
+## IDE Integration Using the Rust Language Server
-To help IDE integration, the Rust project distributes the *Rust Language
-Server* (`rls`). This tool speaks the [Language Server
-Protocol][lsp], which is a specification for IDEs and programming
-languages to communicate with each other. Different clients can use the `rls`,
-such as [the Rust plug-in for Visual Studio Code][vscode].
+To help IDE integration, the Rust project distributes the `rls`, which stands
+for the Rust Language Server. This tool speaks the [Language Server
+Protocol][lsp], which is a specification for IDEs and programming languages to
+communicate with each other. The `rls` can be used by different clients, such
+as [the Rust plugin for Visual Studio: Code][vscode].
[lsp]: http://langserver.org/
[vscode]: https://marketplace.visualstudio.com/items?itemName=rust-lang.rust
-To install the `rls`, enter the following:
+The `rls` is not yet at the quality of a version 1.0 release, but a preview is
+available for you to use in the meantime. Please give it a try and let us know
+how it goes!
+
+To install the `rls`:
```text
-$ rustup component add rls
+$ rustup component add rls-preview
```
-Then install the language server support in your particular IDE; you’ll gain
-abilities such as autocompletion, jump to definition, and inline errors.
+Then install the language server support in your particular IDE, and you will
+gain abilities such as autocompletion, jump to definition, and inline errors.
For more information on the `rls`, see [its documentation][rls].
-[rls]: https://github.com/rust-lang/rls
+[rls]: https://github.com/rust-lang-nursery/rls
diff --git a/book-original/src/appendix-05-editions.md b/book-pl-en/src/appendix-05-editions.md
index db98ecc..1e705ea 100644
--- a/book-original/src/appendix-05-editions.md
+++ b/book-pl-en/src/appendix-05-editions.md
@@ -1,43 +1,42 @@
-## Appendix E - Editions
-
-In Chapter 1, you saw that `cargo new` adds a bit of metadata to your
-*Cargo.toml* file about an edition. This appendix talks about what that means!
-
-The Rust language and compiler have a six-week release cycle, meaning users get
-a constant stream of new features. Other programming languages release larger
-changes less often; Rust releases smaller updates more frequently. After a
-while, all of these tiny changes add up. But from release to release, it can be
-difficult to look back and say, “Wow, between Rust 1.10 and Rust 1.31, Rust has
-changed a lot!”
-
-Every two or three years, the Rust team produces a new Rust *edition*. Each
-edition brings together the features that have landed into a clear package with
-fully updated documentation and tooling. New editions ship as part of the usual
-six-week release process.
-
-Editions serve different purposes for different people:
-
-* For active Rust users, a new edition brings together incremental changes into
- an easy-to-understand package.
-* For non-users, a new edition signals that some major advancements have
- landed, which might make Rust worth another look.
-* For those developing Rust, a new edition provides a rallying point for the
+# Appendix E - Editions
+
+Way back in Chapter 1, we saw that `cargo new` adds a bit of metadata to your
+*Cargo.toml* about an `edition`. This appendix talks about what that means!
+
+The Rust language and compiler have a six-week release cycle. This means users
+get a constant stream of new features. Other programming languages release
+larger changes less often; Rust chooses to release smaller updates more
+frequently. After a while, all of those tiny changes add up. But from release
+to release, it can be hard to look back and say “Wow, between Rust 1.10 and
+Rust 1.31, Rust has changed a lot!”
+
+Every two or three years, the Rust team produces a new *edition* of Rust.
+Each edition brings together the features that have landed into a clear
+package with fully updated documentation and tooling. New editions ship
+as part of the usual six-week release process.
+
+This serves different purposes for different people:
+
+* For active Rust users, it brings together incremental changes into an
+ easy-to-understand package.
+* For non-users, it signals that some major advancements have landed, which
+ might make Rust worth another look.
+* For those developing Rust itself, it provides a rallying point for the
project as a whole.
-At the time of this writing, two Rust editions are available: Rust 2015 and
-Rust 2018. This book is written using Rust 2018 edition idioms.
+At the time of writing, there are two editions: Rust 2015 and Rust 2018.
+This book is written using Rust 2018 edition idioms.
-The `edition` key in *Cargo.toml* indicates which edition the compiler should
-use for your code. If the key doesn’t exist, Rust uses `2015` as the edition
-value for backward compatibility reasons.
+The `edition` key in *Cargo.toml* indicates which edition your code should be
+compiled under. If the key does not exist, it defaults to `2015` for backwards
+compatibility reasons.
-Each project can opt in to an edition other than the default 2015 edition.
-Editions can contain incompatible changes, such as including a new keyword that
-conflicts with identifiers in code. However, unless you opt in to those
-changes, your code will continue to compile even as you upgrade the Rust
-compiler version you use.
-
-All Rust compiler versions support any edition that existed prior to that
+Each project can choose to opt in to an edition other than the default 2015
+edition. By doing so, editions can contain incompatible changes, such as adding
+a new keyword that might conflict with identifiers in code or turning warnings
+into errors. But unless you opt in to those changes, your code will continue to
+compile even as you upgrade the version of the Rust compiler that you use. All
+Rust compiler versions support any edition that existed prior to that
compiler’s release, and they can link crates of any supported editions
together. Edition changes only affect the way the compiler initially parses
code. Therefore, if you’re using Rust 2015 and one of your dependencies uses
@@ -46,12 +45,12 @@ opposite situation, where your project uses Rust 2018 and a dependency uses
Rust 2015, works as well.
To be clear: most features will be available on all editions. Developers using
-any Rust edition will continue to see improvements as new stable releases are
-made. However, in some cases, mainly when new keywords are added, some new
-features might only be available in later editions. You will need to switch
-editions if you want to take advantage of such features.
-
-For more details, the [*Edition
-Guide*](https://doc.rust-lang.org/stable/edition-guide/) is a complete book
-about editions that enumerates the differences between editions and explains
-how to automatically upgrade your code to a new edition via `cargo fix`.
+any edition of Rust will continue to see improvements as new stable releases
+are made. In some cases, however, mainly when new keywords are added, there may
+be new features that are only available in later editions. You only need to
+switch editions if you want to take advantage of such features.
+
+For more details, the [Edition
+Guide](https://rust-lang-nursery.github.io/edition-guide/) is a complete
+book about editions, including how to automatically upgrade your code to
+a new edition via `cargo fix`.
diff --git a/book-original/src/appendix-06-translation.md b/book-pl-en/src/appendix-06-translation.md
index 8193f51..62fdef4 100644
--- a/book-original/src/appendix-06-translation.md
+++ b/book-pl-en/src/appendix-06-translation.md
@@ -11,14 +11,13 @@ For resources in languages other than English. Most are still in progress; see
- [Українська](https://github.com/pavloslav/rust-book-uk-ua)
- [Español](https://github.com/thecodix/book), [alternate](https://github.com/ManRR/rust-book-es)
- [Italiano](https://github.com/AgeOfWar/rust-book-it)
-- [Русский](https://github.com/ruRust/rust_book_2ed)
+- [Русский](https://github.com/iDeBugger/rust-book-ru)
- [한국어](https://github.com/rinthel/rust-lang-book-ko)
-- [日本語](https://github.com/rust-lang-ja/book-ja)
-- [Français](https://github.com/Jimskapt/rust-book-fr)
+- [日本語](https://github.com/hazama-yuinyan/book)
+- [Français](https://github.com/quadrifoglio/rust-book-fr)
- [Polski](https://github.com/paytchoo/book-pl)
- [עברית](https://github.com/idanmel/rust-book-heb)
- [Cebuano](https://github.com/agentzero1/book)
- [Tagalog](https://github.com/josephace135/book)
- [Esperanto](https://github.com/psychoslave/Rust-libro)
- [ελληνική](https://github.com/TChatzigiannakis/rust-book-greek)
-- [Svenska](https://github.com/sebras/book)
diff --git a/book-original/src/appendix-07-nightly-rust.md b/book-pl-en/src/appendix-07-nightly-rust.md
index ac86091..d8fd0da 100644
--- a/book-original/src/appendix-07-nightly-rust.md
+++ b/book-pl-en/src/appendix-07-nightly-rust.md
@@ -1,4 +1,4 @@
-## Appendix G - How Rust is Made and “Nightly Rust”
+# Appendix G - How Rust is Made and “Nightly Rust”
This appendix is about how Rust is made and how that affects you as a Rust
developer.
@@ -142,7 +142,7 @@ global or per-project basis. By default, you’ll have stable Rust installed. To
install nightly, for example:
```text
-$ rustup toolchain install nightly
+$ rustup install nightly
```
You can see all of the *toolchains* (releases of Rust and associated
diff --git a/book-original/src/ch00-00-introduction.md b/book-pl-en/src/ch00-00-introduction.md
index 86fe469..7a37ee4 100644
--- a/book-original/src/ch00-00-introduction.md
+++ b/book-pl-en/src/ch00-00-introduction.md
@@ -104,7 +104,7 @@ chapters. In concept chapters, you’ll learn about an aspect of Rust. In projec
chapters, we’ll build small programs together, applying what you’ve learned so
far. Chapters 2, 12, and 20 are project chapters; the rest are concept chapters.
-Chapter 1 explains how to install Rust, how to write a “Hello, world!” program,
+Chapter 1 explains how to install Rust, how to write a Hello, world! program,
and how to use Cargo, Rust’s package manager and build tool. Chapter 2 is a
hands-on introduction to the Rust language. Here we cover concepts at a high
level, and later chapters will provide additional detail. If you want to get
diff --git a/book-original/src/ch01-01-installation.md b/book-pl-en/src/ch01-01-installation.md
index d7659eb..e03a50d 100644
--- a/book-original/src/ch01-01-installation.md
+++ b/book-pl-en/src/ch01-01-installation.md
@@ -71,11 +71,11 @@ On Windows, go to [https://www.rust-lang.org/tools/install][install] and follow
the instructions for installing Rust. At some point in the installation, you’ll
receive a message explaining that you’ll also need the C++ build tools for
Visual Studio 2013 or later. The easiest way to acquire the build tools is to
-install [Build Tools for Visual Studio 2019][visualstudio]. The tools are in
+install [Build Tools for Visual Studio 2017][visualstudio]. The tools are in
the Other Tools and Frameworks section.
[install]: https://www.rust-lang.org/tools/install
-[visualstudio]: https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2019
+[visualstudio]: https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2017
The rest of this book uses commands that work in both *cmd.exe* and PowerShell.
If there are specific differences, we’ll explain which to use.
@@ -115,20 +115,22 @@ rustc x.y.z (abcabcabc yyyy-mm-dd)
If you see this information, you have installed Rust successfully! If you don’t
see this information and you’re on Windows, check that Rust is in your `%PATH%`
system variable. If that’s all correct and Rust still isn’t working, there are
-a number of places you can get help. The easiest is the #beginners channel on
-[the official Rust Discord][discord]. There, you can chat with other Rustaceans
-(a silly nickname we call ourselves) who can help you out. Other great
-resources include [the Users forum][users] and [Stack Overflow][stackoverflow].
-
-[discord]: https://discord.gg/rust-lang
+a number of places you can get help. The easiest is [the #rust IRC channel on
+irc.mozilla.org][irc]<!-- ignore -->, which you can access through
+[Mibbit][mibbit]. At that address you can chat with other Rustaceans (a silly
+nickname we call ourselves) who can help you out. Other great resources include
+[the Users forum][users] and [Stack Overflow][stackoverflow].
+
+[irc]: irc://irc.mozilla.org/#rust
+[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
[users]: https://users.rust-lang.org/
[stackoverflow]: http://stackoverflow.com/questions/tagged/rust
### Local Documentation
-The installation of Rust also includes a copy of the documentation locally, so
-you can read it offline. Run `rustup doc` to open the local documentation in
-your browser.
+The installer also includes a copy of the documentation locally, so you can
+read it offline. Run `rustup doc` to open the local documentation in your
+browser.
Any time a type or function is provided by the standard library and you’re not
sure what it does or how to use it, use the application programming interface
diff --git a/book-original/src/ch01-02-hello-world.md b/book-pl-en/src/ch01-02-hello-world.md
index 82a545a..a1aaf7e 100644
--- a/book-original/src/ch01-02-hello-world.md
+++ b/book-pl-en/src/ch01-02-hello-world.md
@@ -20,7 +20,7 @@ we suggest making a *projects* directory in your home directory and keeping all
your projects there.
Open a terminal and enter the following commands to make a *projects* directory
-and a directory for the “Hello, world!” project within the *projects* directory.
+and a directory for the Hello, world! project within the *projects* directory.
For Linux, macOS, and PowerShell on Windows, enter this:
@@ -86,7 +86,7 @@ program. That makes you a Rust programmer—welcome!
### Anatomy of a Rust Program
-Let’s review in detail what just happened in your “Hello, world!” program.
+Let’s review in detail what just happened in your Hello, world! program.
Here’s the first piece of the puzzle:
```rust
@@ -150,16 +150,30 @@ $ rustc main.rs
If you have a C or C++ background, you’ll notice that this is similar to `gcc`
or `clang`. After compiling successfully, Rust outputs a binary executable.
-On Linux, macOS, and PowerShell on Windows, you can see the executable by
-entering the `ls` command in your shell. On Linux and macOS, you’ll see two
-files. With PowerShell on Windows, you’ll see the same three files that you
-would see using CMD.
+On Linux and macOS you can see the executable by entering the `ls` command in
+your shell as follows:
```text
$ ls
main main.rs
```
+With PowerShell on Windows, you can use `ls` as well, but you’ll see three files:
+
+```text
+> ls
+
+
+ Directory: Path:\to\the\project
+
+
+Mode LastWriteTime Length Name
+---- ------------- ------ ----
+-a---- 6/1/2018 7:31 AM 137728 main.exe
+-a---- 6/1/2018 7:31 AM 1454080 main.pdb
+-a---- 6/1/2018 7:31 AM 14 main.rs
+```
+
With CMD on Windows, you would enter the following:
```cmd
@@ -171,14 +185,14 @@ main.rs
This shows the source code file with the *.rs* extension, the executable file
(*main.exe* on Windows, but *main* on all other platforms), and, when using
-Windows, a file containing debugging information with the *.pdb* extension.
-From here, you run the *main* or *main.exe* file, like this:
+CMD, a file containing debugging information with the *.pdb* extension. From
+here, you run the *main* or *main.exe* file, like this:
```text
$ ./main # or .\main.exe on Windows
```
-If *main.rs* was your “Hello, world!” program, this line would print `Hello,
+If *main.rs* was your Hello, world! program, this line would print `Hello,
world!` to your terminal.
If you’re more familiar with a dynamic language, such as Ruby, Python, or
diff --git a/book-original/src/ch01-03-hello-cargo.md b/book-pl-en/src/ch01-03-hello-cargo.md
index fe029d9..8bca73a 100644
--- a/book-original/src/ch01-03-hello-cargo.md
+++ b/book-pl-en/src/ch01-03-hello-cargo.md
@@ -6,17 +6,17 @@ such as building your code, downloading the libraries your code depends on, and
building those libraries. (We call libraries your code needs *dependencies*.)
The simplest Rust programs, like the one we’ve written so far, don’t have any
-dependencies. So if we had built the “Hello, world!” project with Cargo, it
-would only use the part of Cargo that handles building your code. As you write
-more complex Rust programs, you’ll add dependencies, and if you start a project
+dependencies. So if we had built the Hello, world! project with Cargo, it would
+only use the part of Cargo that handles building your code. As you write more
+complex Rust programs, you’ll add dependencies, and if you start a project
using Cargo, adding dependencies will be much easier to do.
Because the vast majority of Rust projects use Cargo, the rest of this book
assumes that you’re using Cargo too. Cargo comes installed with Rust if you
-used the official installers discussed in the
-[“Installation”][installation]<!-- ignore --> section. If you installed Rust
-through some other means, check whether Cargo is installed by entering the
-following into your terminal:
+used the official installers discussed in the [“Installation”]
+[installation]<!-- ignore --> section. If you installed Rust through some other
+means, check whether Cargo is installed by entering the following into your
+terminal:
```text
$ cargo --version
@@ -29,7 +29,7 @@ determine how to install Cargo separately.
### Creating a Project with Cargo
Let’s create a new project using Cargo and look at how it differs from our
-original “Hello, world!” project. Navigate back to your *projects* directory (or
+original Hello, world! project. Navigate back to your *projects* directory (or
wherever you decided to store your code). Then, on any operating system, run
the following:
@@ -44,11 +44,8 @@ same name.
Go into the *hello_cargo* directory and list the files. You’ll see that Cargo
has generated two files and one directory for us: a *Cargo.toml* file and a
-*src* directory with a *main.rs* file inside.
-
-It has also initialized a new Git repository along with a *.gitignore* file.
-Git files won’t be generated if you run `cargo new` within an existing Git
-repository; you can override this behavior by using `cargo new --vcs=git`.
+*src* directory with a *main.rs* file inside. It has also initialized a new Git
+repository along with a *.gitignore* file.
> Note: Git is a common version control system. You can change `cargo new` to
> use a different version control system or no version control system by using
@@ -82,10 +79,10 @@ following statements are configuring a package. As we add more information to
this file, we’ll add other sections.
The next four lines set the configuration information Cargo needs to compile
-your program: the name, the version, who wrote it, and the edition of Rust to
-use. Cargo gets your name and email information from your environment, so if
-that information is not correct, fix the information now and then save the
-file. We’ll talk about the `edition` key in Appendix E.
+your program: the name, the version, and who wrote it. Cargo gets your name and
+email information from your environment, so if that information is not correct,
+fix the information now and then save the file. We’ll talk about the `edition`
+key in Appendix E.
The last line, `[dependencies]`, is the start of a section for you to list any
of your project’s dependencies. In Rust, packages of code are referred to as
@@ -102,10 +99,10 @@ fn main() {
}
```
-Cargo has generated a “Hello, world!” program for you, just like the one we
-wrote in Listing 1-1! So far, the differences between our previous project and
-the project Cargo generates are that Cargo placed the code in the *src*
-directory, and we have a *Cargo.toml* configuration file in the top directory.
+Cargo has generated a Hello, world! program for you, just like the one we wrote
+in Listing 1-1! So far, the differences between our previous project and the
+project Cargo generates are that Cargo placed the code in the *src* directory,
+and we have a *Cargo.toml* configuration file in the top directory.
Cargo expects your source files to live inside the *src* directory. The
top-level project directory is just for README files, license information,
@@ -113,14 +110,14 @@ configuration files, and anything else not related to your code. Using Cargo
helps you organize your projects. There’s a place for everything, and
everything is in its place.
-If you started a project that doesn’t use Cargo, as we did with the “Hello,
-world!” project, you can convert it to a project that does use Cargo. Move the
+If you started a project that doesn’t use Cargo, as we did with the Hello,
+world! project, you can convert it to a project that does use Cargo. Move the
project code into the *src* directory and create an appropriate *Cargo.toml*
file.
### Building and Running a Cargo Project
-Now let’s look at what’s different when we build and run the “Hello, world!”
+Now let’s look at what’s different when we build and run the Hello, world!
program with Cargo! From your *hello_cargo* directory, build your project by
entering the following command:
@@ -240,7 +237,7 @@ you’ve learned how to:
* Install the latest stable version of Rust using `rustup`
* Update to a newer Rust version
* Open locally installed documentation
-* Write and run a “Hello, world!” program using `rustc` directly
+* Write and run a Hello, world! program using `rustc` directly
* Create and run a new project using the conventions of Cargo
This is a great time to build a more substantial program to get used to reading
diff --git a/book-original/src/ch02-00-guessing-game-tutorial.md b/book-pl-en/src/ch02-00-guessing-game-tutorial.md
index b09dade..eefa899 100644
--- a/book-original/src/ch02-00-guessing-game-tutorial.md
+++ b/book-pl-en/src/ch02-00-guessing-game-tutorial.md
@@ -31,7 +31,13 @@ Look at the generated *Cargo.toml* file:
<span class="filename">Filename: Cargo.toml</span>
```toml
-{{#include ../listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml}}
+[package]
+name = "guessing_game"
+version = "0.1.0"
+authors = ["Your Name <you@example.com>"]
+edition = "2018"
+
+[dependencies]
```
If the author information that Cargo obtained from your environment is not
@@ -43,14 +49,20 @@ you. Check out the *src/main.rs* file:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/src/main.rs}}
+fn main() {
+ println!("Hello, world!");
+}
```
Now let’s compile this “Hello, world!” program and run it in the same step
using the `cargo run` command:
```text
-{{#include ../listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/output.txt}}
+$ cargo run
+ Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+ Finished dev [unoptimized + debuginfo] target(s) in 1.50 secs
+ Running `target/debug/guessing_game`
+Hello, world!
```
The `run` command comes in handy when you need to rapidly iterate on a project,
@@ -69,7 +81,20 @@ allow the player to input a guess. Enter the code in Listing 2-1 into
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:all}}
+use std::io;
+
+fn main() {
+ println!("Guess the number!");
+
+ println!("Please input your guess.");
+
+ let mut guess = String::new();
+
+ io::stdin().read_line(&mut guess)
+ .expect("Failed to read line");
+
+ println!("You guessed: {}", guess);
+}
```
<span class="caption">Listing 2-1: Code that gets a guess from the user and
@@ -81,7 +106,7 @@ obtain user input and then print the result as output, we need to bring the
standard library (which is known as `std`):
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:io}}
+use std::io;
```
By default, Rust brings only a few types into the scope of every program in
@@ -96,7 +121,7 @@ As you saw in Chapter 1, the `main` function is the entry point into the
program:
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:main}}
+fn main() {
```
The `fn` syntax declares a new function, the parentheses, `()`, indicate there
@@ -106,7 +131,9 @@ As you also learned in Chapter 1, `println!` is a macro that prints a string to
the screen:
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:print}}
+println!("Guess the number!");
+
+println!("Please input your guess.");
```
This code is printing a prompt stating what the game is and requesting input
@@ -117,7 +144,7 @@ from the user.
Next, we’ll create a place to store the user input, like this:
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:string}}
+let mut guess = String::new();
```
Now the program is getting interesting! There’s a lot going on in this little
@@ -130,10 +157,10 @@ let foo = bar;
This line creates a new variable named `foo` and binds it to the value of the
`bar` variable. In Rust, variables are immutable by default. We’ll be
-discussing this concept in detail in the [“Variables and
-Mutability”][variables-and-mutability]<!-- ignore --> section in Chapter 3.
-The following example shows how to use `mut` before the variable name to make
-a variable mutable:
+discussing this concept in detail in the [“Variables and Mutability”]
+[variables-and-mutability]<!-- ignore --> section in Chapter 3. The following
+example shows how to use `mut` before the variable name to make a variable
+mutable:
```rust,ignore
let foo = 5; // immutable
@@ -144,7 +171,7 @@ let mut bar = 5; // mutable
> line. Rust ignores everything in comments, which are discussed in more detail
> in Chapter 3.
-Let’s return to the guessing game program. You now know that `let mut guess`
+Let's return to the guessing game program. You now know that `let mut guess`
will introduce a mutable variable named `guess`. On the other side of the equal
sign (`=`) is the value that `guess` is bound to, which is the result of
calling `String::new`, a function that returns a new instance of a `String`.
@@ -166,14 +193,15 @@ To summarize, the `let mut guess = String::new();` line has created a mutable
variable that is currently bound to a new, empty instance of a `String`. Whew!
Recall that we included the input/output functionality from the standard
-library with `use std::io;` on the first line of the program. Now we’ll call
-the `stdin` function from the `io` module:
+library with `use std::io;` on the first line of the program. Now we’ll call an
+associated function, `stdin`, on `io`:
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:read}}
+io::stdin().read_line(&mut guess)
+ .expect("Failed to read line");
```
-If we hadn’t put the `use std::io` line at the beginning of the program, we
+If we hadn’t listed the `use std::io` line at the beginning of the program, we
could have written this function call as `std::io::stdin`. The `stdin` function
returns an instance of [`std::io::Stdin`][iostdin]<!-- ignore -->, which is a
type that represents a handle to the standard input for your terminal.
@@ -204,12 +232,12 @@ thoroughly.)
### Handling Potential Failure with the `Result` Type
-We’re still working on this line of code. Although we’re now discussing a third
-line of text, it’s still part of a single logical line of code. The next part
-is this method:
+We’re not quite done with this line of code. Although what we’ve discussed so
+far is a single line of text, it’s only the first part of the single logical
+line of code. The second part is this method:
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:expect}}
+.expect("Failed to read line");
```
When you call a method with the `.foo()` syntax, it’s often wise to introduce a
@@ -220,8 +248,8 @@ written this code as:
io::stdin().read_line(&mut guess).expect("Failed to read line");
```
-However, one long line is difficult to read, so it’s best to divide it. Now
-let’s discuss what this line does.
+However, one long line is difficult to read, so it’s best to divide it: two
+lines for two method calls. Now let’s discuss what this line does.
As mentioned earlier, `read_line` puts what the user types into the string
we’re passing it, but it also returns a value—in this case, an
@@ -261,7 +289,15 @@ entered into standard input.
If you don’t call `expect`, the program will compile, but you’ll get a warning:
```text
-{{#include ../listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt}}
+$ cargo build
+ Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+warning: unused `std::result::Result` which must be used
+ --> src/main.rs:10:5
+ |
+10 | io::stdin().read_line(&mut guess);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: #[warn(unused_must_use)] on by default
```
Rust warns that you haven’t used the `Result` value returned from `read_line`,
@@ -273,11 +309,11 @@ because you just want to crash this program when a problem occurs, you can use
### Printing Values with `println!` Placeholders
-Aside from the closing curly bracket, there’s only one more line to discuss in
+Aside from the closing curly brackets, there’s only one more line to discuss in
the code added so far, which is the following:
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:print_guess}}
+println!("You guessed: {}", guess);
```
This line prints the string we saved the user’s input in. The set of curly
@@ -300,16 +336,10 @@ This code would print `x = 5 and y = 10`.
Let’s test the first part of the guessing game. Run it using `cargo run`:
-<!-- manual-regeneration
-cd listings/ch02-guessing-game-tutorial/listing-02-01/
-cargo clean
-cargo run
-input 6 -->
-
```text
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
- Finished dev [unoptimized + debuginfo] target(s) in 6.44s
+ Finished dev [unoptimized + debuginfo] target(s) in 2.53 secs
Running `target/debug/guessing_game`
Guess the number!
Please input your guess.
@@ -343,53 +373,38 @@ code that uses `rand`, we need to modify the *Cargo.toml* file to include the
the bottom beneath the `[dependencies]` section header that Cargo created for
you:
-<!-- When updating the version of `rand` used, also update the version of
-`rand` used in these files so they all match:
-* ch07-04-bringing-paths-into-scope-with-the-use-keyword.md
-* ch14-03-cargo-workspaces.md
--->
-
<span class="filename">Filename: Cargo.toml</span>
```toml
-{{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:9:}}
+[dependencies]
+
+rand = "0.3.14"
```
In the *Cargo.toml* file, everything that follows a header is part of a section
that continues until another section starts. The `[dependencies]` section is
where you tell Cargo which external crates your project depends on and which
versions of those crates you require. In this case, we’ll specify the `rand`
-crate with the semantic version specifier `0.5.5`. Cargo understands [Semantic
+crate with the semantic version specifier `0.3.14`. Cargo understands [Semantic
Versioning][semver]<!-- ignore --> (sometimes called *SemVer*), which is a
-standard for writing version numbers. The number `0.5.5` is actually shorthand
-for `^0.5.5`, which means “any version that has a public API compatible with
-version 0.5.5.”
+standard for writing version numbers. The number `0.3.14` is actually shorthand
+for `^0.3.14`, which means “any version that has a public API compatible with
+version 0.3.14.”
[semver]: http://semver.org
Now, without changing any of the code, let’s build the project, as shown in
Listing 2-2.
-<!-- manual-regeneration
-cd listings/ch02-guessing-game-tutorial/listing-02-02/
-cargo clean
-cargo build -->
-
```text
$ cargo build
- Updating crates.io index
- Downloaded rand v0.5.5
- Downloaded libc v0.2.62
- Downloaded rand_core v0.2.2
- Downloaded rand_core v0.3.1
- Downloaded rand_core v0.4.2
- Compiling rand_core v0.4.2
- Compiling libc v0.2.62
- Compiling rand_core v0.3.1
- Compiling rand_core v0.2.2
- Compiling rand v0.5.5
+ Updating registry `https://github.com/rust-lang/crates.io-index`
+ Downloading rand v0.3.14
+ Downloading libc v0.2.14
+ Compiling libc v0.2.14
+ Compiling rand v0.3.14
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
- Finished dev [unoptimized + debuginfo] target(s) in 2.53s
+ Finished dev [unoptimized + debuginfo] target(s) in 2.53 secs
```
<span class="caption">Listing 2-2: The output from running `cargo build` after
@@ -403,13 +418,13 @@ everything from the *registry*, which is a copy of data from
[Crates.io][cratesio]. Crates.io is where people in the Rust ecosystem post
their open source Rust projects for others to use.
-[cratesio]: https://crates.io/
+[cratesio]: https://crates.io
After updating the registry, Cargo checks the `[dependencies]` section and
downloads any crates you don’t have yet. In this case, although we only listed
-`rand` as a dependency, Cargo also grabbed `libc` and `rand_core`, because
-`rand` depends on those to work. After downloading the crates, Rust compiles
-them and then compiles the project with the dependencies available.
+`rand` as a dependency, Cargo also grabbed a copy of `libc`, because `rand`
+depends on `libc` to work. After downloading the crates, Rust compiles them and
+then compiles the project with the dependencies available.
If you immediately run `cargo build` again without making any changes, you
won’t get any output aside from the `Finished` line. Cargo knows it has already
@@ -421,11 +436,6 @@ do, it simply exits.
If you open up the *src/main.rs* file, make a trivial change, and then save it
and build again, you’ll only see two lines of output:
-<!-- manual-regeneration
-cd listings/ch02-guessing-game-tutorial/listing-02-02/
-touch src/main.rs
-cargo build -->
-
```text
$ cargo build
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
@@ -442,7 +452,7 @@ your part of the code.
Cargo has a mechanism that ensures you can rebuild the same artifact every time
you or anyone else builds your code: Cargo will use only the versions of the
dependencies you specified until you indicate otherwise. For example, what
-happens if next week version 0.5.6 of the `rand` crate comes out and
+happens if next week version 0.3.15 of the `rand` crate comes out and
contains an important bug fix but also contains a regression that will break
your code?
@@ -454,7 +464,7 @@ the *Cargo.lock* file. When you build your project in the future, Cargo will
see that the *Cargo.lock* file exists and use the versions specified there
rather than doing all the work of figuring out versions again. This lets you
have a reproducible build automatically. In other words, your project will
-remain at `0.5.5` until you explicitly upgrade, thanks to the *Cargo.lock*
+remain at `0.3.14` until you explicitly upgrade, thanks to the *Cargo.lock*
file.
#### Updating a Crate to Get a New Version
@@ -464,31 +474,26 @@ which will ignore the *Cargo.lock* file and figure out all the latest versions
that fit your specifications in *Cargo.toml*. If that works, Cargo will write
those versions to the *Cargo.lock* file.
-But by default, Cargo will only look for versions greater than `0.5.5` and less
-than `0.6.0`. If the `rand` crate has released two new versions, `0.5.6` and
-`0.6.0`, you would see the following if you ran `cargo update`:
-
-<!-- manual-regeneration
-cd listings/ch02-guessing-game-tutorial/listing-02-02/
-cargo update
-assuming there is a new 0.5.x version of rand; otherwise use another update
-as a guide to creating the hypothetical output shown here -->
+But by default, Cargo will only look for versions greater than `0.3.0` and less
+than `0.4.0`. If the `rand` crate has released two new versions, `0.3.15` and
+`0.4.0`, you would see the following if you ran `cargo update`:
```text
$ cargo update
- Updating crates.io index
- Updating rand v0.5.5 -> v0.5.6
+ Updating registry `https://github.com/rust-lang/crates.io-index`
+ Updating rand v0.3.14 -> v0.3.15
```
At this point, you would also notice a change in your *Cargo.lock* file noting
-that the version of the `rand` crate you are now using is `0.5.6`.
+that the version of the `rand` crate you are now using is `0.3.15`.
-If you wanted to use `rand` version `0.6.0` or any version in the `0.6.x`
+If you wanted to use `rand` version `0.4.0` or any version in the `0.4.x`
series, you’d have to update the *Cargo.toml* file to look like this instead:
```toml
[dependencies]
-rand = "0.6.0"
+
+rand = "0.4.0"
```
The next time you run `cargo build`, Cargo will update the registry of crates
@@ -512,7 +517,25 @@ Now that you’ve added the `rand` crate to *Cargo.toml*, let’s start using
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs:all}}
+use std::io;
+use rand::Rng;
+
+fn main() {
+ println!("Guess the number!");
+
+ let secret_number = rand::thread_rng().gen_range(1, 101);
+
+ println!("The secret number is: {}", secret_number);
+
+ println!("Please input your guess.");
+
+ let mut guess = String::new();
+
+ io::stdin().read_line(&mut guess)
+ .expect("Failed to read line");
+
+ println!("You guessed: {}", guess);
+}
```
<span class="caption">Listing 2-3: Adding code to generate a random
@@ -547,27 +570,17 @@ program prints the answer as soon as it starts!
Try running the program a few times:
-<!-- manual-regeneration
-cd listings/ch02-guessing-game-tutorial/listing-02-03/
-cargo run
-4
-cargo run
-5
--->
-
```text
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
- Finished dev [unoptimized + debuginfo] target(s) in 2.53s
+ Finished dev [unoptimized + debuginfo] target(s) in 2.53 secs
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 7
Please input your guess.
4
You guessed: 4
-
$ cargo run
- Finished dev [unoptimized + debuginfo] target(s) in 0.02s
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 83
@@ -588,7 +601,22 @@ will explain.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-04/src/main.rs:here}}
+use std::io;
+use std::cmp::Ordering;
+use rand::Rng;
+
+fn main() {
+
+ // ---snip---
+
+ println!("You guessed: {}", guess);
+
+ match guess.cmp(&secret_number) {
+ Ordering::Less => println!("Too small!"),
+ Ordering::Greater => println!("Too big!"),
+ Ordering::Equal => println!("You win!"),
+ }
+}
```
<span class="caption">Listing 2-4: Handling the possible return values of
@@ -634,12 +662,24 @@ expression ends because it has no need to look at the last arm in this scenario.
However, the code in Listing 2-4 won’t compile yet. Let’s try it:
```text
-{{#include ../listings/ch02-guessing-game-tutorial/listing-02-04/output.txt}}
+$ cargo build
+ Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+error[E0308]: mismatched types
+ --> src/main.rs:23:21
+ |
+23 | match guess.cmp(&secret_number) {
+ | ^^^^^^^^^^^^^^ expected struct `std::string::String`, found integral variable
+ |
+ = note: expected type `&std::string::String`
+ = note: found type `&{integer}`
+
+error: aborting due to previous error
+Could not compile `guessing_game`.
```
The core of the error states that there are *mismatched types*. Rust has a
strong, static type system. However, it also has type inference. When we wrote
-`let mut guess = String::new()`, Rust was able to infer that `guess` should be
+`let mut guess = String::new();`, Rust was able to infer that `guess` should be
a `String` and didn’t make us write the type. The `secret_number`, on the other
hand, is a number type. A few number types can have a value between 1 and 100:
`i32`, a 32-bit number; `u32`, an unsigned 32-bit number; `i64`, a 64-bit
@@ -649,13 +689,30 @@ to infer a different numerical type. The reason for the error is that Rust
cannot compare a string and a number type.
Ultimately, we want to convert the `String` the program reads as input into a
-real number type so we can compare it numerically to the secret number. We can
-do that by adding the following two lines to the `main` function body:
+real number type so we can compare it numerically to the guess. We can do that
+by adding the following two lines to the `main` function body:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/src/main.rs:here}}
+// --snip--
+
+ let mut guess = String::new();
+
+ io::stdin().read_line(&mut guess)
+ .expect("Failed to read line");
+
+ let guess: u32 = guess.trim().parse()
+ .expect("Please type a number!");
+
+ println!("You guessed: {}", guess);
+
+ match guess.cmp(&secret_number) {
+ Ordering::Less => println!("Too small!"),
+ Ordering::Greater => println!("Too big!"),
+ Ordering::Equal => println!("You win!"),
+ }
+}
```
The two new lines are:
@@ -712,16 +769,10 @@ number that we want from the `Ok` value.
Let’s run the program now!
-<!-- manual-regeneration
-cd listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/
-cargo run
- 76
--->
-
```text
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
- Finished dev [unoptimized + debuginfo] target(s) in 0.43s
+ Finished dev [unoptimized + debuginfo] target(s) in 0.43 secs
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 58
@@ -747,7 +798,22 @@ more chances at guessing the number:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/no-listing-04-looping/src/main.rs:here}}
+// --snip--
+
+ println!("The secret number is: {}", secret_number);
+
+ loop {
+ println!("Please input your guess.");
+
+ // --snip--
+
+ match guess.cmp(&secret_number) {
+ Ordering::Less => println!("Too small!"),
+ Ordering::Greater => println!("Too big!"),
+ Ordering::Equal => println!("You win!"),
+ }
+ }
+}
```
As you can see, we’ve moved everything into a loop from the guess input prompt
@@ -756,26 +822,17 @@ and run the program again. Notice that there is a new problem because the
program is doing exactly what we told it to do: ask for another guess forever!
It doesn’t seem like the user can quit!
-The user could always interrupt the program by using the keyboard shortcut <span
+The user could always halt the program by using the keyboard shortcut <span
class="keystroke">ctrl-c</span>. But there’s another way to escape this
insatiable monster, as mentioned in the `parse` discussion in [“Comparing the
Guess to the Secret Number”](#comparing-the-guess-to-the-secret-number)<!--
ignore -->: if the user enters a non-number answer, the program will crash. The
user can take advantage of that in order to quit, as shown here:
-<!-- manual-regeneration
-cd listings/ch02-guessing-game-tutorial/no-listing-04-looping/
-cargo run
-(too small guess)
-(too big guess)
-(correct guess)
-quit
--->
-
```text
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
- Finished dev [unoptimized + debuginfo] target(s) in 1.50s
+ Finished dev [unoptimized + debuginfo] target(s) in 1.50 secs
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 59
@@ -793,8 +850,9 @@ You guessed: 59
You win!
Please input your guess.
quit
-thread 'main' panicked at 'Please type a number!: ParseIntError { kind: InvalidDigit }', src/libcore/result.rs:999:5
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
+thread 'main' panicked at 'Please type a number!: ParseIntError { kind: InvalidDigit }', src/libcore/result.rs:785
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
+error: Process didn't exit successfully: `target/debug/guess` (exit code: 101)
```
Typing `quit` actually quits the game, but so will any other non-number input.
@@ -808,7 +866,18 @@ Let’s program the game to quit when the user wins by adding a `break` statemen
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/no-listing-05-quitting/src/main.rs:here}}
+// --snip--
+
+ match guess.cmp(&secret_number) {
+ Ordering::Less => println!("Too small!"),
+ Ordering::Greater => println!("Too big!"),
+ Ordering::Equal => {
+ println!("You win!");
+ break;
+ }
+ }
+ }
+}
```
Adding the `break` line after `You win!` makes the program exit the loop when
@@ -825,7 +894,19 @@ is converted from a `String` to a `u32`, as shown in Listing 2-5.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs:here}}
+// --snip--
+
+io::stdin().read_line(&mut guess)
+ .expect("Failed to read line");
+
+let guess: u32 = match guess.trim().parse() {
+ Ok(num) => num,
+ Err(_) => continue,
+};
+
+println!("You guessed: {}", guess);
+
+// --snip--
```
<span class="caption">Listing 2-5: Ignoring a non-number guess and asking for
@@ -850,20 +931,11 @@ match the `Err(_)` pattern in the second arm. The underscore, `_`, is a
catchall value; in this example, we’re saying we want to match all `Err`
values, no matter what information they have inside them. So the program will
execute the second arm’s code, `continue`, which tells the program to go to the
-next iteration of the `loop` and ask for another guess. So, effectively, the
+next iteration of the `loop` and ask for another guess. So effectively, the
program ignores all errors that `parse` might encounter!
Now everything in the program should work as expected. Let’s try it:
-<!-- manual-regeneration
-cd listings/ch02-guessing-game-tutorial/listing-02-05/
-cargo run
-(too small guess)
-(too big guess)
-foo
-(correct guess)
--->
-
```text
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
@@ -894,7 +966,40 @@ secret number. Listing 2-6 shows the final code.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-06/src/main.rs}}
+use std::io;
+use std::cmp::Ordering;
+use rand::Rng;
+
+fn main() {
+ println!("Guess the number!");
+
+ let secret_number = rand::thread_rng().gen_range(1, 101);
+
+ loop {
+ println!("Please input your guess.");
+
+ let mut guess = String::new();
+
+ io::stdin().read_line(&mut guess)
+ .expect("Failed to read line");
+
+ let guess: u32 = match guess.trim().parse() {
+ Ok(num) => num,
+ Err(_) => continue,
+ };
+
+ println!("You guessed: {}", guess);
+
+ match guess.cmp(&secret_number) {
+ Ordering::Less => println!("Too small!"),
+ Ordering::Greater => println!("Too big!"),
+ Ordering::Equal => {
+ println!("You win!");
+ break;
+ }
+ }
+ }
+}
```
<span class="caption">Listing 2-6: Complete guessing game code</span>
diff --git a/book-original/src/ch03-00-common-programming-concepts.md b/book-pl-en/src/ch03-00-common-programming-concepts.md
index 801ecc3..a4f1a62 100644
--- a/book-original/src/ch03-00-common-programming-concepts.md
+++ b/book-pl-en/src/ch03-00-common-programming-concepts.md
@@ -10,14 +10,46 @@ Specifically, you’ll learn about variables, basic types, functions, comments,
and control flow. These foundations will be in every Rust program, and learning
them early will give you a strong core to start from.
-> #### Keywords
->
-> The Rust language has a set of *keywords* that are reserved for use by
-> the language only, much as in other languages. Keep in mind that you cannot
-> use these words as names of variables or functions. Most of the keywords have
-> special meanings, and you’ll be using them to do various tasks in your Rust
-> programs; a few have no current functionality associated with them but have
-> been reserved for functionality that might be added to Rust in the future. You
-> can find a list of the keywords in [Appendix A][appendix_a].
-
-[appendix_a]: appendix-01-keywords.md
+## Keywords
+
+The Rust language has a set of *keywords* that are reserved for use by
+the language only, much as in other languages. Keep in mind that you cannot
+use these words as names of variables or functions. Most of the keywords have
+special meanings, and you’ll be using them to do various tasks in your Rust
+programs; a few have no current functionality associated with them but have
+been reserved for functionality that might be added to Rust in the future. You
+can find a list of the keywords in Appendix A.
+
+## Identifiers
+
+We’re going to be explaining a bunch of concepts in this book: variables,
+functions, structs, lots of things. All of these things need names. A name
+in Rust is called an “identifier,” and can be made up of any nonempty ASCII
+string, with some restrictions:
+
+Either:
+
+* The first character is a letter.
+* The remaining characters are alphanumeric or _.
+
+or:
+
+* The first character is _.
+* The identifier is more than one character. _ alone is not an identifier.
+* The remaining characters are alphanumeric or _.
+
+### Raw identifiers
+
+Sometimes, you may need to use a name that’s a keyword for another purpose.
+Maybe you need to call a function named *match* that is coming from a C
+library, where ‘match’ is not a keyword. To do this, you can use a “raw identifier.”
+Raw identifiers start with `r#`:
+
+```rust,ignore
+let r#fn = "this variable is named 'fn' even though that's a keyword";
+
+// call a function named 'match'
+r#match();
+```
+
+You won’t need raw identifiers often, but when you do, you *really* need them.
diff --git a/book-original/src/ch03-01-variables-and-mutability.md b/book-pl-en/src/ch03-01-variables-and-mutability.md
index 05fea9a..45b9a9d 100644
--- a/book-original/src/ch03-01-variables-and-mutability.md
+++ b/book-pl-en/src/ch03-01-variables-and-mutability.md
@@ -17,14 +17,26 @@ code with the following code that won’t compile just yet:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs}}
+fn main() {
+ let x = 5;
+ println!("The value of x is: {}", x);
+ x = 6;
+ println!("The value of x is: {}", x);
+}
```
Save and run the program using `cargo run`. You should receive an error
message, as shown in this output:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt}}
+error[E0384]: cannot assign twice to immutable variable `x`
+ --> src/main.rs:4:5
+ |
+2 | let x = 5;
+ | - first assignment to `x`
+3 | println!("The value of x is: {}", x);
+4 | x = 6;
+ | ^^^^^ cannot assign twice to immutable variable
```
This example shows how the compiler helps you find errors in your programs.
@@ -53,20 +65,30 @@ But mutability can be very useful. Variables are immutable only by default; as
you did in Chapter 2, you can make them mutable by adding `mut` in front of the
variable name. In addition to allowing this value to change, `mut` conveys
intent to future readers of the code by indicating that other parts of the code
-will be changing this variable’s value.
+will be changing this variable value.
For example, let’s change *src/main.rs* to the following:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-02-adding-mut/src/main.rs}}
+fn main() {
+ let mut x = 5;
+ println!("The value of x is: {}", x);
+ x = 6;
+ println!("The value of x is: {}", x);
+}
```
When we run the program now, we get this:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-02-adding-mut/output.txt}}
+$ cargo run
+ Compiling variables v0.1.0 (file:///projects/variables)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.30 secs
+ Running `target/debug/variables`
+The value of x is: 5
+The value of x is: 6
```
We’re allowed to change the value that `x` binds to from `5` to `6` when `mut`
@@ -138,7 +160,15 @@ of the `let` keyword as follows:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-03-shadowing/src/main.rs}}
+fn main() {
+ let x = 5;
+
+ let x = x + 1;
+
+ let x = x * 2;
+
+ println!("The value of x is: {}", x);
+}
```
This program first binds `x` to a value of `5`. Then it shadows `x` by
@@ -148,10 +178,14 @@ previous value by `2` to give `x` a final value of `12`. When we run this
program, it will output the following:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-03-shadowing/output.txt}}
+$ cargo run
+ Compiling variables v0.1.0 (file:///projects/variables)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.31 secs
+ Running `target/debug/variables`
+The value of x is: 12
```
-Shadowing is different from marking a variable as `mut`, because we’ll get a
+Shadowing is different than marking a variable as `mut`, because we’ll get a
compile-time error if we accidentally try to reassign to this variable without
using the `let` keyword. By using `let`, we can perform a few transformations
on a value but have the variable be immutable after those transformations have
@@ -164,7 +198,8 @@ program asks a user to show how many spaces they want between some text by
inputting space characters, but we really want to store that input as a number:
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-04-shadowing-can-change-types/src/main.rs:here}}
+let spaces = " ";
+let spaces = spaces.len();
```
This construct is allowed because the first `spaces` variable is a string type
@@ -175,13 +210,21 @@ from having to come up with different names, such as `spaces_str` and
try to use `mut` for this, as shown here, we’ll get a compile-time error:
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/src/main.rs:here}}
+let mut spaces = " ";
+spaces = spaces.len();
```
The error says we’re not allowed to mutate a variable’s type:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt}}
+error[E0308]: mismatched types
+ --> src/main.rs:3:14
+ |
+3 | spaces = spaces.len();
+ | ^^^^^^^^^^^^ expected &str, found usize
+ |
+ = note: expected type `&str`
+ found type `usize`
```
Now that we’ve explored how variables work, let’s look at more data types they
diff --git a/book-original/src/ch03-02-data-types.md b/book-pl-en/src/ch03-02-data-types.md
index 5c8b162..2221b8a 100644
--- a/book-original/src/ch03-02-data-types.md
+++ b/book-pl-en/src/ch03-02-data-types.md
@@ -8,9 +8,9 @@ Keep in mind that Rust is a *statically typed* language, which means that it
must know the types of all variables at compile time. The compiler can usually
infer what type we want to use based on the value and how we use it. In cases
when many types are possible, such as when we converted a `String` to a numeric
-type using `parse` in the [“Comparing the Guess to the Secret
-Number”][comparing-the-guess-to-the-secret-number]<!-- ignore --> section in
-Chapter 2, we must add a type annotation, like this:
+type using `parse` in the [“Comparing the Guess to the Secret Number”]
+[comparing-the-guess-to-the-secret-number]<!-- ignore --> section in Chapter 2,
+we must add a type annotation, like this:
```rust
let guess: u32 = "42".parse().expect("Not a number!");
@@ -21,7 +21,14 @@ error, which means the compiler needs more information from us to know which
type we want to use:
```text
-{{#include ../listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt}}
+error[E0282]: type annotations needed
+ --> src/main.rs:2:9
+ |
+2 | let guess = "42".parse().expect("Not a number!");
+ | ^^^^^
+ | |
+ | cannot infer type for `_`
+ | consider giving `guess` a type
```
You’ll see different type annotations for other data types.
@@ -60,7 +67,9 @@ with it (signed) or whether it will only ever be positive and can therefore be
represented without a sign (unsigned). It’s like writing numbers on paper: when
the sign matters, a number is shown with a plus sign or a minus sign; however,
when it’s safe to assume the number is positive, it’s shown with no sign.
-Signed numbers are stored using [two’s complement](https://en.wikipedia.org/wiki/Two%27s_complement) representation.
+Signed numbers are stored using two’s complement representation (if you’re
+unsure what this is, you can search for it online; an explanation is outside
+the scope of this book).
Each signed variant can store numbers from -(2<sup>n - 1</sup>) to 2<sup>n -
1</sup> - 1 inclusive, where *n* is the number of bits that variant uses. So an
@@ -91,27 +100,20 @@ defaults are generally good choices, and integer types default to `i32`: this
type is generally the fastest, even on 64-bit systems. The primary situation in
which you’d use `isize` or `usize` is when indexing some sort of collection.
-> ##### Integer Overflow
->
-> Let’s say you have a variable of type `u8` that can hold values between 0 and 255.
-> If you try to change the variable to a value outside of that range, such
-> as 256, *integer overflow* will occur. Rust has some interesting rules
-> involving this behavior. When you’re compiling in debug mode, Rust includes
-> checks for integer overflow that cause your program to *panic* at runtime if
-> this behavior occurs. Rust uses the term panicking when a program exits with
-> an error; we’ll discuss panics in more depth in the [“Unrecoverable Errors
-> with `panic!`”][unrecoverable-errors-with-panic]<!-- ignore --> section in
-> Chapter 9.
->
-> When you’re compiling in release mode with the `--release` flag, Rust does
-> *not* include checks for integer overflow that cause panics. Instead, if
-> overflow occurs, Rust performs *two’s complement wrapping*. In short, values
-> greater than the maximum value the type can hold “wrap around” to the minimum
-> of the values the type can hold. In the case of a `u8`, 256 becomes 0, 257
-> becomes 1, and so on. The program won’t panic, but the variable will have a
-> value that probably isn’t what you were expecting it to have. Relying on
-> integer overflow’s wrapping behavior is considered an error. If you want to
-> wrap explicitly, you can use the standard library type [`Wrapping`][wrapping].
+##### Integer Overflow
+
+Let’s say that you have a `u8`, which can hold values between zero and `255`.
+What happens if you try to change it to `256`? This is called “integer
+overflow,” and Rust has some interesting rules around this behavior. When
+compiling in debug mode, Rust checks for this kind of issue and will cause
+your program to *panic*, which is the term Rust uses when a program exits
+with an error. We’ll discuss panics more in Chapter 9.
+
+In release builds, Rust does not check for overflow, and instead will
+do something called “two’s complement wrapping.” In short, `256` becomes
+`0`, `257` becomes `1`, etc. Relying on overflow is considered an error,
+even if this behavior happens. If you want this behavior explicitly, the
+standard library has a type, `Wrapping`, that provides it explicitly.
#### Floating-Point Types
@@ -126,7 +128,11 @@ Here’s an example that shows floating-point numbers in action:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-06-floating-point/src/main.rs}}
+fn main() {
+ let x = 2.0; // f64
+
+ let y: f32 = 3.0; // f32
+}
```
Floating-point numbers are represented according to the IEEE-754 standard. The
@@ -141,7 +147,22 @@ The following code shows how you’d use each one in a `let` statement:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs}}
+fn main() {
+ // addition
+ let sum = 5 + 10;
+
+ // subtraction
+ let difference = 95.5 - 4.3;
+
+ // multiplication
+ let product = 4 * 30;
+
+ // division
+ let quotient = 56.7 / 32.2;
+
+ // remainder
+ let remainder = 43 % 5;
+}
```
Each expression in these statements uses a mathematical operator and evaluates
@@ -151,41 +172,50 @@ list of all operators that Rust provides.
#### The Boolean Type
As in most other programming languages, a Boolean type in Rust has two possible
-values: `true` and `false`. Booleans are one byte in size. The Boolean type in
-Rust is specified using `bool`. For example:
+values: `true` and `false`. The Boolean type in Rust is specified using `bool`.
+For example:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-08-boolean/src/main.rs}}
+fn main() {
+ let t = true;
+
+ let f: bool = false; // with explicit type annotation
+}
```
The main way to use Boolean values is through conditionals, such as an `if`
expression. We’ll cover how `if` expressions work in Rust in the [“Control
Flow”][control-flow]<!-- ignore --> section.
+Booleans are one byte in size.
+
#### The Character Type
So far we’ve worked only with numbers, but Rust supports letters too. Rust’s
`char` type is the language’s most primitive alphabetic type, and the following
-code shows one way to use it. (Note that `char` literals are specified with
+code shows one way to use it. (Note that the `char` literal is specified with
single quotes, as opposed to string literals, which use double quotes.)
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs}}
+fn main() {
+ let c = 'z';
+ let z = 'ℤ';
+ let heart_eyed_cat = '😻';
+}
```
-Rust’s `char` type is four bytes in size and represents a Unicode Scalar Value,
-which means it can represent a lot more than just ASCII. Accented letters;
-Chinese, Japanese, and Korean characters; emoji; and zero-width spaces are all
-valid `char` values in Rust. Unicode Scalar Values range from `U+0000` to
-`U+D7FF` and `U+E000` to `U+10FFFF` inclusive. However, a “character” isn’t
-really a concept in Unicode, so your human intuition for what a “character” is
-may not match up with what a `char` is in Rust. We’ll discuss this topic in
-detail in [“Storing UTF-8 Encoded Text with Strings”][strings]<!-- ignore -->
-in Chapter 8.
+Rust’s `char` type represents a Unicode Scalar Value, which means it can
+represent a lot more than just ASCII. Accented letters; Chinese, Japanese, and
+Korean characters; emoji; and zero-width spaces are all valid `char` values in
+Rust. Unicode Scalar Values range from `U+0000` to `U+D7FF` and `U+E000` to
+`U+10FFFF` inclusive. However, a “character” isn’t really a concept in Unicode,
+so your human intuition for what a “character” is may not match up with what a
+`char` is in Rust. We’ll discuss this topic in detail in [“Storing UTF-8
+Encoded Text with Strings”][strings]<!-- ignore --> in Chapter 8.
### Compound Types
@@ -194,9 +224,9 @@ primitive compound types: tuples and arrays.
#### The Tuple Type
-A tuple is a general way of grouping together a number of values with a variety
-of types into one compound type. Tuples have a fixed length: once declared,
-they cannot grow or shrink in size.
+A tuple is a general way of grouping together some number of other values
+with a variety of types into one compound type. Tuples have a fixed length:
+once declared, they cannot grow or shrink in size.
We create a tuple by writing a comma-separated list of values inside
parentheses. Each position in the tuple has a type, and the types of the
@@ -206,7 +236,9 @@ type annotations in this example:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-10-tuples/src/main.rs}}
+fn main() {
+ let tup: (i32, f64, u8) = (500, 6.4, 1);
+}
```
The variable `tup` binds to the entire tuple, because a tuple is considered a
@@ -216,7 +248,13 @@ use pattern matching to destructure a tuple value, like this:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/src/main.rs}}
+fn main() {
+ let tup = (500, 6.4, 1);
+
+ let (x, y, z) = tup;
+
+ println!("The value of y is: {}", y);
+}
```
This program first creates a tuple and binds it to the variable `tup`. It then
@@ -232,12 +270,20 @@ want to access. For example:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-12-tuple-indexing/src/main.rs}}
+fn main() {
+ let x: (i32, f64, u8) = (500, 6.4, 1);
+
+ let five_hundred = x.0;
+
+ let six_point_four = x.1;
+
+ let one = x.2;
+}
```
This program creates a tuple, `x`, and then makes new variables for each
-element by using their respective indices. As with most programming languages,
-the first index in a tuple is 0.
+element by using their index. As with most programming languages, the first
+index in a tuple is 0.
#### The Array Type
@@ -252,7 +298,9 @@ inside square brackets:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-13-arrays/src/main.rs}}
+fn main() {
+ let a = [1, 2, 3, 4, 5];
+}
```
Arrays are useful when you want your data allocated on the stack rather than
@@ -266,36 +314,27 @@ vector. Chapter 8 discusses vectors in more detail.
An example of when you might want to use an array rather than a vector is in a
program that needs to know the names of the months of the year. It’s very
unlikely that such a program will need to add or remove months, so you can use
-an array because you know it will always contain 12 elements:
+an array because you know it will always contain 12 items:
```rust
let months = ["January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"];
```
-You would write an array’s type by using square brackets, and within the
-brackets include the type of each element, a semicolon, and then the number of
-elements in the array, like so:
+Arrays have an interesting type; it looks like this: `[type; number]`. For
+example:
```rust
let a: [i32; 5] = [1, 2, 3, 4, 5];
```
-Here, `i32` is the type of each element. After the semicolon, the number `5`
-indicates the array contains five elements.
-
-Writing an array’s type this way looks similar to an alternative syntax for
-initializing an array: if you want to create an array that contains the same
-value for each element, you can specify the initial value, followed by a
-semicolon, and then the length of the array in square brackets, as shown here:
-
-```rust
-let a = [3; 5];
-```
-
-The array named `a` will contain `5` elements that will all be set to the value
-`3` initially. This is the same as writing `let a = [3, 3, 3, 3, 3];` but in a
-more concise way.
+First, there’s square brackets; they look like the syntax for creating an
+array. Inside, there’s two pieces of information, separated by a semicolon.
+The first is the type of each element of the array. Since all elements have
+the same type, we only need to list it once. After the semicolon, there’s
+a number that indicates the length of the array. Since an array has a fixed size,
+this number is always the same, even if the array’s elements are modified, it
+cannot grow or shrink.
##### Accessing Array Elements
@@ -305,7 +344,12 @@ elements of an array using indexing, like this:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-14-array-indexing/src/main.rs}}
+fn main() {
+ let a = [1, 2, 3, 4, 5];
+
+ let first = a[0];
+ let second = a[1];
+}
```
In this example, the variable named `first` will get the value `1`, because
@@ -321,13 +365,26 @@ compile but exit with an error when it runs:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,panics
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/src/main.rs}}
+fn main() {
+ let a = [1, 2, 3, 4, 5];
+ let index = 10;
+
+ let element = a[index];
+
+ println!("The value of element is: {}", element);
+}
```
Running this code using `cargo run` produces the following result:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/output.txt}}
+$ cargo run
+ Compiling arrays v0.1.0 (file:///projects/arrays)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.31 secs
+ Running `target/debug/arrays`
+thread '<main>' panicked at 'index out of bounds: the len is 5 but the index is
+ 10', src/main.rs:6
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
The compilation didn’t produce any errors, but the program resulted in a
@@ -346,5 +403,3 @@ continuing. Chapter 9 discusses more of Rust’s error handling.
ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number
[control-flow]: ch03-05-control-flow.html#control-flow
[strings]: ch08-02-strings.html#storing-utf-8-encoded-text-with-strings
-[unrecoverable-errors-with-panic]: ch09-01-unrecoverable-errors-with-panic.html
-[wrapping]: ../std/num/struct.Wrapping.html
diff --git a/book-original/src/ch03-03-how-functions-work.md b/book-pl-en/src/ch03-03-how-functions-work.md
index 491a69b..1f6b082 100644
--- a/book-original/src/ch03-03-how-functions-work.md
+++ b/book-pl-en/src/ch03-03-how-functions-work.md
@@ -12,7 +12,15 @@ Here’s a program that contains an example function definition:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-16-functions/src/main.rs}}
+fn main() {
+ println!("Hello, world!");
+
+ another_function();
+}
+
+fn another_function() {
+ println!("Another function.");
+}
```
Function definitions in Rust start with `fn` and have a set of parentheses
@@ -31,7 +39,12 @@ further. Place the `another_function` example in *src/main.rs* and run it. You
should see the following output:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-16-functions/output.txt}}
+$ cargo run
+ Compiling functions v0.1.0 (file:///projects/functions)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.28 secs
+ Running `target/debug/functions`
+Hello, world!
+Another function.
```
The lines execute in the order in which they appear in the `main` function.
@@ -54,13 +67,23 @@ look like in Rust:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/src/main.rs}}
+fn main() {
+ another_function(5);
+}
+
+fn another_function(x: i32) {
+ println!("The value of x is: {}", x);
+}
```
Try running this program; you should get the following output:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/output.txt}}
+$ cargo run
+ Compiling functions v0.1.0 (file:///projects/functions)
+ Finished dev [unoptimized + debuginfo] target(s) in 1.21 secs
+ Running `target/debug/functions`
+The value of x is: 5
```
The declaration of `another_function` has one parameter named `x`. The type of
@@ -79,7 +102,14 @@ declarations with commas, like this:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/src/main.rs}}
+fn main() {
+ another_function(5, 6);
+}
+
+fn another_function(x: i32, y: i32) {
+ println!("The value of x is: {}", x);
+ println!("The value of y is: {}", y);
+}
```
This example creates a function with two parameters, both of which are `i32`
@@ -92,7 +122,12 @@ project’s *src/main.rs* file with the preceding example and run it using `carg
run`:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/output.txt}}
+$ cargo run
+ Compiling functions v0.1.0 (file:///projects/functions)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.31 secs
+ Running `target/debug/functions`
+The value of x is: 5
+The value of y is: 6
```
Because we called the function with `5` as the value for `x` and `6` is passed
@@ -118,7 +153,9 @@ statement. In Listing 3-1, `let y = 6;` is a statement.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/listing-03-01/src/main.rs}}
+fn main() {
+ let y = 6;
+}
```
<span class="caption">Listing 3-1: A `main` function declaration containing one statement</span>
@@ -132,14 +169,13 @@ to another variable, as the following code tries to do; you’ll get an error:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/src/main.rs}}
+fn main() {
+ let x = (let y = 6);
+}
```
When you run this program, the error you’ll get looks like this:
-<!--TODO: not extracting this because the new error message is incorrect; see
-https://github.com/rust-lang/rust/issues/65254 -->
-
```text
$ cargo run
Compiling functions v0.1.0 (file:///projects/functions)
@@ -169,7 +205,16 @@ new scopes, `{}`, is an expression, for example:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs}}
+fn main() {
+ let x = 5;
+
+ let y = {
+ let x = 3;
+ x + 1
+ };
+
+ println!("The value of y is: {}", y);
+}
```
This expression:
@@ -201,16 +246,28 @@ value:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-21-function-return-values/src/main.rs}}
+fn five() -> i32 {
+ 5
+}
+
+fn main() {
+ let x = five();
+
+ println!("The value of x is: {}", x);
+}
```
There are no function calls, macros, or even `let` statements in the `five`
function—just the number `5` by itself. That’s a perfectly valid function in
-Rust. Note that the function’s return type is specified too, as `-> i32`. Try
+Rust. Note that the function’s return type is specified, too, as `-> i32`. Try
running this code; the output should look like this:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-21-function-return-values/output.txt}}
+$ cargo run
+ Compiling functions v0.1.0 (file:///projects/functions)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.30 secs
+ Running `target/debug/functions`
+The value of x is: 5
```
The `5` in `five` is the function’s return value, which is why the return type
@@ -232,7 +289,15 @@ Let’s look at another example:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/src/main.rs}}
+fn main() {
+ let x = plus_one(5);
+
+ println!("The value of x is: {}", x);
+}
+
+fn plus_one(x: i32) -> i32 {
+ x + 1
+}
```
Running this code will print `The value of x is: 6`. But if we place a
@@ -242,19 +307,38 @@ expression to a statement, we’ll get an error.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/src/main.rs}}
+fn main() {
+ let x = plus_one(5);
+
+ println!("The value of x is: {}", x);
+}
+
+fn plus_one(x: i32) -> i32 {
+ x + 1;
+}
```
Compiling this code produces an error, as follows:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt}}
+error[E0308]: mismatched types
+ --> src/main.rs:7:28
+ |
+7 | fn plus_one(x: i32) -> i32 {
+ | ____________________________^
+8 | | x + 1;
+ | | - help: consider removing this semicolon
+9 | | }
+ | |_^ expected i32, found ()
+ |
+ = note: expected type `i32`
+ found type `()`
```
The main error message, “mismatched types,” reveals the core issue with this
code. The definition of the function `plus_one` says that it will return an
`i32`, but statements don’t evaluate to a value, which is expressed by `()`,
-an empty tuple. Therefore, nothing is returned, which contradicts the function
+the empty tuple. Therefore, nothing is returned, which contradicts the function
definition and results in an error. In this output, Rust provides a message to
possibly help rectify this issue: it suggests removing the semicolon, which
would fix the error.
diff --git a/book-original/src/ch03-04-comments.md b/book-pl-en/src/ch03-04-comments.md
index 6a3f8ef..7d6281e 100644
--- a/book-original/src/ch03-04-comments.md
+++ b/book-pl-en/src/ch03-04-comments.md
@@ -11,9 +11,9 @@ Here’s a simple comment:
// hello, world
```
-In Rust, the idiomatic comment style starts a comment with two slashes, and the
-comment continues until the end of the line. For comments that extend beyond a
-single line, you’ll need to include `//` on each line, like this:
+In Rust, comments must start with two slashes and continue until the end of the
+line. For comments that extend beyond a single line, you’ll need to include
+`//` on each line, like this:
```rust
// So we’re doing something complicated here, long enough that we need
@@ -26,7 +26,9 @@ Comments can also be placed at the end of lines containing code:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-24-comments-end-of-line/src/main.rs}}
+fn main() {
+ let lucky_number = 7; // I’m feeling lucky today
+}
```
But you’ll more often see them used in this format, with the comment on a
@@ -35,8 +37,11 @@ separate line above the code it’s annotating:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-25-comments-above-line/src/main.rs}}
+fn main() {
+ // I’m feeling lucky today
+ let lucky_number = 7;
+}
```
Rust also has another kind of comment, documentation comments, which we’ll
-discuss in the “Publishing a Crate to Crates.io” section of Chapter 14.
+discuss in Chapter 14.
diff --git a/book-original/src/ch03-05-control-flow.md b/book-pl-en/src/ch03-05-control-flow.md
index 8c6ce75..7fbad10 100644
--- a/book-original/src/ch03-05-control-flow.md
+++ b/book-pl-en/src/ch03-05-control-flow.md
@@ -18,7 +18,15 @@ the `if` expression. In the *src/main.rs* file, input the following:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-26-if-true/src/main.rs}}
+fn main() {
+ let number = 3;
+
+ if number < 5 {
+ println!("condition was true");
+ } else {
+ println!("condition was false");
+ }
+}
```
All `if` expressions start with the keyword `if`, which is followed by a
@@ -27,9 +35,8 @@ condition. In this case, the condition checks whether or not the variable
condition is true is placed immediately after the condition inside curly
brackets. Blocks of code associated with the conditions in `if` expressions are
sometimes called *arms*, just like the arms in `match` expressions that we
-discussed in the [“Comparing the Guess to the Secret
-Number”][comparing-the-guess-to-the-secret-number]<!-- ignore --> section of
-Chapter 2.
+discussed in the [“Comparing the Guess to the Secret Number”]
+[comparing-the-guess-to-the-secret-number]<!-- ignore --> section of Chapter 2.
Optionally, we can also include an `else` expression, which we chose
to do here, to give the program an alternative block of code to execute should
@@ -40,20 +47,28 @@ to the next bit of code.
Try running this code; you should see the following output:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-26-if-true/output.txt}}
+$ cargo run
+ Compiling branches v0.1.0 (file:///projects/branches)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.31 secs
+ Running `target/debug/branches`
+condition was true
```
Let’s try changing the value of `number` to a value that makes the condition
`false` to see what happens:
```rust,ignore
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-27-if-false/src/main.rs:here}}
+let number = 7;
```
Run the program again, and look at the output:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-27-if-false/output.txt}}
+$ cargo run
+ Compiling branches v0.1.0 (file:///projects/branches)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.31 secs
+ Running `target/debug/branches`
+condition was false
```
It’s also worth noting that the condition in this code *must* be a `bool`. If
@@ -63,14 +78,27 @@ following code:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/src/main.rs}}
+fn main() {
+ let number = 3;
+
+ if number {
+ println!("number was three");
+ }
+}
```
The `if` condition evaluates to a value of `3` this time, and Rust throws an
error:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt}}
+error[E0308]: mismatched types
+ --> src/main.rs:4:8
+ |
+4 | if number {
+ | ^^^^^^ expected bool, found integral variable
+ |
+ = note: expected type `bool`
+ found type `{integer}`
```
The error indicates that Rust expected a `bool` but got an integer. Unlike
@@ -83,7 +111,13 @@ expression to the following:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-29-if-not-equal-0/src/main.rs}}
+fn main() {
+ let number = 3;
+
+ if number != 0 {
+ println!("number was something other than zero");
+ }
+}
```
Running this code will print `number was something other than zero`.
@@ -96,14 +130,30 @@ expression. For example:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-30-else-if/src/main.rs}}
+fn main() {
+ let number = 6;
+
+ if number % 4 == 0 {
+ println!("number is divisible by 4");
+ } else if number % 3 == 0 {
+ println!("number is divisible by 3");
+ } else if number % 2 == 0 {
+ println!("number is divisible by 2");
+ } else {
+ println!("number is not divisible by 4, 3, or 2");
+ }
+}
```
This program has four possible paths it can take. After running it, you should
see the following output:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-30-else-if/output.txt}}
+$ cargo run
+ Compiling branches v0.1.0 (file:///projects/branches)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.31 secs
+ Running `target/debug/branches`
+number is divisible by 3
```
When this program executes, it checks each `if` expression in turn and executes
@@ -125,7 +175,16 @@ statement, as in Listing 3-2.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/listing-03-02/src/main.rs}}
+fn main() {
+ let condition = true;
+ let number = if condition {
+ 5
+ } else {
+ 6
+ };
+
+ println!("The value of number is: {}", number);
+}
```
<span class="caption">Listing 3-2: Assigning the result of an `if` expression
@@ -135,7 +194,11 @@ The `number` variable will be bound to a value based on the outcome of the `if`
expression. Run this code to see what happens:
```text
-{{#include ../listings/ch03-common-programming-concepts/listing-03-02/output.txt}}
+$ cargo run
+ Compiling branches v0.1.0 (file:///projects/branches)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.30 secs
+ Running `target/debug/branches`
+The value of number is: 5
```
Remember that blocks of code evaluate to the last expression in them, and
@@ -149,7 +212,17 @@ example, we’ll get an error:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/src/main.rs}}
+fn main() {
+ let condition = true;
+
+ let number = if condition {
+ 5
+ } else {
+ "six"
+ };
+
+ println!("The value of number is: {}", number);
+}
```
When we try to compile this code, we’ll get an error. The `if` and `else` arms
@@ -157,7 +230,19 @@ have value types that are incompatible, and Rust indicates exactly where to
find the problem in the program:
```text
-{{#include ../listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt}}
+error[E0308]: if and else have incompatible types
+ --> src/main.rs:4:18
+ |
+4 | let number = if condition {
+ | __________________^
+5 | | 5
+6 | | } else {
+7 | | "six"
+8 | | };
+ | |_____^ expected integral variable, found &str
+ |
+ = note: expected type `{integer}`
+ found type `&str`
```
The expression in the `if` block evaluates to an integer, and the expression in
@@ -189,24 +274,22 @@ like this:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-32-loop/src/main.rs}}
+fn main() {
+ loop {
+ println!("again!");
+ }
+}
```
When we run this program, we’ll see `again!` printed over and over continuously
until we stop the program manually. Most terminals support a keyboard shortcut,
-<span class="keystroke">ctrl-c</span>, to interrupt a program that is stuck in
-a continual loop. Give it a try:
-
-<!-- manual-regeneration
-cd listings/ch03-common-programming-concepts/no-listing-32-loop
-cargo run
-CTRL-C
--->
+<span class="keystroke">ctrl-c</span>, to halt a program that is stuck in a
+continual loop. Give it a try:
```text
$ cargo run
Compiling loops v0.1.0 (file:///projects/loops)
- Finished dev [unoptimized + debuginfo] target(s) in 0.29s
+ Finished dev [unoptimized + debuginfo] target(s) in 0.29 secs
Running `target/debug/loops`
again!
again!
@@ -217,8 +300,7 @@ again!
The symbol `^C` represents where you pressed <span class="keystroke">ctrl-c
</span>. You may or may not see the word `again!` printed after the `^C`,
-depending on where the code was in the loop when it received the interrupt
-signal.
+depending on where the code was in the loop when it received the halt signal.
Fortunately, Rust provides another, more reliable way to break out of a loop.
You can place the `break` keyword within the loop to tell the program when to
@@ -227,26 +309,28 @@ stop executing the loop. Recall that we did this in the guessing game in the
--> section of Chapter 2 to exit the program when the user won the game by
guessing the correct number.
-#### Returning Values from Loops
+#### Returning from loops
-One of the uses of a `loop` is to retry an operation you know might fail, such
-as checking whether a thread has completed its job. However, you might need to
-pass the result of that operation to the rest of your code. To do this, you can
-add the value you want returned after the `break` expression you use to stop
-the loop; that value will be returned out of the loop so you can use it, as
-shown here:
+One of the uses of a `loop` is to retry an operation you know can fail, such as
+checking if a thread completed its job. However, you might need to pass the
+result of that operation to the rest of your code. If you add it to the `break`
+expression you use to stop the loop, it will be returned by the broken loop:
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs}}
-```
+fn main() {
+ let mut counter = 0;
+
+ let result = loop {
+ counter += 1;
-Before the loop, we declare a variable named `counter` and initialize it to
-`0`. Then we declare a variable named `result` to hold the value returned from
-the loop. On every iteration of the loop, we add `1` to the `counter` variable,
-and then check whether the counter is equal to `10`. When it is, we use the
-`break` keyword with the value `counter * 2`. After the loop, we use a
-semicolon to end the statement that assigns the value to `result`. Finally, we
-print the value in `result`, which in this case is 20.
+ if counter == 10 {
+ break counter * 2;
+ }
+ };
+
+ assert_eq!(result, 20);
+}
+```
#### Conditional Loops with `while`
@@ -264,7 +348,17 @@ another message and exits.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/listing-03-03/src/main.rs}}
+fn main() {
+ let mut number = 3;
+
+ while number != 0 {
+ println!("{}!", number);
+
+ number = number - 1;
+ }
+
+ println!("LIFTOFF!!!");
+}
```
<span class="caption">Listing 3-3: Using a `while` loop to run code while a
@@ -282,7 +376,16 @@ such as an array. For example, let’s look at Listing 3-4.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/listing-03-04/src/main.rs}}
+fn main() {
+ let a = [10, 20, 30, 40, 50];
+ let mut index = 0;
+
+ while index < 5 {
+ println!("the value is: {}", a[index]);
+
+ index = index + 1;
+ }
+}
```
<span class="caption">Listing 3-4: Looping through each element of a collection
@@ -294,7 +397,15 @@ when `index < 5` is no longer true). Running this code will print every element
in the array:
```text
-{{#include ../listings/ch03-common-programming-concepts/listing-03-04/output.txt}}
+$ cargo run
+ Compiling loops v0.1.0 (file:///projects/loops)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs
+ Running `target/debug/loops`
+the value is: 10
+the value is: 20
+the value is: 30
+the value is: 40
+the value is: 50
```
All five array values appear in the terminal, as expected. Even though `index`
@@ -312,7 +423,13 @@ for each item in a collection. A `for` loop looks like the code in Listing 3-5.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/listing-03-05/src/main.rs}}
+fn main() {
+ let a = [10, 20, 30, 40, 50];
+
+ for element in a.iter() {
+ println!("the value is: {}", element);
+ }
+}
```
<span class="caption">Listing 3-5: Looping through each element of a collection
@@ -323,11 +440,10 @@ importantly, we’ve now increased the safety of the code and eliminated the
chance of bugs that might result from going beyond the end of the array or not
going far enough and missing some items.
-For example, in the code in Listing 3-4, if you changed the definition of the
-`a` array to have four elements but forgot to update the condition to `while
-index < 4`, the code would panic. Using the `for` loop, you wouldn’t need to
-remember to change any other code if you changed the number of values in the
-array.
+For example, in the code in Listing 3-4, if you removed an item from the `a`
+array but forgot to update the condition to `while index < 4`, the code would
+panic. Using the `for` loop, you wouldn’t need to remember to change any other
+code if you changed the number of values in the array.
The safety and conciseness of `for` loops make them the most commonly used loop
construct in Rust. Even in situations in which you want to run some code a
@@ -343,7 +459,12 @@ we’ve not yet talked about, `rev`, to reverse the range:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-34-for-range/src/main.rs}}
+fn main() {
+ for number in (1..4).rev() {
+ println!("{}!", number);
+ }
+ println!("LIFTOFF!!!");
+}
```
This code is a bit nicer, isn’t it?
diff --git a/book-original/src/ch04-01-what-is-ownership.md b/book-pl-en/src/ch04-01-what-is-ownership.md
index 0018300..c9370da 100644
--- a/book-original/src/ch04-01-what-is-ownership.md
+++ b/book-pl-en/src/ch04-01-what-is-ownership.md
@@ -30,37 +30,36 @@ strings.
> be described in relation to the stack and the heap later in this chapter, so
> here is a brief explanation in preparation.
>
-> Both the stack and the heap are parts of memory that are available to your
-> code to use at runtime, but they are structured in different ways. The stack
-> stores values in the order it gets them and removes the values in the
-> opposite order. This is referred to as *last in, first out*. Think of a stack
-> of plates: when you add more plates, you put them on top of the pile, and
-> when you need a plate, you take one off the top. Adding or removing plates
-> from the middle or bottom wouldn’t work as well! Adding data is called
-> *pushing onto the stack*, and removing data is called *popping off the stack*.
+> Both the stack and the heap are parts of memory that are available to your code
+> to use at runtime, but they are structured in different ways. The stack stores
+> values in the order it gets them and removes the values in the opposite order.
+> This is referred to as *last in, first out*. Think of a stack of plates: when
+> you add more plates, you put them on top of the pile, and when you need a
+> plate, you take one off the top. Adding or removing plates from the middle or
+> bottom wouldn’t work as well! Adding data is called *pushing onto the stack*,
+> and removing data is called *popping off the stack*.
>
-> All data stored on the stack must have a known, fixed size. Data with an
-> unknown size at compile time or a size that might change must be stored on
+> All data stored on the stack must have a known, fixed size. Data with a size
+> that is unknown at compile time or a size that might change must be stored on
> the heap instead. The heap is less organized: when you put data on the heap,
-> you request a certain amount of space. The operating system finds an empty
-> spot in the heap that is big enough, marks it as being in use, and returns a
-> *pointer*, which is the address of that location. This process is called
-> *allocating on the heap* and is sometimes abbreviated as just *allocating*.
+> you ask for some amount of space. The operating system finds an empty spot
+> somewhere in the heap that is big enough, marks it as being in use, and
+> returns a *pointer*, which is the address of that location. This process is
+> called *allocating on the heap*, sometimes abbreviated as just “allocating.”
> Pushing values onto the stack is not considered allocating. Because the
> pointer is a known, fixed size, you can store the pointer on the stack, but
-> when you want the actual data, you must follow the pointer.
+> when you want the actual data, you have to follow the pointer.
>
> Think of being seated at a restaurant. When you enter, you state the number of
> people in your group, and the staff finds an empty table that fits everyone
> and leads you there. If someone in your group comes late, they can ask where
> you’ve been seated to find you.
>
-> Pushing to the stack is faster than allocating on the heap because the
-> operating system never has to search for a place to store new data; that
-> location is always at the top of the stack. Comparatively, allocating space
-> on the heap requires more work, because the operating system must first find
-> a big enough space to hold the data and then perform bookkeeping to prepare
-> for the next allocation.
+> Pushing to the stack is faster than allocating on the heap because it never
+> has to search for a place to put new data; that place is always at the top
+> of the stack. Comparatively, allocating space on the heap requires more work,
+> because the operating system must first find a space big enough to hold the
+> data and then perform bookkeeping to prepare for the next allocation.
>
> Accessing data in the heap is slower than accessing data on the stack because
> you have to follow a pointer to get there. Contemporary processors are faster
@@ -117,7 +116,11 @@ which it’s declared until the end of the current *scope*. Listing 4-1 has
comments annotating where the variable `s` is valid.
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-01/src/main.rs:here}}
+{ // s is not valid here, it’s not yet declared
+ let s = "hello"; // s is valid from this point forward
+
+ // do stuff with s
+} // this scope is now over, and s is no longer valid
```
<span class="caption">Listing 4-1: A variable and the scope in which it is
@@ -142,9 +145,9 @@ that is stored on the heap and explore how Rust knows when to clean up that
data.
We’ll use `String` as the example here and concentrate on the parts of `String`
-that relate to ownership. These aspects also apply to other complex data types,
-whether they are provided by the standard library or created by you. We’ll
-discuss `String` in more depth in Chapter 8.
+that relate to ownership. These aspects also apply to other complex data types
+provided by the standard library and that you create. We’ll discuss `String` in
+more depth in Chapter 8.
We’ve already seen string literals, where a string value is hardcoded into our
program. String literals are convenient, but they aren’t suitable for every
@@ -170,7 +173,11 @@ Module Tree”][paths-module-tree]<!-- ignore --> in Chapter 7.
This kind of string *can* be mutated:
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/src/main.rs:here}}
+let mut s = String::from("hello");
+
+s.push_str(", world!"); // push_str() appends a literal to a String
+
+println!("{}", s); // This will print `hello, world!`
```
So, what’s the difference here? Why can `String` be mutated but literals
@@ -211,7 +218,12 @@ variable that owns it goes out of scope. Here’s a version of our scope example
from Listing 4-1 using a `String` instead of a string literal:
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs:here}}
+{
+ let s = String::from("hello"); // s is valid from this point forward
+
+ // do stuff with s
+} // this scope is now over, and s is no
+ // longer valid
```
There is a natural point at which we can return the memory our `String` needs
@@ -236,7 +248,8 @@ Multiple variables can interact with the same data in different ways in Rust.
Let’s look at an example using an integer in Listing 4-2.
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-02/src/main.rs:here}}
+let x = 5;
+let y = x;
```
<span class="caption">Listing 4-2: Assigning the integer value of variable `x`
@@ -251,7 +264,8 @@ onto the stack.
Now let’s look at the `String` version:
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-03-string-move/src/main.rs:here}}
+let s1 = String::from("hello");
+let s2 = s1;
```
This looks very similar to the previous code, so we might assume that the way
@@ -310,14 +324,27 @@ anything when `s1` goes out of scope. Check out what happens when you try to
use `s1` after `s2` is created; it won’t work:
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/src/main.rs:here}}
+let s1 = String::from("hello");
+let s2 = s1;
+
+println!("{}, world!", s1);
```
You’ll get an error like this because Rust prevents you from using the
invalidated reference:
```text
-{{#include ../listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt}}
+error[E0382]: use of moved value: `s1`
+ --> src/main.rs:5:28
+ |
+3 | let s2 = s1;
+ | -- value moved here
+4 |
+5 | println!("{}, world!", s1);
+ | ^^ value used here after move
+ |
+ = note: move occurs because `s1` has type `std::string::String`, which does
+ not implement the `Copy` trait
```
If you’ve heard the terms *shallow copy* and *deep copy* while working with
@@ -349,7 +376,10 @@ programming languages, you’ve probably seen them before.
Here’s an example of the `clone` method in action:
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-05-clone/src/main.rs:here}}
+let s1 = String::from("hello");
+let s2 = s1.clone();
+
+println!("s1 = {}, s2 = {}", s1, s2);
```
This works just fine and explicitly produces the behavior shown in Figure 4-3,
@@ -365,7 +395,10 @@ There’s another wrinkle we haven’t talked about yet. This code using integer
part of which was shown in Listing 4-2, works and is valid:
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-06-copy/src/main.rs:here}}
+let x = 5;
+let y = x;
+
+println!("x = {}, y = {}", x, y);
```
But this code seems to contradict what we just learned: we don’t have a call to
@@ -410,7 +443,29 @@ showing where variables go into and out of scope.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-03/src/main.rs}}
+fn main() {
+ let s = String::from("hello"); // s comes into scope
+
+ takes_ownership(s); // s's value moves into the function...
+ // ... and so is no longer valid here
+
+ let x = 5; // x comes into scope
+
+ makes_copy(x); // x would move into the function,
+ // but i32 is Copy, so it’s okay to still
+ // use x afterward
+
+} // Here, x goes out of scope, then s. But because s's value was moved, nothing
+ // special happens.
+
+fn takes_ownership(some_string: String) { // some_string comes into scope
+ println!("{}", some_string);
+} // Here, some_string goes out of scope and `drop` is called. The backing
+ // memory is freed.
+
+fn makes_copy(some_integer: i32) { // some_integer comes into scope
+ println!("{}", some_integer);
+} // Here, some_integer goes out of scope. Nothing special happens.
```
<span class="caption">Listing 4-3: Functions with ownership and scope
@@ -429,7 +484,35 @@ similar annotations to those in Listing 4-3.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-04/src/main.rs}}
+fn main() {
+ let s1 = gives_ownership(); // gives_ownership moves its return
+ // value into s1
+
+ let s2 = String::from("hello"); // s2 comes into scope
+
+ let s3 = takes_and_gives_back(s2); // s2 is moved into
+ // takes_and_gives_back, which also
+ // moves its return value into s3
+} // Here, s3 goes out of scope and is dropped. s2 goes out of scope but was
+ // moved, so nothing happens. s1 goes out of scope and is dropped.
+
+fn gives_ownership() -> String { // gives_ownership will move its
+ // return value into the function
+ // that calls it
+
+ let some_string = String::from("hello"); // some_string comes into scope
+
+ some_string // some_string is returned and
+ // moves out to the calling
+ // function
+}
+
+// takes_and_gives_back will take a String and return one
+fn takes_and_gives_back(a_string: String) -> String { // a_string comes into
+ // scope
+
+ a_string // a_string is returned and moves out to the calling function
+}
```
<span class="caption">Listing 4-4: Transferring ownership of return
@@ -451,7 +534,19 @@ It’s possible to return multiple values using a tuple, as shown in Listing 4-5
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-05/src/main.rs}}
+fn main() {
+ let s1 = String::from("hello");
+
+ let (s2, len) = calculate_length(s1);
+
+ println!("The length of '{}' is {}.", s2, len);
+}
+
+fn calculate_length(s: String) -> (String, usize) {
+ let length = s.len(); // len() returns the length of a String
+
+ (s, length)
+}
```
<span class="caption">Listing 4-5: Returning ownership of parameters</span>
@@ -461,6 +556,6 @@ common. Luckily for us, Rust has a feature for this concept, called
*references*.
[data-types]: ch03-02-data-types.html#data-types
-[derivable-traits]: appendix-03-derivable-traits.html
+[derivable-traits]: appendix-03-derivable-traits.html#derivable-traits
[method-syntax]: ch05-03-method-syntax.html#method-syntax
-[paths-module-tree]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html
+[paths-module-tree]: ch07-02-modules-and-use-to-control-scope-and-privacy.html#paths-for-referring-to-an-item-in-the-module-tree
diff --git a/book-original/src/ch04-02-references-and-borrowing.md b/book-pl-en/src/ch04-02-references-and-borrowing.md
index 5554fc3..5f57283 100644
--- a/book-original/src/ch04-02-references-and-borrowing.md
+++ b/book-pl-en/src/ch04-02-references-and-borrowing.md
@@ -12,7 +12,17 @@ value:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs:all}}
+fn main() {
+ let s1 = String::from("hello");
+
+ let len = calculate_length(&s1);
+
+ println!("The length of '{}' is {}.", s1, len);
+}
+
+fn calculate_length(s: &String) -> usize {
+ s.len()
+}
```
First, notice that all the tuple code in the variable declaration and the
@@ -36,7 +46,12 @@ s1`</span>
Let’s take a closer look at the function call here:
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs:here}}
+# fn calculate_length(s: &String) -> usize {
+# s.len()
+# }
+let s1 = String::from("hello");
+
+let len = calculate_length(&s1);
```
The `&s1` syntax lets us create a reference that *refers* to the value of `s1`
@@ -47,7 +62,10 @@ Likewise, the signature of the function uses `&` to indicate that the type of
the parameter `s` is a reference. Let’s add some explanatory annotations:
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/src/main.rs:here}}
+fn calculate_length(s: &String) -> usize { // s is a reference to a String
+ s.len()
+} // Here, s goes out of scope. But because it does not have ownership of what
+ // it refers to, nothing happens.
```
The scope in which the variable `s` is valid is the same as any function
@@ -66,7 +84,15 @@ Listing 4-6. Spoiler alert: it doesn’t work!
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-06/src/main.rs}}
+fn main() {
+ let s = String::from("hello");
+
+ change(&s);
+}
+
+fn change(some_string: &String) {
+ some_string.push_str(", world");
+}
```
<span class="caption">Listing 4-6: Attempting to modify a borrowed value</span>
@@ -74,7 +100,13 @@ Listing 4-6. Spoiler alert: it doesn’t work!
Here’s the error:
```text
-{{#include ../listings/ch04-understanding-ownership/listing-04-06/output.txt}}
+error[E0596]: cannot borrow immutable borrowed content `*some_string` as mutable
+ --> error.rs:8:5
+ |
+7 | fn change(some_string: &String) {
+ | ------- use `&mut String` here to make mutable
+8 | some_string.push_str(", world");
+ | ^^^^^^^^^^^ cannot borrow as mutable
```
Just as variables are immutable by default, so are references. We’re not
@@ -87,7 +119,15 @@ We can fix the error in the code from Listing 4-6 with just a small tweak:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/src/main.rs}}
+fn main() {
+ let mut s = String::from("hello");
+
+ change(&mut s);
+}
+
+fn change(some_string: &mut String) {
+ some_string.push_str(", world");
+}
```
First, we had to change `s` to be `mut`. Then we had to create a mutable
@@ -101,13 +141,26 @@ fail:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/src/main.rs:here}}
+let mut s = String::from("hello");
+
+let r1 = &mut s;
+let r2 = &mut s;
+
+println!("{}, {}", r1, r2);
```
Here’s the error:
```text
-{{#include ../listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt}}
+error[E0499]: cannot borrow `s` as mutable more than once at a time
+ --> src/main.rs:5:10
+ |
+4 | let r1 = &mut s;
+ | ------ first mutable borrow occurs here
+5 | let r2 = &mut s;
+ | ^^^^^^ second mutable borrow occurs here
+6 | println!("{}, {}", r1, r2);
+ | -- borrow later used here
```
This restriction allows for mutation but in a very controlled fashion. It’s
@@ -130,20 +183,43 @@ As always, we can use curly brackets to create a new scope, allowing for
multiple mutable references, just not *simultaneous* ones:
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/src/main.rs:here}}
+let mut s = String::from("hello");
+
+{
+ let r1 = &mut s;
+
+} // r1 goes out of scope here, so we can make a new reference with no problems.
+
+let r2 = &mut s;
```
A similar rule exists for combining mutable and immutable references. This code
results in an error:
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/src/main.rs:here}}
+let mut s = String::from("hello");
+
+let r1 = &s; // no problem
+let r2 = &s; // no problem
+let r3 = &mut s; // BIG PROBLEM
+
+println!("{}, {}, and {}", r1, r2, r3);
```
Here’s the error:
```text
-{{#include ../listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt}}
+error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
+ --> src/main.rs:6:10
+ |
+4 | let r1 = &s; // no problem
+ | -- immutable borrow occurs here
+5 | let r2 = &s; // no problem
+6 | let r3 = &mut s; // BIG PROBLEM
+ | ^^^^^^ mutable borrow occurs here
+7 |
+8 | println!("{}, {}, and {}", r1, r2, r3);
+ | -- borrow later used here
```
Whew! We *also* cannot have a mutable reference while we have an immutable one.
@@ -152,23 +228,10 @@ from under them! However, multiple immutable references are okay because no one
who is just reading the data has the ability to affect anyone else’s reading of
the data.
-Note that a reference’s scope starts from where it is introduced and continues
-through the last time that reference is used. For instance, this code will
-compile because the last usage of the immutable references occurs before the
-mutable reference is introduced:
-
-```rust,edition2018
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs:here}}
-```
-
-The scopes of the immutable references `r1` and `r2` end after the `println!`
-where they are last used, which is before the mutable reference `r3` is
-created. These scopes don’t overlap, so this code is allowed.
-
-Even though borrowing errors may be frustrating at times, remember that it’s
-the Rust compiler pointing out a potential bug early (at compile time rather
-than at runtime) and showing you exactly where the problem is. Then you don’t
-have to track down why your data isn’t what you thought it was.
+Even though these errors may be frustrating at times, remember that it’s the
+Rust compiler pointing out a potential bug early (at compile time rather than
+at runtime) and showing you exactly where the problem is. Then you don’t have
+to track down why your data isn’t what you thought it was.
### Dangling References
@@ -186,13 +249,29 @@ compile-time error:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-14-dangling-reference/src/main.rs}}
+fn main() {
+ let reference_to_nothing = dangle();
+}
+
+fn dangle() -> &String {
+ let s = String::from("hello");
+
+ &s
+}
```
Here’s the error:
```text
-{{#include ../listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt}}
+error[E0106]: missing lifetime specifier
+ --> main.rs:5:16
+ |
+5 | fn dangle() -> &String {
+ | ^ expected lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is
+ no value for it to be borrowed from
+ = help: consider giving it a 'static lifetime
```
This error message refers to a feature we haven’t covered yet: lifetimes. We’ll
@@ -207,10 +286,14 @@ for it to be borrowed from.
Let’s take a closer look at exactly what’s happening at each stage of our
`dangle` code:
-<span class="filename">Filename: src/main.rs</span>
+```rust,ignore
+fn dangle() -> &String { // dangle returns a reference to a String
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs:here}}
+ let s = String::from("hello"); // s is a new String
+
+ &s // we return a reference to the String, s
+} // Here, s goes out of scope, and is dropped. Its memory goes away.
+ // Danger!
```
Because `s` is created inside `dangle`, when the code of `dangle` is finished,
@@ -221,7 +304,11 @@ won’t let us do this.
The solution here is to return the `String` directly:
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-16-no-dangle/src/main.rs:here}}
+fn no_dangle() -> String {
+ let s = String::from("hello");
+
+ s
+}
```
This works without any problems. Ownership is moved out, and nothing is
diff --git a/book-original/src/ch04-03-slices.md b/book-pl-en/src/ch04-03-slices.md
index 902cf3a..3eb186e 100644
--- a/book-original/src/ch04-03-slices.md
+++ b/book-pl-en/src/ch04-03-slices.md
@@ -23,7 +23,17 @@ end of the word. Let’s try that, as shown in Listing 4-7.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-07/src/main.rs:here}}
+fn first_word(s: &String) -> usize {
+ let bytes = s.as_bytes();
+
+ for (i, &item) in bytes.iter().enumerate() {
+ if item == b' ' {
+ return i;
+ }
+ }
+
+ s.len()
+}
```
<span class="caption">Listing 4-7: The `first_word` function that returns a
@@ -34,13 +44,13 @@ a value is a space, we’ll convert our `String` to an array of bytes using the
`as_bytes` method:
```rust,ignore
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-07/src/main.rs:as_bytes}}
+let bytes = s.as_bytes();
```
Next, we create an iterator over the array of bytes using the `iter` method:
```rust,ignore
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-07/src/main.rs:iter}}
+for (i, &item) in bytes.iter().enumerate() {
```
We’ll discuss iterators in more detail in Chapter 13. For now, know that `iter`
@@ -61,7 +71,12 @@ using the byte literal syntax. If we find a space, we return the position.
Otherwise, we return the length of the string by using `s.len()`:
```rust,ignore
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-07/src/main.rs:inside_for}}
+ if item == b' ' {
+ return i;
+ }
+}
+
+s.len()
```
We now have a way to find out the index of the end of the first word in the
@@ -74,7 +89,28 @@ uses the `first_word` function from Listing 4-7.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-08/src/main.rs:here}}
+# fn first_word(s: &String) -> usize {
+# let bytes = s.as_bytes();
+#
+# for (i, &item) in bytes.iter().enumerate() {
+# if item == b' ' {
+# return i;
+# }
+# }
+#
+# s.len()
+# }
+#
+fn main() {
+ let mut s = String::from("hello world");
+
+ let word = first_word(&s); // word will get the value 5
+
+ s.clear(); // this empties the String, making it equal to ""
+
+ // word still has the value 5 here, but there's no more string that
+ // we could meaningfully use the value 5 with. word is now totally invalid!
+}
```
<span class="caption">Listing 4-8: Storing the result from calling the
@@ -106,12 +142,27 @@ Luckily, Rust has a solution to this problem: string slices.
A *string slice* is a reference to part of a `String`, and it looks like this:
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-17-slice/src/main.rs:here}}
+let s = String::from("hello world");
+
+let hello = &s[0..5];
+let world = &s[6..11];
```
This is similar to taking a reference to the whole `String` but with the extra
`[0..5]` bit. Rather than a reference to the entire `String`, it’s a reference
-to a portion of the `String`.
+to a portion of the `String`. The `start..end` syntax is a range that begins at
+`start` and continues up to, but not including, `end`. If we wanted to include
+`end`, we can use `..=` instead of `..`:
+
+```rust
+let s = String::from("hello world");
+
+let hello = &s[0..=4];
+let world = &s[6..=10];
+```
+
+The `=` means that we’re including the last number, if that helps you remember
+the difference between `..` and `..=`.
We can create slices using a range within brackets by specifying
`[starting_index..ending_index]`, where `starting_index` is the first position
@@ -119,7 +170,7 @@ in the slice and `ending_index` is one more than the last position in the
slice. Internally, the slice data structure stores the starting position and
the length of the slice, which corresponds to `ending_index` minus
`starting_index`. So in the case of `let world = &s[6..11];`, `world` would be
-a slice that contains a pointer to the 7th byte (counting from 1) of `s` with a length value of 5.
+a slice that contains a pointer to the 7th byte of `s` with a length value of 5.
Figure 4-6 shows this in a diagram.
@@ -175,7 +226,17 @@ slice. The type that signifies “string slice” is written as `&str`:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-18-first-word-slice/src/main.rs:here}}
+fn first_word(s: &String) -> &str {
+ let bytes = s.as_bytes();
+
+ for (i, &item) in bytes.iter().enumerate() {
+ if item == b' ' {
+ return &s[0..i];
+ }
+ }
+
+ &s[..]
+}
```
We get the index for the end of the word in the same way as we did in Listing
@@ -206,20 +267,38 @@ compile-time error:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-19-slice-error/src/main.rs:here}}
+fn main() {
+ let mut s = String::from("hello world");
+
+ let word = first_word(&s);
+
+ s.clear(); // error!
+
+ println!("the first word is: {}", word);
+}
```
Here’s the compiler error:
```text
-{{#include ../listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt}}
+error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
+ --> src/main.rs:10:5
+ |
+8 | let word = first_word(&s);
+ | -- immutable borrow occurs here
+9 |
+10 | s.clear(); // error!
+ | ^^^^^^^^^ mutable borrow occurs here
+11 |
+12 | println!("the first word is: {}", word);
+ | ---- borrow later used here
```
Recall from the borrowing rules that if we have an immutable reference to
something, we cannot also take a mutable reference. Because `clear` needs to
-truncate the `String`, it needs to get a mutable reference. Rust disallows
-this, and compilation fails. Not only has Rust made our API easier to use, but
-it has also eliminated an entire class of errors at compile time!
+truncate the `String`, it tries to take a mutable reference, which fails. Not
+only has Rust made our API easier to use, but it has also eliminated an entire
+class of errors at compile time!
#### String Literals Are Slices
@@ -244,11 +323,11 @@ fn first_word(s: &String) -> &str {
```
A more experienced Rustacean would write the signature shown in Listing 4-9
-instead because it allows us to use the same function on both `&String` values
+instead because it allows us to use the same function on both `String` values
and `&str` values.
```rust,ignore
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-09/src/main.rs:here}}
+fn first_word(s: &str) -> &str {
```
<span class="caption">Listing 4-9: Improving the `first_word` function by using
@@ -262,7 +341,32 @@ without losing any functionality:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-09/src/main.rs:usage}}
+# fn first_word(s: &str) -> &str {
+# let bytes = s.as_bytes();
+#
+# for (i, &item) in bytes.iter().enumerate() {
+# if item == b' ' {
+# return &s[0..i];
+# }
+# }
+#
+# &s[..]
+# }
+fn main() {
+ let my_string = String::from("hello world");
+
+ // first_word works on slices of `String`s
+ let word = first_word(&my_string[..]);
+
+ let my_string_literal = "hello world";
+
+ // first_word works on slices of string literals
+ let word = first_word(&my_string_literal[..]);
+
+ // Because string literals *are* string slices already,
+ // this works too, without the slice syntax!
+ let word = first_word(my_string_literal);
+}
```
### Other Slices
diff --git a/book-original/src/ch05-01-defining-structs.md b/book-pl-en/src/ch05-01-defining-structs.md
index 04479e5..f08b45b 100644
--- a/book-original/src/ch05-01-defining-structs.md
+++ b/book-pl-en/src/ch05-01-defining-structs.md
@@ -13,7 +13,12 @@ the pieces of data, which we call *fields*. For example, Listing 5-1 shows a
struct that stores information about a user account.
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs:here}}
+struct User {
+ username: String,
+ email: String,
+ sign_in_count: u64,
+ active: bool,
+}
```
<span class="caption">Listing 5-1: A `User` struct definition</span>
@@ -29,7 +34,19 @@ in that template with particular data to create values of the type. For
example, we can declare a particular user as shown in Listing 5-2.
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs:here}}
+# struct User {
+# username: String,
+# email: String,
+# sign_in_count: u64,
+# active: bool,
+# }
+#
+let user1 = User {
+ email: String::from("someone@example.com"),
+ username: String::from("someusername123"),
+ active: true,
+ sign_in_count: 1,
+};
```
<span class="caption">Listing 5-2: Creating an instance of the `User`
@@ -42,7 +59,21 @@ the dot notation and assigning into a particular field. Listing 5-3 shows how
to change the value in the `email` field of a mutable `User` instance.
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs:here}}
+# struct User {
+# username: String,
+# email: String,
+# sign_in_count: u64,
+# active: bool,
+# }
+#
+let mut user1 = User {
+ email: String::from("someone@example.com"),
+ username: String::from("someusername123"),
+ active: true,
+ sign_in_count: 1,
+};
+
+user1.email = String::from("anotheremail@example.com");
```
<span class="caption">Listing 5-3: Changing the value in the `email` field of a
@@ -58,7 +89,21 @@ the given email and username. The `active` field gets the value of `true`, and
the `sign_in_count` gets a value of `1`.
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs:here}}
+# struct User {
+# username: String,
+# email: String,
+# sign_in_count: u64,
+# active: bool,
+# }
+#
+fn build_user(email: String, username: String) -> User {
+ User {
+ email: email,
+ username: username,
+ active: true,
+ sign_in_count: 1,
+ }
+}
```
<span class="caption">Listing 5-4: A `build_user` function that takes an email
@@ -77,7 +122,21 @@ Listing 5-4, we can use the *field init shorthand* syntax to rewrite
repetition of `email` and `username`, as shown in Listing 5-5.
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs:here}}
+# struct User {
+# username: String,
+# email: String,
+# sign_in_count: u64,
+# active: bool,
+# }
+#
+fn build_user(email: String, username: String) -> User {
+ User {
+ email,
+ username,
+ active: true,
+ sign_in_count: 1,
+ }
+}
```
<span class="caption">Listing 5-5: A `build_user` function that uses field init
@@ -100,7 +159,26 @@ the update syntax. We set new values for `email` and `username` but otherwise
use the same values from `user1` that we created in Listing 5-2.
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs:here}}
+# struct User {
+# username: String,
+# email: String,
+# sign_in_count: u64,
+# active: bool,
+# }
+#
+# let user1 = User {
+# email: String::from("someone@example.com"),
+# username: String::from("someusername123"),
+# active: true,
+# sign_in_count: 1,
+# };
+#
+let user2 = User {
+ email: String::from("another@example.com"),
+ username: String::from("anotherusername567"),
+ active: user1.active,
+ sign_in_count: user1.sign_in_count,
+};
```
<span class="caption">Listing 5-6: Creating a new `User` instance using some of
@@ -111,7 +189,25 @@ shown in Listing 5-7. The syntax `..` specifies that the remaining fields not
explicitly set should have the same value as the fields in the given instance.
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs:here}}
+# struct User {
+# username: String,
+# email: String,
+# sign_in_count: u64,
+# active: bool,
+# }
+#
+# let user1 = User {
+# email: String::from("someone@example.com"),
+# username: String::from("someusername123"),
+# active: true,
+# sign_in_count: 1,
+# };
+#
+let user2 = User {
+ email: String::from("another@example.com"),
+ username: String::from("anotherusername567"),
+ ..user1
+};
```
<span class="caption">Listing 5-7: Using struct update syntax to set new
@@ -128,7 +224,7 @@ You can also define structs that look similar to tuples, called *tuple
structs*. Tuple structs have the added meaning the struct name provides but
don’t have names associated with their fields; rather, they just have the types
of the fields. Tuple structs are useful when you want to give the whole tuple a
-name and make the tuple be a different type from other tuples, and naming each
+name and make the tuple be a different type than other tuples, and naming each
field as in a regular struct would be verbose or redundant.
To define a tuple struct, start with the `struct` keyword and the struct name
@@ -136,7 +232,11 @@ followed by the types in the tuple. For example, here are definitions and
usages of two tuple structs named `Color` and `Point`:
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs:here}}
+struct Color(i32, i32, i32);
+struct Point(i32, i32, i32);
+
+let black = Color(0, 0, 0);
+let origin = Point(0, 0, 0);
```
Note that the `black` and `origin` values are different types, because they’re
@@ -171,8 +271,6 @@ itself. We’ll discuss traits in Chapter 10.
>
> <span class="filename">Filename: src/main.rs</span>
>
-> <!-- CAN'T EXTRACT SEE https://github.com/rust-lang/mdBook/issues/1127 -->
->
> ```rust,ignore,does_not_compile
> struct User {
> username: &str,
@@ -194,35 +292,19 @@ itself. We’ll discuss traits in Chapter 10.
> The compiler will complain that it needs lifetime specifiers:
>
> ```text
-> $ cargo run
-> Compiling structs v0.1.0 (file:///projects/structs)
> error[E0106]: missing lifetime specifier
-> --> src/main.rs:2:15
+> -->
> |
> 2 | username: &str,
> | ^ expected lifetime parameter
>
> error[E0106]: missing lifetime specifier
-> --> src/main.rs:3:12
+> -->
> |
> 3 | email: &str,
> | ^ expected lifetime parameter
->
-> error: aborting due to 2 previous errors
->
-> For more information about this error, try `rustc --explain E0106`.
-> error: could not compile `structs`.
->
-> To learn more, run the command again with --verbose.
> ```
>
> In Chapter 10, we’ll discuss how to fix these errors so you can store
> references in structs, but for now, we’ll fix errors like these using owned
> types like `String` instead of references like `&str`.
-
-<!-- manual-regeneration
-for the error above
-after running update-rustc.sh:
-pbcopy < listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt
-paste above
-add `> ` before every line -->
diff --git a/book-original/src/ch05-02-example-structs.md b/book-pl-en/src/ch05-02-example-structs.md
index 03f69d9..55ac459 100644
--- a/book-original/src/ch05-02-example-structs.md
+++ b/book-pl-en/src/ch05-02-example-structs.md
@@ -12,7 +12,19 @@ exactly that in our project’s *src/main.rs*.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs:all}}
+fn main() {
+ let width1 = 30;
+ let height1 = 50;
+
+ println!(
+ "The area of the rectangle is {} square pixels.",
+ area(width1, height1)
+ );
+}
+
+fn area(width: u32, height: u32) -> u32 {
+ width * height
+}
```
<span class="caption">Listing 5-8: Calculating the area of a rectangle
@@ -21,7 +33,7 @@ specified by separate width and height variables</span>
Now, run this program using `cargo run`:
```text
-{{#include ../listings/ch05-using-structs-to-structure-related-data/listing-05-08/output.txt}}
+The area of the rectangle is 1500 square pixels.
```
Even though Listing 5-8 works and figures out the area of the rectangle by
@@ -32,7 +44,7 @@ rectangle.
The issue with this code is evident in the signature of `area`:
```rust,ignore
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs:here}}
+fn area(width: u32, height: u32) -> u32 {
```
The `area` function is supposed to calculate the area of one rectangle, but the
@@ -49,7 +61,18 @@ Listing 5-9 shows another version of our program that uses tuples.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-09/src/main.rs}}
+fn main() {
+ let rect1 = (30, 50);
+
+ println!(
+ "The area of the rectangle is {} square pixels.",
+ area(rect1)
+ );
+}
+
+fn area(dimensions: (u32, u32)) -> u32 {
+ dimensions.0 * dimensions.1
+}
```
<span class="caption">Listing 5-9: Specifying the width and height of the
@@ -77,7 +100,23 @@ parts, as shown in Listing 5-10.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-10/src/main.rs}}
+struct Rectangle {
+ width: u32,
+ height: u32,
+}
+
+fn main() {
+ let rect1 = Rectangle { width: 30, height: 50 };
+
+ println!(
+ "The area of the rectangle is {} square pixels.",
+ area(&rect1)
+ );
+}
+
+fn area(rectangle: &Rectangle) -> u32 {
+ rectangle.width * rectangle.height
+}
```
<span class="caption">Listing 5-10: Defining a `Rectangle` struct</span>
@@ -111,16 +150,25 @@ work, however.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-11/src/main.rs}}
+struct Rectangle {
+ width: u32,
+ height: u32,
+}
+
+fn main() {
+ let rect1 = Rectangle { width: 30, height: 50 };
+
+ println!("rect1 is {}", rect1);
+}
```
<span class="caption">Listing 5-11: Attempting to print a `Rectangle`
instance</span>
-When we compile this code, we get an error with this core message:
+When we run this code, we get an error with this core message:
```text
-{{#include ../listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt:3}}
+error[E0277]: the trait bound `Rectangle: std::fmt::Display` is not satisfied
```
The `println!` macro can do many kinds of formatting, and by default, the curly
@@ -137,7 +185,8 @@ implementation of `Display`.
If we continue reading the errors, we’ll find this helpful note:
```text
-{{#include ../listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt:9:10}}
+`Rectangle` cannot be formatted with the default formatter; try using
+`:?` instead if you are using a format string
```
Let’s try it! The `println!` macro call will now look like `println!("rect1 is
@@ -146,16 +195,17 @@ Let’s try it! The `println!` macro call will now look like `println!("rect1 is
enables us to print our struct in a way that is useful for developers so we can
see its value while we’re debugging our code.
-Compile the code with this change. Drat! We still get an error:
+Run the code with this change. Drat! We still get an error:
```text
-{{#include ../listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt:3}}
+error[E0277]: the trait bound `Rectangle: std::fmt::Debug` is not satisfied
```
But again, the compiler gives us a helpful note:
```text
-{{#include ../listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt:9:10}}
+`Rectangle` cannot be formatted using `:?`; if it is defined in your
+crate, add `#[derive(Debug)]` or manually implement it
```
Rust *does* include functionality to print out debugging information, but we
@@ -166,7 +216,17 @@ definition, as shown in Listing 5-12.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-12/src/main.rs}}
+#[derive(Debug)]
+struct Rectangle {
+ width: u32,
+ height: u32,
+}
+
+fn main() {
+ let rect1 = Rectangle { width: 30, height: 50 };
+
+ println!("rect1 is {:?}", rect1);
+}
```
<span class="caption">Listing 5-12: Adding the annotation to derive the `Debug`
@@ -176,7 +236,7 @@ Now when we run the program, we won’t get any errors, and we’ll see the
following output:
```text
-{{#include ../listings/ch05-using-structs-to-structure-related-data/listing-05-12/output.txt}}
+rect1 is Rectangle { width: 30, height: 50 }
```
Nice! It’s not the prettiest output, but it shows the values of all the fields
@@ -186,7 +246,10 @@ those cases, we can use `{:#?}` instead of `{:?}` in the `println!` string.
When we use the `{:#?}` style in the example, the output will look like this:
```text
-{{#include ../listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/output.txt}}
+rect1 is Rectangle {
+ width: 30,
+ height: 50
+}
```
Rust has provided a number of traits for us to use with the `derive` annotation
diff --git a/book-original/src/ch05-03-method-syntax.md b/book-pl-en/src/ch05-03-method-syntax.md
index f074497..d8a338c 100644
--- a/book-original/src/ch05-03-method-syntax.md
+++ b/book-pl-en/src/ch05-03-method-syntax.md
@@ -17,7 +17,26 @@ in Listing 5-13.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-13/src/main.rs}}
+#[derive(Debug)]
+struct Rectangle {
+ width: u32,
+ height: u32,
+}
+
+impl Rectangle {
+ fn area(&self) -> u32 {
+ self.width * self.height
+ }
+}
+
+fn main() {
+ let rect1 = Rectangle { width: 30, height: 50 };
+
+ println!(
+ "The area of the rectangle is {} square pixels.",
+ rect1.area()
+ );
+}
```
<span class="caption">Listing 5-13: Defining an `area` method on the
@@ -71,7 +90,6 @@ provide.
> automatically adds in `&`, `&mut`, or `*` so `object` matches the signature of
> the method. In other words, the following are the same:
>
-<!-- CAN'T EXTRACT SEE BUG TODO -->
> ```rust
> # #[derive(Debug,Copy,Clone)]
> # struct Point {
@@ -112,7 +130,14 @@ method.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-14/src/main.rs}}
+fn main() {
+ let rect1 = Rectangle { width: 30, height: 50 };
+ let rect2 = Rectangle { width: 10, height: 40 };
+ let rect3 = Rectangle { width: 60, height: 45 };
+
+ println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
+ println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
+}
```
<span class="caption">Listing 5-14: Using the as-yet-unwritten `can_hold`
@@ -144,7 +169,21 @@ Listing 5-13, shown in Listing 5-15.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-15/src/main.rs:here}}
+# #[derive(Debug)]
+# struct Rectangle {
+# width: u32,
+# height: u32,
+# }
+#
+impl Rectangle {
+ fn area(&self) -> u32 {
+ self.width * self.height
+ }
+
+ fn can_hold(&self, other: &Rectangle) -> bool {
+ self.width > other.width && self.height > other.height
+ }
+}
```
<span class="caption">Listing 5-15: Implementing the `can_hold` method on
@@ -173,7 +212,17 @@ specify the same value twice:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/src/main.rs:here}}
+# #[derive(Debug)]
+# struct Rectangle {
+# width: u32,
+# height: u32,
+# }
+#
+impl Rectangle {
+ fn square(size: u32) -> Rectangle {
+ Rectangle { width: size, height: size }
+ }
+}
```
To call this associated function, we use the `::` syntax with the struct name;
@@ -188,7 +237,23 @@ Each struct is allowed to have multiple `impl` blocks. For example, Listing
in its own `impl` block.
```rust
-{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-16/src/main.rs:here}}
+# #[derive(Debug)]
+# struct Rectangle {
+# width: u32,
+# height: u32,
+# }
+#
+impl Rectangle {
+ fn area(&self) -> u32 {
+ self.width * self.height
+ }
+}
+
+impl Rectangle {
+ fn can_hold(&self, other: &Rectangle) -> bool {
+ self.width > other.width && self.height > other.height
+ }
+}
```
<span class="caption">Listing 5-16: Rewriting Listing 5-15 using multiple `impl`
diff --git a/book-original/src/ch06-00-enums.md b/book-pl-en/src/ch06-00-enums.md
index cf7ea67..767f866 100644
--- a/book-original/src/ch06-00-enums.md
+++ b/book-pl-en/src/ch06-00-enums.md
@@ -1,7 +1,7 @@
# Enums and Pattern Matching
In this chapter we’ll look at *enumerations*, also referred to as *enums*.
-Enums allow you to define a type by enumerating its possible *variants*. First,
+Enums allow you to define a type by enumerating its possible values. First,
we’ll define and use an enum to show how an enum can encode meaning along with
data. Next, we’ll explore a particularly useful enum, called `Option`, which
expresses that a value can be either something or nothing. Then we’ll look at
diff --git a/book-original/src/ch06-01-defining-an-enum.md b/book-pl-en/src/ch06-01-defining-an-enum.md
index 1067af0..45317a0 100644
--- a/book-original/src/ch06-01-defining-an-enum.md
+++ b/book-pl-en/src/ch06-01-defining-an-enum.md
@@ -5,21 +5,24 @@ are useful and more appropriate than structs in this case. Say we need to work
with IP addresses. Currently, two major standards are used for IP addresses:
version four and version six. These are the only possibilities for an IP
address that our program will come across: we can *enumerate* all possible
-variants, which is where enumeration gets its name.
+values, which is where enumeration gets its name.
Any IP address can be either a version four or a version six address, but not
both at the same time. That property of IP addresses makes the enum data
-structure appropriate, because enum values can only be one of its variants.
+structure appropriate, because enum values can only be one of the variants.
Both version four and version six addresses are still fundamentally IP
addresses, so they should be treated as the same type when the code is handling
situations that apply to any kind of IP address.
We can express this concept in code by defining an `IpAddrKind` enumeration and
-listing the possible kinds an IP address can be, `V4` and `V6`. These are the
-variants of the enum:
+listing the possible kinds an IP address can be, `V4` and `V6`. These are known
+as the *variants* of the enum:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/src/main.rs:def}}
+enum IpAddrKind {
+ V4,
+ V6,
+}
```
`IpAddrKind` is now a custom data type that we can use elsewhere in our code.
@@ -29,7 +32,13 @@ variants of the enum:
We can create instances of each of the two variants of `IpAddrKind` like this:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/src/main.rs:instance}}
+# enum IpAddrKind {
+# V4,
+# V6,
+# }
+#
+let four = IpAddrKind::V4;
+let six = IpAddrKind::V6;
```
Note that the variants of the enum are namespaced under its identifier, and we
@@ -39,13 +48,26 @@ both values `IpAddrKind::V4` and `IpAddrKind::V6` are of the same type:
`IpAddrKind`:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/src/main.rs:fn}}
+# enum IpAddrKind {
+# V4,
+# V6,
+# }
+#
+fn route(ip_type: IpAddrKind) { }
```
And we can call this function with either variant:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/src/main.rs:fn_call}}
+# enum IpAddrKind {
+# V4,
+# V6,
+# }
+#
+# fn route(ip_type: IpAddrKind) { }
+#
+route(IpAddrKind::V4);
+route(IpAddrKind::V6);
```
Using enums has even more advantages. Thinking more about our IP address type,
@@ -54,7 +76,25 @@ only know what *kind* it is. Given that you just learned about structs in
Chapter 5, you might tackle this problem as shown in Listing 6-1.
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-01/src/main.rs:here}}
+enum IpAddrKind {
+ V4,
+ V6,
+}
+
+struct IpAddr {
+ kind: IpAddrKind,
+ address: String,
+}
+
+let home = IpAddr {
+ kind: IpAddrKind::V4,
+ address: String::from("127.0.0.1"),
+};
+
+let loopback = IpAddr {
+ kind: IpAddrKind::V6,
+ address: String::from("::1"),
+};
```
<span class="caption">Listing 6-1: Storing the data and `IpAddrKind` variant of
@@ -75,7 +115,14 @@ variant. This new definition of the `IpAddr` enum says that both `V4` and `V6`
variants will have associated `String` values:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/src/main.rs:here}}
+enum IpAddr {
+ V4(String),
+ V6(String),
+}
+
+let home = IpAddr::V4(String::from("127.0.0.1"));
+
+let loopback = IpAddr::V6(String::from("::1"));
```
We attach data to each variant of the enum directly, so there is no need for an
@@ -89,7 +136,14 @@ still express `V6` addresses as one `String` value, we wouldn’t be able to wit
a struct. Enums handle this case with ease:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/src/main.rs:here}}
+enum IpAddr {
+ V4(u8, u8, u8, u8),
+ V6(String),
+}
+
+let home = IpAddr::V4(127, 0, 0, 1);
+
+let loopback = IpAddr::V6(String::from("::1"));
```
We’ve shown several different ways to define data structures to store version
@@ -132,7 +186,12 @@ Let’s look at another example of an enum in Listing 6-2: this one has a wide
variety of types embedded in its variants.
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-02/src/main.rs:here}}
+enum Message {
+ Quit,
+ Move { x: i32, y: i32 },
+ Write(String),
+ ChangeColor(i32, i32, i32),
+}
```
<span class="caption">Listing 6-2: A `Message` enum whose variants each store
@@ -152,7 +211,13 @@ type. The following structs could hold the same data that the preceding enum
variants hold:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/src/main.rs:here}}
+struct QuitMessage; // unit struct
+struct MoveMessage {
+ x: i32,
+ y: i32,
+}
+struct WriteMessage(String); // tuple struct
+struct ChangeColorMessage(i32, i32, i32); // tuple struct
```
But if we used the different structs, which each have their own type, we
@@ -164,7 +229,21 @@ define methods on structs using `impl`, we’re also able to define methods on
enums. Here’s a method named `call` that we could define on our `Message` enum:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/src/main.rs:here}}
+# enum Message {
+# Quit,
+# Move { x: i32, y: i32 },
+# Write(String),
+# ChangeColor(i32, i32, i32),
+# }
+#
+impl Message {
+ fn call(&self) {
+ // method body would be defined here
+ }
+}
+
+let m = Message::Write(String::from("hello"));
+m.call();
```
The body of the method would use `self` to get the value that we called the
@@ -240,7 +319,10 @@ For now, all you need to know is that `<T>` means the `Some` variant of the
using `Option` values to hold number types and string types:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/src/main.rs:here}}
+let some_number = Some(5);
+let some_string = Some("a string");
+
+let absent_number: Option<i32> = None;
```
If we use `None` rather than `Some`, we need to tell Rust what type of
@@ -258,13 +340,22 @@ definitely a valid value. For example, this code won’t compile because it’s
trying to add an `i8` to an `Option<i8>`:
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/src/main.rs:here}}
+let x: i8 = 5;
+let y: Option<i8> = Some(5);
+
+let sum = x + y;
```
If we run this code, we get an error message like this:
```text
-{{#include ../listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt}}
+error[E0277]: the trait bound `i8: std::ops::Add<std::option::Option<i8>>` is
+not satisfied
+ -->
+ |
+5 | let sum = x + y;
+ | ^ no implementation for `i8 + std::option::Option<i8>`
+ |
```
Intense! In effect, this error message means that Rust doesn’t understand how
diff --git a/book-original/src/ch06-02-match.md b/book-pl-en/src/ch06-02-match.md
index f403808..92668b6 100644
--- a/book-original/src/ch06-02-match.md
+++ b/book-pl-en/src/ch06-02-match.md
@@ -20,7 +20,21 @@ similar way as the counting machine, determine which coin it is and return its
value in cents, as shown here in Listing 6-3.
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-03/src/main.rs:here}}
+enum Coin {
+ Penny,
+ Nickel,
+ Dime,
+ Quarter,
+}
+
+fn value_in_cents(coin: Coin) -> u32 {
+ match coin {
+ Coin::Penny => 1,
+ Coin::Nickel => 5,
+ Coin::Dime => 10,
+ Coin::Quarter => 25,
+ }
+}
```
<span class="caption">Listing 6-3: An enum and a `match` expression that has
@@ -55,7 +69,24 @@ following code would print “Lucky penny!” every time the method was called w
a `Coin::Penny` but would still return the last value of the block, `1`:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/src/main.rs:here}}
+# enum Coin {
+# Penny,
+# Nickel,
+# Dime,
+# Quarter,
+# }
+#
+fn value_in_cents(coin: Coin) -> u32 {
+ match coin {
+ Coin::Penny => {
+ println!("Lucky penny!");
+ 1
+ },
+ Coin::Nickel => 5,
+ Coin::Dime => 10,
+ Coin::Quarter => 25,
+ }
+}
```
### Patterns that Bind to Values
@@ -72,7 +103,19 @@ our `enum` by changing the `Quarter` variant to include a `UsState` value stored
inside it, which we’ve done here in Listing 6-4.
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-04/src/main.rs:here}}
+#[derive(Debug)] // so we can inspect the state in a minute
+enum UsState {
+ Alabama,
+ Alaska,
+ // --snip--
+}
+
+enum Coin {
+ Penny,
+ Nickel,
+ Dime,
+ Quarter(UsState),
+}
```
<span class="caption">Listing 6-4: A `Coin` enum in which the `Quarter` variant
@@ -89,7 +132,30 @@ pattern that matches values of the variant `Coin::Quarter`. When a
quarter’s state. Then we can use `state` in the code for that arm, like so:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/src/main.rs:here}}
+# #[derive(Debug)]
+# enum UsState {
+# Alabama,
+# Alaska,
+# }
+#
+# enum Coin {
+# Penny,
+# Nickel,
+# Dime,
+# Quarter(UsState),
+# }
+#
+fn value_in_cents(coin: Coin) -> u32 {
+ match coin {
+ Coin::Penny => 1,
+ Coin::Nickel => 5,
+ Coin::Dime => 10,
+ Coin::Quarter(state) => {
+ println!("State quarter from {:?}!", state);
+ 25
+ },
+ }
+}
```
If we were to call `value_in_cents(Coin::Quarter(UsState::Alaska))`, `coin`
@@ -116,7 +182,16 @@ This function is very easy to write, thanks to `match`, and will look like
Listing 6-5.
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-05/src/main.rs:here}}
+fn plus_one(x: Option<i32>) -> Option<i32> {
+ match x {
+ None => None,
+ Some(i) => Some(i + 1),
+ }
+}
+
+let five = Some(5);
+let six = plus_one(five);
+let none = plus_one(None);
```
<span class="caption">Listing 6-5: A function that uses a `match` expression on
@@ -127,14 +202,14 @@ Let’s examine the first execution of `plus_one` in more detail. When we call
value `Some(5)`. We then compare that against each match arm.
```rust,ignore
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-05/src/main.rs:first_arm}}
+None => None,
```
The `Some(5)` value doesn’t match the pattern `None`, so we continue to the
next arm.
```rust,ignore
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-05/src/main.rs:second_arm}}
+Some(i) => Some(i + 1),
```
Does `Some(5)` match `Some(i)`? Why yes it does! We have the same variant. The
@@ -146,7 +221,7 @@ Now let’s consider the second call of `plus_one` in Listing 6-5, where `x` is
`None`. We enter the `match` and compare to the first arm.
```rust,ignore
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-05/src/main.rs:first_arm}}
+None => None,
```
It matches! There’s no value to add to, so the program stops and returns the
@@ -165,7 +240,11 @@ There’s one other aspect of `match` we need to discuss. Consider this version
of our `plus_one` function that has a bug and won’t compile:
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/src/main.rs:here}}
+fn plus_one(x: Option<i32>) -> Option<i32> {
+ match x {
+ Some(i) => Some(i + 1),
+ }
+}
```
We didn’t handle the `None` case, so this code will cause a bug. Luckily, it’s
@@ -173,7 +252,11 @@ a bug Rust knows how to catch. If we try to compile this code, we’ll get this
error:
```text
-{{#include ../listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt}}
+error[E0004]: non-exhaustive patterns: `None` not covered
+ -->
+ |
+6 | match x {
+ | ^ pattern `None` not covered
```
Rust knows that we didn’t cover every possible case and even knows which
@@ -192,7 +275,14 @@ care about the values 1, 3, 5, and 7, we don’t want to have to list out 0, 2,
special pattern `_` instead:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/src/main.rs:here}}
+let some_u8_value = 0u8;
+match some_u8_value {
+ 1 => println!("one"),
+ 3 => println!("three"),
+ 5 => println!("five"),
+ 7 => println!("seven"),
+ _ => (),
+}
```
The `_` pattern will match any value. By putting it after our other arms, the
diff --git a/book-original/src/ch06-03-if-let.md b/book-pl-en/src/ch06-03-if-let.md
index 3eb0cc3..6583546 100644
--- a/book-original/src/ch06-03-if-let.md
+++ b/book-pl-en/src/ch06-03-if-let.md
@@ -6,7 +6,11 @@ program in Listing 6-6 that matches on an `Option<u8>` value but only wants to
execute code if the value is 3.
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-06/src/main.rs:here}}
+let some_u8_value = Some(0u8);
+match some_u8_value {
+ Some(3) => println!("three"),
+ _ => (),
+}
```
<span class="caption">Listing 6-6: A `match` that only cares about executing
@@ -21,7 +25,10 @@ Instead, we could write this in a shorter way using `if let`. The following
code behaves the same as the `match` in Listing 6-6:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/src/main.rs:here}}
+# let some_u8_value = Some(0u8);
+if let Some(3) = some_u8_value {
+ println!("three");
+}
```
The syntax `if let` takes a pattern and an expression separated by an equal
@@ -46,13 +53,48 @@ announcing the state of the quarters, we could do that with a `match`
expression like this:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/src/main.rs:here}}
+# #[derive(Debug)]
+# enum UsState {
+# Alabama,
+# Alaska,
+# }
+#
+# enum Coin {
+# Penny,
+# Nickel,
+# Dime,
+# Quarter(UsState),
+# }
+# let coin = Coin::Penny;
+let mut count = 0;
+match coin {
+ Coin::Quarter(state) => println!("State quarter from {:?}!", state),
+ _ => count += 1,
+}
```
Or we could use an `if let` and `else` expression like this:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/src/main.rs:here}}
+# #[derive(Debug)]
+# enum UsState {
+# Alabama,
+# Alaska,
+# }
+#
+# enum Coin {
+# Penny,
+# Nickel,
+# Dime,
+# Quarter(UsState),
+# }
+# let coin = Coin::Penny;
+let mut count = 0;
+if let Coin::Quarter(state) = coin {
+ println!("State quarter from {:?}!", state);
+} else {
+ count += 1;
+}
```
If you have a situation in which your program has logic that is too verbose to
diff --git a/book-original/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md b/book-original/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md
deleted file mode 100644
index b61cae4..0000000
--- a/book-original/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md
+++ /dev/null
@@ -1,49 +0,0 @@
-# Managing Growing Projects with Packages, Crates, and Modules
-
-As you write large programs, organizing your code will be important because
-keeping track of your entire program in your head will become impossible. By
-grouping related functionality and separating code with distinct features,
-you’ll clarify where to find code that implements a particular feature and
-where to go to change how a feature works.
-
-The programs we’ve written so far have been in one module in one file. As a
-project grows, you can organize code by splitting it into multiple modules and
-then multiple files. A package can contain multiple binary crates and
-optionally one library crate. As a package grows, you can extract parts into
-separate crates that become external dependencies. This chapter covers all
-these techniques. For very large projects of a set of interrelated packages
-that evolve together, Cargo provides workspaces, which we’ll cover in the
-[“Cargo Workspaces”][workspaces]<!-- ignore --> section in Chapter 14.
-
-In addition to grouping functionality, encapsulating implementation details
-lets you reuse code at a higher level: once you’ve implemented an operation,
-other code can call that code via the code’s public interface without knowing
-how the implementation works. The way you write code defines which parts are
-public for other code to use and which parts are private implementation details
-that you reserve the right to change. This is another way to limit the amount
-of detail you have to keep in your head.
-
-A related concept is scope: the nested context in which code is written has a
-set of names that are defined as “in scope.” When reading, writing, and
-compiling code, programmers and compilers need to know whether a particular
-name at a particular spot refers to a variable, function, struct, enum, module,
-constant, or other item and what that item means. You can create scopes and
-change which names are in or out of scope. You can’t have two items with the
-same name in the same scope; tools are available to resolve name conflicts.
-
-Rust has a number of features that allow you to manage your code’s
-organization, including which details are exposed, which details are private,
-and what names are in each scope in your programs. These features, sometimes
-collectively referred to as the *module system*, include:
-
-* **Packages:** A Cargo feature that lets you build, test, and share crates
-* **Crates:** A tree of modules that produces a library or executable
-* **Modules** and **use:** Let you control the organization, scope, and
- privacy of paths
-* **Paths:** A way of naming an item, such as a struct, function, or module
-
-In this chapter, we’ll cover all these features, discuss how they interact, and
-explain how to use them to manage scope. By the end, you should have a solid
-understanding of the module system and be able to work with scopes like a pro!
-
-[workspaces]: ch14-03-cargo-workspaces.html
diff --git a/book-pl-en/src/ch07-00-packages-crates-and-modules.md b/book-pl-en/src/ch07-00-packages-crates-and-modules.md
new file mode 100644
index 0000000..7cb29d4
--- /dev/null
+++ b/book-pl-en/src/ch07-00-packages-crates-and-modules.md
@@ -0,0 +1,16 @@
+# Packages, Crates, and Modules
+
+A key question when writing programs is *scope*: what names does the compiler
+know about at this location in the code? What functions am I allowed to call?
+What does this variable refer to?
+
+Rust has a number of features related to scopes. This is sometimes called
+“the module system,” but it encompases more than just modules:
+
+* *Packages* are a Cargo feature that let you build, test, and share crates.
+* *Crates* are a tree of modules that produce a library or executable.
+* *Modules* and the *use* keyword let you control the scope and privacy of paths.
+* A *path* is a way of naming an item such as a struct, function, or module.
+
+This chapter will cover all of these concepts. You’ll be bringing names into
+scopes, defining scopes, and exporting names to scopes like a pro soon!
diff --git a/book-pl-en/src/ch07-01-packages-and-crates-for-making-libraries-and-executables.md b/book-pl-en/src/ch07-01-packages-and-crates-for-making-libraries-and-executables.md
new file mode 100644
index 0000000..e519082
--- /dev/null
+++ b/book-pl-en/src/ch07-01-packages-and-crates-for-making-libraries-and-executables.md
@@ -0,0 +1,43 @@
+## Packages and Crates for Making Libraries and Executables
+
+Let’s talk about *packages* and *crates*. Here’s a summary:
+
+* A *crate* is a binary or library.
+* The *crate root* is a source file that is used to know how to build a crate.
+* A *package* has a *Cargo.toml* that describes how to build one or more crates.
+ At most one crate in a package can be a library.
+
+So when we type `cargo new`, we’re creating a package:
+
+```text
+$ cargo new my-project
+ Created binary (application) `my-project` package
+$ ls my-project
+Cargo.toml
+src
+$ ls my-project/src
+main.rs
+```
+
+Because Cargo created a *Cargo.toml*, that means we now have a package. If we
+look at the contents of *Cargo.toml*, there’s no mention of *src/main.rs*.
+However, Cargo’s conventions are that if you have a *src* directory containing
+*main.rs* in the same directory as a package’s *Cargo.toml*, Cargo knows this
+package contains a binary crate with the same name as the package, and
+*src/main.rs* is its crate root. Another convention of Cargo’s is that if the
+package directory contains *src/lib.rs*, the package contains a library crate
+with the same name as the package, and *src/lib.rs* is its crate root. The
+crate root files are passed by Cargo to `rustc` to actually build the library
+or binary.
+
+A package can contain zero or one library crates and as many binary crates as
+you’d like. There must be at least one crate (either a library or a binary) in
+a package.
+
+If a package contains both *src/main.rs* and *src/lib.rs*, then it has two
+crates: a library and a binary, both with the same name. If we only had one of
+the two, the package would have either a single library or binary crate. A
+package can have multiple binary crates by placing files in the *src/bin*
+directory: each file will be a separate binary crate.
+
+Next, let’s talk about modules!
diff --git a/book-original/src/ch07-01-packages-and-crates.md b/book-original/src/ch07-01-packages-and-crates.md
deleted file mode 100644
index 2bf2f11..0000000
--- a/book-original/src/ch07-01-packages-and-crates.md
+++ /dev/null
@@ -1,64 +0,0 @@
-## Packages and Crates
-
-The first parts of the module system we’ll cover are packages and crates. A
-crate is a binary or library. The *crate root* is a source file that the Rust
-compiler starts from and makes up the root module of your crate (we’ll explain
-modules in depth in the [“Defining Modules to Control Scope and
-Privacy”][modules]<!-- ignore --> section). A *package* is one or more crates
-that provide a set of functionality. A package contains a *Cargo.toml* file
-that describes how to build those crates.
-
-Several rules determine what a package can contain. A package *must* contain
-zero or one library crates, and no more. It can contain as many binary crates
-as you’d like, but it must contain at least one crate (either library or
-binary).
-
-Let’s walk through what happens when we create a package. First, we enter the
-command `cargo new`:
-
-```text
-$ cargo new my-project
- Created binary (application) `my-project` package
-$ ls my-project
-Cargo.toml
-src
-$ ls my-project/src
-main.rs
-```
-
-When we entered the command, Cargo created a *Cargo.toml* file, giving us a
-package. Looking at the contents of *Cargo.toml*, there’s no mention of
-*src/main.rs* because Cargo follows a convention that *src/main.rs* is the
-crate root of a binary crate with the same name as the package. Likewise, Cargo
-knows that if the package directory contains *src/lib.rs*, the package contains
-a library crate with the same name as the package, and *src/lib.rs* is its
-crate root. Cargo passes the crate root files to `rustc` to build the library
-or binary.
-
-Here, we have a package that only contains *src/main.rs*, meaning it only
-contains a binary crate named `my-project`. If a package contains *src/main.rs*
-and *src/lib.rs*, it has two crates: a library and a binary, both with the same
-name as the package. A package can have multiple binary crates by placing files
-in the *src/bin* directory: each file will be a separate binary crate.
-
-A crate will group related functionality together in a scope so the
-functionality is easy to share between multiple projects. For example, the
-`rand` crate we used in [Chapter 2][rand]<!-- ignore --> provides functionality
-that generates random numbers. We can use that functionality in our own
-projects by bringing the `rand` crate into our project’s scope. All the
-functionality provided by the `rand` crate is accessible through the crate’s
-name, `rand`.
-
-Keeping a crate’s functionality in its own scope clarifies whether particular
-functionality is defined in our crate or the `rand` crate and prevents
-potential conflicts. For example, the `rand` crate provides a trait named
-`Rng`. We can also define a `struct` named `Rng` in our own crate. Because a
-crate’s functionality is namespaced in its own scope, when we add `rand` as a
-dependency, the compiler isn’t confused about what the name `Rng` refers to. In
-our crate, it refers to the `struct Rng` that we defined. We would access the
-`Rng` trait from the `rand` crate as `rand::Rng`.
-
-Let’s move on and talk about the module system!
-
-[modules]: ch07-02-defining-modules-to-control-scope-and-privacy.html
-[rand]: ch02-00-guessing-game-tutorial.html#generating-a-random-number
diff --git a/book-original/src/ch07-02-defining-modules-to-control-scope-and-privacy.md b/book-original/src/ch07-02-defining-modules-to-control-scope-and-privacy.md
deleted file mode 100644
index d46ef9b..0000000
--- a/book-original/src/ch07-02-defining-modules-to-control-scope-and-privacy.md
+++ /dev/null
@@ -1,87 +0,0 @@
-## Defining Modules to Control Scope and Privacy
-
-In this section, we’ll talk about modules and other parts of the module system,
-namely *paths* that allow you to name items; the `use` keyword that brings a
-path into scope; and the `pub` keyword to make items public. We’ll also discuss
-the `as` keyword, external packages, and the glob operator. For now, let’s
-focus on modules!
-
-*Modules* let us organize code within a crate into groups for readability and
-easy reuse. Modules also control the *privacy* of items, which is whether an
-item can be used by outside code (*public*) or is an internal implementation
-detail and not available for outside use (*private*).
-
-As an example, let’s write a library crate that provides the functionality of a
-restaurant. We’ll define the signatures of functions but leave their bodies
-empty to concentrate on the organization of the code, rather than actually
-implement a restaurant in code.
-
-In the restaurant industry, some parts of a restaurant are referred to as
-*front of house* and others as *back of house*. Front of house is where
-customers are; this is where hosts seat customers, servers take orders and
-payment, and bartenders make drinks. Back of house is where the chefs and cooks
-work in the kitchen, dishwashers clean up, and managers do administrative work.
-
-To structure our crate in the same way that a real restaurant works, we can
-organize the functions into nested modules. Create a new library named
-`restaurant` by running `cargo new --lib restaurant`; then put the code in
-Listing 7-1 into *src/lib.rs* to define some modules and function signatures.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs:here}}
-```
-
-<span class="caption">Listing 7-1: A `front_of_house` module containing other
-modules that then contain functions</span>
-
-We define a module by starting with the `mod` keyword and then specify the
-name of the module (in this case, `front_of_house`) and place curly brackets
-around the body of the module. Inside modules, we can have other modules, as in
-this case with the modules `hosting` and `serving`. Modules can also hold
-definitions for other items, such as structs, enums, constants, traits, or—as
-in Listing 7-1—functions.
-
-By using modules, we can group related definitions together and name why
-they’re related. Programmers using this code would have an easier time finding
-the definitions they wanted to use because they could navigate the code based
-on the groups rather than having to read through all the definitions.
-Programmers adding new functionality to this code would know where to place the
-code to keep the program organized.
-
-Earlier, we mentioned that *src/main.rs* and *src/lib.rs* are called crate
-roots. The reason for their name is that the contents of either of these two
-files form a module named `crate` at the root of the crate’s module structure,
-known as the *module tree*.
-
-Listing 7-2 shows the module tree for the structure in Listing 7-1.
-
-```text
-crate
- └── front_of_house
- ├── hosting
- │ ├── add_to_waitlist
- │ └── seat_at_table
- └── serving
- ├── take_order
- ├── serve_order
- └── take_payment
-```
-
-<span class="caption">Listing 7-2: The module tree for the code in Listing
-7-1</span>
-
-This tree shows how some of the modules nest inside one another (for example,
-`hosting` nests inside `front_of_house`). The tree also shows that some modules
-are *siblings* to each other, meaning they’re defined in the same module
-(`hosting` and `serving` are defined within `front_of_house`). To continue the
-family metaphor, if module A is contained inside module B, we say that module A
-is the *child* of module B and that module B is the *parent* of module A.
-Notice that the entire module tree is rooted under the implicit module named
-`crate`.
-
-The module tree might remind you of the filesystem’s directory tree on your
-computer; this is a very apt comparison! Just like directories in a filesystem,
-you use modules to organize your code. And just like files in a directory, we
-need a way to find our modules.
diff --git a/book-pl-en/src/ch07-02-modules-and-use-to-control-scope-and-privacy.md b/book-pl-en/src/ch07-02-modules-and-use-to-control-scope-and-privacy.md
new file mode 100644
index 0000000..f8d00b6
--- /dev/null
+++ b/book-pl-en/src/ch07-02-modules-and-use-to-control-scope-and-privacy.md
@@ -0,0 +1,985 @@
+## The Module System to Control Scope and Privacy
+
+Rust has a feature that’s often referred to as “the module system,” but it
+encompasses a few more features than modules. In this section, we’ll talk about:
+
+* Modules, a way to organize code and control the privacy of paths
+* Paths, a way to name items
+* `use` a keyword to bring a path into scope
+* `pub`, a keyword to make items public
+* Renaming items when bringing them into scope with the `as` keyword
+* Using external packages
+* Nested paths to clean up large `use` lists
+* Using the glob operator to bring everything in a module into scope
+* How to split modules into individual files
+
+First up, modules. Modules let us organize code into groups. Listing 7-1 has an
+example of some code that defines a module named `sound` that contains a
+function named `guitar`.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+mod sound {
+ fn guitar() {
+ // Function body code goes here
+ }
+}
+
+fn main() {
+
+}
+```
+
+<span class="caption">Listing 7-1: A `sound` module containing a `guitar`
+function and a `main` function</span>
+
+We’ve defined two functions, `guitar` and `main`. We’ve defined the `guitar`
+function within a `mod` block. This block defines a module named `sound`.
+
+To organize code into a hierarchy of modules, you can nest modules inside of
+other modules, as shown in Listing 7-2:
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+mod sound {
+ mod instrument {
+ mod woodwind {
+ fn clarinet() {
+ // Function body code goes here
+ }
+ }
+ }
+
+ mod voice {
+
+ }
+}
+
+fn main() {
+
+}
+```
+
+<span class="caption">Listing 7-2: Modules inside modules</span>
+
+In this example, we defined a `sound` module in the same way as we did in
+Listing 7-1. We then defined two modules within the `sound` module named
+`instrument` and `voice`. The `instrument` module has another module defined
+within it, `woodwind`, and that module contains a function named `clarinet`.
+
+We mentioned in the [“Packages and Crates for Making Libraries and
+Executables”][packages]<!-- ignore --> section that *src/main.rs* and
+*src/lib.rs* are called *crate roots*. They are called crate roots because the
+contents of either of these two files form a module named `crate` at the root
+of the crate’s module tree. So in Listing 7-2, we have a module tree that looks
+like Listing 7-3:
+
+```text
+crate
+ └── sound
+ └── instrument
+ └── woodwind
+ └── voice
+```
+
+<span class="caption">Listing 7-3: The module tree for the code in Listing
+7-2</span>
+
+This tree shows how some of the modules nest inside one another (such as
+`woodwind` nests inside `instrument`) and how some modules are siblings to
+each other (`instrument` and `voice` are both defined within `sound`). The
+entire module tree is rooted under the implicit module named `crate`.
+
+This tree might remind you of the directory tree of the filesystem you have on
+your computer; this is a very apt comparison! Just like directories in a
+filesystem, you place code inside whichever module will create the organization
+you’d like. Another similarity is that to refer to an item in a filesystem or a
+module tree, you use its *path*.
+
+### Paths for Referring to an Item in the Module Tree
+
+If we want to call a function, we need to know its *path*. “Path” is a synonym
+for “name” in a way, but it evokes that filesystem metaphor. Additionally,
+functions, structs, and other items may have multiple paths that refer to the
+same item, so “name” isn’t quite the right concept.
+
+A *path* can take two forms:
+
+* An *absolute path* starts from a crate root by using a crate name or a
+ literal `crate`.
+* A *relative path* starts from the current module and uses `self`, `super`, or
+ an identifier in the current module.
+
+Both absolute and relative paths are followed by one or more identifiers
+separated by double colons (`::`).
+
+How do we call the `clarinet` function in the `main` function in Listing 7-2?
+That is, what’s the path of the `clarinet` function? In Listing 7-4, let’s
+simplify our code a bit by removing some of the modules, and we’ll show two
+ways to call the `clarinet` function from `main`. This example won’t compile
+just yet, we’ll explain why in a bit.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust,ignore,does_not_compile
+mod sound {
+ mod instrument {
+ fn clarinet() {
+ // Function body code goes here
+ }
+ }
+}
+
+fn main() {
+ // Absolute path
+ crate::sound::instrument::clarinet();
+
+ // Relative path
+ sound::instrument::clarinet();
+}
+```
+
+<span class="caption">Listing 7-4: Calling the `clarinet` function in a
+simplified module tree from the `main` function using absolute and relative
+paths</span>
+
+The first way we’re calling the `clarinet` function from the `main` function
+uses an absolute path. Because `clarinet` is defined within the same crate as
+`main`, we use the `crate` keyword to start an absolute path. Then we include
+each of the modules until we make our way to `clarinet`. This is similar to
+specifying the path `/sound/instrument/clarinet` to run the program at that
+location on your computer; using the `crate` name to start from the crate root
+is like using `/` to start from the filesystem root in your shell.
+
+The second way we’re calling the `clarinet` function from the `main` function
+uses a relative path. The path starts with the name `sound`, a module defined
+at the same level of the module tree as the `main` function. This is similar to
+specifying the path `sound/instrument/clarinet` to run the program at that
+location on your computer; starting with a name means that the path is relative.
+
+We mentioned that Listing 7-4 won’t compile yet, let’s try to compile it and
+find out why not! The error we get is shown in Listing 7-5.
+
+```text
+$ cargo build
+ Compiling sampleproject v0.1.0 (file:///projects/sampleproject)
+error[E0603]: module `instrument` is private
+ --> src/main.rs:11:19
+ |
+11 | crate::sound::instrument::clarinet();
+ | ^^^^^^^^^^
+
+error[E0603]: module `instrument` is private
+ --> src/main.rs:14:12
+ |
+14 | sound::instrument::clarinet();
+ | ^^^^^^^^^^
+```
+
+<span class="caption">Listing 7-5: Compiler errors from building the code in
+Listing 7-4</span>
+
+The error messsages say that module `instrument` is private. We can see that we
+have the correct paths for the `instrument` module and the `clarinet` function,
+but Rust won’t let us use them because they’re private. It’s time to learn
+about the `pub` keyword!
+
+### Modules as the Privacy Boundary
+
+Earlier, we talked about the syntax of modules and that they can be used for
+organization. There’s another reason Rust has modules: modules are the *privacy
+boundary* in Rust. If you want to make an item like a function or struct
+private, you put it in a module. Here are the privacy rules:
+
+* All items (functions, methods, structs, enums, modules, annd constants) are
+ private by default.
+* You can use the `pub` keyword to make an item public.
+* You aren’t allowed to use private code defined in modules that are children
+ of the current module.
+* You are allowed to use any code defined in ancestor modules or the current
+ module.
+
+In other words, items without the `pub` keyword are private as you look “down”
+the module tree from the current module, but items without the `pub` keyword
+are public as you look “up” the tree from the current module. Again, think of a
+filesystem: if you don’t have permissions to a directory, you can’t look into
+it from its parent directory. If you do have permissions to a directory, you
+can look inside it and any of its ancestor directories.
+
+### Using the `pub` Keyword to Make Items Public
+
+The error in Listing 7-5 said the `instrument` module is private. Let’s mark
+the `instrument` module with the `pub` keyword so that we can use it from the
+`main` function. This change is shown in Listing 7-6, which still won’t
+compile, but we’ll get a different error:
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust,ignore,does_not_compile
+mod sound {
+ pub mod instrument {
+ fn clarinet() {
+ // Function body code goes here
+ }
+ }
+}
+
+fn main() {
+ // Absolute path
+ crate::sound::instrument::clarinet();
+
+ // Relative path
+ sound::instrument::clarinet();
+}
+```
+
+<span class="caption">Listing 7-6: Declaring the `instrument` module as `pub`
+so that we’re allowed to use it from `main`</span>
+
+Adding the `pub` keyword in front of `mod instrument` makes the module public.
+With this change, if we’re allowed to access `sound`, we can access
+`instrument`. The contents of `instrument` are still private; making the module
+public does not make its contents public. The `pub` keyword on a module lets
+code in its parent module refer to it.
+
+The code in Listing 7-6 still results in an error, though, as shown in Listing
+7-7:
+
+```text
+$ cargo build
+ Compiling sampleproject v0.1.0 (file:///projects/sampleproject)
+error[E0603]: function `clarinet` is private
+ --> src/main.rs:11:31
+ |
+11 | crate::sound::instrument::clarinet();
+ | ^^^^^^^^
+
+error[E0603]: function `clarinet` is private
+ --> src/main.rs:14:24
+ |
+14 | sound::instrument::clarinet();
+ | ^^^^^^^^
+```
+
+<span class="caption">Listing 7-7: Compiler errors from building the code in
+Listing 7-6</span>
+
+The errors now say that the `clarinet` function is private. The privacy rules
+apply to structs, enums, functions, and methods as well as modules.
+
+Let’s make the `clarinet` function public as well by adding the `pub` keyword
+before its definition, as shown in Listing 7-8:
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+mod sound {
+ pub mod instrument {
+ pub fn clarinet() {
+ // Function body code goes here
+ }
+ }
+}
+
+fn main() {
+ // Absolute path
+ crate::sound::instrument::clarinet();
+
+ // Relative path
+ sound::instrument::clarinet();
+}
+```
+
+<span class="caption">Listing 7-8: Adding the `pub` keyword to both `mod
+instrument` and `fn clarinet` lets us call the function from `main`</span>
+
+This will now compile! Let’s look at both the absolute and the relative path
+and double check why adding the `pub` keyword lets us use these paths in `main`.
+
+In the absolute path case, we start with `crate`, the root of our crate. From
+there, we have `sound`, and it is a module that is defined in the crate root.
+The `sound` module isn’t public, but because the `main` function is defined in
+the same module that `sound` is defined, we’re allowed to refer to `sound` from
+`main`. Next is `instrument`, which is a module marked with `pub`. We can
+access the parent module of `instrument`, so we’re allowed to access
+`instrument`. Finally, `clarinet` is a function marked with `pub` and we can
+access its parent module, so this function call works!
+
+In the relative path case, the logic is the same as the absolute path except
+for the first step. Rather than starting from the crate root, the path starts
+from `sound`. The `sound` module is defined within the same module as `main`
+is, so the relative path starting from the module in which `main` is defined
+works. Then because `instrument` and `clarinet` are marked with `pub`, the rest
+of the path works and this function call is valid as well!
+
+### Starting Relative Paths with `super`
+
+You can also construct relative paths beginning with `super`. Doing so is like
+starting a filesystem path with `..`: the path starts from the *parent* module,
+rather than the current module. This is useful in situations such as the
+example in Listing 7-9, where the function `clarinet` calls the function
+`breathe_in` by specifying the path to `breathe_in` start with `super`:
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust
+# fn main() {}
+#
+mod instrument {
+ fn clarinet() {
+ super::breathe_in();
+ }
+}
+
+fn breathe_in() {
+ // Function body code goes here
+}
+```
+
+<span class="caption">Listing 7-9: Calling a function using a relative path
+starting with `super` to look in the parent module</span>
+
+The `clarinet` function is in the `instrument` module, so we can use `super` to
+go to the parent module of `instrument`, which in this case is `crate`, the
+root. From there, we look for `breathe_in`, and find it. Success!
+
+The reason you might want to choose a relative path starting with `super`
+rather than an absolute path starting with `crate` is that using `super` may
+make it easier to update your code to have a different module hierarchy, if the
+code defining the item and the code calling the item are moved together. For
+example, if we decide to put the `instrument` module and the `breathe_in`
+function into a module named `sound`, we would only need to add the `sound`
+module, as shown in Listing 7-10.
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust
+mod sound {
+ mod instrument {
+ fn clarinet() {
+ super::breathe_in();
+ }
+ }
+
+ fn breathe_in() {
+ // Function body code goes here
+ }
+}
+```
+
+<span class="caption">Listing 7-10: Adding a parent module named `sound`
+doesn’t affect the relative path `super::breathe_in`</span>
+
+The call to `super::breathe_in` from the `clarinet` function will continue to
+work in Listing 7-10 as it did in Listing 7-9, without needing to update the
+path. If instead of `super::breathe_in` we had used `crate::breathe_in` in the
+`clarinet` function, when we add the parent `sound` module, we would need to
+update the `clarinet` function to use the path `crate::sound::breathe_in`
+instead. Using a relative path can mean fewer updates are necessary when
+rearranging modules.
+
+### Using `pub` with Structs and Enums
+
+You can designate structs and enums to be public in a similar way as we’ve
+shown with modules and functions, with a few additional details.
+
+If you use `pub` before a struct definition, you make the struct public.
+However, the struct’s fields are still private. You can choose to make each
+field public or not on a case-by-case basis. In Listing 7-11, we’ve defined a
+public `plant::Vegetable` struct with a public `name` field but a private `id`
+field.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+mod plant {
+ pub struct Vegetable {
+ pub name: String,
+ id: i32,
+ }
+
+ impl Vegetable {
+ pub fn new(name: &str) -> Vegetable {
+ Vegetable {
+ name: String::from(name),
+ id: 1,
+ }
+ }
+ }
+}
+
+fn main() {
+ let mut v = plant::Vegetable::new("squash");
+
+ v.name = String::from("butternut squash");
+ println!("{} are delicious", v.name);
+
+ // The next line won't compile if we uncomment it:
+ // println!("The ID is {}", v.id);
+}
+```
+
+<span class="caption">Listing 7-11: A struct with some public fields and some
+private fields</span>
+
+Because the `name` field of the `plant::Vegetable` struct is public, in `main`
+we can write and read to the `name` field by using dot notation. We’re not
+allowed to use the `id` field in `main` because it’s private. Try uncommenting
+the line printing the `id` field value to see what error you get! Also note
+that because `plant::Vegetable` has a private field, the struct needs to
+provide a public associated function that constructs an instance of `Vegetable`
+(we’ve used the conventional name `new` here). If `Vegetable` didn’t have such
+a function, we wouldn’t be able to create an instance of `Vegetable` in `main`
+because we’re not allowed to set the value of the private `id` field in `main`.
+
+In contrast, if you make a public enum, all of its variants are public. You
+only need the `pub` before the `enum` keyword, as shown in Listing 7-12.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+mod menu {
+ pub enum Appetizer {
+ Soup,
+ Salad,
+ }
+}
+
+fn main() {
+ let order1 = menu::Appetizer::Soup;
+ let order2 = menu::Appetizer::Salad;
+}
+```
+
+<span class="caption">Listing 7-12: Designating an enum as public makes all its
+variants public</span>
+
+Because we made the `Appetizer` enum public, we’re able to use the `Soup` and
+`Salad` variants in `main`.
+
+There’s one more situation involving `pub` that we haven’t covered, and that’s
+with our last module system feature: the `use` keyword. Let’s cover `use` by
+itself, and then we’ll show how `pub` and `use` can be combined.
+
+### The `use` Keyword to Bring Paths into a Scope
+
+You may have been thinking that many of the paths we’ve written to call
+functions in the listings in this chapter are long and repetitive. For example,
+in Listing 7-8, whether we chose the absolute or relative path to the
+`clarinet` function, every time we wanted to call `clarinet` we had to specify
+`sound` and `instrument` too. Luckily, there’s a way to bring a path into a
+scope once and then call the items in that path as if they’re local items: with
+the `use` keyword. In Listing 7-13, we bring the `crate::sound::instrument`
+module into the scope of the `main` function so that we only have to specify
+`instrument::clarinet` to call the `clarinet` function in `main`.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+mod sound {
+ pub mod instrument {
+ pub fn clarinet() {
+ // Function body code goes here
+ }
+ }
+}
+
+use crate::sound::instrument;
+
+fn main() {
+ instrument::clarinet();
+ instrument::clarinet();
+ instrument::clarinet();
+}
+```
+
+<span class="caption">Listing 7-13: Bringing a module into scope with `use` and
+an absolute path to shorten the path we have to specify to call an item within
+that module</span>
+
+Adding `use` and a path in a scope is similar to creating a symbolic link in
+the filesystem. By adding `use crate::sound::instrument` in the crate root,
+`instrument` is now a valid name in that scope as if the `instrument` module
+had been defined in the crate root. We can now reach items in the `instrument`
+module through the older, full paths, or we can reach items through the new,
+shorter path that we’ve created with `use`. Paths brought into scope with `use`
+also check privacy, like any other paths.
+
+If you want to bring an item into scope with `use` and a relative path, there’s
+a small difference from directly calling the item using a relative path:
+instead of starting from a name in the current scope, you must start the path
+given to `use` with `self`. Listing 7-14 shows how to specify a relative path
+to get the same behavior as Listing 7-13 that used an absolute path.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+mod sound {
+ pub mod instrument {
+ pub fn clarinet() {
+ // Function body code goes here
+ }
+ }
+}
+
+use self::sound::instrument;
+
+fn main() {
+ instrument::clarinet();
+ instrument::clarinet();
+ instrument::clarinet();
+}
+```
+
+<span class="caption">Listing 7-14: Bringing a module into scope with `use` and
+a relative path starting with `self`</span>
+
+Starting relative paths with `self` when specified after `use` might not be
+necessary in the future; it’s an inconsistency in the language that people are
+working on eliminating.
+
+Choosing to specify absolute paths with `use` can make updates easier if the
+code calling the items moves to a different place in the module tree but the
+code defining the items does not, as opposed to when they moved together in the
+changes we made in Listing 7-10. For example, if we decide to take the code
+from Listing 7-13, extract the behavior in the `main` function to a function
+called `clarinet_trio`, and move that function into a module named
+`performance_group`, the path specified in `use` wouldn’t need to change, as
+shown in Listing 7-15.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+mod sound {
+ pub mod instrument {
+ pub fn clarinet() {
+ // Function body code goes here
+ }
+ }
+}
+
+mod performance_group {
+ use crate::sound::instrument;
+
+ pub fn clarinet_trio() {
+ instrument::clarinet();
+ instrument::clarinet();
+ instrument::clarinet();
+ }
+}
+
+fn main() {
+ performance_group::clarinet_trio();
+}
+```
+
+<span class="caption">Listing 7-15: The absolute path doesn’t need to be
+updated when moving the code that calls the item</span>
+
+In contrast, if we made the same change to the code in Listing 7-14 that
+specifies a relative path, we would need to change `use
+self::sound::instrument` to `use super::sound::instrument`. Choosing whether
+relative or absolute paths will result in fewer updates can be a guess if
+you’re not sure how your module tree will change in the future, but your
+authors tend to specify absolute paths starting with `crate` because code
+defining and calling items is more likely to be moved around the module tree
+independently of each other, rather than together as we saw in Listing 7-10.
+
+### Idiomatic `use` Paths for Functions vs. Other Items
+
+In Listing 7-13, you may have wondered why we specified `use
+crate::sound::instrument` and then called `instrument::clarinet` in `main`,
+rather than the code shown in Listing 7-16 that has the same behavior:
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+mod sound {
+ pub mod instrument {
+ pub fn clarinet() {
+ // Function body code goes here
+ }
+ }
+}
+
+use crate::sound::instrument::clarinet;
+
+fn main() {
+ clarinet();
+ clarinet();
+ clarinet();
+}
+```
+
+<span class="caption">Listing 7-16: Bringing the `clarinet` function into
+scope with `use`, which is unidiomatic</span>
+
+For functions, it’s considered idiomatic to specify the function’s parent
+module with `use`, and then specify the parent module when calling the
+function. Doing so rather than specifying the path to the function with `use`,
+as Listing 7-16 does, makes it clear that the function isn’t locally defined,
+while still minimizing repetition of the full path.
+
+For structs, enums, and other items, specifying the full path to the item with
+`use` is idiomatic. For example, Listing 7-17 shows the idiomatic way to bring
+the standard library’s `HashMap` struct into scope.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+use std::collections::HashMap;
+
+fn main() {
+ let mut map = HashMap::new();
+ map.insert(1, 2);
+}
+```
+
+<span class="caption">Listing 7-17: Bringing `HashMap` into scope in an
+idiomatic way</span>
+
+In contrast, the code in Listing 7-18 that brings the parent module of
+`HashMap` into scope would not be considered idiomatic. There’s not a strong
+reason for this idiom; this is the convention that has emerged and folks have
+gotten used to reading and writing.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+use std::collections;
+
+fn main() {
+ let mut map = collections::HashMap::new();
+ map.insert(1, 2);
+}
+```
+
+<span class="caption">Listing 7-18: Bringing `HashMap` into scope in an
+unidiomatic way</span>
+
+The exception to this idiom is if the `use` statements would bring two items
+with the same name into scope, which isn’t allowed. Listing 7-19 shows how to
+bring two `Result` types that have different parent modules into scope and
+refer to them.
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust
+use std::fmt;
+use std::io;
+
+fn function1() -> fmt::Result {
+# Ok(())
+}
+
+fn function2() -> io::Result<()> {
+# Ok(())
+}
+```
+
+<span class="caption">Listing 7-19: Bringing two types with the same name into
+the same scope requires using their parent modules</span>
+
+If instead we specified `use std::fmt::Result` and `use std::io::Result`, we’d
+have two `Result` types in the same scope and Rust wouldn’t know which one we
+meant when we used `Result`. Try it and see what compiler error you get!
+
+### Renaming Types Brought Into Scope with the `as` Keyword
+
+There’s another solution to the problem of bringing two types of the same name
+into the same scope: we can specify a new local name for the type by adding
+`as` and a new name after the `use`. Listing 7-20 shows another way to write
+the code from Listing 7-19 by renaming one of the two `Result` types using `as`.
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust
+use std::fmt::Result;
+use std::io::Result as IoResult;
+
+fn function1() -> Result {
+# Ok(())
+}
+fn function2() -> IoResult<()> {
+# Ok(())
+}
+```
+
+<span class="caption">Listing 7-20: Renaming a type when it’s brought into
+scope with the `as` keyword</span>
+
+In the second `use` statement, we chose the new name `IoResult` for the
+`std::io::Result` type, which won’t conflict with the `Result` from `std::fmt`
+that we’ve also brought into scope. This is also considered idiomatic; choosing
+between the code in Listing 7-19 and Listing 7-20 is up to you.
+
+### Re-exporting Names with `pub use`
+
+When you bring a name into scope with the `use` keyword, the name being
+available in the new scope is private. If you want to enable code calling your
+code to be able to refer to the type as if it was defined in that scope just as
+your code does, you can combine `pub` and `use`. This technique is called
+*re-exporting* because you’re bringing an item into scope but also making that
+item available for others to bring into their scope.
+
+For example, Listing 7-21 shows the code from Listing 7-15 with the `use`
+within the `performance_group` module changed to `pub use`.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+mod sound {
+ pub mod instrument {
+ pub fn clarinet() {
+ // Function body code goes here
+ }
+ }
+}
+
+mod performance_group {
+ pub use crate::sound::instrument;
+
+ pub fn clarinet_trio() {
+ instrument::clarinet();
+ instrument::clarinet();
+ instrument::clarinet();
+ }
+}
+
+fn main() {
+ performance_group::clarinet_trio();
+ performance_group::instrument::clarinet();
+}
+```
+
+<span class="caption">Listing 7-21: Making a name available for any code to use
+from a new scope with `pub use`</span>
+
+By using `pub use`, the `main` function can now call the `clarinet` function
+through this new path with `performance_group::instrument::clarinet`. If we
+hadn’t specified `pub use`, the `clarinet_trio` function can call
+`instrument::clarinet` in its scope but `main` wouldn’t be allowed to take
+advantage of this new path.
+
+### Using External Packages
+
+In Chapter 2, we programmed a guessing game. That project used an external
+package, `rand`, to get random numbers. To use `rand` in our project, we added
+this line to *Cargo.toml*:
+
+<span class="filename">Filename: Cargo.toml</span>
+
+```toml
+[dependencies]
+rand = "0.5.5"
+```
+
+Adding `rand` as a dependency in *Cargo.toml* tells Cargo to download the
+`rand` package and its dependencies from *https://crates.io* and make its code
+available to our project.
+
+Then, to bring `rand` definitions into the scope of our package, we added a
+`use` line starting with the name of the package, `rand`, and listing the items
+we wanted to bring into scope. Recall that in the [“Generating a Random
+Number”][rand]<!-- ignore --> section in Chapter 2, we brought the `Rng` trait
+into scope and called the `rand::thread_rng` function:
+
+```rust,ignore
+use rand::Rng;
+
+fn main() {
+ let secret_number = rand::thread_rng().gen_range(1, 101);
+}
+```
+
+There are many packages that members of the community have published on
+*https://crates.io*, and pulling any of them in to your package involves these
+same steps: listing them in your package’s *Cargo.toml* and bringing items
+defined in them into a scope in your package with `use`.
+
+Note that the standard library (`std`) is also a crate that’s external to your
+package. Because the standard library is shipped with the Rust language, you
+don’t need to change *Cargo.toml* to include `std`, but you refer to it in
+`use` to bring items the standard library defines into your package’s scope,
+such as with `HashMap`:
+
+```rust
+use std::collections::HashMap;
+```
+
+This is an absolute path starting with `std`, the name of the standard library
+crate.
+
+### Nested Paths for Cleaning Up Large `use` Lists
+
+When you use many items defined by the same package or in the same module,
+listing each item on its own line can take up a lot of vertical space in your
+files. For example, these two `use` statements we had in Listing 2-4 in the
+Guessing Game both bring items from `std` into scope:
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+use std::cmp::Ordering;
+use std::io;
+// ---snip---
+```
+
+We can use nested paths to bring the same items into scope in one line instead
+of two, by specifying the common part of the path, then two colons, then curly
+brackets around a list of the parts of the paths that differ, as shown in
+Listing 7-22.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+use std::{cmp::Ordering, io};
+// ---snip---
+```
+
+<span class="caption">Listing 7-22: Specifying a nested path to bring multiple
+items with the same prefix into scope in one line instead of two</span>
+
+In programs bringing many items into scope from the same package or module,
+using nested paths can reduce the number of separate `use` statements needed by
+a lot!
+
+We can also deduplicate paths where one path is completely shared with part of
+another path. For example, Listing 7-23 shows two `use` statements: one that
+brings `std::io` into scope, and one that brings `std::io::Write` into scope:
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust
+use std::io;
+use std::io::Write;
+```
+
+<span class="caption">Listing 7-23: Bringing two paths into scope in two `use`
+statements where one is a sub-path of the other</span>
+
+The common part between these two paths is `std::io`, and that’s the complete
+first path. To deduplicate these two paths into one `use` statement, we can use
+`self` in the nested path as shown in Listing 7-24.
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust
+use std::io::{self, Write};
+```
+
+<span class="caption">Listing 7-24: Deduplicating the paths from Listing 7-23
+into one `use` statement</span>
+
+This brings both `std::io` and `std::io::Write` into scope.
+
+### Bringing All Public Definitions into Scope with the Glob Operator
+
+If you’d like to bring *all* public items defined in a path into scope, you can
+use specify that path followed by `*`, the glob operator:
+
+```rust
+use std::collections::*;
+```
+
+This `use` statements brings all public items defined in `std::collections`
+into the current scope.
+
+Be careful with using the glob operator! It makes it harder to tell what names
+are in scope and where a name your program uses was defined.
+
+The glob operator is often used when testing to bring everything under test
+into the `tests` module; we’ll talk about that in the [“How to Write
+Tests”][writing-tests]<!-- ignore --> section of Chapter 11. The glob operator
+is also sometimes used as part of the prelude pattern; see [the standard
+library documentation](../std/prelude/index.html#other-preludes)<!-- ignore -->
+for more information on that pattern.
+
+### Separating Modules into Different Files
+
+All of the examples in this chapter so far defined multiple modules in one
+file. When modules get large, you may want to move their definitions to a
+separate file to make the code easier to navigate.
+
+For example, if we started from the code in Listing 7-8, we can move the
+`sound` module to its own file *src/sound.rs* by changing the crate root file
+(in this case, *src/main.rs*) to contain the code shown in Listing 7-25.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust,ignore
+mod sound;
+
+fn main() {
+ // Absolute path
+ crate::sound::instrument::clarinet();
+
+ // Relative path
+ sound::instrument::clarinet();
+}
+```
+
+<span class="caption">Listing 7-25: Declaring the `sound` module whose body
+will be in *src/sound.rs*</span>
+
+And *src/sound.rs* gets the definitions from the body of the `sound` module,
+shown in Listing 7-26.
+
+<span class="filename">Filename: src/sound.rs</span>
+
+```rust
+pub mod instrument {
+ pub fn clarinet() {
+ // Function body code goes here
+ }
+}
+```
+
+<span class="caption">Listing 7-26: Definitions inside the `sound` module in
+*src/sound.rs*</span>
+
+Using a semicolon after `mod sound` instead of a block tells Rust to load the
+contents of the module from another file with the same name as the module.
+
+To continue with our example and extract the `instrument` module to its own
+file as well, we change *src/sound.rs* to contain only the declaration of the
+`instrument` module:
+
+<span class="filename">Filename: src/sound.rs</span>
+
+```rust
+pub mod instrument;
+```
+
+Then we create a *src/sound* directory and a file *src/sound/instrument.rs* to
+contain the definitions made in the `instrument` module:
+
+<span class="filename">Filename: src/sound/instrument.rs</span>
+
+```rust
+pub fn clarinet() {
+ // Function body code goes here
+}
+```
+
+The module tree remains the same and the function calls in `main` continue to
+work without any modification, even though the definitions live in different
+files. This lets you move modules to new files as they grow in size.
+
+## Summary
+
+Rust provides ways to organize your packages into crates, your crates into
+modules, and to refer to items defined in one module from another by specifying
+absolute or relative paths. These paths can be brought into a scope with a
+`use` statement so that you can use a shorter path for multiple uses of the
+item in that scope. Modules define code that’s private by default, but you can
+choose to make definitions public by adding the `pub` keyword.
+
+Next, we’ll look at some collection data structures in the standard library
+that you can use in your nice, neat code.
+
+[packages]: ch07-01-packages-and-crates-for-making-libraries-and-executables.html#packages-and-crates-for-making-libraries-and-executables
+[rand]: ch02-00-guessing-game-tutorial.html#generating-a-random-number
+[writing-tests]: ch11-01-writing-tests.html#how-to-write-tests
diff --git a/book-original/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md b/book-original/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md
deleted file mode 100644
index d765a66..0000000
--- a/book-original/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md
+++ /dev/null
@@ -1,261 +0,0 @@
-## Paths for Referring to an Item in the Module Tree
-
-To show Rust where to find an item in a module tree, we use a path in the same
-way we use a path when navigating a filesystem. If we want to call a function,
-we need to know its path.
-
-A path can take two forms:
-
-* An *absolute path* starts from a crate root by using a crate name or a
- literal `crate`.
-* A *relative path* starts from the current module and uses `self`, `super`, or
- an identifier in the current module.
-
-Both absolute and relative paths are followed by one or more identifiers
-separated by double colons (`::`).
-
-Let’s return to the example in Listing 7-1. How do we call the
-`add_to_waitlist` function? This is the same as asking, what’s the path of the
-`add_to_waitlist` function? In Listing 7-3, we simplified our code a bit by
-removing some of the modules and functions. We’ll show two ways to call the
-`add_to_waitlist` function from a new function `eat_at_restaurant` defined in
-the crate root. The `eat_at_restaurant` function is part of our library crate’s
-public API, so we mark it with the `pub` keyword. In the [”Exposing Paths with
-the `pub` Keyword”][pub]<!-- ignore --> section, we’ll go into more detail
-about `pub`. Note that this example won’t compile just yet; we’ll explain why
-in a bit.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-03/src/lib.rs}}
-```
-
-<span class="caption">Listing 7-3: Calling the `add_to_waitlist` function using
-absolute and relative paths</span>
-
-The first time we call the `add_to_waitlist` function in `eat_at_restaurant`,
-we use an absolute path. The `add_to_waitlist` function is defined in the same
-crate as `eat_at_restaurant`, which means we can use the `crate` keyword to
-start an absolute path.
-
-After `crate`, we include each of the successive modules until we make our way
-to `add_to_waitlist`. You can imagine a filesystem with the same structure, and
-we’d specify the path `/front_of_house/hosting/add_to_waitlist` to run the
-`add_to_waitlist` program; using the `crate` name to start from the crate root
-is like using `/` to start from the filesystem root in your shell.
-
-The second time we call `add_to_waitlist` in `eat_at_restaurant`, we use a
-relative path. The path starts with `front_of_house`, the name of the module
-defined at the same level of the module tree as `eat_at_restaurant`. Here the
-filesystem equivalent would be using the path
-`front_of_house/hosting/add_to_waitlist`. Starting with a name means that the
-path is relative.
-
-Choosing whether to use a relative or absolute path is a decision you’ll make
-based on your project. The decision should depend on whether you’re more likely
-to move item definition code separately from or together with the code that
-uses the item. For example, if we move the `front_of_house` module and the
-`eat_at_restaurant` function into a module named `customer_experience`, we’d
-need to update the absolute path to `add_to_waitlist`, but the relative path
-would still be valid. However, if we moved the `eat_at_restaurant` function
-separately into a module named `dining`, the absolute path to the
-`add_to_waitlist` call would stay the same, but the relative path would need to
-be updated. Our preference is to specify absolute paths because it’s more
-likely to move code definitions and item calls independently of each other.
-
-Let’s try to compile Listing 7-3 and find out why it won’t compile yet! The
-error we get is shown in Listing 7-4.
-
-```text
-{{#include ../listings/ch07-managing-growing-projects/listing-07-03/output.txt}}
-```
-
-<span class="caption">Listing 7-4: Compiler errors from building the code in
-Listing 7-3</span>
-
-The error messages say that module `hosting` is private. In other words, we
-have the correct paths for the `hosting` module and the `add_to_waitlist`
-function, but Rust won’t let us use them because it doesn’t have access to the
-private sections.
-
-Modules aren’t useful only for organizing your code. They also define Rust’s
-*privacy boundary*: the line that encapsulates the implementation details
-external code isn’t allowed to know about, call, or rely on. So, if you want to
-make an item like a function or struct private, you put it in a module.
-
-The way privacy works in Rust is that all items (functions, methods, structs,
-enums, modules, and constants) are private by default. Items in a parent module
-can’t use the private items inside child modules, but items in child modules
-can use the items in their ancestor modules. The reason is that child modules
-wrap and hide their implementation details, but the child modules can see the
-context in which they’re defined. To continue with the restaurant metaphor,
-think of the privacy rules as being like the back office of a restaurant: what
-goes on in there is private to restaurant customers, but office managers can
-see and do everything in the restaurant in which they operate.
-
-Rust chose to have the module system function this way so that hiding inner
-implementation details is the default. That way, you know which parts of the
-inner code you can change without breaking outer code. But you can expose inner
-parts of child modules code to outer ancestor modules by using the `pub`
-keyword to make an item public.
-
-### Exposing Paths with the `pub` Keyword
-
-Let’s return to the error in Listing 7-4 that told us the `hosting` module is
-private. We want the `eat_at_restaurant` function in the parent module to have
-access to the `add_to_waitlist` function in the child module, so we mark the
-`hosting` module with the `pub` keyword, as shown in Listing 7-5.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-05/src/lib.rs}}
-```
-
-<span class="caption">Listing 7-5: Declaring the `hosting` module as `pub` to
-use it from `eat_at_restaurant`</span>
-
-Unfortunately, the code in Listing 7-5 still results in an error, as shown in
-Listing 7-6.
-
-```text
-{{#include ../listings/ch07-managing-growing-projects/listing-07-05/output.txt}}
-```
-
-<span class="caption">Listing 7-6: Compiler errors from building the code in
-Listing 7-5</span>
-
-What happened? Adding the `pub` keyword in front of `mod hosting` makes the
-module public. With this change, if we can access `front_of_house`, we can
-access `hosting`. But the *contents* of `hosting` are still private; making the
-module public doesn’t make its contents public. The `pub` keyword on a module
-only lets code in its ancestor modules refer to it.
-
-The errors in Listing 7-6 say that the `add_to_waitlist` function is private.
-The privacy rules apply to structs, enums, functions, and methods as well as
-modules.
-
-Let’s also make the `add_to_waitlist` function public by adding the `pub`
-keyword before its definition, as in Listing 7-7.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs:here}}
-```
-
-<span class="caption">Listing 7-7: Adding the `pub` keyword to `mod hosting`
-and `fn add_to_waitlist` lets us call the function from
-`eat_at_restaurant`</span>
-
-Now the code will compile! Let’s look at the absolute and the relative path and
-double-check why adding the `pub` keyword lets us use these paths in
-`add_to_waitlist` with respect to the privacy rules.
-
-In the absolute path, we start with `crate`, the root of our crate’s module
-tree. Then the `front_of_house` module is defined in the crate root. The
-`front_of_house` module isn’t public, but because the `eat_at_restaurant`
-function is defined in the same module as `front_of_house` (that is,
-`eat_at_restaurant` and `front_of_house` are siblings), we can refer to
-`front_of_house` from `eat_at_restaurant`. Next is the `hosting` module marked
-with `pub`. We can access the parent module of `hosting`, so we can access
-`hosting`. Finally, the `add_to_waitlist` function is marked with `pub` and we
-can access its parent module, so this function call works!
-
-In the relative path, the logic is the same as the absolute path except for the
-first step: rather than starting from the crate root, the path starts from
-`front_of_house`. The `front_of_house` module is defined within the same module
-as `eat_at_restaurant`, so the relative path starting from the module in which
-`eat_at_restaurant` is defined works. Then, because `hosting` and
-`add_to_waitlist` are marked with `pub`, the rest of the path works, and this
-function call is valid!
-
-### Starting Relative Paths with `super`
-
-We can also construct relative paths that begin in the parent module by using
-`super` at the start of the path. This is like starting a filesystem path with
-the `..` syntax. Why would we want to do this?
-
-Consider the code in Listing 7-8 that models the situation in which a chef
-fixes an incorrect order and personally brings it out to the customer. The
-function `fix_incorrect_order` calls the function `serve_order` by specifying
-the path to `serve_order` starting with `super`:
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs:here}}
-```
-
-<span class="caption">Listing 7-8: Calling a function using a relative path
-starting with `super`</span>
-
-The `fix_incorrect_order` function is in the `back_of_house` module, so we can
-use `super` to go to the parent module of `back_of_house`, which in this case
-is `crate`, the root. From there, we look for `serve_order` and find it.
-Success! We think the `back_of_house` module and the `serve_order` function are
-likely to stay in the same relationship to each other and get moved together
-should we decide to reorganize the crate’s module tree. Therefore, we used
-`super` so we’ll have fewer places to update code in the future if this code
-gets moved to a different module.
-
-### Making Structs and Enums Public
-
-We can also use `pub` to designate structs and enums as public, but there are a
-few extra details. If we use `pub` before a struct definition, we make the
-struct public, but the struct’s fields will still be private. We can make each
-field public or not on a case-by-case basis. In Listing 7-9, we’ve defined a
-public `back_of_house::Breakfast` struct with a public `toast` field but a
-private `seasonal_fruit` field. This models the case in a restaurant where the
-customer can pick the type of bread that comes with a meal, but the chef
-decides which fruit accompanies the meal based on what’s in season and in
-stock. The available fruit changes quickly, so customers can’t choose the fruit
-or even see which fruit they’ll get.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-09/src/lib.rs}}
-```
-
-<span class="caption">Listing 7-9: A struct with some public fields and some
-private fields</span>
-
-Because the `toast` field in the `back_of_house::Breakfast` struct is public,
-in `eat_at_restaurant` we can write and read to the `toast` field using dot
-notation. Notice that we can’t use the `seasonal_fruit` field in
-`eat_at_restaurant` because `seasonal_fruit` is private. Try uncommenting the
-line modifying the `seasonal_fruit` field value to see what error you get!
-
-Also, note that because `back_of_house::Breakfast` has a private field, the
-struct needs to provide a public associated function that constructs an
-instance of `Breakfast` (we’ve named it `summer` here). If `Breakfast` didn’t
-have such a function, we couldn’t create an instance of `Breakfast` in
-`eat_at_restaurant` because we couldn’t set the value of the private
-`seasonal_fruit` field in `eat_at_restaurant`.
-
-In contrast, if we make an enum public, all of its variants are then public. We
-only need the `pub` before the `enum` keyword, as shown in Listing 7-10.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-10/src/lib.rs}}
-```
-
-<span class="caption">Listing 7-10: Designating an enum as public makes all its
-variants public</span>
-
-Because we made the `Appetizer` enum public, we can use the `Soup` and `Salad`
-variants in `eat_at_restaurant`. Enums aren’t very useful unless their variants
-are public; it would be annoying to have to annotate all enum variants with
-`pub` in every case, so the default for enum variants is to be public. Structs
-are often useful without their fields being public, so struct fields follow the
-general rule of everything being private by default unless annotated with `pub`.
-
-There’s one more situation involving `pub` that we haven’t covered, and that is
-our last module system feature: the `use` keyword. We’ll cover `use` by itself
-first, and then we’ll show how to combine `pub` and `use`.
-
-[pub]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#exposing-paths-with-the-pub-keyword
diff --git a/book-original/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md b/book-original/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md
deleted file mode 100644
index 3bb5870..0000000
--- a/book-original/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md
+++ /dev/null
@@ -1,291 +0,0 @@
-## Bringing Paths into Scope with the `use` Keyword
-
-It might seem like the paths we’ve written to call functions so far are
-inconveniently long and repetitive. For example, in Listing 7-7, whether we
-chose the absolute or relative path to the `add_to_waitlist` function, every
-time we wanted to call `add_to_waitlist` we had to specify `front_of_house` and
-`hosting` too. Fortunately, there’s a way to simplify this process. We can
-bring a path into a scope once and then call the items in that path as if
-they’re local items with the `use` keyword.
-
-In Listing 7-11, we bring the `crate::front_of_house::hosting` module into the
-scope of the `eat_at_restaurant` function so we only have to specify
-`hosting::add_to_waitlist` to call the `add_to_waitlist` function in
-`eat_at_restaurant`.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs:here}}
-```
-
-<span class="caption">Listing 7-11: Bringing a module into scope with
-`use`</span>
-
-Adding `use` and a path in a scope is similar to creating a symbolic link in
-the filesystem. By adding `use crate::front_of_house::hosting` in the crate
-root, `hosting` is now a valid name in that scope, just as though the `hosting`
-module had been defined in the crate root. Paths brought into scope with `use`
-also check privacy, like any other paths.
-
-You can also bring an item into scope with `use` and a relative path. Listing
-7-12 shows how to specify a relative path to get the same behavior as in
-Listing 7-11.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs:here}}
-```
-
-<span class="caption">Listing 7-12: Bringing a module into scope with `use` and
-a relative path</span>
-
-### Creating Idiomatic `use` Paths
-
-In Listing 7-11, you might have wondered why we specified `use
-crate::front_of_house::hosting` and then called `hosting::add_to_waitlist` in
-`eat_at_restaurant` rather than specifying the `use` path all the way out to
-the `add_to_waitlist` function to achieve the same result, as in Listing 7-13.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs:here}}
-```
-
-<span class="caption">Listing 7-13: Bringing the `add_to_waitlist` function
-into scope with `use`, which is unidiomatic</span>
-
-Although both Listing 7-11 and 7-13 accomplish the same task, Listing 7-11 is
-the idiomatic way to bring a function into scope with `use`. Bringing the
-function’s parent module into scope with `use` so we have to specify the parent
-module when calling the function makes it clear that the function isn’t locally
-defined while still minimizing repetition of the full path. The code in Listing
-7-13 is unclear as to where `add_to_waitlist` is defined.
-
-On the other hand, when bringing in structs, enums, and other items with `use`,
-it’s idiomatic to specify the full path. Listing 7-14 shows the idiomatic way
-to bring the standard library’s `HashMap` struct into the scope of a binary
-crate.
-
-<span class="filename">Filename: src/main.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-14/src/main.rs}}
-```
-
-<span class="caption">Listing 7-14: Bringing `HashMap` into scope in an
-idiomatic way</span>
-
-There’s no strong reason behind this idiom: it’s just the convention that has
-emerged, and folks have gotten used to reading and writing Rust code this way.
-
-The exception to this idiom is if we’re bringing two items with the same name
-into scope with `use` statements, because Rust doesn’t allow that. Listing 7-15
-shows how to bring two `Result` types into scope that have the same name but
-different parent modules and how to refer to them.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-15/src/lib.rs:here}}
-```
-
-<span class="caption">Listing 7-15: Bringing two types with the same name into
-the same scope requires using their parent modules.</span>
-
-As you can see, using the parent modules distinguishes the two `Result` types.
-If instead we specified `use std::fmt::Result` and `use std::io::Result`, we’d
-have two `Result` types in the same scope and Rust wouldn’t know which one we
-meant when we used `Result`.
-
-### Providing New Names with the `as` Keyword
-
-There’s another solution to the problem of bringing two types of the same name
-into the same scope with `use`: after the path, we can specify `as` and a new
-local name, or alias, for the type. Listing 7-16 shows another way to write the
-code in Listing 7-15 by renaming one of the two `Result` types using `as`.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-16/src/lib.rs:here}}
-```
-
-<span class="caption">Listing 7-16: Renaming a type when it’s brought into
-scope with the `as` keyword</span>
-
-In the second `use` statement, we chose the new name `IoResult` for the
-`std::io::Result` type, which won’t conflict with the `Result` from `std::fmt`
-that we’ve also brought into scope. Listing 7-15 and Listing 7-16 are
-considered idiomatic, so the choice is up to you!
-
-### Re-exporting Names with `pub use`
-
-When we bring a name into scope with the `use` keyword, the name available in
-the new scope is private. To enable the code that calls our code to refer to
-that name as if it had been defined in that code’s scope, we can combine `pub`
-and `use`. This technique is called *re-exporting* because we’re bringing
-an item into scope but also making that item available for others to bring into
-their scope.
-
-Listing 7-17 shows the code in Listing 7-11 with `use` in the root module
-changed to `pub use`.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs:here}}
-```
-
-<span class="caption">Listing 7-17: Making a name available for any code to use
-from a new scope with `pub use`</span>
-
-By using `pub use`, external code can now call the `add_to_waitlist` function
-using `hosting::add_to_waitlist`. If we hadn’t specified `pub use`, the
-`eat_at_restaurant` function could call `hosting::add_to_waitlist` in its
-scope, but external code couldn’t take advantage of this new path.
-
-Re-exporting is useful when the internal structure of your code is different
-from how programmers calling your code would think about the domain. For
-example, in this restaurant metaphor, the people running the restaurant think
-about “front of house” and “back of house.” But customers visiting a restaurant
-probably won’t think about the parts of the restaurant in those terms. With
-`pub use`, we can write our code with one structure but expose a different
-structure. Doing so makes our library well organized for programmers working on
-the library and programmers calling the library.
-
-### Using External Packages
-
-In Chapter 2, we programmed a guessing game project that used an external
-package called `rand` to get random numbers. To use `rand` in our project, we
-added this line to *Cargo.toml*:
-
-<!-- When updating the version of `rand` used, also update the version of
-`rand` used in these files so they all match:
-* ch02-00-guessing-game-tutorial.md
-* ch14-03-cargo-workspaces.md
--->
-
-<span class="filename">Filename: Cargo.toml</span>
-
-```toml
-{{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:9:}}
-```
-
-Adding `rand` as a dependency in *Cargo.toml* tells Cargo to download the
-`rand` package and any dependencies from [crates.io](https://crates.io/) and
-make `rand` available to our project.
-
-Then, to bring `rand` definitions into the scope of our package, we added a
-`use` line starting with the name of the package, `rand`, and listed the items
-we wanted to bring into scope. Recall that in the [“Generating a Random
-Number”][rand]<!-- ignore --> section in Chapter 2, we brought the `Rng` trait
-into scope and called the `rand::thread_rng` function:
-
-```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs:ch07-04}}
-```
-
-Members of the Rust community have made many packages available at
-[crates.io](https://crates.io/), and pulling any of them into your package
-involves these same steps: listing them in your package’s *Cargo.toml* file and
-using `use` to bring items into scope.
-
-Note that the standard library (`std`) is also a crate that’s external to our
-package. Because the standard library is shipped with the Rust language, we
-don’t need to change *Cargo.toml* to include `std`. But we do need to refer to
-it with `use` to bring items from there into our package’s scope. For example,
-with `HashMap` we would use this line:
-
-```rust
-use std::collections::HashMap;
-```
-
-This is an absolute path starting with `std`, the name of the standard library
-crate.
-
-### Using Nested Paths to Clean Up Large `use` Lists
-
-If we’re using multiple items defined in the same package or same module,
-listing each item on its own line can take up a lot of vertical space in our
-files. For example, these two `use` statements we had in the Guessing Game in
-Listing 2-4 bring items from `std` into scope:
-
-<span class="filename">Filename: src/main.rs</span>
-
-```rust,ignore
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs:here}}
-```
-
-Instead, we can use nested paths to bring the same items into scope in one
-line. We do this by specifying the common part of the path, followed by two
-colons, and then curly brackets around a list of the parts of the paths that
-differ, as shown in Listing 7-18.
-
-<span class="filename">Filename: src/main.rs</span>
-
-```rust,ignore
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-18/src/main.rs:here}}
-```
-
-<span class="caption">Listing 7-18: Specifying a nested path to bring multiple
-items with the same prefix into scope</span>
-
-In bigger programs, bringing many items into scope from the same package or
-module using nested paths can reduce the number of separate `use` statements
-needed by a lot!
-
-We can use a nested path at any level in a path, which is useful when combining
-two `use` statements that share a subpath. For example, Listing 7-19 shows two
-`use` statements: one that brings `std::io` into scope and one that brings
-`std::io::Write` into scope.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-19/src/lib.rs}}
-```
-
-<span class="caption">Listing 7-19: Two `use` statements where one is a subpath
-of the other</span>
-
-The common part of these two paths is `std::io`, and that’s the complete first
-path. To merge these two paths into one `use` statement, we can use `self` in
-the nested path, as shown in Listing 7-20.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-20/src/lib.rs}}
-```
-
-<span class="caption">Listing 7-20: Combining the paths in Listing 7-19 into
-one `use` statement</span>
-
-This line brings `std::io` and `std::io::Write` into scope.
-
-### The Glob Operator
-
-If we want to bring *all* public items defined in a path into scope, we can
-specify that path followed by `*`, the glob operator:
-
-```rust
-use std::collections::*;
-```
-
-This `use` statement brings all public items defined in `std::collections` into
-the current scope. Be careful when using the glob operator! Glob can make it
-harder to tell what names are in scope and where a name used in your program
-was defined.
-
-The glob operator is often used when testing to bring everything under test
-into the `tests` module; we’ll talk about that in the [“How to Write
-Tests”][writing-tests]<!-- ignore --> section in Chapter 11. The glob operator
-is also sometimes used as part of the prelude pattern: see [the standard
-library documentation](../std/prelude/index.html#other-preludes)<!-- ignore -->
-for more information on that pattern.
-
-[rand]: ch02-00-guessing-game-tutorial.html#generating-a-random-number
-[writing-tests]: ch11-01-writing-tests.html#how-to-write-tests
diff --git a/book-original/src/ch07-05-separating-modules-into-different-files.md b/book-original/src/ch07-05-separating-modules-into-different-files.md
deleted file mode 100644
index cff0e43..0000000
--- a/book-original/src/ch07-05-separating-modules-into-different-files.md
+++ /dev/null
@@ -1,77 +0,0 @@
-## Separating Modules into Different Files
-
-So far, all the examples in this chapter defined multiple modules in one file.
-When modules get large, you might want to move their definitions to a separate
-file to make the code easier to navigate.
-
-For example, let’s start from the code in Listing 7-17 and move the
-`front_of_house` module to its own file *src/front_of_house.rs* by changing the
-crate root file so it contains the code shown in Listing 7-21. In this case,
-the crate root file is *src/lib.rs*, but this procedure also works with binary
-crates whose crate root file is *src/main.rs*.
-
-<span class="filename">Filename: src/lib.rs</span>
-
-```rust,ignore
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs}}
-```
-
-<span class="caption">Listing 7-21: Declaring the `front_of_house` module whose
-body will be in *src/front_of_house.rs*</span>
-
-And *src/front_of_house.rs* gets the definitions from the body of the
-`front_of_house` module, as shown in Listing 7-22.
-
-<span class="filename">Filename: src/front_of_house.rs</span>
-
-```rust,ignore
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-21-and-22/src/front_of_house.rs}}
-```
-
-<span class="caption">Listing 7-22: Definitions inside the `front_of_house`
-module in *src/front_of_house.rs*</span>
-
-Using a semicolon after `mod front_of_house` rather than using a block tells
-Rust to load the contents of the module from another file with the same name as
-the module. To continue with our example and extract the `hosting` module to
-its own file as well, we change *src/front_of_house.rs* to contain only the
-declaration of the `hosting` module:
-
-<span class="filename">Filename: src/front_of_house.rs</span>
-
-```
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/front_of_house.rs}}
-```
-
-Then we create a *src/front_of_house* directory and a file
-*src/front_of_house/hosting.rs* to contain the definitions made in the
-`hosting` module:
-
-<span class="filename">Filename: src/front_of_house/hosting.rs</span>
-
-```
-{{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/front_of_house/hosting.rs}}
-```
-
-The module tree remains the same, and the function calls in `eat_at_restaurant`
-will work without any modification, even though the definitions live in
-different files. This technique lets you move modules to new files as they grow
-in size.
-
-Note that the `pub use crate::front_of_house::hosting` statement in
-*src/lib.rs* also hasn’t changed, nor does `use` have any impact on what files
-are compiled as part of the crate. The `mod` keyword declares modules, and Rust
-looks in a file with the same name as the module for the code that goes into
-that module.
-
-## Summary
-
-Rust lets you split a package into multiple crates and a crate into modules
-so you can refer to items defined in one module from another module. You can do
-this by specifying absolute or relative paths. These paths can be brought into
-scope with a `use` statement so you can use a shorter path for multiple uses of
-the item in that scope. Module code is private by default, but you can make
-definitions public by adding the `pub` keyword.
-
-In the next chapter, we’ll look at some collection data structures in the
-standard library that you can use in your neatly organized code.
diff --git a/book-original/src/ch08-01-vectors.md b/book-pl-en/src/ch08-01-vectors.md
index 2f93e6b..c80c718 100644
--- a/book-original/src/ch08-01-vectors.md
+++ b/book-pl-en/src/ch08-01-vectors.md
@@ -12,7 +12,7 @@ To create a new, empty vector, we can call the `Vec::new` function, as shown in
Listing 8-1.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-01/src/main.rs:here}}
+let v: Vec<i32> = Vec::new();
```
<span class="caption">Listing 8-1: Creating a new, empty vector to hold values
@@ -32,12 +32,10 @@ store once you insert values, so you rarely need to do this type annotation.
It’s more common to create a `Vec<T>` that has initial values, and Rust
provides the `vec!` macro for convenience. The macro will create a new vector
that holds the values you give it. Listing 8-2 creates a new `Vec<i32>` that
-holds the values `1`, `2`, and `3`. The integer type is `i32` because that’s
-the default integer type, as we discussed in the [“Data Types”][data-types]<!--
-ignore --> section of Chapter 3.
+holds the values `1`, `2`, and `3`.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-02/src/main.rs:here}}
+let v = vec![1, 2, 3];
```
<span class="caption">Listing 8-2: Creating a new vector containing
@@ -53,7 +51,12 @@ To create a vector and then add elements to it, we can use the `push` method,
as shown in Listing 8-3.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-03/src/main.rs:here}}
+let mut v = Vec::new();
+
+v.push(5);
+v.push(6);
+v.push(7);
+v.push(8);
```
<span class="caption">Listing 8-3: Using the `push` method to add values to a
@@ -70,7 +73,12 @@ Like any other `struct`, a vector is freed when it goes out of scope, as
annotated in Listing 8-4.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-04/src/main.rs:here}}
+{
+ let v = vec![1, 2, 3, 4];
+
+ // do stuff with v
+
+} // <- v goes out of scope and is freed here
```
<span class="caption">Listing 8-4: Showing where the vector and its elements
@@ -92,7 +100,15 @@ Listing 8-5 shows both methods of accessing a value in a vector, either with
indexing syntax or the `get` method.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-05/src/main.rs:here}}
+let v = vec![1, 2, 3, 4, 5];
+
+let third: &i32 = &v[2];
+println!("The third element is {}", third);
+
+match v.get(2) {
+ Some(third) => println!("The third element is {}", third),
+ None => println!("There is no third element."),
+}
```
<span class="caption">Listing 8-5: Using indexing syntax or the `get` method to
@@ -111,7 +127,10 @@ that holds five elements and then tries to access an element at index 100, as
shown in Listing 8-6.
```rust,should_panic,panics
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-06/src/main.rs:here}}
+let v = vec![1, 2, 3, 4, 5];
+
+let does_not_exist = &v[100];
+let does_not_exist = v.get(100);
```
<span class="caption">Listing 8-6: Attempting to access the element at index
@@ -141,7 +160,13 @@ the first element in a vector and try to add an element to the end, which won’
work.
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-07/src/main.rs:here}}
+let mut v = vec![1, 2, 3, 4, 5];
+
+let first = &v[0];
+
+v.push(6);
+
+println!("The first element is: {}", first);
```
<span class="caption">Listing 8-7: Attempting to add an element to a vector
@@ -150,7 +175,17 @@ while holding a reference to an item</span>
Compiling this code will result in this error:
```text
-{{#include ../listings/ch08-common-collections/listing-08-07/output.txt}}
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+ --> src/main.rs:10:5
+ |
+8 | let first = &v[0];
+ | - immutable borrow occurs here
+9 |
+10 | v.push(6);
+ | ^^^^^^^^^ mutable borrow occurs here
+11 |
+12 | println!("The first element is: {}", first);
+ | ----- borrow later used here
```
The code in Listing 8-7 might look like it should work: why should a reference
@@ -162,18 +197,21 @@ other where the vector currently is. In that case, the reference to the first
element would be pointing to deallocated memory. The borrowing rules prevent
programs from ending up in that situation.
-> Note: For more on the implementation details of the `Vec<T>` type, see [“The
-> Rustonomicon”][nomicon].
+> Note: For more on the implementation details of the `Vec<T>` type, see “The
+> Rustonomicon” at https://doc.rust-lang.org/stable/nomicon/vec.html.
### Iterating over the Values in a Vector
If we want to access each element in a vector in turn, we can iterate through
-all of the elements rather than use indices to access one at a time. Listing
+all of the elements rather than use indexes to access one at a time. Listing
8-8 shows how to use a `for` loop to get immutable references to each element
in a vector of `i32` values and print them.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-08/src/main.rs:here}}
+let v = vec![100, 32, 57];
+for i in &v {
+ println!("{}", i);
+}
```
<span class="caption">Listing 8-8: Printing each element in a vector by
@@ -184,7 +222,10 @@ in order to make changes to all the elements. The `for` loop in Listing 8-9
will add `50` to each element.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-09/src/main.rs:here}}
+let mut v = vec![100, 32, 57];
+for i in &mut v {
+ *i += 50;
+}
```
<span class="caption">Listing 8-9: Iterating over mutable references to
@@ -192,9 +233,7 @@ elements in a vector</span>
To change the value that the mutable reference refers to, we have to use the
dereference operator (`*`) to get to the value in `i` before we can use the
-`+=` operator. We’ll talk more about the dereference operator in the
-[“Following the Pointer to the Value with the Dereference Operator”][deref]
-section of Chapter 15.
+`+=` operator. We’ll talk more about `*` in Chapter 15.
### Using an Enum to Store Multiple Types
@@ -212,7 +251,17 @@ that of the enum. Then we can create a vector that holds that enum and so,
ultimately, holds different types. We’ve demonstrated this in Listing 8-10.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-10/src/main.rs:here}}
+enum SpreadsheetCell {
+ Int(i32),
+ Float(f64),
+ Text(String),
+}
+
+let row = vec![
+ SpreadsheetCell::Int(3),
+ SpreadsheetCell::Text(String::from("blue")),
+ SpreadsheetCell::Float(10.12),
+];
```
<span class="caption">Listing 8-10: Defining an `enum` to store values of
@@ -236,7 +285,3 @@ to review the API documentation for all the many useful methods defined on
`Vec<T>` by the standard library. For example, in addition to `push`, a `pop`
method removes and returns the last element. Let’s move on to the next
collection type: `String`!
-
-[data-types]: ch03-02-data-types.html#data-types
-[nomicon]: ../nomicon/vec.html
-[deref]: ch15-02-deref.html#following-the-pointer-to-the-value-with-the-dereference-operator
diff --git a/book-original/src/ch08-02-strings.md b/book-pl-en/src/ch08-02-strings.md
index bcee93e..63832bf 100644
--- a/book-original/src/ch08-02-strings.md
+++ b/book-pl-en/src/ch08-02-strings.md
@@ -22,8 +22,8 @@ We’ll first define what we mean by the term *string*. Rust has only one string
type in the core language, which is the string slice `str` that is usually seen
in its borrowed form `&str`. In Chapter 4, we talked about *string slices*,
which are references to some UTF-8 encoded string data stored elsewhere. String
-literals, for example, are stored in the program’s binary and are therefore
-string slices.
+literals, for example, are stored in the binary output of the program and are
+therefore string slices.
The `String` type, which is provided by Rust’s standard library rather than
coded into the core language, is a growable, mutable, owned, UTF-8 encoded
@@ -48,7 +48,7 @@ as well, starting with the `new` function to create a string, shown in Listing
8-11.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-11/src/main.rs:here}}
+let mut s = String::new();
```
<span class="caption">Listing 8-11: Creating a new, empty `String`</span>
@@ -60,7 +60,12 @@ that implements the `Display` trait, as string literals do. Listing 8-12 shows
two examples.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-12/src/main.rs:here}}
+let data = "initial contents";
+
+let s = data.to_string();
+
+// the method also works on a literal directly:
+let s = "initial contents".to_string();
```
<span class="caption">Listing 8-12: Using the `to_string` method to create a
@@ -73,7 +78,7 @@ literal. The code in Listing 8-13 is equivalent to the code from Listing 8-12
that uses `to_string`.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-13/src/main.rs:here}}
+let s = String::from("initial contents");
```
<span class="caption">Listing 8-13: Using the `String::from` function to create
@@ -88,7 +93,17 @@ Remember that strings are UTF-8 encoded, so we can include any properly encoded
data in them, as shown in Listing 8-14.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-14/src/main.rs:here}}
+let hello = String::from("السلام عليكم");
+let hello = String::from("Dobrý den");
+let hello = String::from("Hello");
+let hello = String::from("שָׁלוֹם");
+let hello = String::from("नमस्ते");
+let hello = String::from("こんにちは");
+let hello = String::from("안녕하세요");
+let hello = String::from("你好");
+let hello = String::from("Olá");
+let hello = String::from("Здравствуйте");
+let hello = String::from("Hola");
```
<span class="caption">Listing 8-14: Storing greetings in different languages in
@@ -108,7 +123,8 @@ We can grow a `String` by using the `push_str` method to append a string slice,
as shown in Listing 8-15.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-15/src/main.rs:here}}
+let mut s = String::from("foo");
+s.push_str("bar");
```
<span class="caption">Listing 8-15: Appending a string slice to a `String`
@@ -120,7 +136,10 @@ parameter. For example, the code in Listing 8-16 shows that it would be
unfortunate if we weren’t able to use `s2` after appending its contents to `s1`.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-16/src/main.rs:here}}
+let mut s1 = String::from("foo");
+let s2 = "bar";
+s1.push_str(s2);
+println!("s2 is {}", s2);
```
<span class="caption">Listing 8-16: Using a string slice after appending its
@@ -134,7 +153,8 @@ The `push` method takes a single character as a parameter and adds it to the
the `push` method.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-17/src/main.rs:here}}
+let mut s = String::from("lo");
+s.push('l');
```
<span class="caption">Listing 8-17: Adding one character to a `String` value
@@ -148,7 +168,9 @@ Often, you’ll want to combine two existing strings. One way is to use the `+`
operator, as shown in Listing 8-18.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-18/src/main.rs:here}}
+let s1 = String::from("Hello, ");
+let s2 = String::from("world!");
+let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used
```
<span class="caption">Listing 8-18: Using the `+` operator to combine two
@@ -197,7 +219,11 @@ If we need to concatenate multiple strings, the behavior of the `+` operator
gets unwieldy:
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/no-listing-01-concat-multiple-strings/src/main.rs:here}}
+let s1 = String::from("tic");
+let s2 = String::from("tac");
+let s3 = String::from("toe");
+
+let s = s1 + "-" + &s2 + "-" + &s3;
```
At this point, `s` will be `tic-tac-toe`. With all of the `+` and `"`
@@ -205,7 +231,11 @@ characters, it’s difficult to see what’s going on. For more complicated stri
combining, we can use the `format!` macro:
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/no-listing-02-format/src/main.rs:here}}
+let s1 = String::from("tic");
+let s2 = String::from("tac");
+let s3 = String::from("toe");
+
+let s = format!("{}-{}-{}", s1, s2, s3);
```
This code also sets `s` to `tic-tac-toe`. The `format!` macro works in the same
@@ -221,7 +251,8 @@ if you try to access parts of a `String` using indexing syntax in Rust, you’ll
get an error. Consider the invalid code in Listing 8-19.
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-19/src/main.rs:here}}
+let s1 = String::from("hello");
+let h = s1[0];
```
<span class="caption">Listing 8-19: Attempting to use indexing syntax with a
@@ -230,7 +261,13 @@ String</span>
This code will result in the following error:
```text
-{{#include ../listings/ch08-common-collections/listing-08-19/output.txt}}
+error[E0277]: the trait bound `std::string::String: std::ops::Index<{integer}>` is not satisfied
+ -->
+ |
+3 | let h = s1[0];
+ | ^^^^^ the type `std::string::String` cannot be indexed by `{integer}`
+ |
+ = help: the trait `std::ops::Index<{integer}>` is not implemented for `std::string::String`
```
The error and the note tell the story: Rust strings don’t support indexing. But
@@ -243,7 +280,7 @@ A `String` is a wrapper over a `Vec<u8>`. Let’s look at some of our properly
encoded UTF-8 example strings from Listing 8-14. First, this one:
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-14/src/main.rs:spanish}}
+let len = String::from("Hola").len();
```
In this case, `len` will be 4, which means the vector storing the string “Hola”
@@ -252,7 +289,7 @@ what about the following line? (Note that this string begins with the capital
Cyrillic letter Ze, not the Arabic number 3.)
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-14/src/main.rs:russian}}
+let len = String::from("Здравствуйте").len();
```
Asked how long the string is, you might say 12. However, Rust’s answer is 24:
@@ -343,7 +380,7 @@ What would happen if we used `&hello[0..1]`? The answer: Rust would panic at
runtime in the same way as if an invalid index were accessed in a vector:
```text
-{{#include ../listings/ch08-common-collections/output-only-01-not-char-boundary/output.txt}}
+thread 'main' panicked at 'byte index 1 is not a char boundary; it is inside 'З' (bytes 0..2) of `Здравствуйте`', src/libcore/str/mod.rs:2188:4
```
You should use ranges to create string slices with caution, because doing so
@@ -399,7 +436,7 @@ than 1 byte.
Getting grapheme clusters from strings is complex, so this functionality is not
provided by the standard library. Crates are available on
-[crates.io](https://crates.io/) if this is the functionality you need.
+[crates.io](https://crates.io) if this is the functionality you need.
### Strings Are Not So Simple
diff --git a/book-original/src/ch08-03-hash-maps.md b/book-pl-en/src/ch08-03-hash-maps.md
index 5abadbd..d1db520 100644
--- a/book-original/src/ch08-03-hash-maps.md
+++ b/book-pl-en/src/ch08-03-hash-maps.md
@@ -25,7 +25,12 @@ Blue and Yellow. The Blue team starts with 10 points, and the Yellow team
starts with 50.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-20/src/main.rs:here}}
+use std::collections::HashMap;
+
+let mut scores = HashMap::new();
+
+scores.insert(String::from("Blue"), 10);
+scores.insert(String::from("Yellow"), 50);
```
<span class="caption">Listing 8-20: Creating a new hash map and inserting some
@@ -42,19 +47,21 @@ keys of type `String` and values of type `i32`. Like vectors, hash maps are
homogeneous: all of the keys must have the same type, and all of the values
must have the same type.
-Another way of constructing a hash map is by using iterators and the `collect`
-method on a vector of tuples, where each tuple consists of a key and its value.
-We’ll be going into more detail about iterators and their associated methods in
-the [”Processing a Series of Items with Iterators” section of Chapter
-13][iterators]<!-- ignore -->. The `collect` method gathers data into a number
-of collection types, including `HashMap`. For example, if we had the team names
-and initial scores in two separate vectors, we could use the `zip` method to
-create a vector of tuples where “Blue” is paired with 10, and so forth. Then we
-could use the `collect` method to turn that vector of tuples into a hash map,
-as shown in Listing 8-21.
+Another way of constructing a hash map is by using the `collect` method on a
+vector of tuples, where each tuple consists of a key and its value. The
+`collect` method gathers data into a number of collection types, including
+`HashMap`. For example, if we had the team names and initial scores in two
+separate vectors, we could use the `zip` method to create a vector of tuples
+where “Blue” is paired with 10, and so forth. Then we could use the `collect`
+method to turn that vector of tuples into a hash map, as shown in Listing 8-21.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-21/src/main.rs:here}}
+use std::collections::HashMap;
+
+let teams = vec![String::from("Blue"), String::from("Yellow")];
+let initial_scores = vec![10, 50];
+
+let scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();
```
<span class="caption">Listing 8-21: Creating a hash map from a list of teams
@@ -64,9 +71,7 @@ The type annotation `HashMap<_, _>` is needed here because it’s possible to
`collect` into many different data structures and Rust doesn’t know which you
want unless you specify. For the parameters for the key and value types,
however, we use underscores, and Rust can infer the types that the hash map
-contains based on the types of the data in the vectors. In Listing 8-21, the
-key type will be `String` and the value type will be `i32`, just as the types
-were in Listing 8-20.
+contains based on the types of the data in the vectors.
### Hash Maps and Ownership
@@ -75,7 +80,15 @@ into the hash map. For owned values like `String`, the values will be moved and
the hash map will be the owner of those values, as demonstrated in Listing 8-22.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-22/src/main.rs:here}}
+use std::collections::HashMap;
+
+let field_name = String::from("Favorite color");
+let field_value = String::from("Blue");
+
+let mut map = HashMap::new();
+map.insert(field_name, field_value);
+// field_name and field_value are invalid at this point, try using them and
+// see what compiler error you get!
```
<span class="caption">Listing 8-22: Showing that keys and values are owned by
@@ -87,9 +100,8 @@ they’ve been moved into the hash map with the call to `insert`.
If we insert references to values into the hash map, the values won’t be moved
into the hash map. The values that the references point to must be valid for at
least as long as the hash map is valid. We’ll talk more about these issues in
-the [“Validating References with
-Lifetimes”][validating-references-with-lifetimes]<!-- ignore --> section in
-Chapter 10.
+the [“Validating References with Lifetimes”]
+[validating-references-with-lifetimes]<!-- ignore --> section in Chapter 10.
### Accessing Values in a Hash Map
@@ -97,7 +109,15 @@ We can get a value out of the hash map by providing its key to the `get`
method, as shown in Listing 8-23.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-23/src/main.rs:here}}
+use std::collections::HashMap;
+
+let mut scores = HashMap::new();
+
+scores.insert(String::from("Blue"), 10);
+scores.insert(String::from("Yellow"), 50);
+
+let team_name = String::from("Blue");
+let score = scores.get(&team_name);
```
<span class="caption">Listing 8-23: Accessing the score for the Blue team
@@ -113,7 +133,16 @@ We can iterate over each key/value pair in a hash map in a similar manner as we
do with vectors, using a `for` loop:
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs:here}}
+use std::collections::HashMap;
+
+let mut scores = HashMap::new();
+
+scores.insert(String::from("Blue"), 10);
+scores.insert(String::from("Yellow"), 50);
+
+for (key, value) in &scores {
+ println!("{}: {}", key, value);
+}
```
This code will print each pair in an arbitrary order:
@@ -143,7 +172,14 @@ only contain one key/value pair because we’re inserting the value for the Blue
team’s key both times.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-24/src/main.rs:here}}
+use std::collections::HashMap;
+
+let mut scores = HashMap::new();
+
+scores.insert(String::from("Blue"), 10);
+scores.insert(String::from("Blue"), 25);
+
+println!("{:?}", scores);
```
<span class="caption">Listing 8-24: Replacing a value stored with a particular
@@ -164,7 +200,15 @@ and the same for the Blue team. Using the `entry` API, the code looks like
Listing 8-25.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-25/src/main.rs:here}}
+use std::collections::HashMap;
+
+let mut scores = HashMap::new();
+scores.insert(String::from("Blue"), 10);
+
+scores.entry(String::from("Yellow")).or_insert(50);
+scores.entry(String::from("Blue")).or_insert(50);
+
+println!("{:?}", scores);
```
<span class="caption">Listing 8-25: Using the `entry` method to only insert if
@@ -192,7 +236,18 @@ seen that word. If it’s the first time we’ve seen a word, we’ll first inse
the value 0.
```rust
-{{#rustdoc_include ../listings/ch08-common-collections/listing-08-26/src/main.rs:here}}
+use std::collections::HashMap;
+
+let text = "hello world wonderful world";
+
+let mut map = HashMap::new();
+
+for word in text.split_whitespace() {
+ let count = map.entry(word).or_insert(0);
+ *count += 1;
+}
+
+println!("{:?}", map);
```
<span class="caption">Listing 8-26: Counting occurrences of words using a hash
@@ -216,7 +271,7 @@ purposes, you can switch to another function by specifying a different
*hasher*. A hasher is a type that implements the `BuildHasher` trait. We’ll
talk about traits and how to implement them in Chapter 10. You don’t
necessarily have to implement your own hasher from scratch;
-[crates.io](https://crates.io/) has libraries shared by other Rust users that
+[crates.io](https://crates.io) has libraries shared by other Rust users that
provide hashers implementing many common hashing algorithms.
[^siphash]: [https://www.131002.net/siphash/siphash.pdf](https://www.131002.net/siphash/siphash.pdf)
@@ -246,6 +301,5 @@ and hash maps have that will be helpful for these exercises!
We’re getting into more complex programs in which operations can fail, so, it’s
a perfect time to discuss error handling. We’ll do that next!
-[iterators]: ch13-02-iterators.html
[validating-references-with-lifetimes]:
ch10-03-lifetime-syntax.html#validating-references-with-lifetimes
diff --git a/book-original/src/ch09-01-unrecoverable-errors-with-panic.md b/book-pl-en/src/ch09-01-unrecoverable-errors-with-panic.md
index e677281..77bb0cd 100644
--- a/book-original/src/ch09-01-unrecoverable-errors-with-panic.md
+++ b/book-pl-en/src/ch09-01-unrecoverable-errors-with-panic.md
@@ -29,13 +29,20 @@ Let’s try calling `panic!` in a simple program:
<span class="filename">Filename: src/main.rs</span>
```rust,should_panic,panics
-{{#rustdoc_include ../listings/ch09-error-handling/no-listing-01-panic/src/main.rs}}
+fn main() {
+ panic!("crash and burn");
+}
```
When you run the program, you’ll see something like this:
```text
-{{#include ../listings/ch09-error-handling/no-listing-01-panic/output.txt}}
+$ cargo run
+ Compiling panic v0.1.0 (file:///projects/panic)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.25s
+ Running `target/debug/panic`
+thread 'main' panicked at 'crash and burn', src/main.rs:2:5
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
The call to `panic!` causes the error message contained in the last two lines.
@@ -62,7 +69,11 @@ element by index in a vector.
<span class="filename">Filename: src/main.rs</span>
```rust,should_panic,panics
-{{#rustdoc_include ../listings/ch09-error-handling/listing-09-01/src/main.rs}}
+fn main() {
+ let v = vec![1, 2, 3];
+
+ v[99];
+}
```
<span class="caption">Listing 9-1: Attempting to access an element beyond the
@@ -74,20 +85,25 @@ situation, Rust will panic. Using `[]` is supposed to return an element, but if
you pass an invalid index, there’s no element that Rust could return here that
would be correct.
-In C, attempting to read beyond the end of a data structure is undefined
-behavior. You might get whatever is at the location in memory that would
-correspond to that element in the data structure, even though the memory
-doesn’t belong to that structure. This is called a *buffer overread* and can
-lead to security vulnerabilities if an attacker is able to manipulate the index
-in such a way as to read data they shouldn’t be allowed to that is stored after
-the data structure.
+Other languages, like C, will attempt to give you exactly what you asked for in
+this situation, even though it isn’t what you want: you’ll get whatever is at
+the location in memory that would correspond to that element in the vector,
+even though the memory doesn’t belong to the vector. This is called a *buffer
+overread* and can lead to security vulnerabilities if an attacker is able to
+manipulate the index in such a way as to read data they shouldn’t be allowed to
+that is stored after the array.
To protect your program from this sort of vulnerability, if you try to read an
element at an index that doesn’t exist, Rust will stop execution and refuse to
continue. Let’s try it and see:
```text
-{{#include ../listings/ch09-error-handling/listing-09-01/output.txt}}
+$ cargo run
+ Compiling panic v0.1.0 (file:///projects/panic)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.27s
+ Running `target/debug/panic`
+thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', libcore/slice/mod.rs:2046:10
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
This error points at a file we didn’t write, *libcore/slice/mod.rs*. That’s the
@@ -107,69 +123,55 @@ library code, or crates that you’re using. Let’s try getting a backtrace by
setting the `RUST_BACKTRACE` environment variable to any value except 0.
Listing 9-2 shows output similar to what you’ll see.
-<!-- manual-regeneration
-cd listings/ch09-error-handling/listing-09-01
-RUST_BACKTRACE=1 cargo run
-copy the backtrace output below
-check the backtrace number mentioned in the text below the listing
--->
-
```text
$ RUST_BACKTRACE=1 cargo run
-thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libcore/slice/mod.rs:2806:10
+ Finished dev [unoptimized + debuginfo] target(s) in 0.00s
+ Running `target/debug/panic`
+thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', libcore/slice/mod.rs:2046:10
stack backtrace:
- 0: backtrace::backtrace::libunwind::trace
- at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
- 1: backtrace::backtrace::trace_unsynchronized
- at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
- 2: std::sys_common::backtrace::_print_fmt
- at src/libstd/sys_common/backtrace.rs:84
- 3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
- at src/libstd/sys_common/backtrace.rs:61
- 4: core::fmt::ArgumentV1::show_usize
- 5: std::io::Write::write_fmt
- at src/libstd/io/mod.rs:1426
- 6: std::sys_common::backtrace::_print
- at src/libstd/sys_common/backtrace.rs:65
- 7: std::sys_common::backtrace::print
- at src/libstd/sys_common/backtrace.rs:50
- 8: std::panicking::default_hook::{{closure}}
- at src/libstd/panicking.rs:193
- 9: std::panicking::default_hook
- at src/libstd/panicking.rs:210
- 10: std::panicking::rust_panic_with_hook
- at src/libstd/panicking.rs:471
- 11: rust_begin_unwind
- at src/libstd/panicking.rs:375
- 12: core::panicking::panic_fmt
- at src/libcore/panicking.rs:84
- 13: core::panicking::panic_bounds_check
- at src/libcore/panicking.rs:62
- 14: <usize as core::slice::SliceIndex<[T]>>::index
- at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libcore/slice/mod.rs:2806
- 15: core::slice::<impl core::ops::index::Index<I> for [T]>::index
- at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libcore/slice/mod.rs:2657
- 16: <alloc::vec::Vec<T> as core::ops::index::Index<I>>::index
- at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/liballoc/vec.rs:1871
- 17: panic::main
+ 0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
+ at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
+ 1: std::sys_common::backtrace::print
+ at libstd/sys_common/backtrace.rs:71
+ at libstd/sys_common/backtrace.rs:59
+ 2: std::panicking::default_hook::{{closure}}
+ at libstd/panicking.rs:211
+ 3: std::panicking::default_hook
+ at libstd/panicking.rs:227
+ 4: std::panicking::rust_panic_with_hook
+ at libstd/panicking.rs:477
+ 5: std::panicking::continue_panic_fmt
+ at libstd/panicking.rs:391
+ 6: rust_begin_unwind
+ at libstd/panicking.rs:326
+ 7: core::panicking::panic_fmt
+ at libcore/panicking.rs:77
+ 8: core::panicking::panic_bounds_check
+ at libcore/panicking.rs:59
+ 9: <usize as core::slice::SliceIndex<[T]>>::index
+ at libcore/slice/mod.rs:2046
+ 10: core::slice::<impl core::ops::index::Index<I> for [T]>::index
+ at libcore/slice/mod.rs:1914
+ 11: <alloc::vec::Vec<T> as core::ops::index::Index<I>>::index
+ at liballoc/vec.rs:1725
+ 12: panic::main
at src/main.rs:4
- 18: std::rt::lang_start::{{closure}}
- at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/rt.rs:67
- 19: std::rt::lang_start_internal::{{closure}}
- at src/libstd/rt.rs:52
- 20: std::panicking::try::do_call
- at src/libstd/panicking.rs:292
- 21: __rust_maybe_catch_panic
- at src/libpanic_unwind/lib.rs:78
- 22: std::panicking::try
- at src/libstd/panicking.rs:270
- 23: std::panic::catch_unwind
- at src/libstd/panic.rs:394
- 24: std::rt::lang_start_internal
- at src/libstd/rt.rs:51
- 25: std::rt::lang_start
- at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/rt.rs:67
- 26: panic::main
+ 13: std::rt::lang_start::{{closure}}
+ at libstd/rt.rs:74
+ 14: std::panicking::try::do_call
+ at libstd/rt.rs:59
+ at libstd/panicking.rs:310
+ 15: __rust_maybe_catch_panic
+ at libpanic_unwind/lib.rs:103
+ 16: std::rt::lang_start_internal
+ at libstd/panicking.rs:289
+ at libstd/panic.rs:392
+ at libstd/rt.rs:58
+ 17: std::rt::lang_start
+ at libstd/rt.rs:74
+ 18: main
+ 19: __libc_start_main
+ 20: _start
```
<span class="caption">Listing 9-2: The backtrace generated by a call to
@@ -181,7 +183,7 @@ information, debug symbols must be enabled. Debug symbols are enabled by
default when using `cargo build` or `cargo run` without the `--release` flag,
as we have here.
-In the output in Listing 9-2, line 17 of the backtrace points to the line in
+In the output in Listing 9-2, line 12 of the backtrace points to the line in
our project that’s causing the problem: line 4 of *src/main.rs*. If we don’t
want our program to panic, the location pointed to by the first line mentioning
a file we wrote is where we should start investigating. In Listing 9-1, where
@@ -192,9 +194,9 @@ you’ll need to figure out what action the code is taking with what values to
cause the panic and what the code should do instead.
We’ll come back to `panic!` and when we should and should not use `panic!` to
-handle error conditions in the [“To `panic!` or Not to
-`panic!`”][to-panic-or-not-to-panic]<!-- ignore --> section later in this
-chapter. Next, we’ll look at how to recover from an error using `Result`.
+handle error conditions in the [“To `panic!` or Not to `panic!`”]
+[to-panic-or-not-to-panic]<!-- ignore --> section later in this chapter. Next,
+we’ll look at how to recover from an error using `Result`.
[to-panic-or-not-to-panic]:
ch09-03-to-panic-or-not-to-panic.html#to-panic-or-not-to-panic
diff --git a/book-original/src/ch09-02-recoverable-errors-with-result.md b/book-pl-en/src/ch09-02-recoverable-errors-with-result.md
index 26f9e51..a28582b 100644
--- a/book-original/src/ch09-02-recoverable-errors-with-result.md
+++ b/book-pl-en/src/ch09-02-recoverable-errors-with-result.md
@@ -34,7 +34,11 @@ fail. In Listing 9-3 we try to open a file.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch09-error-handling/listing-09-03/src/main.rs}}
+use std::fs::File;
+
+fn main() {
+ let f = File::open("hello.txt");
+}
```
<span class="caption">Listing 9-3: Opening a file</span>
@@ -47,14 +51,22 @@ us that the types don’t match. The error message will then tell us what the
type of `f` *is*. Let’s try it! We know that the return type of `File::open`
isn’t of type `u32`, so let’s change the `let f` statement to this:
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/src/main.rs:here}}
+```rust,ignore
+let f: u32 = File::open("hello.txt");
```
Attempting to compile now gives us the following output:
```text
-{{#include ../listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/output.txt}}
+error[E0308]: mismatched types
+ --> src/main.rs:4:18
+ |
+4 | let f: u32 = File::open("hello.txt");
+ | ^^^^^^^^^^^^^^^^^^^^^^^ expected u32, found enum
+`std::result::Result`
+ |
+ = note: expected type `u32`
+ found type `std::result::Result<std::fs::File, std::io::Error>`
```
This tells us the return type of the `File::open` function is a `Result<T, E>`.
@@ -83,7 +95,18 @@ Chapter 6.
<span class="filename">Filename: src/main.rs</span>
```rust,should_panic
-{{#rustdoc_include ../listings/ch09-error-handling/listing-09-04/src/main.rs}}
+use std::fs::File;
+
+fn main() {
+ let f = File::open("hello.txt");
+
+ let f = match f {
+ Ok(file) => file,
+ Err(error) => {
+ panic!("There was a problem opening the file: {:?}", error)
+ },
+ };
+}
```
<span class="caption">Listing 9-4: Using a `match` expression to handle the
@@ -104,7 +127,8 @@ there’s no file named *hello.txt* in our current directory and we run this
code, we’ll see the following output from the `panic!` macro:
```text
-{{#include ../listings/ch09-error-handling/listing-09-04/output.txt}}
+thread 'main' panicked at 'There was a problem opening the file: Error { repr:
+Os { code: 2, message: "No such file or directory" } }', src/main.rs:9:12
```
As usual, this output tells us exactly what has gone wrong.
@@ -117,7 +141,7 @@ if `File::open` failed because the file doesn’t exist, we want to create the
file and return the handle to the new file. If `File::open` failed for any
other reason—for example, because we didn’t have permission to open the file—we
still want the code to `panic!` in the same way as it did in Listing 9-4. Look
-at Listing 9-5, which adds an inner `match` expression.
+at Listing 9-5, which adds an inner `match` expression:
<span class="filename">Filename: src/main.rs</span>
@@ -125,7 +149,23 @@ at Listing 9-5, which adds an inner `match` expression.
tests to fail lol -->
```rust,ignore
-{{#rustdoc_include ../listings/ch09-error-handling/listing-09-05/src/main.rs}}
+use std::fs::File;
+use std::io::ErrorKind;
+
+fn main() {
+ let f = File::open("hello.txt");
+
+ let f = match f {
+ Ok(file) => file,
+ Err(error) => match error.kind() {
+ ErrorKind::NotFound => match File::create("hello.txt") {
+ Ok(fc) => fc,
+ Err(e) => panic!("Tried to create file but there was a problem: {:?}", e),
+ },
+ other_error => panic!("There was a problem opening the file: {:?}", other_error),
+ },
+ };
+}
```
<span class="caption">Listing 9-5: Handling different kinds of errors in
@@ -137,32 +177,43 @@ has a method `kind` that we can call to get an `io::ErrorKind` value. The enum
`io::ErrorKind` is provided by the standard library and has variants
representing the different kinds of errors that might result from an `io`
operation. The variant we want to use is `ErrorKind::NotFound`, which indicates
-the file we’re trying to open doesn’t exist yet. So we match on `f`, but we
-also have an inner match on `error.kind()`.
+the file we’re trying to open doesn’t exist yet. So we `match` on `f`, but we
+also have an inner `match` on `error.kind()`.
The condition we want to check in the inner match is whether the value returned
by `error.kind()` is the `NotFound` variant of the `ErrorKind` enum. If it is,
we try to create the file with `File::create`. However, because `File::create`
could also fail, we need a second arm in the inner `match` expression. When the
-file can’t be created, a different error message is printed. The second arm of
-the outer `match` stays the same, so the program panics on any error besides
-the missing file error.
+file can’t be created, a different error message will be printed. The second
+arm of the outer `match` stays the same so the program panics on any error
+besides the missing file error.
-That’s a lot of `match`! The `match` expression is very useful but also very
-much a primitive. In Chapter 13, you’ll learn about closures; the `Result<T,
-E>` type has many methods that accept a closure and are implemented using
-`match` expressions. Using those methods will make your code more concise. A
-more seasoned Rustacean might write this code instead of Listing 9-5:
+That’s a lot of `match`! `match` is very powerful, but also very much a
+primitive. In Chapter 13, we’ll learn about closures. The `Result<T, E>` type
+has many methods that accept a closure, and are implemented as `match`
+expressions. A more seasoned Rustacean might write this:
```rust,ignore
-{{#rustdoc_include ../listings/ch09-error-handling/no-listing-03-closures/src/main.rs}}
+use std::fs::File;
+use std::io::ErrorKind;
+
+fn main() {
+ let f = File::open("hello.txt").map_err(|error| {
+ if error.kind() == ErrorKind::NotFound {
+ File::create("hello.txt").unwrap_or_else(|error| {
+ panic!("Tried to create file but there was a problem: {:?}", error);
+ })
+ } else {
+ panic!("There was a problem opening the file: {:?}", error);
+ }
+ });
+}
```
-Although this code has the same behavior as Listing 9-5, it doesn’t contain any
-`match` expressions and is cleaner to read. Come back to this example after
-you’ve read Chapter 13, and look up the `unwrap_or_else` method in the standard
-library documentation. Many more of these methods can clean up huge nested
-`match` expressions when you’re dealing with errors.
+Come back to this example after you’ve read Chapter 13, and look up what the
+`map_err` and `unwrap_or_else` methods do in the standard library
+documentation. There’s many more of these methods that can clean up huge nested
+`match` expressions when dealing with errors.
### Shortcuts for Panic on Error: `unwrap` and `expect`
@@ -177,7 +228,11 @@ call the `panic!` macro for us. Here is an example of `unwrap` in action:
<span class="filename">Filename: src/main.rs</span>
```rust,should_panic
-{{#rustdoc_include ../listings/ch09-error-handling/no-listing-04-unwrap/src/main.rs}}
+use std::fs::File;
+
+fn main() {
+ let f = File::open("hello.txt").unwrap();
+}
```
If we run this code without a *hello.txt* file, we’ll see an error message from
@@ -197,7 +252,11 @@ panic easier. The syntax of `expect` looks like this:
<span class="filename">Filename: src/main.rs</span>
```rust,should_panic
-{{#rustdoc_include ../listings/ch09-error-handling/no-listing-05-expect/src/main.rs}}
+use std::fs::File;
+
+fn main() {
+ let f = File::open("hello.txt").expect("Failed to open hello.txt");
+}
```
We use `expect` in the same way as `unwrap`: to return the file handle or call
@@ -227,16 +286,30 @@ handled than what you have available in the context of your code.
For example, Listing 9-6 shows a function that reads a username from a file. If
the file doesn’t exist or can’t be read, this function will return those errors
-to the code that called this function.
+to the code that called this function:
<span class="filename">Filename: src/main.rs</span>
-<!-- Deliberately not using rustdoc_include here; the `main` function in the
-file panics. We do want to include it for reader experimentation purposes, but
-don't want to include it for rustdoc testing purposes. -->
-
```rust
-{{#include ../listings/ch09-error-handling/listing-09-06/src/main.rs:here}}
+use std::io;
+use std::io::Read;
+use std::fs::File;
+
+fn read_username_from_file() -> Result<String, io::Error> {
+ let f = File::open("hello.txt");
+
+ let mut f = match f {
+ Ok(file) => file,
+ Err(e) => return Err(e),
+ };
+
+ let mut s = String::new();
+
+ match f.read_to_string(&mut s) {
+ Ok(_) => Ok(s),
+ Err(e) => Err(e),
+ }
+}
```
<span class="caption">Listing 9-6: A function that returns errors to the
@@ -244,10 +317,10 @@ calling code using `match`</span>
This function can be written in a much shorter way, but we’re going to start by
doing a lot of it manually in order to explore error handling; at the end,
-we’ll show the shorter way. Let’s look at the return type of the function first:
+we’ll show the easy way. Let’s look at the return type of the function first:
`Result<String, io::Error>`. This means the function is returning a value of
the type `Result<T, E>` where the generic parameter `T` has been filled in
-with the concrete type `String` and the generic type `E` has been filled in
+with the concrete type `String`, and the generic type `E` has been filled in
with the concrete type `io::Error`. If this function succeeds without any
problems, the code that calls this function will receive an `Ok` value that
holds a `String`—the username that this function read from the file. If this
@@ -293,20 +366,25 @@ question mark operator `?` to make this easier.
Listing 9-7 shows an implementation of `read_username_from_file` that has the
same functionality as it had in Listing 9-6, but this implementation uses the
-`?` operator.
+question mark operator:
<span class="filename">Filename: src/main.rs</span>
-<!-- Deliberately not using rustdoc_include here; the `main` function in the
-file panics. We do want to include it for reader experimentation purposes, but
-don't want to include it for rustdoc testing purposes. -->
-
```rust
-{{#include ../listings/ch09-error-handling/listing-09-07/src/main.rs:here}}
+use std::io;
+use std::io::Read;
+use std::fs::File;
+
+fn read_username_from_file() -> Result<String, io::Error> {
+ let mut f = File::open("hello.txt")?;
+ let mut s = String::new();
+ f.read_to_string(&mut s)?;
+ Ok(s)
+}
```
<span class="caption">Listing 9-7: A function that returns errors to the
-calling code using the `?` operator</span>
+calling code using `?`</span>
The `?` placed after a `Result` value is defined to work in almost the same way
as the `match` expressions we defined to handle the `Result` values in Listing
@@ -317,39 +395,43 @@ used the `return` keyword so the error value gets propagated to the calling
code.
There is a difference between what the `match` expression from Listing 9-6 and
-the `?` operator do: error values that have the `?` operator called on them go
-through the `from` function, defined in the `From` trait in the standard
-library, which is used to convert errors from one type into another. When the
-`?` operator calls the `from` function, the error type received is converted
-into the error type defined in the return type of the current function. This is
-useful when a function returns one error type to represent all the ways a
-function might fail, even if parts might fail for many different reasons. As
-long as each error type implements the `from` function to define how to convert
-itself to the returned error type, the `?` operator takes care of the
+`?` do: error values taken by `?` go through the `from` function, defined in
+the `From` trait in the standard library, which is used to convert errors from
+one type into another. When `?` calls the `from` function, the error type
+received is converted into the error type defined in the return type of the
+current function. This is useful when a function returns one error type to
+represent all the ways a function might fail, even if parts might fail for many
+different reasons. As long as each error type implements the `from` function to
+define how to convert itself to the returned error type, `?` takes care of the
conversion automatically.
In the context of Listing 9-7, the `?` at the end of the `File::open` call will
-return the value inside an `Ok` to the variable `f`. If an error occurs, the
-`?` operator will return early out of the whole function and give any `Err`
-value to the calling code. The same thing applies to the `?` at the end of the
+return the value inside an `Ok` to the variable `f`. If an error occurs, `?`
+will return early out of the whole function and give any `Err` value to the
+calling code. The same thing applies to the `?` at the end of the
`read_to_string` call.
The `?` operator eliminates a lot of boilerplate and makes this function’s
implementation simpler. We could even shorten this code further by chaining
-method calls immediately after the `?`, as shown in Listing 9-8.
+method calls immediately after the `?`, as shown in Listing 9-8:
<span class="filename">Filename: src/main.rs</span>
-<!-- Deliberately not using rustdoc_include here; the `main` function in the
-file panics. We do want to include it for reader experimentation purposes, but
-don't want to include it for rustdoc testing purposes. -->
-
```rust
-{{#include ../listings/ch09-error-handling/listing-09-08/src/main.rs:here}}
+use std::io;
+use std::io::Read;
+use std::fs::File;
+
+fn read_username_from_file() -> Result<String, io::Error> {
+ let mut s = String::new();
+
+ File::open("hello.txt")?.read_to_string(&mut s)?;
+
+ Ok(s)
+}
```
-<span class="caption">Listing 9-8: Chaining method calls after the `?`
-operator</span>
+<span class="caption">Listing 9-8: Chaining method calls after `?`</span>
We’ve moved the creation of the new `String` in `s` to the beginning of the
function; that part hasn’t changed. Instead of creating a variable `f`, we’ve
@@ -360,76 +442,83 @@ username in `s` when both `File::open` and `read_to_string` succeed rather than
returning errors. The functionality is again the same as in Listing 9-6 and
Listing 9-7; this is just a different, more ergonomic way to write it.
-Speaking of different ways to write this function, Listing 9-9 shows that
-there’s a way to make this even shorter.
+Speaking of different ways to write this function, there’s a way to make this even
+shorter:
<span class="filename">Filename: src/main.rs</span>
-<!-- Deliberately not using rustdoc_include here; the `main` function in the
-file panics. We do want to include it for reader experimentation purposes, but
-don't want to include it for rustdoc testing purposes. -->
-
```rust
-{{#include ../listings/ch09-error-handling/listing-09-09/src/main.rs:here}}
+use std::io;
+use std::fs;
+
+fn read_username_from_file() -> Result<String, io::Error> {
+ fs::read_to_string("hello.txt")
+}
```
-<span class="caption">Listing 9-9: Using `fs::read_to_string` instead of
-opening and then reading the file</span>
+<span class="caption">Listing 9-9: Using `fs::read_to_string`</span>
-Reading a file into a string is a fairly common operation, so Rust provides the
-convenient `fs::read_to_string` function that opens the file, creates a new
-`String`, reads the contents of the file, puts the contents into that `String`,
-and returns it. Of course, using `fs::read_to_string` doesn’t give us the
-opportunity to explain all the error handling, so we did it the longer way
-first.
+Reading a file into a string is a fairly common operation, and so Rust
+provides a convenience function called `fs::read_to_string` that will
+open the file, create a new `String`, read the contents of the file,
+and put the contents into that `String`, and then return it. Of course,
+this doesn’t give us the opportunity to show off all of this error handling,
+so we did it the hard way at first.
-#### The `?` Operator Can Be Used in Functions That Return `Result`
+#### The `?` Operator Can Only Be Used in Functions That Return `Result`
-The `?` operator can be used in functions that have a return type of
+The `?` operator can only be used in functions that have a return type of
`Result`, because it is defined to work in the same way as the `match`
expression we defined in Listing 9-6. The part of the `match` that requires a
return type of `Result` is `return Err(e)`, so the return type of the function
-can be a `Result` to be compatible with this `return`.
+must be a `Result` to be compatible with this `return`.
+
+Let’s look at what happens if we use `?` in the `main` function, which you’ll
+recall has a return type of `()`:
-Let’s look at what happens if we use the `?` operator in the `main` function,
-which you’ll recall has a return type of `()`:
+```rust,ignore
+use std::fs::File;
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch09-error-handling/no-listing-06-question-mark-in-main/src/main.rs}}
+fn main() {
+ let f = File::open("hello.txt")?;
+}
```
When we compile this code, we get the following error message:
```text
-{{#include ../listings/ch09-error-handling/no-listing-06-question-mark-in-main/output.txt}}
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
+ --> src/main.rs:4:13
+ |
+4 | let f = File::open("hello.txt")?;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+ |
+ = help: the trait `std::ops::Try` is not implemented for `()`
+ = note: required by `std::ops::Try::from_error`
```
-This error points out that we’re only allowed to use the `?` operator in a
-function that returns `Result` or `Option` or another type that implements
-`std::ops::Try`. When you’re writing code in a function
-that doesn’t return one of these types, and you want to use `?` when you call other
-functions that return `Result<T, E>`, you have two choices to fix this problem.
-One technique is to change the return type of your function to be `Result<T,
-E>` if you have no restrictions preventing that. The other technique is to use
-a `match` or one of the `Result<T, E>` methods to handle the `Result<T, E>` in
-whatever way is appropriate.
+This error points out that we’re only allowed to use `?` in a function that
+returns `Result<T, E>`. In functions that don’t return `Result<T, E>`, when
+you call other functions that return `Result<T, E>`, you’ll need to use a
+`match` or one of the `Result<T, E>` methods to handle the `Result<T, E>`
+instead of using `?` to potentially propagate the error to the calling code.
-The `main` function is special, and there are restrictions on what its return
-type must be. One valid return type for main is `()`, and conveniently, another
-valid return type is `Result<T, E>`, as shown here:
+However, the `main` function can return a `Result<T, E>`:
```rust,ignore
-{{#rustdoc_include ../listings/ch09-error-handling/no-listing-07-main-returning-result/src/main.rs}}
+use std::error::Error;
+use std::fs::File;
+
+fn main() -> Result<(), Box<dyn Error>> {
+ let f = File::open("hello.txt")?;
+
+ Ok(())
+}
```
-The `Box<dyn Error>` type is called a trait object, which we’ll talk about in
-the [“Using Trait Objects that Allow for Values of Different
-Types”][trait-objects]<!-- ignore --> section in Chapter 17. For now, you can
-read `Box<dyn Error>` to mean “any kind of error.” Using `?` in a `main`
-function with this return type is allowed.
+The `Box<dyn Error>` is called a “trait object”, which we’ll talk about in Chapter 17.
+For now, you can read `Box<dyn Error>` to mean “any kind of error.”
Now that we’ve discussed the details of calling `panic!` or returning `Result`,
let’s return to the topic of how to decide which is appropriate to use in which
cases.
-
-[trait-objects]: ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
diff --git a/book-original/src/ch09-03-to-panic-or-not-to-panic.md b/book-pl-en/src/ch09-03-to-panic-or-not-to-panic.md
index e5af81d..033a766 100644
--- a/book-original/src/ch09-03-to-panic-or-not-to-panic.md
+++ b/book-pl-en/src/ch09-03-to-panic-or-not-to-panic.md
@@ -48,7 +48,9 @@ have an `Err` variant, it’s perfectly acceptable to call `unwrap`. Here’s an
example:
```rust
-{{#rustdoc_include ../listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/src/main.rs:here}}
+use std::net::IpAddr;
+
+let home: IpAddr = "127.0.0.1".parse().unwrap();
```
We’re creating an `IpAddr` instance by parsing a hardcoded string. We can see
@@ -79,7 +81,7 @@ bug in their code so they can fix it during development. Similarly, `panic!` is
often appropriate if you’re calling external code that is out of your control
and it returns an invalid state that you have no way of fixing.
-However, when failure is expected, it’s more appropriate to return a `Result`
+However, when failure is expected, it is more appropriate to return a `Result`
than to make a `panic!` call. Examples include a parser being given malformed
data or an HTTP request returning a status that indicates you have hit a rate
limit. In these cases, returning a `Result` indicates that failure is an
@@ -113,8 +115,6 @@ even compile, so your function doesn’t have to check for that case at runtime.
Another example is using an unsigned integer type such as `u32`, which ensures
the parameter is never negative.
-### Creating Custom Types for Validation
-
Let’s take the idea of using Rust’s type system to ensure we have a valid value
one step further and look at creating a custom type for validation. Recall the
guessing game in Chapter 2 in which our code asked the user to guess a number
@@ -131,7 +131,22 @@ One way to do this would be to parse the guess as an `i32` instead of only a
number being in range, like so:
```rust,ignore
-{{#rustdoc_include ../listings/ch09-error-handling/no-listing-09-guess-out-of-range/src/main.rs:here}}
+loop {
+ // --snip--
+
+ let guess: i32 = match guess.trim().parse() {
+ Ok(num) => num,
+ Err(_) => continue,
+ };
+
+ if guess < 1 || guess > 100 {
+ println!("The secret number will be between 1 and 100.");
+ continue;
+ }
+
+ match guess.cmp(&secret_number) {
+ // --snip--
+}
```
The `if` expression checks whether our value is out of range, tells the user
@@ -150,22 +165,35 @@ an instance of the type rather than repeating the validations everywhere. That
way, it’s safe for functions to use the new type in their signatures and
confidently use the values they receive. Listing 9-10 shows one way to define a
`Guess` type that will only create an instance of `Guess` if the `new` function
-receives a value between 1 and 100.
-
-<!-- Deliberately not using rustdoc_include here; the `main` function in the
-file requires the `rand` crate. We do want to include it for reader
-experimentation purposes, but don't want to include it for rustdoc testing
-purposes. -->
+receives a value between 1 and 100:
```rust
-{{#include ../listings/ch09-error-handling/listing-09-10/src/main.rs:here}}
+pub struct Guess {
+ value: i32,
+}
+
+impl Guess {
+ pub fn new(value: i32) -> Guess {
+ if value < 1 || value > 100 {
+ panic!("Guess value must be between 1 and 100, got {}.", value);
+ }
+
+ Guess {
+ value
+ }
+ }
+
+ pub fn value(&self) -> i32 {
+ self.value
+ }
+}
```
<span class="caption">Listing 9-10: A `Guess` type that will only continue with
values between 1 and 100</span>
First, we define a struct named `Guess` that has a field named `value` that
-holds an `i32`. This is where the number will be stored.
+holds a `i32`. This is where the number will be stored.
Then we implement an associated function named `new` on `Guess` that creates
instances of `Guess` values. The `new` function is defined to have one
@@ -182,7 +210,7 @@ of a `panic!` in the API documentation that you create in Chapter 14. If
to the `value` parameter and return the `Guess`.
Next, we implement a method named `value` that borrows `self`, doesn’t have any
-other parameters, and returns an `i32`. This kind of method is sometimes called
+other parameters, and returns a `i32`. This kind of method is sometimes called
a *getter*, because its purpose is to get some data from its fields and return
it. This public method is necessary because the `value` field of the `Guess`
struct is private. It’s important that the `value` field be private so code
@@ -192,7 +220,7 @@ the module *must* use the `Guess::new` function to create an instance of
hasn’t been checked by the conditions in the `Guess::new` function.
A function that has a parameter or returns only numbers between 1 and 100 could
-then declare in its signature that it takes or returns a `Guess` rather than an
+then declare in its signature that it takes or returns a `Guess` rather than a
`i32` and wouldn’t need to do any additional checks in its body.
## Summary
@@ -209,3 +237,4 @@ situations will make your code more reliable in the face of inevitable problems.
Now that you’ve seen useful ways that the standard library uses generics with
the `Option` and `Result` enums, we’ll talk about how generics work and how you
can use them in your code.
+
diff --git a/book-original/src/ch10-00-generics.md b/book-pl-en/src/ch10-00-generics.md
index 032f437..3c52723 100644
--- a/book-original/src/ch10-00-generics.md
+++ b/book-pl-en/src/ch10-00-generics.md
@@ -41,7 +41,20 @@ Listing 10-1.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/src/main.rs:here}}
+fn main() {
+ let number_list = vec![34, 50, 25, 100, 65];
+
+ let mut largest = number_list[0];
+
+ for number in number_list {
+ if number > largest {
+ largest = number;
+ }
+ }
+
+ println!("The largest number is {}", largest);
+# assert_eq!(largest, 100);
+}
```
<span class="caption">Listing 10-1: Code to find the largest number in a list
@@ -51,10 +64,10 @@ This code stores a list of integers in the variable `number_list` and places
the first number in the list in a variable named `largest`. Then it iterates
through all the numbers in the list, and if the current number is greater than
the number stored in `largest`, it replaces the number in that variable.
-However, if the current number is less than or equal to the largest number seen
-so far, the variable doesn’t change, and the code moves on to the next number
-in the list. After considering all the numbers in the list, `largest` should
-hold the largest number, which in this case is 100.
+However, if the current number is less than the largest number seen so far, the
+variable doesn’t change, and the code moves on to the next number in the list.
+After considering all the numbers in the list, `largest` should hold the
+largest number, which in this case is 100.
To find the largest number in two different lists of numbers, we can duplicate
the code in Listing 10-1 and use the same logic at two different places in the
@@ -63,7 +76,31 @@ program, as shown in Listing 10-2.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/src/main.rs}}
+fn main() {
+ let number_list = vec![34, 50, 25, 100, 65];
+
+ let mut largest = number_list[0];
+
+ for number in number_list {
+ if number > largest {
+ largest = number;
+ }
+ }
+
+ println!("The largest number is {}", largest);
+
+ let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8];
+
+ let mut largest = number_list[0];
+
+ for number in number_list {
+ if number > largest {
+ largest = number;
+ }
+ }
+
+ println!("The largest number is {}", largest);
+}
```
<span class="caption">Listing 10-2: Code to find the largest number in *two*
@@ -85,7 +122,31 @@ number in two different lists.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/src/main.rs:here}}
+fn largest(list: &[i32]) -> i32 {
+ let mut largest = list[0];
+
+ for &item in list.iter() {
+ if item > largest {
+ largest = item;
+ }
+ }
+
+ largest
+}
+
+fn main() {
+ let number_list = vec![34, 50, 25, 100, 65];
+
+ let result = largest(&number_list);
+ println!("The largest number is {}", result);
+# assert_eq!(result, 100);
+
+ let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8];
+
+ let result = largest(&number_list);
+ println!("The largest number is {}", result);
+# assert_eq!(result, 6000);
+}
```
<span class="caption">Listing 10-3: Abstracted code to find the largest number
diff --git a/book-original/src/ch10-01-syntax.md b/book-pl-en/src/ch10-01-syntax.md
index 3d86ebf..d7d03c3 100644
--- a/book-original/src/ch10-01-syntax.md
+++ b/book-pl-en/src/ch10-01-syntax.md
@@ -18,7 +18,43 @@ both find the largest value in a slice.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/src/main.rs:here}}
+fn largest_i32(list: &[i32]) -> i32 {
+ let mut largest = list[0];
+
+ for &item in list.iter() {
+ if item > largest {
+ largest = item;
+ }
+ }
+
+ largest
+}
+
+fn largest_char(list: &[char]) -> char {
+ let mut largest = list[0];
+
+ for &item in list.iter() {
+ if item > largest {
+ largest = item;
+ }
+ }
+
+ largest
+}
+
+fn main() {
+ let number_list = vec![34, 50, 25, 100, 65];
+
+ let result = largest_i32(&number_list);
+ println!("The largest number is {}", result);
+# assert_eq!(result, 100);
+
+ let char_list = vec!['y', 'm', 'a', 'q'];
+
+ let result = largest_char(&char_list);
+ println!("The largest char is {}", result);
+# assert_eq!(result, 'y');
+}
```
<span class="caption">Listing 10-4: Two functions that differ only in their
@@ -59,7 +95,29 @@ compile yet, but we’ll fix it later in this chapter.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/src/main.rs}}
+fn largest<T>(list: &[T]) -> T {
+ let mut largest = list[0];
+
+ for &item in list.iter() {
+ if item > largest {
+ largest = item;
+ }
+ }
+
+ largest
+}
+
+fn main() {
+ let number_list = vec![34, 50, 25, 100, 65];
+
+ let result = largest(&number_list);
+ println!("The largest number is {}", result);
+
+ let char_list = vec!['y', 'm', 'a', 'q'];
+
+ let result = largest(&char_list);
+ println!("The largest char is {}", result);
+}
```
<span class="caption">Listing 10-5: A definition of the `largest` function that
@@ -68,7 +126,13 @@ uses generic type parameters but doesn’t compile yet</span>
If we compile this code right now, we’ll get this error:
```text
-{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt}}
+error[E0369]: binary operation `>` cannot be applied to type `T`
+ --> src/main.rs:5:12
+ |
+5 | if item > largest {
+ | ^^^^^^^^^^^^^^
+ |
+ = note: an implementation of `std::cmp::PartialOrd` might be missing for `T`
```
The note mentions `std::cmp::PartialOrd`, which is a *trait*. We’ll talk about
@@ -78,9 +142,8 @@ to compare values of type `T` in the body, we can only use types whose values
can be ordered. To enable comparisons, the standard library has the
`std::cmp::PartialOrd` trait that you can implement on types (see Appendix C
for more on this trait). You’ll learn how to specify that a generic type has a
-particular trait in the [“Traits as Parameters”][traits-as-parameters]<!--
-ignore --> section, but let’s first explore other ways of using generic type
-parameters.
+particular trait in the [“Trait Bounds”][trait-bounds]<!-- ignore --> section,
+but let’s first explore other ways of using generic type parameters.
### In Struct Definitions
@@ -91,7 +154,15 @@ struct to hold `x` and `y` coordinate values of any type.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-06/src/main.rs}}
+struct Point<T> {
+ x: T,
+ y: T,
+}
+
+fn main() {
+ let integer = Point { x: 5, y: 10 };
+ let float = Point { x: 1.0, y: 4.0 };
+}
```
<span class="caption">Listing 10-6: A `Point<T>` struct that holds `x` and `y`
@@ -112,7 +183,14 @@ Listing 10-7, our code won’t compile.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/src/main.rs}}
+struct Point<T> {
+ x: T,
+ y: T,
+}
+
+fn main() {
+ let wont_work = Point { x: 5, y: 4.0 };
+}
```
<span class="caption">Listing 10-7: The fields `x` and `y` must be the same
@@ -124,7 +202,15 @@ compiler know that the generic type `T` will be an integer for this instance of
same type as `x`, we’ll get a type mismatch error like this:
```text
-{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/output.txt}}
+error[E0308]: mismatched types
+ --> src/main.rs:7:38
+ |
+7 | let wont_work = Point { x: 5, y: 4.0 };
+ | ^^^ expected integral variable, found
+floating-point variable
+ |
+ = note: expected type `{integer}`
+ found type `{float}`
```
To define a `Point` struct where `x` and `y` are both generics but could have
@@ -135,7 +221,16 @@ Listing 10-8, we can change the definition of `Point` to be generic over types
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-08/src/main.rs}}
+struct Point<T, U> {
+ x: T,
+ y: U,
+}
+
+fn main() {
+ let both_integer = Point { x: 5, y: 10 };
+ let both_float = Point { x: 1.0, y: 4.0 };
+ let integer_and_float = Point { x: 5, y: 4.0 };
+}
```
<span class="caption">Listing 10-8: A `Point<T, U>` generic over two types so
@@ -198,7 +293,22 @@ struct we defined in Listing 10-6 with a method named `x` implemented on it.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-09/src/main.rs}}
+struct Point<T> {
+ x: T,
+ y: T,
+}
+
+impl<T> Point<T> {
+ fn x(&self) -> &T {
+ &self.x
+ }
+}
+
+fn main() {
+ let p = Point { x: 5, y: 10 };
+
+ println!("p.x = {}", p.x());
+}
```
<span class="caption">Listing 10-9: Implementing a method named `x` on the
@@ -217,10 +327,17 @@ We could, for example, implement methods only on `Point<f32>` instances rather
than on `Point<T>` instances with any generic type. In Listing 10-10 we use the
concrete type `f32`, meaning we don’t declare any types after `impl`.
-<span class="filename">Filename: src/main.rs</span>
-
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-10/src/main.rs:here}}
+# struct Point<T> {
+# x: T,
+# y: T,
+# }
+#
+impl Point<f32> {
+ fn distance_from_origin(&self) -> f32 {
+ (self.x.powi(2) + self.y.powi(2)).sqrt()
+ }
+}
```
<span class="caption">Listing 10-10: An `impl` block that only applies to a
@@ -235,7 +352,7 @@ operations that are available only for floating point types.
Generic type parameters in a struct definition aren’t always the same as those
you use in that struct’s method signatures. For example, Listing 10-11 defines
the method `mixup` on the `Point<T, U>` struct from Listing 10-8. The method
-takes another `Point` as a parameter, which might have different types from the
+takes another `Point` as a parameter, which might have different types than the
`self` `Point` we’re calling `mixup` on. The method creates a new `Point`
instance with the `x` value from the `self` `Point` (of type `T`) and the `y`
value from the passed-in `Point` (of type `W`).
@@ -243,11 +360,32 @@ value from the passed-in `Point` (of type `W`).
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/src/main.rs}}
+struct Point<T, U> {
+ x: T,
+ y: U,
+}
+
+impl<T, U> Point<T, U> {
+ fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
+ Point {
+ x: self.x,
+ y: other.y,
+ }
+ }
+}
+
+fn main() {
+ let p1 = Point { x: 5, y: 10.4 };
+ let p2 = Point { x: "Hello", y: 'c'};
+
+ let p3 = p1.mixup(p2);
+
+ println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
+}
```
<span class="caption">Listing 10-11: A method that uses different generic types
-from its struct’s definition</span>
+than its struct’s definition</span>
In `main`, we’ve defined a `Point` that has an `i32` for `x` (with value `5`)
and an `f64` for `y` (with value `10.4`). The `p2` variable is a `Point` struct
@@ -323,4 +461,4 @@ performs just as it would if we had duplicated each definition by hand. The
process of monomorphization makes Rust’s generics extremely efficient at
runtime.
-[traits-as-parameters]: ch10-02-traits.html#traits-as-parameters
+[trait-bounds]: ch10-02-traits.html#trait-bounds
diff --git a/book-original/src/ch10-02-traits.md b/book-pl-en/src/ch10-02-traits.md
index 0e01361..985e57e 100644
--- a/book-original/src/ch10-02-traits.md
+++ b/book-pl-en/src/ch10-02-traits.md
@@ -30,7 +30,9 @@ need a summary from each type, and we need to request that summary by calling a
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/src/lib.rs}}
+pub trait Summary {
+ fn summarize(&self) -> String;
+}
```
<span class="caption">Listing 10-12: A `Summary` trait that consists of the
@@ -63,7 +65,35 @@ already limited to 280 characters.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/src/lib.rs:here}}
+# pub trait Summary {
+# fn summarize(&self) -> String;
+# }
+#
+pub struct NewsArticle {
+ pub headline: String,
+ pub location: String,
+ pub author: String,
+ pub content: String,
+}
+
+impl Summary for NewsArticle {
+ fn summarize(&self) -> String {
+ format!("{}, by {} ({})", self.headline, self.author, self.location)
+ }
+}
+
+pub struct Tweet {
+ pub username: String,
+ pub content: String,
+ pub reply: bool,
+ pub retweet: bool,
+}
+
+impl Summary for Tweet {
+ fn summarize(&self) -> String {
+ format!("{}: {}", self.username, self.content)
+ }
+}
```
<span class="caption">Listing 10-13: Implementing the `Summary` trait on the
@@ -82,7 +112,14 @@ After implementing the trait, we can call the methods on instances of
`NewsArticle` and `Tweet` in the same way we call regular methods, like this:
```rust,ignore
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs:here}}
+let tweet = Tweet {
+ username: String::from("horse_ebooks"),
+ content: String::from("of course, as you probably already know, people"),
+ reply: false,
+ retweet: false,
+};
+
+println!("1 new tweet: {}", tweet.summarize());
```
This code prints `1 new tweet: horse_ebooks: of course, as you probably already
@@ -131,7 +168,11 @@ in Listing 10-12.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/src/lib.rs:here}}
+pub trait Summary {
+ fn summarize(&self) -> String {
+ String::from("(Read more...)")
+ }
+}
```
<span class="caption">Listing 10-14: Definition of a `Summary` trait with a
@@ -147,7 +188,15 @@ directly, we’ve provided a default implementation and specified that
the `summarize` method on an instance of `NewsArticle`, like this:
```rust,ignore
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/src/main.rs:here}}
+let article = NewsArticle {
+ headline: String::from("Penguins win the Stanley Cup Championship!"),
+ location: String::from("Pittsburgh, PA, USA"),
+ author: String::from("Iceburgh"),
+ content: String::from("The Pittsburgh Penguins once again are the best
+ hockey team in the NHL."),
+};
+
+println!("New article available! {}", article.summarize());
```
This code prints `New article available! (Read more...)`.
@@ -167,14 +216,24 @@ a small part of it. For example, we could define the `Summary` trait to have a
`summarize_author` method:
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/lib.rs:here}}
+pub trait Summary {
+ fn summarize_author(&self) -> String;
+
+ fn summarize(&self) -> String {
+ format!("(Read more from {}...)", self.summarize_author())
+ }
+}
```
To use this version of `Summary`, we only need to define `summarize_author`
when we implement the trait on a type:
```rust,ignore
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/lib.rs:impl}}
+impl Summary for Tweet {
+ fn summarize_author(&self) -> String {
+ format!("@{}", self.username)
+ }
+}
```
After we define `summarize_author`, we can call `summarize` on instances of the
@@ -184,7 +243,14 @@ definition of `summarize_author` that we’ve provided. Because we’ve implemen
`summarize` method without requiring us to write any more code.
```rust,ignore
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/main.rs:here}}
+let tweet = Tweet {
+ username: String::from("horse_ebooks"),
+ content: String::from("of course, as you probably already know, people"),
+ reply: false,
+ retweet: false,
+};
+
+println!("1 new tweet: {}", tweet.summarize());
```
This code prints `1 new tweet: (Read more from @horse_ebooks...)`.
@@ -192,34 +258,29 @@ This code prints `1 new tweet: (Read more from @horse_ebooks...)`.
Note that it isn’t possible to call the default implementation from an
overriding implementation of that same method.
-### Traits as Parameters
+### Traits as arguments
-Now that you know how to define and implement traits, we can explore how to use
-traits to define functions that accept many different types.
+Now that you know how to define traits and implement those traits on types, we
+can explore how to use traits to accept arguments of many different types.
-For example, in Listing 10-13, we implemented the `Summary` trait on the
-`NewsArticle` and `Tweet` types. We can define a `notify` function that calls
-the `summarize` method on its `item` parameter, which is of some type that
-implements the `Summary` trait. To do this, we can use the `impl Trait`
-syntax, like this:
+For example, in Listing 10-13, we implemented the `Summary` trait on the types
+`NewsArticle` and `Tweet`. We can define a function `notify` that calls the
+`summarize` method on its parameter `item`, which is of some type that implements
+the `Summary` trait. To do this, we can use the ‘`impl Trait`’ syntax, like this:
```rust,ignore
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/src/lib.rs:here}}
+pub fn notify(item: impl Summary) {
+ println!("Breaking news! {}", item.summarize());
+}
```
-Instead of a concrete type for the `item` parameter, we specify the `impl`
-keyword and the trait name. This parameter accepts any type that implements the
-specified trait. In the body of `notify`, we can call any methods on `item`
-that come from the `Summary` trait, such as `summarize`. We can call `notify`
-and pass in any instance of `NewsArticle` or `Tweet`. Code that calls the
-function with any other type, such as a `String` or an `i32`, won’t compile
-because those types don’t implement `Summary`.
+In the body of `notify`, we can call any methods on `item` that come from
+the `Summary` trait, like `summarize`.
-#### Trait Bound Syntax
+#### Trait Bounds
-The `impl Trait` syntax works for straightforward cases but is actually
-syntax sugar for a longer form, which is called a *trait bound*; it looks like
-this:
+The `impl Trait` syntax works for short examples, but is syntax sugar for a
+longer form. This is called a *trait bound*, and it looks like this:
```rust,ignore
pub fn notify<T: Summary>(item: T) {
@@ -227,60 +288,53 @@ pub fn notify<T: Summary>(item: T) {
}
```
-This longer form is equivalent to the example in the previous section but is
-more verbose. We place trait bounds with the declaration of the generic type
-parameter after a colon and inside angle brackets.
+This is equivalent to the example above, but is a bit more verbose. We place
+trait bounds with the declaration of the generic type parameter, after a
+colon and inside angle brackets. Because of the trait bound on `T`, we can
+call `notify` and pass in any instance of `NewsArticle` or `Tweet`. Code that
+calls the function with any other type, like a `String` or an `i32`, won’t
+compile, because those types don’t implement `Summary`.
-The `impl Trait` syntax is convenient and makes for more concise code in simple
-cases. The trait bound syntax can express more complexity in other cases. For
-example, we can have two parameters that implement `Summary`. Using the `impl
-Trait` syntax looks like this:
+When should you use this form over `impl Trait`? While `impl Trait` is nice for
+shorter examples, trait bounds are nice for more complex ones. For example,
+say we wanted to take two things that implement `Summary`:
```rust,ignore
pub fn notify(item1: impl Summary, item2: impl Summary) {
```
-If we wanted this function to allow `item1` and `item2` to have different
-types, using `impl Trait` would be appropriate (as long as both types implement
-`Summary`). If we wanted to force both parameters to have the same type, that’s
-only possible to express using a trait bound, like this:
+This would work well if `item1` and `item2` were allowed to have diferent types
+(as long as both implement `Summary`). But what if you wanted to force both to
+have the exact same type? That is only possible if you use a trait bound:
```rust,ignore
pub fn notify<T: Summary>(item1: T, item2: T) {
```
-The generic type `T` specified as the type of the `item1` and `item2`
-parameters constrains the function such that the concrete type of the value
-passed as an argument for `item1` and `item2` must be the same.
-
-#### Specifying Multiple Trait Bounds with the `+` Syntax
+#### Specify multiple traits with `+`
-We can also specify more than one trait bound. Say we wanted `notify` to use
-display formatting on `item` as well as the `summarize` method: we specify in
-the `notify` definition that `item` must implement both `Display` and
-`Summary`. We can do so using the `+` syntax:
+If `notify` needed to display formatting on `item`, as well as use the
+`summarize` method, then `item` would need to implement two different traits at
+the same time: `Display` and `Summary`. This can be done using the `+` syntax:
```rust,ignore
pub fn notify(item: impl Summary + Display) {
```
-The `+` syntax is also valid with trait bounds on generic types:
+This syntax is also valid with trait bounds on generic types:
```rust,ignore
pub fn notify<T: Summary + Display>(item: T) {
```
-With the two trait bounds specified, the body of `notify` can call `summarize`
-and use `{}` to format `item`.
+#### `where` clauses for clearer code
-#### Clearer Trait Bounds with `where` Clauses
-
-Using too many trait bounds has its downsides. Each generic has its own trait
-bounds, so functions with multiple generic type parameters can contain lots of
-trait bound information between the function’s name and its parameter list,
-making the function signature hard to read. For this reason, Rust has alternate
-syntax for specifying trait bounds inside a `where` clause after the function
-signature. So instead of writing this:
+However, there are downsides to using too many trait bounds. Each generic has
+its own trait bounds, so functions with multiple generic type parameters can
+have lots of trait bound information between a function’s name and its
+parameter list, making the function signature hard to read. For this reason,
+Rust has alternate syntax for specifying trait bounds inside a `where` clause
+after the function signature. So instead of writing this:
```rust,ignore
fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {
@@ -295,43 +349,63 @@ fn some_function<T, U>(t: T, u: U) -> i32
{
```
-This function’s signature is less cluttered: the function name, parameter list,
-and return type are close together, similar to a function without lots of trait
-bounds.
+This function’s signature is less cluttered in that the function name,
+parameter list, and return type are close together, similar to a function
+without lots of trait bounds.
-### Returning Types that Implement Traits
+### Returning Traits
-We can also use the `impl Trait` syntax in the return position to return a
-value of some type that implements a trait, as shown here:
+We can use the `impl Trait` syntax in return position as well, to return
+something that implements a trait:
```rust,ignore
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/src/lib.rs:here}}
+fn returns_summarizable() -> impl Summary {
+ Tweet {
+ username: String::from("horse_ebooks"),
+ content: String::from("of course, as you probably already know, people"),
+ reply: false,
+ retweet: false,
+ }
+}
```
-By using `impl Summary` for the return type, we specify that the
-`returns_summarizable` function returns some type that implements the `Summary`
-trait without naming the concrete type. In this case, `returns_summarizable`
-returns a `Tweet`, but the code calling this function doesn’t know that.
+This signature says, “I’m going to return something that implements the
+`Summary` trait, but I’m not going to tell you the exact type.” In our case,
+we’re returning a `Tweet`, but the caller doesn’t know that.
-The ability to return a type that is only specified by the trait it implements
-is especially useful in the context of closures and iterators, which we cover
-in Chapter 13. Closures and iterators create types that only the compiler knows
-or types that are very long to specify. The `impl Trait` syntax lets you
-concisely specify that a function returns some type that implements the
-`Iterator` trait without needing to write out a very long type.
+Why is this useful? In chapter 13, we’re going to learn about two features
+that rely heavily on traits: closures, and iterators. These features create
+types that only the compiler knows, or types that are very, very long.
+`impl Trait` lets you simply say “this returns an `Iterator`” without
+needing to write out a really long type.
-However, you can only use `impl Trait` if you’re returning a single type. For
-example, this code that returns either a `NewsArticle` or a `Tweet` with the
-return type specified as `impl Summary` wouldn’t work:
+This only works if you have a single type that you’re returning, however.
+For example, this would *not* work:
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/src/lib.rs:here}}
+fn returns_summarizable(switch: bool) -> impl Summary {
+ if switch {
+ NewsArticle {
+ headline: String::from("Penguins win the Stanley Cup Championship!"),
+ location: String::from("Pittsburgh, PA, USA"),
+ author: String::from("Iceburgh"),
+ content: String::from("The Pittsburgh Penguins once again are the best
+ hockey team in the NHL."),
+ }
+ } else {
+ Tweet {
+ username: String::from("horse_ebooks"),
+ content: String::from("of course, as you probably already know, people"),
+ reply: false,
+ retweet: false,
+ }
+ }
+}
```
-Returning either a `NewsArticle` or a `Tweet` isn’t allowed due to restrictions
-around how the `impl Trait` syntax is implemented in the compiler. We’ll cover
-how to write a function with this behavior in the [“Using Trait Objects That
-Allow for Values of Different
+Here, we try to return either a `NewsArticle` or a `Tweet`. This cannot work,
+due to restrictions around how `impl Trait` works. To write this code, you’ll
+have to wait until the [“Using Trait Objects That Allow for Values of Different
Types”][using-trait-objects-that-allow-for-values-of-different-types]<!--
ignore --> section of Chapter 17.
@@ -343,7 +417,13 @@ the `largest` function that uses a generic type parameter! Last time we tried
to run that code, we received this error:
```text
-{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt}}
+error[E0369]: binary operation `>` cannot be applied to type `T`
+ --> src/main.rs:5:12
+ |
+5 | if item > largest {
+ | ^^^^^^^^^^^^^^
+ |
+ = note: an implementation of `std::cmp::PartialOrd` might be missing for `T`
```
In the body of `largest` we wanted to compare two values of type `T` using the
@@ -355,25 +435,40 @@ into scope because it’s in the prelude. Change the signature of `largest` to
look like this:
```rust,ignore
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/src/main.rs:here}}
+fn largest<T: PartialOrd>(list: &[T]) -> T {
```
This time when we compile the code, we get a different set of errors:
```text
-{{#include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/output.txt}}
+error[E0508]: cannot move out of type `[T]`, a non-copy slice
+ --> src/main.rs:2:23
+ |
+2 | let mut largest = list[0];
+ | ^^^^^^^
+ | |
+ | cannot move out of here
+ | help: consider using a reference instead: `&list[0]`
+
+error[E0507]: cannot move out of borrowed content
+ --> src/main.rs:4:9
+ |
+4 | for &item in list.iter() {
+ | ^----
+ | ||
+ | |hint: to prevent move, use `ref item` or `ref mut item`
+ | cannot move out of borrowed content
```
The key line in this error is `cannot move out of type [T], a non-copy slice`.
With our non-generic versions of the `largest` function, we were only trying to
-find the largest `i32` or `char`. As discussed in the [“Stack-Only Data:
-Copy”][stack-only-data-copy]<!-- ignore --> section in Chapter 4, types like
-`i32` and `char` that have a known size can be stored on the stack, so they
-implement the `Copy` trait. But when we made the `largest` function generic,
-it became possible for the `list` parameter to have types in it that don’t
-implement the `Copy` trait. Consequently, we wouldn’t be able to move the
-value out of `list[0]` and into the `largest` variable, resulting in this
-error.
+find the largest `i32` or `char`. As discussed in the [“Stack-Only Data: Copy”]
+[stack-only-data-copy]<!-- ignore --> section in Chapter 4, types like `i32`
+and `char` that have a known size can be stored on the stack, so they implement
+the `Copy` trait. But when we made the `largest` function generic, it became
+possible for the `list` parameter to have types in it that don’t implement the
+`Copy` trait. Consequently, we wouldn’t be able to move the value out of
+`list[0]` and into the `largest` variable, resulting in this error.
To call this code with only those types that implement the `Copy` trait, we can
add `Copy` to the trait bounds of `T`! Listing 10-15 shows the complete code of
@@ -384,7 +479,29 @@ values in the slice that we pass into the function implement the `PartialOrd`
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/main.rs}}
+fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
+ let mut largest = list[0];
+
+ for &item in list.iter() {
+ if item > largest {
+ largest = item;
+ }
+ }
+
+ largest
+}
+
+fn main() {
+ let number_list = vec![34, 50, 25, 100, 65];
+
+ let result = largest(&number_list);
+ println!("The largest number is {}", result);
+
+ let char_list = vec!['y', 'm', 'a', 'q'];
+
+ let result = largest(&char_list);
+ println!("The largest char is {}", result);
+}
```
<span class="caption">Listing 10-15: A working definition of the `largest`
@@ -414,10 +531,32 @@ traits. For example, the type `Pair<T>` in Listing 10-16 always implements the
inner type `T` implements the `PartialOrd` trait that enables comparison *and*
the `Display` trait that enables printing.
-<span class="filename">Filename: src/lib.rs</span>
-
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/lib.rs}}
+use std::fmt::Display;
+
+struct Pair<T> {
+ x: T,
+ y: T,
+}
+
+impl<T> Pair<T> {
+ fn new(x: T, y: T) -> Self {
+ Self {
+ x,
+ y,
+ }
+ }
+}
+
+impl<T: Display + PartialOrd> Pair<T> {
+ fn cmp_display(&self) {
+ if self.x >= self.y {
+ println!("The largest member is x = {}", self.x);
+ } else {
+ println!("The largest member is y = {}", self.y);
+ }
+ }
+}
```
<span class="caption">Listing 10-16: Conditionally implement methods on a
@@ -453,12 +592,12 @@ reduce duplication but also specify to the compiler that we want the generic
type to have particular behavior. The compiler can then use the trait bound
information to check that all the concrete types used with our code provide the
correct behavior. In dynamically typed languages, we would get an error at
-runtime if we called a method on a type which didn’t implement the type which
-defines the method. But Rust moves these errors to compile time so we’re forced
-to fix the problems before our code is even able to run. Additionally, we don’t
-have to write code that checks for behavior at runtime because we’ve already
-checked at compile time. Doing so improves performance without having to give
-up the flexibility of generics.
+runtime if we called a method on a type that the type didn’t implement. But
+Rust moves these errors to compile time so we’re forced to fix the problems
+before our code is even able to run. Additionally, we don’t have to write code
+that checks for behavior at runtime because we’ve already checked at compile
+time. Doing so improves performance without having to give up the flexibility
+of generics.
Another kind of generic that we’ve already been using is called *lifetimes*.
Rather than ensuring that a type has the behavior we want, lifetimes ensure
diff --git a/book-original/src/ch10-03-lifetime-syntax.md b/book-pl-en/src/ch10-03-lifetime-syntax.md
index c007039..02e79ec 100644
--- a/book-original/src/ch10-03-lifetime-syntax.md
+++ b/book-pl-en/src/ch10-03-lifetime-syntax.md
@@ -1,21 +1,21 @@
## Validating References with Lifetimes
-One detail we didn’t discuss in the [“References and
-Borrowing”][references-and-borrowing]<!-- ignore --> section in Chapter 4 is
-that every reference in Rust has a *lifetime*, which is the scope for which
-that reference is valid. Most of the time, lifetimes are implicit and
-inferred, just like most of the time, types are inferred. We must annotate
-types when multiple types are possible. In a similar way, we must annotate
-lifetimes when the lifetimes of references could be related in a few different
-ways. Rust requires us to annotate the relationships using generic lifetime
-parameters to ensure the actual references used at runtime will definitely be
-valid.
+One detail we didn’t discuss in the [“References and Borrowing”]
+[references-and-borrowing]<!-- ignore --> section in Chapter 4 is that every
+reference in Rust has a *lifetime*, which is the scope for which that reference
+is valid. Most of the time, lifetimes are implicit and inferred, just like most
+of the time, types are inferred. We must annotate types when multiple types are
+possible. In a similar way, we must annotate lifetimes when the lifetimes of
+references could be related in a few different ways. Rust requires us to
+annotate the relationships using generic lifetime parameters to ensure the
+actual references used at runtime will definitely be valid.
The concept of lifetimes is somewhat different from tools in other programming
languages, arguably making lifetimes Rust’s most distinctive feature. Although
we won’t cover lifetimes in their entirety in this chapter, we’ll discuss
common ways you might encounter lifetime syntax so you can become familiar with
-the concepts.
+the concepts. See the [“Advanced Lifetimes”][advanced-lifetimes]<!-- ignore -->
+section in Chapter 19 for more detailed information.
### Preventing Dangling References with Lifetimes
@@ -25,7 +25,16 @@ Consider the program in Listing 10-17, which has an outer scope and an inner
scope.
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/src/main.rs:here}}
+{
+ let r;
+
+ {
+ let x = 5;
+ r = &x;
+ }
+
+ println!("r: {}", r);
+}
```
<span class="caption">Listing 10-17: An attempt to use a reference whose value
@@ -46,7 +55,16 @@ compile because the value `r` is referring to has gone out of scope before we
try to use it. Here is the error message:
```text
-{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/output.txt}}
+error[E0597]: `x` does not live long enough
+ --> src/main.rs:7:5
+ |
+6 | r = &x;
+ | - borrow occurs here
+7 | }
+ | ^ `x` dropped here while still borrowed
+...
+10 | }
+ | - borrowed value needs to live until here
```
The variable `x` doesn’t “live long enough.” The reason is that `x` will be out
@@ -64,7 +82,16 @@ whether all borrows are valid. Listing 10-18 shows the same code as Listing
10-17 but with annotations showing the lifetimes of the variables.
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/src/main.rs:here}}
+{
+ let r; // ---------+-- 'a
+ // |
+ { // |
+ let x = 5; // -+-- 'b |
+ r = &x; // | |
+ } // -+ |
+ // |
+ println!("r: {}", r); // |
+} // ---------+
```
<span class="caption">Listing 10-18: Annotations of the lifetimes of `r` and
@@ -81,7 +108,14 @@ Listing 10-19 fixes the code so it doesn’t have a dangling reference and
compiles without any errors.
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/src/main.rs:here}}
+{
+ let x = 5; // ----------+-- 'b
+ // |
+ let r = &x; // --+-- 'a |
+ // | |
+ println!("r: {}", r); // | |
+ // --+ |
+} // ----------+
```
<span class="caption">Listing 10-19: A valid reference because the data has a
@@ -105,7 +139,13 @@ longest string is abcd`.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/src/main.rs}}
+fn main() {
+ let string1 = String::from("abcd");
+ let string2 = "xyz";
+
+ let result = longest(string1.as_str(), string2);
+ println!("The longest string is {}", result);
+}
```
<span class="caption">Listing 10-20: A `main` function that calls the `longest`
@@ -127,7 +167,13 @@ won’t compile.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/src/main.rs:here}}
+fn longest(x: &str, y: &str) -> &str {
+ if x.len() > y.len() {
+ x
+ } else {
+ y
+ }
+}
```
<span class="caption">Listing 10-21: An implementation of the `longest`
@@ -137,7 +183,14 @@ compile</span>
Instead, we get the following error that talks about lifetimes:
```text
-{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/output.txt}}
+error[E0106]: missing lifetime specifier
+ --> src/main.rs:1:33
+ |
+1 | fn longest(x: &str, y: &str) -> &str {
+ | ^ expected lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but the
+signature does not say whether it is borrowed from `x` or `y`
```
The help text reveals that the return type needs a generic lifetime parameter
@@ -204,7 +257,13 @@ Listing 10-22.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/src/main.rs:here}}
+fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
+ if x.len() > y.len() {
+ x
+ } else {
+ y
+ }
+}
```
<span class="caption">Listing 10-22: The `longest` function definition
@@ -218,15 +277,13 @@ The function signature now tells Rust that for some lifetime `'a`, the function
takes two parameters, both of which are string slices that live at least as
long as lifetime `'a`. The function signature also tells Rust that the string
slice returned from the function will live at least as long as lifetime `'a`.
-In practice, it means that the lifetime of the reference returned by the
-`longest` function is the same as the smaller of the lifetimes of the
-references passed in. These constraints are what we want Rust to enforce.
-Remember, when we specify the lifetime parameters in this function signature,
-we’re not changing the lifetimes of any values passed in or returned. Rather,
-we’re specifying that the borrow checker should reject any values that don’t
-adhere to these constraints. Note that the `longest` function doesn’t need to
-know exactly how long `x` and `y` will live, only that some scope can be
-substituted for `'a` that will satisfy this signature.
+These constraints are what we want Rust to enforce. Remember, when we specify
+the lifetime parameters in this function signature, we’re not changing the
+lifetimes of any values passed in or returned. Rather, we’re specifying that
+the borrow checker should reject any values that don’t adhere to these
+constraints. Note that the `longest` function doesn’t need to know exactly how
+long `x` and `y` will live, only that some scope can be substituted for `'a`
+that will satisfy this signature.
When annotating lifetimes in functions, the annotations go in the function
signature, not in the function body. Rust can analyze the code within the
@@ -251,7 +308,23 @@ a straightforward example.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/src/main.rs:here}}
+# fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
+# if x.len() > y.len() {
+# x
+# } else {
+# y
+# }
+# }
+#
+fn main() {
+ let string1 = String::from("long string is long");
+
+ {
+ let string2 = String::from("xyz");
+ let result = longest(string1.as_str(), string2.as_str());
+ println!("The longest string is {}", result);
+ }
+}
```
<span class="caption">Listing 10-23: Using the `longest` function with
@@ -274,7 +347,15 @@ compile.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/src/main.rs:here}}
+fn main() {
+ let string1 = String::from("long string is long");
+ let result;
+ {
+ let string2 = String::from("xyz");
+ result = longest(string1.as_str(), string2.as_str());
+ }
+ println!("The longest string is {}", result);
+}
```
<span class="caption">Listing 10-24: Attempting to use `result` after `string2`
@@ -283,7 +364,16 @@ has gone out of scope</span>
When we try to compile this code, we’ll get this error:
```text
-{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt}}
+error[E0597]: `string2` does not live long enough
+ --> src/main.rs:15:5
+ |
+14 | result = longest(string1.as_str(), string2.as_str());
+ | ------- borrow occurs here
+15 | }
+ | ^ `string2` dropped here while still borrowed
+16 | println!("The longest string is {}", result);
+17 | }
+ | - borrowed value needs to live until here
```
The error shows that for `result` to be valid for the `println!` statement,
@@ -316,7 +406,9 @@ following code will compile:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-08-only-one-reference-with-lifetime/src/main.rs:here}}
+fn longest<'a>(x: &'a str, y: &str) -> &'a str {
+ x
+}
```
In this example, we’ve specified a lifetime parameter `'a` for the parameter
@@ -333,7 +425,10 @@ this attempted implementation of the `longest` function that won’t compile:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/src/main.rs:here}}
+fn longest<'a>(x: &str, y: &str) -> &'a str {
+ let result = String::from("really long string");
+ result.as_str()
+}
```
Here, even though we’ve specified a lifetime parameter `'a` for the return
@@ -342,7 +437,23 @@ lifetime is not related to the lifetime of the parameters at all. Here is the
error message we get:
```text
-{{#include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt}}
+error[E0597]: `result` does not live long enough
+ --> src/main.rs:3:5
+ |
+3 | result.as_str()
+ | ^^^^^^ does not live long enough
+4 | }
+ | - borrowed value only lives until here
+ |
+note: borrowed value must be valid for the lifetime 'a as defined on the
+function body at 1:1...
+ --> src/main.rs:1:1
+ |
+1 | / fn longest<'a>(x: &str, y: &str) -> &'a str {
+2 | | let result = String::from("really long string");
+3 | | result.as_str()
+4 | | }
+ | |_^
```
The problem is that `result` goes out of scope and gets cleaned up at the end
@@ -368,7 +479,17 @@ struct named `ImportantExcerpt` that holds a string slice.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/src/main.rs}}
+struct ImportantExcerpt<'a> {
+ part: &'a str,
+}
+
+fn main() {
+ let novel = String::from("Call me Ishmael. Some years ago...");
+ let first_sentence = novel.split('.')
+ .next()
+ .expect("Could not find a '.'");
+ let i = ImportantExcerpt { part: first_sentence };
+}
```
<span class="caption">Listing 10-25: A struct that holds a reference, so its
@@ -398,7 +519,17 @@ Chapter 4 we had a function in Listing 4-9, which is shown again in Listing
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/src/main.rs:here}}
+fn first_word(s: &str) -> &str {
+ let bytes = s.as_bytes();
+
+ for (i, &item) in bytes.iter().enumerate() {
+ if item == b' ' {
+ return &s[0..i];
+ }
+ }
+
+ &s[..]
+}
```
<span class="caption">Listing 10-26: A function we defined in Listing 4-9 that
@@ -444,8 +575,9 @@ The compiler uses three rules to figure out what lifetimes references have when
there aren’t explicit annotations. The first rule applies to input lifetimes,
and the second and third rules apply to output lifetimes. If the compiler gets
to the end of the three rules and there are still references for which it can’t
-figure out lifetimes, the compiler will stop with an error. These rules apply
-to `fn` definitions as well as `impl` blocks.
+figure out lifetimes, the compiler will stop with an error.
+
+These rules apply to `fn` definitions, as well as `impl` blocks.
The first rule is that each parameter that is a reference gets its own lifetime
parameter. In other words, a function with one parameter gets one lifetime
@@ -538,17 +670,34 @@ First, we’ll use a method named `level` whose only parameter is a reference to
`self` and whose return value is an `i32`, which is not a reference to anything:
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-10-lifetimes-on-methods/src/main.rs:1st}}
+# struct ImportantExcerpt<'a> {
+# part: &'a str,
+# }
+#
+impl<'a> ImportantExcerpt<'a> {
+ fn level(&self) -> i32 {
+ 3
+ }
+}
```
-The lifetime parameter declaration after `impl` and its use after the type name
-are required, but we’re not required to annotate the lifetime of the reference
-to `self` because of the first elision rule.
+The lifetime parameter declaration after `impl` and use after the type name is
+required, but we’re not required to annotate the lifetime of the reference to
+`self` because of the first elision rule.
Here is an example where the third lifetime elision rule applies:
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-10-lifetimes-on-methods/src/main.rs:3rd}}
+# struct ImportantExcerpt<'a> {
+# part: &'a str,
+# }
+#
+impl<'a> ImportantExcerpt<'a> {
+ fn announce_and_return_part(&self, announcement: &str) -> &str {
+ println!("Attention please: {}", announcement);
+ self.part
+ }
+}
```
There are two input lifetimes, so Rust applies the first lifetime elision rule
@@ -558,15 +707,15 @@ and all lifetimes have been accounted for.
### The Static Lifetime
-One special lifetime we need to discuss is `'static`, which means that this
-reference *can* live for the entire duration of the program. All string
-literals have the `'static` lifetime, which we can annotate as follows:
+One special lifetime we need to discuss is `'static`, which denotes the entire
+duration of the program. All string literals have the `'static` lifetime, which
+we can annotate as follows:
```rust
let s: &'static str = "I have a static lifetime.";
```
-The text of this string is stored directly in the program’s binary, which
+The text of this string is stored directly in the binary of your program, which
is always available. Therefore, the lifetime of all string literals is
`'static`.
@@ -584,7 +733,18 @@ Let’s briefly look at the syntax of specifying generic type parameters, trait
bounds, and lifetimes all in one function!
```rust
-{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-11-generics-traits-and-lifetimes/src/main.rs:here}}
+use std::fmt::Display;
+
+fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str
+ where T: Display
+{
+ println!("Announcement! {}", ann);
+ if x.len() > y.len() {
+ x
+ } else {
+ y
+ }
+}
```
This is the `longest` function from Listing 10-22 that returns the longer of
@@ -613,6 +773,8 @@ traits. Chapter 19 covers more complex scenarios involving lifetime annotations
as well as some advanced type system features. But next, you’ll learn how to
write tests in Rust so you can make sure your code is working the way it should.
+[advanced-lifetimes]:
+ch19-02-advanced-lifetimes.html#advanced-lifetimes
[references-and-borrowing]:
ch04-02-references-and-borrowing.html#references-and-borrowing
[string-slices-as-parameters]:
diff --git a/book-original/src/ch11-01-writing-tests.md b/book-pl-en/src/ch11-01-writing-tests.md
index a2f62ce..69d7cdf 100644
--- a/book-original/src/ch11-01-writing-tests.md
+++ b/book-pl-en/src/ch11-01-writing-tests.md
@@ -42,12 +42,19 @@ $ cd adder
```
The contents of the *src/lib.rs* file in your `adder` library should look like
-Listing 11-1.
+Listing 11-1:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/listing-11-01/src/lib.rs:here}}
+# fn main() {}
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn it_works() {
+ assert_eq!(2 + 2, 4);
+ }
+}
```
<span class="caption">Listing 11-1: The test module and function generated
@@ -65,10 +72,24 @@ This assertion serves as an example of the format for a typical test. Let’s ru
it to see that this test passes.
The `cargo test` command runs all tests in our project, as shown in Listing
-11-2.
+11-2:
```text
-{{#include ../listings/ch11-writing-automated-tests/listing-11-01/output.txt}}
+$ cargo test
+ Compiling adder v0.1.0 (file:///projects/adder)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.22 secs
+ Running target/debug/deps/adder-ce99bcc2479f4607
+
+running 1 test
+test tests::it_works ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
+ Doc-tests adder
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
<span class="caption">Listing 11-2: The output from running the automatically
@@ -84,8 +105,8 @@ reads `1 passed; 0 failed` totals the number of tests that passed or failed.
Because we don’t have any tests we’ve marked as ignored, the summary shows `0
ignored`. We also haven’t filtered the tests being run, so the end of the
summary shows `0 filtered out`. We’ll talk about ignoring and filtering out
-tests in the next section, [“Controlling How Tests Are
-Run.”][controlling-how-tests-are-run]<!-- ignore -->
+tests in the next section, [“Controlling How Tests Are Run.”]
+[controlling-how-tests-are-run]<!-- ignore -->
The `0 measured` statistic is for benchmark tests that measure performance.
Benchmark tests are, as of this writing, only available in nightly Rust. See
@@ -97,8 +118,8 @@ The next part of the test output, which starts with `Doc-tests adder`, is for
the results of any documentation tests. We don’t have any documentation tests
yet, but Rust can compile any code examples that appear in our API
documentation. This feature helps us keep our docs and our code in sync! We’ll
-discuss how to write documentation tests in the [“Documentation Comments as
-Tests”][doc-comments]<!-- ignore --> section of Chapter 14. For now, we’ll
+discuss how to write documentation tests in the [“Making Useful Documentation
+Comments”][doc-comments]<!-- ignore --> section of Chapter 14. For now, we’ll
ignore the `Doc-tests` output.
Let’s change the name of our test to see how that changes the test output.
@@ -108,14 +129,24 @@ so:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-01-changing-test-name/src/lib.rs:here}}
+# fn main() {}
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn exploration() {
+ assert_eq!(2 + 2, 4);
+ }
+}
```
Then run `cargo test` again. The output now shows `exploration` instead of
`it_works`:
```text
-{{#include ../listings/ch11-writing-automated-tests/no-listing-01-changing-test-name/output.txt}}
+running 1 test
+test tests::exploration ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
Let’s add another test, but this time we’ll make a test that fails! Tests fail
@@ -123,22 +154,49 @@ when something in the test function panics. Each test is run in a new thread,
and when the main thread sees that a test thread has died, the test is marked
as failed. We talked about the simplest way to cause a panic in Chapter 9,
which is to call the `panic!` macro. Enter the new test, `another`, so your
-*src/lib.rs* file looks like Listing 11-3.
+*src/lib.rs* file looks like Listing 11-3:
<span class="filename">Filename: src/lib.rs</span>
```rust,panics
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/listing-11-03/src/lib.rs:here}}
+# fn main() {}
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn exploration() {
+ assert_eq!(2 + 2, 4);
+ }
+
+ #[test]
+ fn another() {
+ panic!("Make this test fail");
+ }
+}
```
<span class="caption">Listing 11-3: Adding a second test that will fail because
we call the `panic!` macro</span>
Run the tests again using `cargo test`. The output should look like Listing
-11-4, which shows that our `exploration` test passed and `another` failed.
+11-4, which shows that our `exploration` test passed and `another` failed:
```text
-{{#include ../listings/ch11-writing-automated-tests/listing-11-03/output.txt}}
+running 2 tests
+test tests::exploration ... ok
+test tests::another ... FAILED
+
+failures:
+
+---- tests::another stdout ----
+ thread 'tests::another' panicked at 'Make this test fail', src/lib.rs:10:8
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
+
+failures:
+ tests::another
+
+test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
+
+error: test failed
```
<span class="caption">Listing 11-4: Test results when one test passes and one
@@ -178,7 +236,18 @@ method, which are repeated here in Listing 11-5. Let’s put this code in the
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/listing-11-05/src/lib.rs:here}}
+# fn main() {}
+#[derive(Debug)]
+pub struct Rectangle {
+ length: u32,
+ width: u32,
+}
+
+impl Rectangle {
+ pub fn can_hold(&self, other: &Rectangle) -> bool {
+ self.length > other.length && self.width > other.width
+ }
+}
```
<span class="caption">Listing 11-5: Using the `Rectangle` struct and its
@@ -186,14 +255,26 @@ method, which are repeated here in Listing 11-5. Let’s put this code in the
The `can_hold` method returns a Boolean, which means it’s a perfect use case
for the `assert!` macro. In Listing 11-6, we write a test that exercises the
-`can_hold` method by creating a `Rectangle` instance that has a width of 8 and
-a height of 7 and asserting that it can hold another `Rectangle` instance that
-has a width of 5 and a height of 1.
+`can_hold` method by creating a `Rectangle` instance that has a length of 8 and
+a width of 7 and asserting that it can hold another `Rectangle` instance that
+has a length of 5 and a width of 1:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/listing-11-06/src/lib.rs:here}}
+# fn main() {}
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn larger_can_hold_smaller() {
+ let larger = Rectangle { length: 8, width: 7 };
+ let smaller = Rectangle { length: 5, width: 1 };
+
+ assert!(larger.can_hold(&smaller));
+ }
+}
```
<span class="caption">Listing 11-6: A test for `can_hold` that checks whether a
@@ -201,12 +282,11 @@ larger rectangle can indeed hold a smaller rectangle</span>
Note that we’ve added a new line inside the `tests` module: `use super::*;`.
The `tests` module is a regular module that follows the usual visibility rules
-we covered in Chapter 7 in the [“Paths for Referring to an Item in the Module
-Tree”][paths-for-referring-to-an-item-in-the-module-tree]<!-- ignore -->
-section. Because the `tests` module is an inner module, we need to bring the
-code under test in the outer module into the scope of the inner module. We use
-a glob here so anything we define in the outer module is available to this
-`tests` module.
+we covered in Chapter 7 in the [“Modules as the Privacy
+Boundary”][modules-as-privacy-boundary]<!-- ignore --> section. Because the
+`tests` module is an inner module, we need to bring the code under test in the
+outer module into the scope of the inner module. We use a glob here so anything
+we define in the outer module is available to this `tests` module.
We’ve named our test `larger_can_hold_smaller`, and we’ve created the two
`Rectangle` instances that we need. Then we called the `assert!` macro and
@@ -214,7 +294,10 @@ passed it the result of calling `larger.can_hold(&smaller)`. This expression
is supposed to return `true`, so our test should pass. Let’s find out!
```text
-{{#include ../listings/ch11-writing-automated-tests/listing-11-06/output.txt}}
+running 1 test
+test tests::larger_can_hold_smaller ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
It does pass! Let’s add another test, this time asserting that a smaller
@@ -223,7 +306,24 @@ rectangle cannot hold a larger rectangle:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-02-adding-another-rectangle-test/src/lib.rs:here}}
+# fn main() {}
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn larger_can_hold_smaller() {
+ // --snip--
+ }
+
+ #[test]
+ fn smaller_cannot_hold_larger() {
+ let larger = Rectangle { length: 8, width: 7 };
+ let smaller = Rectangle { length: 5, width: 1 };
+
+ assert!(!smaller.can_hold(&larger));
+ }
+}
```
Because the correct result of the `can_hold` function in this case is `false`,
@@ -231,26 +331,56 @@ we need to negate that result before we pass it to the `assert!` macro. As a
result, our test will pass if `can_hold` returns `false`:
```text
-{{#include ../listings/ch11-writing-automated-tests/no-listing-02-adding-another-rectangle-test/output.txt}}
+running 2 tests
+test tests::smaller_cannot_hold_larger ... ok
+test tests::larger_can_hold_smaller ... ok
+
+test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
Two tests that pass! Now let’s see what happens to our test results when we
introduce a bug in our code. Let’s change the implementation of the `can_hold`
-method by replacing the greater than sign with a less than sign when it
-compares the widths:
+method by replacing the greater-than sign with a less-than sign when it
+compares the lengths:
```rust,not_desired_behavior
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/src/lib.rs:here}}
+# fn main() {}
+# #[derive(Debug)]
+# pub struct Rectangle {
+# length: u32,
+# width: u32,
+# }
+// --snip--
+
+impl Rectangle {
+ pub fn can_hold(&self, other: &Rectangle) -> bool {
+ self.length < other.length && self.width > other.width
+ }
+}
```
Running the tests now produces the following:
```text
-{{#include ../listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt}}
+running 2 tests
+test tests::smaller_cannot_hold_larger ... ok
+test tests::larger_can_hold_smaller ... FAILED
+
+failures:
+
+---- tests::larger_can_hold_smaller stdout ----
+ thread 'tests::larger_can_hold_smaller' panicked at 'assertion failed:
+ larger.can_hold(&smaller)', src/lib.rs:22:8
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
+
+failures:
+ tests::larger_can_hold_smaller
+
+test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
```
-Our tests caught the bug! Because `larger.width` is 8 and `smaller.width` is
-5, the comparison of the widths in `can_hold` now returns `false`: 8 is not
+Our tests caught the bug! Because `larger.length` is 8 and `smaller.length` is
+5, the comparison of the lengths in `can_hold` now returns `false`: 8 is not
less than 5.
### Testing Equality with the `assert_eq!` and `assert_ne!` Macros
@@ -273,7 +403,20 @@ parameter and returns the result. Then we test this function using the
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/listing-11-07/src/lib.rs:here}}
+# fn main() {}
+pub fn add_two(a: i32) -> i32 {
+ a + 2
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_adds_two() {
+ assert_eq!(4, add_two(2));
+ }
+}
```
<span class="caption">Listing 11-7: Testing the function `add_two` using the
@@ -282,7 +425,10 @@ parameter and returns the result. Then we test this function using the
Let’s check that it passes!
```text
-{{#include ../listings/ch11-writing-automated-tests/listing-11-07/output.txt}}
+running 1 test
+test tests::it_adds_two ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
The first argument we gave to the `assert_eq!` macro, `4`, is equal to the
@@ -294,13 +440,30 @@ uses `assert_eq!` fails. Change the implementation of the `add_two` function to
instead add `3`:
```rust,not_desired_behavior
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/src/lib.rs:here}}
+# fn main() {}
+pub fn add_two(a: i32) -> i32 {
+ a + 3
+}
```
Run the tests again:
```text
-{{#include ../listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt}}
+running 1 test
+test tests::it_adds_two ... FAILED
+
+failures:
+
+---- tests::it_adds_two stdout ----
+ thread 'tests::it_adds_two' panicked at 'assertion failed: `(left == right)`
+ left: `4`,
+ right: `5`', src/lib.rs:11:8
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
+
+failures:
+ tests::it_adds_two
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
```
Our test caught the bug! The `it_adds_two` test failed, displaying the message
@@ -346,12 +509,12 @@ optional arguments to the `assert!`, `assert_eq!`, and `assert_ne!` macros. Any
arguments specified after the one required argument to `assert!` or the two
required arguments to `assert_eq!` and `assert_ne!` are passed along to the
`format!` macro (discussed in Chapter 8 in the [“Concatenation with the `+`
-Operator or the `format!`
-Macro”][concatenation-with-the--operator-or-the-format-macro]<!-- ignore -->
-section), so you can pass a format string that contains `{}` placeholders and
-values to go in those placeholders. Custom messages are useful to document
-what an assertion means; when a test fails, you’ll have a better idea of what
-the problem is with the code.
+Operator or the `format!` Macro”]
+[concatenation-with-the--operator-or-the-format-macro]<!-- ignore --> section),
+so you can pass a format string that contains `{}` placeholders and values to
+go in those placeholders. Custom messages are useful to document what an
+assertion means; when a test fails, you’ll have a better idea of what the
+problem is with the code.
For example, let’s say we have a function that greets people by name and we
want to test that the name we pass into the function appears in the output:
@@ -359,7 +522,21 @@ want to test that the name we pass into the function appears in the output:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-05-greeter/src/lib.rs:here}}
+# fn main() {}
+pub fn greeting(name: &str) -> String {
+ format!("Hello {}!", name)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn greeting_contains_name() {
+ let result = greeting("Carol");
+ assert!(result.contains("Carol"));
+ }
+}
```
The requirements for this program haven’t been agreed upon yet, and we’re
@@ -373,13 +550,27 @@ Let’s introduce a bug into this code by changing `greeting` to not include
`name` to see what this test failure looks like:
```rust,not_desired_behavior
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/src/lib.rs:here}}
+# fn main() {}
+pub fn greeting(name: &str) -> String {
+ String::from("Hello!")
+}
```
Running this test produces the following:
```text
-{{#include ../listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt}}
+running 1 test
+test tests::greeting_contains_name ... FAILED
+
+failures:
+
+---- tests::greeting_contains_name stdout ----
+ thread 'tests::greeting_contains_name' panicked at 'assertion failed:
+result.contains("Carol")', src/lib.rs:12:8
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
+
+failures:
+ tests::greeting_contains_name
```
This result just indicates that the assertion failed and which line the
@@ -389,13 +580,23 @@ giving it a custom failure message made from a format string with a placeholder
filled in with the actual value we got from the `greeting` function:
```rust,ignore
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/src/lib.rs:here}}
+#[test]
+fn greeting_contains_name() {
+ let result = greeting("Carol");
+ assert!(
+ result.contains("Carol"),
+ "Greeting did not contain name, value was `{}`", result
+ );
+}
```
Now when we run the test, we’ll get a more informative error message:
```text
-{{#include ../listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt}}
+---- tests::greeting_contains_name stdout ----
+ thread 'tests::greeting_contains_name' panicked at 'Greeting did not
+contain name, value was `Hello!`', src/lib.rs:12:8
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
We can see the value we actually got in the test output, which would help us
@@ -416,12 +617,38 @@ This attribute makes a test pass if the code inside the function panics; the
test will fail if the code inside the function doesn’t panic.
Listing 11-8 shows a test that checks that the error conditions of `Guess::new`
-happen when we expect them to.
+happen when we expect them to:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/listing-11-08/src/lib.rs:here}}
+# fn main() {}
+pub struct Guess {
+ value: i32,
+}
+
+impl Guess {
+ pub fn new(value: i32) -> Guess {
+ if value < 1 || value > 100 {
+ panic!("Guess value must be between 1 and 100, got {}.", value);
+ }
+
+ Guess {
+ value
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ #[should_panic]
+ fn greater_than_100() {
+ Guess::new(200);
+ }
+}
```
<span class="caption">Listing 11-8: Testing that a condition will cause a
@@ -432,20 +659,48 @@ before the test function it applies to. Let’s look at the result when this tes
passes:
```text
-{{#include ../listings/ch11-writing-automated-tests/listing-11-08/output.txt}}
+running 1 test
+test tests::greater_than_100 ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
Looks good! Now let’s introduce a bug in our code by removing the condition
that the `new` function will panic if the value is greater than 100:
```rust,not_desired_behavior
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-08-guess-with-bug/src/lib.rs:here}}
+# fn main() {}
+# pub struct Guess {
+# value: i32,
+# }
+#
+// --snip--
+
+impl Guess {
+ pub fn new(value: i32) -> Guess {
+ if value < 1 {
+ panic!("Guess value must be between 1 and 100, got {}.", value);
+ }
+
+ Guess {
+ value
+ }
+ }
+}
```
When we run the test in Listing 11-8, it will fail:
```text
-{{#include ../listings/ch11-writing-automated-tests/no-listing-08-guess-with-bug/output.txt}}
+running 1 test
+test tests::greater_than_100 ... FAILED
+
+failures:
+
+failures:
+ tests::greater_than_100
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
```
We don’t get a very helpful message in this case, but when we look at the test
@@ -454,17 +709,49 @@ means that the code in the test function did not cause a panic.
Tests that use `should_panic` can be imprecise because they only indicate that
the code has caused some panic. A `should_panic` test would pass even if the
-test panics for a different reason from the one we were expecting to happen. To
+test panics for a different reason than the one we were expecting to happen. To
make `should_panic` tests more precise, we can add an optional `expected`
parameter to the `should_panic` attribute. The test harness will make sure that
the failure message contains the provided text. For example, consider the
modified code for `Guess` in Listing 11-9 where the `new` function panics with
-different messages depending on whether the value is too small or too large.
+different messages depending on whether the value is too small or too large:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/listing-11-09/src/lib.rs:here}}
+# fn main() {}
+# pub struct Guess {
+# value: i32,
+# }
+#
+// --snip--
+
+impl Guess {
+ pub fn new(value: i32) -> Guess {
+ if value < 1 {
+ panic!("Guess value must be greater than or equal to 1, got {}.",
+ value);
+ } else if value > 100 {
+ panic!("Guess value must be less than or equal to 100, got {}.",
+ value);
+ }
+
+ Guess {
+ value
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ #[should_panic(expected = "Guess value must be less than or equal to 100")]
+ fn greater_than_100() {
+ Guess::new(200);
+ }
+}
```
<span class="caption">Listing 11-9: Testing that a condition will cause a
@@ -485,13 +772,32 @@ fails, let’s again introduce a bug into our code by swapping the bodies of the
`if value < 1` and the `else if value > 100` blocks:
```rust,ignore,not_desired_behavior
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/src/lib.rs:here}}
+if value < 1 {
+ panic!("Guess value must be less than or equal to 100, got {}.", value);
+} else if value > 100 {
+ panic!("Guess value must be greater than or equal to 1, got {}.", value);
+}
```
This time when we run the `should_panic` test, it will fail:
```text
-{{#include ../listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt}}
+running 1 test
+test tests::greater_than_100 ... FAILED
+
+failures:
+
+---- tests::greater_than_100 stdout ----
+ thread 'tests::greater_than_100' panicked at 'Guess value must be
+greater than or equal to 1, got 200.', src/lib.rs:11:12
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
+note: Panic did not include expected string 'Guess value must be less than or
+equal to 100'
+
+failures:
+ tests::greater_than_100
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
```
The failure message indicates that this test did indeed panic as we expected,
@@ -500,28 +806,31 @@ less than or equal to 100'`. The panic message that we did get in this case was
`Guess value must be greater than or equal to 1, got 200.` Now we can start
figuring out where our bug is!
-### Using `Result<T, E>` in Tests
+### Using `Result<T, E>` in tests
So far, we’ve written tests that panic when they fail. We can also write tests
-that use `Result<T, E>`! Here’s the test from Listing 11-1, rewritten to use
-`Result<T, E>` and return an `Err` instead of panicking:
+that use `Result<T, E>` too! Here’s that first example, but with results instead:
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-10-result-in-tests/src/lib.rs}}
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn it_works() -> Result<(), String> {
+ if 2 + 2 == 4 {
+ Ok(())
+ } else {
+ Err(String::from("two plus two does not equal four"))
+ }
+ }
+}
```
-The `it_works` function now has a return type, `Result<(), String>`. In the
-body of the function, rather than calling the `assert_eq!` macro, we return
-`Ok(())` when the test passes and an `Err` with a `String` inside when the test
-fails.
-
-Writing tests so they return a `Result<T, E>` enables you to use the question
-mark operator in the body of tests, which can be a convenient way to write
-tests that should fail if any operation within them returns an `Err` variant.
-
-You can’t use the `#[should_panic]` annotation on tests that use `Result<T,
-E>`. Instead, you should return an `Err` value directly when the test should
-fail.
+Here, we’ve changed the `it_works` function to return a result. And in the body,
+rather than `assert_eq!`, we return `Ok(())` for the success case, and an `Err`
+with a `String` inside for the failure case. As before, this test will fail or
+succeed, but instead of being based on panics, it will use the `Result<T, E>` to
+make that determination. Because of this, you can’t use `#[should_panic]` with one
+of these functions; you should have it be returning an `Err` instead!
Now that you know several ways to write tests, let’s look at what is happening
when we run our tests and explore the different options we can use with `cargo
@@ -531,6 +840,6 @@ test`.
ch08-02-strings.html#concatenation-with-the--operator-or-the-format-macro
[controlling-how-tests-are-run]:
ch11-02-running-tests.html#controlling-how-tests-are-run
-[derivable-traits]: appendix-03-derivable-traits.html
-[doc-comments]: ch14-02-publishing-to-crates-io.html#documentation-comments-as-tests
-[paths-for-referring-to-an-item-in-the-module-tree]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html
+[derivable-traits]: appendix-03-derivable-traits.html#derivable-traits
+[doc-comments]: ch14-02-publishing-to-crates-io.html#making-useful-documentation-comments
+[modules-as-privacy-boundary]: ch07-02-modules-and-use-to-control-scope-and-privacy.html#modules-as-the-privacy-boundary
diff --git a/book-original/src/ch11-02-running-tests.md b/book-pl-en/src/ch11-02-running-tests.md
index 2a83f57..959fc47 100644
--- a/book-original/src/ch11-02-running-tests.md
+++ b/book-pl-en/src/ch11-02-running-tests.md
@@ -62,7 +62,27 @@ parameter and returns 10, as well as a test that passes and a test that fails.
<span class="filename">Filename: src/lib.rs</span>
```rust,panics
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/listing-11-10/src/lib.rs}}
+fn prints_and_returns_10(a: i32) -> i32 {
+ println!("I got the value {}", a);
+ 10
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn this_test_will_pass() {
+ let value = prints_and_returns_10(4);
+ assert_eq!(10, value);
+ }
+
+ #[test]
+ fn this_test_will_fail() {
+ let value = prints_and_returns_10(8);
+ assert_eq!(5, value);
+ }
+}
```
<span class="caption">Listing 11-10: Tests for a function that calls
@@ -71,7 +91,23 @@ parameter and returns 10, as well as a test that passes and a test that fails.
When we run these tests with `cargo test`, we’ll see the following output:
```text
-{{#include ../listings/ch11-writing-automated-tests/listing-11-10/output.txt}}
+running 2 tests
+test tests::this_test_will_pass ... ok
+test tests::this_test_will_fail ... FAILED
+
+failures:
+
+---- tests::this_test_will_fail stdout ----
+ I got the value 8
+thread 'tests::this_test_will_fail' panicked at 'assertion failed: `(left == right)`
+ left: `5`,
+ right: `10`', src/lib.rs:19:8
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
+
+failures:
+ tests::this_test_will_fail
+
+test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
```
Note that nowhere in this output do we see `I got the value 4`, which is what
@@ -79,20 +115,40 @@ is printed when the test that passes runs. That output has been captured. The
output from the test that failed, `I got the value 8`, appears in the section
of the test summary output, which also shows the cause of the test failure.
-If we want to see printed values for passing tests as well, we can tell Rust
-to also show the output of successful tests at the end with `--show-output`.
+If we want to see printed values for passing tests as well, we can disable the
+output capture behavior by using the `--nocapture` flag:
```text
-$ cargo test -- --show-output
+$ cargo test -- --nocapture
```
-When we run the tests in Listing 11-10 again with the `--show-output` flag, we
+When we run the tests in Listing 11-10 again with the `--nocapture` flag, we
see the following output:
```text
-{{#include ../listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt}}
+running 2 tests
+I got the value 4
+I got the value 8
+test tests::this_test_will_pass ... ok
+thread 'tests::this_test_will_fail' panicked at 'assertion failed: `(left == right)`
+ left: `5`,
+ right: `10`', src/lib.rs:19:8
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
+test tests::this_test_will_fail ... FAILED
+
+failures:
+
+failures:
+ tests::this_test_will_fail
+
+test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
```
+Note that the output for the tests and the test results are interleaved; the
+reason is that the tests are running in parallel, as we talked about in the
+previous section. Try using the `--test-threads=1` option and the `--nocapture`
+flag, and see what the output looks like then!
+
### Running a Subset of Tests by Name
Sometimes, running a full test suite can take a long time. If you’re working on
@@ -101,12 +157,34 @@ that code. You can choose which tests to run by passing `cargo test` the name
or names of the test(s) you want to run as an argument.
To demonstrate how to run a subset of tests, we’ll create three tests for our
-`add_two` function, as shown in Listing 11-11, and choose which ones to run.
+`add_two` function, as shown in Listing 11-11, and choose which ones to run:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/listing-11-11/src/lib.rs}}
+pub fn add_two(a: i32) -> i32 {
+ a + 2
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn add_two_and_two() {
+ assert_eq!(4, add_two(2));
+ }
+
+ #[test]
+ fn add_three_and_two() {
+ assert_eq!(5, add_two(3));
+ }
+
+ #[test]
+ fn one_hundred() {
+ assert_eq!(102, add_two(100));
+ }
+}
```
<span class="caption">Listing 11-11: Three tests with three different
@@ -116,7 +194,12 @@ If we run the tests without passing any arguments, as we saw earlier, all the
tests will run in parallel:
```text
-{{#include ../listings/ch11-writing-automated-tests/listing-11-11/output.txt}}
+running 3 tests
+test tests::add_two_and_two ... ok
+test tests::add_three_and_two ... ok
+test tests::one_hundred ... ok
+
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
#### Running Single Tests
@@ -124,7 +207,14 @@ tests will run in parallel:
We can pass the name of any test function to `cargo test` to run only that test:
```text
-{{#include ../listings/ch11-writing-automated-tests/output-only-02-single-test/output.txt}}
+$ cargo test one_hundred
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
+ Running target/debug/deps/adder-06a75b4a1f2515e9
+
+running 1 test
+test tests::one_hundred ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out
```
Only the test with the name `one_hundred` ran; the other two tests didn’t match
@@ -141,11 +231,19 @@ will be run. For example, because two of our tests’ names contain `add`, we ca
run those two by running `cargo test add`:
```text
-{{#include ../listings/ch11-writing-automated-tests/output-only-03-multiple-tests/output.txt}}
+$ cargo test add
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
+ Running target/debug/deps/adder-06a75b4a1f2515e9
+
+running 2 tests
+test tests::add_two_and_two ... ok
+test tests::add_three_and_two ... ok
+
+test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out
```
This command ran all tests with `add` in the name and filtered out the test
-named `one_hundred`. Also note that the module in which a test appears becomes
+named `one_hundred`. Also note that the module in which tests appear becomes
part of the test’s name, so we can run all the tests in a module by filtering
on the module’s name.
@@ -160,21 +258,46 @@ here:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/src/lib.rs:here}}
+#[test]
+fn it_works() {
+ assert_eq!(2 + 2, 4);
+}
+
+#[test]
+#[ignore]
+fn expensive_test() {
+ // code that takes an hour to run
+}
```
After `#[test]` we add the `#[ignore]` line to the test we want to exclude. Now
when we run our tests, `it_works` runs, but `expensive_test` doesn’t:
```text
-{{#include ../listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/output.txt}}
+$ cargo test
+ Compiling adder v0.1.0 (file:///projects/adder)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.24 secs
+ Running target/debug/deps/adder-ce99bcc2479f4607
+
+running 2 tests
+test expensive_test ... ignored
+test it_works ... ok
+
+test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out
```
The `expensive_test` function is listed as `ignored`. If we want to run only
the ignored tests, we can use `cargo test -- --ignored`:
```text
-{{#include ../listings/ch11-writing-automated-tests/output-only-04-running-ignored/output.txt}}
+$ cargo test -- --ignored
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
+ Running target/debug/deps/adder-ce99bcc2479f4607
+
+running 1 test
+test expensive_test ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out
```
By controlling which tests run, you can make sure your `cargo test` results
diff --git a/book-original/src/ch11-03-test-organization.md b/book-pl-en/src/ch11-03-test-organization.md
index 9ac9497..52b6466 100644
--- a/book-original/src/ch11-03-test-organization.md
+++ b/book-pl-en/src/ch11-03-test-organization.md
@@ -10,7 +10,7 @@ external code would, using only the public interface and potentially exercising
multiple modules per test.
Writing both kinds of tests is important to ensure that the pieces of your
-library are doing what you expect them to, separately and together.
+library are doing what you expect them to separately and together.
### Unit Tests
@@ -38,7 +38,13 @@ this chapter, Cargo generated this code for us:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/listing-11-01/src/lib.rs:here}}
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn it_works() {
+ assert_eq!(2 + 2, 4);
+ }
+}
```
This code is the automatically generated test module. The attribute `cfg`
@@ -56,12 +62,30 @@ There’s debate within the testing community about whether or not private
functions should be tested directly, and other languages make it difficult or
impossible to test private functions. Regardless of which testing ideology you
adhere to, Rust’s privacy rules do allow you to test private functions.
-Consider the code in Listing 11-12 with the private function `internal_adder`.
+Consider the code in Listing 11-12 with the private function `internal_adder`:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/listing-11-12/src/lib.rs:here}}
+# fn main() {}
+
+pub fn add_two(a: i32) -> i32 {
+ internal_adder(a, 2)
+}
+
+fn internal_adder(a: i32, b: i32) -> i32 {
+ a + b
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn internal() {
+ assert_eq!(4, internal_adder(2, 2));
+ }
+}
```
<span class="caption">Listing 11-12: Testing a private function</span>
@@ -91,19 +115,24 @@ will compile each of the files as an individual crate.
Let’s create an integration test. With the code in Listing 11-12 still in the
*src/lib.rs* file, make a *tests* directory, create a new file named
-*tests/integration_test.rs*, and enter the code in Listing 11-13.
+*tests/integration_test.rs*, and enter the code in Listing 11-13:
<span class="filename">Filename: tests/integration_test.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/listing-11-13/tests/integration_test.rs}}
+use adder;
+
+#[test]
+fn it_adds_two() {
+ assert_eq!(4, adder::add_two(2));
+}
```
<span class="caption">Listing 11-13: An integration test of a function in the
`adder` crate</span>
We’ve added `use adder` at the top of the code, which we didn’t need in the
-unit tests. The reason is that each file in the `tests` directory is a separate
+unit tests. The reason is that each test in the `tests` directory is a separate
crate, so we need to bring our library into each test crate’s scope.
We don’t need to annotate any code in *tests/integration_test.rs* with
@@ -111,7 +140,28 @@ We don’t need to annotate any code in *tests/integration_test.rs* with
in this directory only when we run `cargo test`. Run `cargo test` now:
```text
-{{#include ../listings/ch11-writing-automated-tests/listing-11-13/output.txt}}
+$ cargo test
+ Compiling adder v0.1.0 (file:///projects/adder)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.31 secs
+ Running target/debug/deps/adder-abcabcabc
+
+running 1 test
+test tests::internal ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
+ Running target/debug/deps/integration_test-ce99bcc2479f4607
+
+running 1 test
+test it_adds_two ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
+ Doc-tests adder
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
The three sections of output include the unit tests, the integration test, and
@@ -137,7 +187,14 @@ particular integration test file, use the `--test` argument of `cargo test`
followed by the name of the file:
```text
-{{#include ../listings/ch11-writing-automated-tests/output-only-05-single-integration/output.txt}}
+$ cargo test --test integration_test
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
+ Running target/debug/integration_test-952a27e0126bb565
+
+running 1 test
+test it_adds_two ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
This command runs only the tests in the *tests/integration_test.rs* file.
@@ -167,7 +224,9 @@ multiple test files:
<span class="filename">Filename: tests/common.rs</span>
```rust
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-12-shared-test-code-problem/tests/common.rs}}
+pub fn setup() {
+ // setup code specific to your library's tests would go here
+}
```
When we run the tests again, we’ll see a new section in the test output for the
@@ -175,7 +234,29 @@ When we run the tests again, we’ll see a new section in the test output for th
did we call the `setup` function from anywhere:
```text
-{{#include ../listings/ch11-writing-automated-tests/no-listing-12-shared-test-code-problem/output.txt}}
+running 1 test
+test tests::internal ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
+ Running target/debug/deps/common-b8b07b6f1be2db70
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
+ Running target/debug/deps/integration_test-d993c68b431d39df
+
+running 1 test
+test it_adds_two ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
+ Doc-tests adder
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
Having `common` appear in the test results with `running 0 tests` displayed for
@@ -198,11 +279,19 @@ function from the `it_adds_two` test in *tests/integration_test.rs*:
<span class="filename">Filename: tests/integration_test.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-13-fix-shared-test-code-problem/tests/integration_test.rs}}
+use adder;
+
+mod common;
+
+#[test]
+fn it_adds_two() {
+ common::setup();
+ assert_eq!(4, adder::add_two(2));
+}
```
Note that the `mod common;` declaration is the same as the module declaration
-we demonstrated in Listing 7-21. Then in the test function, we can call the
+we demonstrated in Listing 7-25. Then in the test function, we can call the
`common::setup()` function.
#### Integration Tests for Binary Crates
@@ -236,4 +325,4 @@ Let’s combine the knowledge you learned in this chapter and in previous
chapters to work on a project!
[separating-modules-into-files]:
-ch07-05-separating-modules-into-different-files.html
+ch07-02-modules-and-use-to-control-scope-and-privacy.html#separating-modules-into-different-files
diff --git a/book-original/src/ch12-00-an-io-project.md b/book-pl-en/src/ch12-00-an-io-project.md
index 5802d97..549d5da 100644
--- a/book-original/src/ch12-00-an-io-project.md
+++ b/book-pl-en/src/ch12-00-an-io-project.md
@@ -16,9 +16,9 @@ in that file that contain the string argument, and prints those lines.
Along the way, we’ll show how to make our command line tool use features of the
terminal that many command line tools use. We’ll read the value of an
environment variable to allow the user to configure the behavior of our tool.
-We’ll also print error messages to the standard error console stream (`stderr`)
-instead of standard output (`stdout`), so, for example, the user can redirect
-successful output to a file while still seeing error messages onscreen.
+We’ll also print to the standard error console stream (`stderr`) instead of
+standard output (`stdout`), so, for example, the user can redirect successful
+output to a file while still seeing error messages onscreen.
One Rust community member, Andrew Gallant, has already created a fully
featured, very fast version of `grep`, called `ripgrep`. By comparison, our
@@ -28,22 +28,11 @@ the background knowledge you need to understand a real-world project such as
Our `grep` project will combine a number of concepts you’ve learned so far:
-* Organizing code (using what you learned about modules in [Chapter 7][ch7]<!--
- ignore -->)
-* Using vectors and strings (collections, [Chapter 8][ch8]<!-- ignore -->)
-* Handling errors ([Chapter 9][ch9]<!-- ignore -->)
-* Using traits and lifetimes where appropriate ([Chapter 10][ch10]<!-- ignore
- -->)
-* Writing tests ([Chapter 11][ch11]<!-- ignore -->)
+* Organizing code (using what you learned about modules in Chapter 7)
+* Using vectors and strings (collections, Chapter 8)
+* Handling errors (Chapter 9)
+* Using traits and lifetimes where appropriate (Chapter 10)
+* Writing tests (Chapter 11)
We’ll also briefly introduce closures, iterators, and trait objects, which
-Chapters [13][ch13]<!-- ignore --> and [17][ch17]<!-- ignore --> will cover in
-detail.
-
-[ch7]: ch07-00-managing-growing-projects-with-packages-crates-and-modules.html
-[ch8]: ch08-00-common-collections.html
-[ch9]: ch09-00-error-handling.html
-[ch10]: ch10-00-generics.html
-[ch11]: ch11-00-testing.html
-[ch13]: ch13-00-functional-features.html
-[ch17]: ch17-00-oop.html
+Chapters 13 and 17 will cover in detail.
diff --git a/book-original/src/ch12-01-accepting-command-line-arguments.md b/book-pl-en/src/ch12-01-accepting-command-line-arguments.md
index f327361..71c1ae3 100644
--- a/book-original/src/ch12-01-accepting-command-line-arguments.md
+++ b/book-pl-en/src/ch12-01-accepting-command-line-arguments.md
@@ -20,7 +20,7 @@ $ cargo run searchstring example-filename.txt
```
Right now, the program generated by `cargo new` cannot process arguments we
-give it. Some existing libraries on [crates.io](https://crates.io/) can help
+give it. Some existing libraries on [Crates.io](https://crates.io/) can help
with writing a program that accepts command line arguments, but because you’re
just learning this concept, let’s implement this capability ourselves.
@@ -28,20 +28,25 @@ just learning this concept, let’s implement this capability ourselves.
To enable `minigrep` to read the values of command line arguments we pass to
it, we’ll need a function provided in Rust’s standard library, which is
-`std::env::args`. This function returns an iterator of the command line
-arguments that were given to `minigrep`. We’ll cover iterators fully in
-[Chapter 13][ch13]<!-- ignore -->. For now, you only need to know two details
-about iterators: iterators produce a series of values, and we can call the
-`collect` method on an iterator to turn it into a collection, such as a vector,
-containing all the elements the iterator produces.
+`std::env::args`. This function returns an *iterator* of the command line
+arguments that were given to `minigrep`. We haven’t discussed iterators yet
+(we’ll cover them fully in Chapter 13), but for now, you only need to know two
+details about iterators: iterators produce a series of values, and we can call
+the `collect` method on an iterator to turn it into a collection, such as a
+vector, containing all the elements the iterator produces.
Use the code in Listing 12-1 to allow your `minigrep` program to read any
-command line arguments passed to it and then collect the values into a vector.
+command line arguments passed to it and then collect the values into a vector:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-01/src/main.rs}}
+use std::env;
+
+fn main() {
+ let args: Vec<String> = env::args().collect();
+ println!("{:?}", args);
+}
```
<span class="caption">Listing 12-1: Collecting the command line arguments into
@@ -49,13 +54,13 @@ a vector and printing them</span>
First, we bring the `std::env` module into scope with a `use` statement so we
can use its `args` function. Notice that the `std::env::args` function is
-nested in two levels of modules. As we discussed in [Chapter
-7][ch7-idiomatic-use]<!-- ignore -->, in cases where the desired function is
-nested in more than one module, it’s conventional to bring the parent module
-into scope rather than the function. By doing so, we can easily use other
-functions from `std::env`. It’s also less ambiguous than adding `use
-std::env::args` and then calling the function with just `args`, because `args`
-might easily be mistaken for a function that’s defined in the current module.
+nested in two levels of modules. As we discussed in Chapter 7, in cases where
+the desired function is nested in more than one module, it’s conventional to
+bring the parent module into scope rather than the function. By doing so, we
+can easily use other functions from `std::env`. It’s also less ambiguous than
+adding `use std::env::args` and then calling the function with just `args`,
+because `args` might easily be mistaken for a function that’s defined in the
+current module.
> ### The `args` Function and Invalid Unicode
>
@@ -78,11 +83,13 @@ Finally, we print the vector using the debug formatter, `:?`. Let’s try runnin
the code first with no arguments and then with two arguments:
```text
-{{#include ../listings/ch12-an-io-project/listing-12-01/output.txt}}
-```
+$ cargo run
+--snip--
+["target/debug/minigrep"]
-```text
-{{#include ../listings/ch12-an-io-project/output-only-01-with-args/output.txt}}
+$ cargo run needle haystack
+--snip--
+["target/debug/minigrep", "needle", "haystack"]
```
Notice that the first value in the vector is `"target/debug/minigrep"`, which
@@ -98,12 +105,22 @@ chapter, we’ll ignore it and save only the two arguments we need.
Printing the value of the vector of arguments illustrated that the program is
able to access the values specified as command line arguments. Now we need to
save the values of the two arguments in variables so we can use the values
-throughout the rest of the program. We do that in Listing 12-2.
+throughout the rest of the program. We do that in Listing 12-2:
<span class="filename">Filename: src/main.rs</span>
```rust,should_panic
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-02/src/main.rs}}
+use std::env;
+
+fn main() {
+ let args: Vec<String> = env::args().collect();
+
+ let query = &args[1];
+ let filename = &args[2];
+
+ println!("Searching for {}", query);
+ println!("In file {}", filename);
+}
```
<span class="caption">Listing 12-2: Creating variables to hold the query
@@ -121,7 +138,12 @@ working as we intend. Let’s run this program again with the arguments `test`
and `sample.txt`:
```text
-{{#include ../listings/ch12-an-io-project/listing-12-02/output.txt}}
+$ cargo run test sample.txt
+ Compiling minigrep v0.1.0 (file:///projects/minigrep)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
+ Running `target/debug/minigrep test sample.txt`
+Searching for test
+In file sample.txt
```
Great, the program is working! The values of the arguments we need are being
@@ -129,6 +151,3 @@ saved into the right variables. Later we’ll add some error handling to deal
with certain potential erroneous situations, such as when the user provides no
arguments; for now, we’ll ignore that situation and work on adding file-reading
capabilities instead.
-
-[ch13]: ch13-00-functional-features.html
-[ch7-idiomatic-use]: ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#creating-idiomatic-use-paths
diff --git a/book-original/src/ch12-02-reading-a-file.md b/book-pl-en/src/ch12-02-reading-a-file.md
index 0b07e7a..d99d027 100644
--- a/book-original/src/ch12-02-reading-a-file.md
+++ b/book-pl-en/src/ch12-02-reading-a-file.md
@@ -11,19 +11,44 @@ Who are you?”
<span class="filename">Filename: poem.txt</span>
```text
-{{#include ../listings/ch12-an-io-project/listing-12-03/poem.txt}}
+I'm nobody! Who are you?
+Are you nobody, too?
+Then there's a pair of us - don't tell!
+They'd banish us, you know.
+
+How dreary to be somebody!
+How public, like a frog
+To tell your name the livelong day
+To an admiring bog!
```
<span class="caption">Listing 12-3: A poem by Emily Dickinson makes a good test
case</span>
With the text in place, edit *src/main.rs* and add code to read the file, as
-shown in Listing 12-4.
+shown in Listing 12-4:
<span class="filename">Filename: src/main.rs</span>
```rust,should_panic
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-04/src/main.rs:here}}
+use std::env;
+use std::fs;
+
+fn main() {
+# let args: Vec<String> = env::args().collect();
+#
+# let query = &args[1];
+# let filename = &args[2];
+#
+# println!("Searching for {}", query);
+ // --snip--
+ println!("In file {}", filename);
+
+ let contents = fs::read_to_string(filename)
+ .expect("Something went wrong reading the file");
+
+ println!("With text:\n{}", contents);
+}
```
<span class="caption">Listing 12-4: Reading the contents of the file specified
@@ -32,11 +57,10 @@ by the second argument</span>
First, we add another `use` statement to bring in a relevant part of the
standard library: we need `std::fs` to handle files.
-In `main`, we’ve added a new statement: `fs::read_to_string` takes the
-`filename`, opens that file, and returns a `Result<String>` of the file’s
-contents.
+In `main`, we’ve added a new statement: `fs::read_to_string` will take the
+`filename`, open that file, and then return `Result<String>` with its contents.
-After that statement, we’ve again added a temporary `println!` statement that
+After that line, we’ve again added a temporary `println!` statement that
prints the value of `contents` after the file is read, so we can check that the
program is working so far.
@@ -45,7 +69,22 @@ we haven’t implemented the searching part yet) and the *poem.txt* file as the
second argument:
```text
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-04/output.txt}}
+$ cargo run the poem.txt
+ Compiling minigrep v0.1.0 (file:///projects/minigrep)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
+ Running `target/debug/minigrep the poem.txt`
+Searching for the
+In file poem.txt
+With text:
+I’m nobody! Who are you?
+Are you nobody, too?
+Then there’s a pair of us — don’t tell!
+They’d banish us, you know.
+
+How dreary to be somebody!
+How public, like a frog
+To tell your name the livelong day
+To an admiring bog!
```
Great! The code read and then printed the contents of the file. But the code
diff --git a/book-original/src/ch12-03-improving-error-handling-and-modularity.md b/book-pl-en/src/ch12-03-improving-error-handling-and-modularity.md
index cf5bd88..9a12850 100644
--- a/book-original/src/ch12-03-improving-error-handling-and-modularity.md
+++ b/book-pl-en/src/ch12-03-improving-error-handling-and-modularity.md
@@ -19,11 +19,12 @@ it will be to keep track of the purpose of each. It’s best to group the
configuration variables into one structure to make their purpose clear.
The third problem is that we’ve used `expect` to print an error message when
-reading the file fails, but the error message just prints `Something went wrong
-reading the file`. Reading a file can fail in a number of ways: for example,
-the file could be missing, or we might not have permission to open it. Right
-now, regardless of the situation, we’d print the `Something went wrong reading
-the file` error message, which wouldn’t give the user any information!
+reading the file fails, but the error message just prints
+`something went wrong`. Reading a file can fail in a number of ways: for
+example, the file could be missing, or we might not have permission to open
+it. Right now, regardless of the situation, we’d print the
+`something went wrong` error message, which wouldn’t give the user any
+information!
Fourth, we use `expect` repeatedly to handle different errors, and if the user
runs our program without specifying enough arguments, they’ll get an `index out
@@ -49,14 +50,13 @@ process has the following steps:
*main.rs*.
* When the command line parsing logic starts getting complicated, extract it
from *main.rs* and move it to *lib.rs*.
+* The responsibilities that remain in the `main` function after this process
+ should be limited to the following:
-The responsibilities that remain in the `main` function after this process
-should be limited to the following:
-
-* Calling the command line parsing logic with the argument values
-* Setting up any other configuration
-* Calling a `run` function in *lib.rs*
-* Handling the error if `run` returns an error
+ * Calling the command line parsing logic with the argument values
+ * Setting up any other configuration
+ * Calling a `run` function in *lib.rs*
+ * Handling the error if `run` returns an error
This pattern is about separating concerns: *main.rs* handles running the
program, and *lib.rs* handles all the logic of the task at hand. Because you
@@ -75,15 +75,28 @@ function `parse_config`, which we’ll define in *src/main.rs* for the moment.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-05/src/main.rs:here}}
+fn main() {
+ let args: Vec<String> = env::args().collect();
+
+ let (query, filename) = parse_config(&args);
+
+ // --snip--
+}
+
+fn parse_config(args: &[String]) -> (&str, &str) {
+ let query = &args[1];
+ let filename = &args[2];
+
+ (query, filename)
+}
```
<span class="caption">Listing 12-5: Extracting a `parse_config` function from
`main`</span>
We’re still collecting the command line arguments into a vector, but instead of
-assigning the argument value at index 1 to the variable `query` and the
-argument value at index 2 to the variable `filename` within the `main`
+assigning the argument value at index `1` to the variable `query` and the
+argument value at index `2` to the variable `filename` within the `main`
function, we pass the whole vector to the `parse_config` function. The
`parse_config` function then holds the logic that determines which argument
goes in which variable and passes the values back to `main`. We still create
@@ -115,25 +128,54 @@ other and what their purpose is.
> Note: Using primitive values when a complex type would be more appropriate is
> an anti-pattern known as *primitive obsession*.
-Listing 12-6 shows the improvements to the `parse_config` function.
+Listing 12-6 shows the addition of a struct named `Config` defined to have
+fields named `query` and `filename`. We’ve also changed the `parse_config`
+function to return an instance of the `Config` struct and updated `main` to use
+the struct fields rather than having separate variables:
<span class="filename">Filename: src/main.rs</span>
```rust,should_panic
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-06/src/main.rs:here}}
+# use std::env;
+# use std::fs;
+#
+fn main() {
+ let args: Vec<String> = env::args().collect();
+
+ let config = parse_config(&args);
+
+ println!("Searching for {}", config.query);
+ println!("In file {}", config.filename);
+
+ let contents = fs::read_to_string(config.filename)
+ .expect("Something went wrong reading the file");
+
+ // --snip--
+}
+
+struct Config {
+ query: String,
+ filename: String,
+}
+
+fn parse_config(args: &[String]) -> Config {
+ let query = args[1].clone();
+ let filename = args[2].clone();
+
+ Config { query, filename }
+}
```
<span class="caption">Listing 12-6: Refactoring `parse_config` to return an
instance of a `Config` struct</span>
-We’ve added a struct named `Config` defined to have fields named `query` and
-`filename`. The signature of `parse_config` now indicates that it returns a
-`Config` value. In the body of `parse_config`, where we used to return string
-slices that reference `String` values in `args`, we now define `Config` to
-contain owned `String` values. The `args` variable in `main` is the owner of
-the argument values and is only letting the `parse_config` function borrow
-them, which means we’d violate Rust’s borrowing rules if `Config` tried to take
-ownership of the values in `args`.
+The signature of `parse_config` now indicates that it returns a `Config` value.
+In the body of `parse_config`, where we used to return string slices that
+reference `String` values in `args`, we now define `Config` to contain owned
+`String` values. The `args` variable in `main` is the owner of the argument
+values and is only letting the `parse_config` function borrow them, which means
+we’d violate Rust’s borrowing rules if `Config` tried to take ownership of the
+values in `args`.
We could manage the `String` data in a number of different ways, but the
easiest, though somewhat inefficient, route is to call the `clone` method on
@@ -147,15 +189,14 @@ trade-off.
> ### The Trade-Offs of Using `clone`
>
> There’s a tendency among many Rustaceans to avoid using `clone` to fix
-> ownership problems because of its runtime cost. In
-> [Chapter 13][ch13]<!-- ignore -->, you’ll learn how to use more efficient
-> methods in this type of situation. But for now, it’s okay to copy a few
-> strings to continue making progress because you’ll make these copies only
-> once and your filename and query string are very small. It’s better to have
-> a working program that’s a bit inefficient than to try to hyperoptimize code
-> on your first pass. As you become more experienced with Rust, it’ll be
-> easier to start with the most efficient solution, but for now, it’s
-> perfectly acceptable to call `clone`.
+> ownership problems because of its runtime cost. In Chapter 13, you’ll learn
+> how to use more efficient methods in this type of situation. But for now,
+> it’s okay to copy a few strings to continue making progress because you’ll
+> make these copies only once and your filename and query string are very
+> small. It’s better to have a working program that’s a bit inefficient than to
+> try to hyperoptimize code on your first pass. As you become more experienced
+> with Rust, it’ll be easier to start with the most efficient solution, but for
+> now, it’s perfectly acceptable to call `clone`.
We’ve updated `main` so it places the instance of `Config` returned by
`parse_config` into a variable named `config`, and we updated the code that
@@ -183,12 +224,36 @@ will make the code more idiomatic. We can create instances of types in the
standard library, such as `String`, by calling `String::new`. Similarly, by
changing `parse_config` into a `new` function associated with `Config`, we’ll
be able to create instances of `Config` by calling `Config::new`. Listing 12-7
-shows the changes we need to make.
+shows the changes we need to make:
<span class="filename">Filename: src/main.rs</span>
```rust,should_panic
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-07/src/main.rs:here}}
+# use std::env;
+#
+fn main() {
+ let args: Vec<String> = env::args().collect();
+
+ let config = Config::new(&args);
+
+ // --snip--
+}
+
+# struct Config {
+# query: String,
+# filename: String,
+# }
+#
+// --snip--
+
+impl Config {
+ fn new(args: &[String]) -> Config {
+ let query = args[1].clone();
+ let filename = args[2].clone();
+
+ Config { query, filename }
+ }
+}
```
<span class="caption">Listing 12-7: Changing `parse_config` into
@@ -202,12 +267,18 @@ compiling this code again to make sure it works.
### Fixing the Error Handling
Now we’ll work on fixing our error handling. Recall that attempting to access
-the values in the `args` vector at index 1 or index 2 will cause the program to
-panic if the vector contains fewer than three items. Try running the program
-without any arguments; it will look like this:
+the values in the `args` vector at index `1` or index `2` will cause the
+program to panic if the vector contains fewer than three items. Try running the
+program without any arguments; it will look like this:
```text
-{{#include ../listings/ch12-an-io-project/listing-12-07/output.txt}}
+$ cargo run
+ Compiling minigrep v0.1.0 (file:///projects/minigrep)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
+ Running `target/debug/minigrep`
+thread 'main' panicked at 'index out of bounds: the len is 1
+but the index is 1', src/main.rs:29:21
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
The line `index out of bounds: the len is 1 but the index is 1` is an error
@@ -217,41 +288,51 @@ happened and what they should do instead. Let’s fix that now.
#### Improving the Error Message
In Listing 12-8, we add a check in the `new` function that will verify that the
-slice is long enough before accessing index 1 and 2. If the slice isn’t long
-enough, the program panics and displays a better error message than the `index
-out of bounds` message.
+slice is long enough before accessing index `1` and `2`. If the slice isn’t
+long enough, the program panics and displays a better error message than the
+`index out of bounds` message.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-08/src/main.rs:here}}
+// --snip--
+fn new(args: &[String]) -> Config {
+ if args.len() < 3 {
+ panic!("not enough arguments");
+ }
+ // --snip--
```
<span class="caption">Listing 12-8: Adding a check for the number of
arguments</span>
-This code is similar to [the `Guess::new` function we wrote in Listing
-9-10][ch9-custom-types]<!-- ignore -->, where we called `panic!` when the
-`value` argument was out of the range of valid values. Instead of checking for
-a range of values here, we’re checking that the length of `args` is at least 3
-and the rest of the function can operate under the assumption that this
-condition has been met. If `args` has fewer than three items, this condition
-will be true, and we call the `panic!` macro to end the program immediately.
+This code is similar to the `Guess::new` function we wrote in Listing 9-10, where
+we called `panic!` when the `value` argument was out of the range of valid
+values. Instead of checking for a range of values here, we’re checking that the
+length of `args` is at least `3` and the rest of the function can operate under
+the assumption that this condition has been met. If `args` has fewer than three
+items, this condition will be true, and we call the `panic!` macro to end the
+program immediately.
With these extra few lines of code in `new`, let’s run the program without any
arguments again to see what the error looks like now:
```text
-{{#include ../listings/ch12-an-io-project/listing-12-08/output.txt}}
+$ cargo run
+ Compiling minigrep v0.1.0 (file:///projects/minigrep)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
+ Running `target/debug/minigrep`
+thread 'main' panicked at 'not enough arguments', src/main.rs:30:12
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
This output is better: we now have a reasonable error message. However, we also
have extraneous information we don’t want to give to our users. Perhaps using
the technique we used in Listing 9-10 isn’t the best to use here: a call to
-`panic!` is more appropriate for a programming problem than a usage problem,
-[as discussed in Chapter 9][ch9-error-guidelines]<!-- ignore -->. Instead, we
-can use the other technique you learned about in Chapter 9—[returning a
-`Result`][ch9-result]<!-- ignore --> that indicates either success or an error.
+`panic!` is more appropriate for a programming problem rather than a usage
+problem, as discussed in Chapter 9. Instead, we can use the other technique you
+learned about in Chapter 9—returning a `Result` that indicates either success
+or an error.
#### Returning a `Result` from `new` Instead of Calling `panic!`
@@ -270,7 +351,18 @@ next listing.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-09/src/main.rs:here}}
+impl Config {
+ fn new(args: &[String]) -> Result<Config, &'static str> {
+ if args.len() < 3 {
+ return Err("not enough arguments");
+ }
+
+ let query = args[1].clone();
+ let filename = args[2].clone();
+
+ Ok(Config { query, filename })
+ }
+}
```
<span class="caption">Listing 12-9: Returning a `Result` from
@@ -303,7 +395,17 @@ program that the program exited with an error state.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-10/src/main.rs:here}}
+use std::process;
+
+fn main() {
+ let args: Vec<String> = env::args().collect();
+
+ let config = Config::new(&args).unwrap_or_else(|err| {
+ println!("Problem parsing arguments: {}", err);
+ process::exit(1);
+ });
+
+ // --snip--
```
<span class="caption">Listing 12-10: Exiting with an error code if creating a
@@ -316,12 +418,11 @@ handling. If the `Result` is an `Ok` value, this method’s behavior is similar
to `unwrap`: it returns the inner value `Ok` is wrapping. However, if the value
is an `Err` value, this method calls the code in the *closure*, which is an
anonymous function we define and pass as an argument to `unwrap_or_else`. We’ll
-cover closures in more detail in [Chapter 13][ch13]<!-- ignore -->. For now,
-you just need to know that `unwrap_or_else` will pass the inner value of the
-`Err`, which in this case is the static string `not enough arguments` that we
-added in Listing 12-9, to our closure in the argument `err` that appears
-between the vertical pipes. The code in the closure can then use the `err`
-value when it runs.
+cover closures in more detail in Chapter 13. For now, you just need to know
+that `unwrap_or_else` will pass the inner value of the `Err`, which in this
+case is the static string `not enough arguments` that we added in Listing 12-9,
+to our closure in the argument `err` that appears between the vertical pipes.
+The code in the closure can then use the `err` value when it runs.
We’ve added a new `use` line to bring `process` from the standard library into
scope. The code in the closure that will be run in the error case is only two
@@ -332,7 +433,11 @@ number that was passed as the exit status code. This is similar to the
extra output. Let’s try it:
```text
-{{#include ../listings/ch12-an-io-project/listing-12-10/output.txt}}
+$ cargo run
+ Compiling minigrep v0.1.0 (file:///projects/minigrep)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.48 secs
+ Running `target/debug/minigrep`
+Problem parsing arguments: not enough arguments
```
Great! This output is much friendlier for our users.
@@ -354,7 +459,23 @@ defining the function in *src/main.rs*.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-11/src/main.rs:here}}
+fn main() {
+ // --snip--
+
+ println!("Searching for {}", config.query);
+ println!("In file {}", config.filename);
+
+ run(config);
+}
+
+fn run(config: Config) {
+ let contents = fs::read_to_string(config.filename)
+ .expect("something went wrong reading the file");
+
+ println!("With text:\n{}", contents);
+}
+
+// --snip--
```
<span class="caption">Listing 12-11: Extracting a `run` function containing the
@@ -372,12 +493,22 @@ Instead of allowing the program to panic by calling `expect`, the `run`
function will return a `Result<T, E>` when something goes wrong. This will let
us further consolidate into `main` the logic around handling errors in a
user-friendly way. Listing 12-12 shows the changes we need to make to the
-signature and body of `run`.
+signature and body of `run`:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-12/src/main.rs:here}}
+use std::error::Error;
+
+// --snip--
+
+fn run(config: Config) -> Result<(), Box<dyn Error>> {
+ let contents = fs::read_to_string(config.filename)?;
+
+ println!("With text:\n{}", contents);
+
+ Ok(())
+}
```
<span class="caption">Listing 12-12: Changing the `run` function to return
@@ -390,17 +521,16 @@ returned the unit type, `()`, and we keep that as the value returned in the
For the error type, we used the *trait object* `Box<dyn Error>` (and we’ve
brought `std::error::Error` into scope with a `use` statement at the top).
-We’ll cover trait objects in [Chapter 17][ch17]<!-- ignore -->. For now, just
-know that `Box<dyn Error>` means the function will return a type that
-implements the `Error` trait, but we don’t have to specify what particular type
-the return value will be. This gives us flexibility to return error values that
-may be of different types in different error cases. The `dyn` keyword is short
-for “dynamic.”
-
-Second, we’ve removed the call to `expect` in favor of the `?` operator, as we
-talked about in [Chapter 9][ch9-question-mark]<!-- ignore -->. Rather than
-`panic!` on an error, `?` will return the error value from the current function
-for the caller to handle.
+We’ll cover trait objects in Chapter 17. For now, just know that `Box<dyn
+Error>` means the function will return a type that implements the `Error`
+trait, but we don’t have to specify what particular type the return value
+will be. This gives us flexibility to return error values that may be of
+different types in different error cases. This is what the `dyn` means, it’s
+short for “dynamic.”
+
+Second, we’ve removed the call to `expect` in favor of `?`, as we talked about
+in Chapter 9. Rather than `panic!` on an error, `?` will return the error value
+from the current function for the caller to handle.
Third, the `run` function now returns an `Ok` value in the success case. We’ve
declared the `run` function’s success type as `()` in the signature, which
@@ -412,13 +542,18 @@ it doesn’t return a value we need.
When you run this code, it will compile but will display a warning:
```text
-{{#include ../listings/ch12-an-io-project/listing-12-12/output.txt}}
+warning: unused `std::result::Result` which must be used
+ --> src/main.rs:18:5
+ |
+18 | run(config);
+ | ^^^^^^^^^^^^
+= note: #[warn(unused_must_use)] on by default
```
Rust tells us that our code ignored the `Result` value and the `Result` value
might indicate that an error occurred. But we’re not checking to see whether or
not there was an error, and the compiler reminds us that we probably meant to
-have some error-handling code here! Let’s rectify that problem now.
+have some error handling code here! Let’s rectify that problem now.
#### Handling Errors Returned from `run` in `main`
@@ -428,7 +563,18 @@ with `Config::new` in Listing 12-10, but with a slight difference:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/src/main.rs:here}}
+fn main() {
+ // --snip--
+
+ println!("Searching for {}", config.query);
+ println!("In file {}", config.filename);
+
+ if let Err(e) = run(config) {
+ println!("Application error: {}", e);
+
+ process::exit(1);
+ }
+}
```
We use `if let` rather than `unwrap_or_else` to check whether `run` returns an
@@ -457,12 +603,28 @@ Let’s move all the code that isn’t the `main` function from *src/main.rs* to
The contents of *src/lib.rs* should have the signatures shown in Listing 12-13
(we’ve omitted the bodies of the functions for brevity). Note that this won’t
-compile until we modify *src/main.rs* in Listing 12-14.
+compile until we modify *src/main.rs* in the listing after this one.
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-13/src/lib.rs:here}}
+use std::error::Error;
+use std::fs;
+
+pub struct Config {
+ pub query: String,
+ pub filename: String,
+}
+
+impl Config {
+ pub fn new(args: &[String]) -> Result<Config, &'static str> {
+ // --snip--
+ }
+}
+
+pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
+ // --snip--
+}
```
<span class="caption">Listing 12-13: Moving `Config` and `run` into
@@ -473,22 +635,33 @@ We’ve made liberal use of the `pub` keyword: on `Config`, on its fields and it
public API that we can test!
Now we need to bring the code we moved to *src/lib.rs* into the scope of the
-binary crate in *src/main.rs*, as shown in Listing 12-14.
+binary crate in *src/main.rs*, as shown in Listing 12-14:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-14/src/main.rs:here}}
+use std::env;
+use std::process;
+
+use minigrep;
+use minigrep::Config;
+
+fn main() {
+ // --snip--
+ if let Err(e) = minigrep::run(config) {
+ // --snip--
+ }
+}
```
-<span class="caption">Listing 12-14: Using the `minigrep` library crate in
-*src/main.rs*</span>
+<span class="caption">Listing 12-14: Bringing the `minigrep` crate into the
+scope of *src/main.rs*</span>
-We add a `use minigrep::Config` line to bring the `Config` type from the
-library crate into the binary crate’s scope, and we prefix the `run` function
-with our crate name. Now all the functionality should be connected and should
-work. Run the program with `cargo run` and make sure everything works
-correctly.
+To bring the library crate into the binary crate, we use `use minigrep`.
+Then we add a `use minigrep::Config` line to bring the `Config` type
+into scope as well, and we prefix the `run` function with our crate name. Now
+all the functionality should be connected and should work. Run the program with
+`cargo run` and make sure everything works correctly.
Whew! That was a lot of work, but we’ve set ourselves up for success in the
future. Now it’s much easier to handle errors, and we’ve made the code more
@@ -499,9 +672,3 @@ have been difficult with the old code but is easy with the new code: we’ll
write some tests!
[the-static-lifetime]: ch10-03-lifetime-syntax.html#the-static-lifetime
-[ch13]: ch13-00-functional-features.html
-[ch9-custom-types]: ch09-03-to-panic-or-not-to-panic.html#creating-custom-types-for-validation
-[ch9-error-guidelines]: ch09-03-to-panic-or-not-to-panic.html#guidelines-for-error-handling
-[ch9-result]: ch09-02-recoverable-errors-with-result.html
-[ch17]: ch17-00-oop.html
-[ch9-question-mark]: ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator
diff --git a/book-original/src/ch12-04-testing-the-librarys-functionality.md b/book-pl-en/src/ch12-04-testing-the-librarys-functionality.md
index 17a0f97..87a00cf 100644
--- a/book-original/src/ch12-04-testing-the-librarys-functionality.md
+++ b/book-pl-en/src/ch12-04-testing-the-librarys-functionality.md
@@ -32,16 +32,36 @@ lines that match the query. We’ll add this functionality in a function called
Because we don’t need them anymore, let’s remove the `println!` statements from
*src/lib.rs* and *src/main.rs* that we used to check the program’s behavior.
Then, in *src/lib.rs*, we’ll add a `tests` module with a test function, as we
-did in [Chapter 11][ch11-anatomy]<!-- ignore -->. The test function specifies
-the behavior we want the `search` function to have: it will take a query and
-the text to search for the query in, and it will return only the lines from the
-text that contain the query. Listing 12-15 shows this test, which won’t compile
-yet.
+did in Chapter 11. The test function specifies the behavior we want the
+`search` function to have: it will take a query and the text to search for the
+query in, and it will return only the lines from the text that contain the
+query. Listing 12-15 shows this test, which won’t compile yet:
<span class="filename">Filename: src/lib.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-15/src/lib.rs:here}}
+```rust
+# fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+# vec![]
+# }
+#
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn one_result() {
+ let query = "duct";
+ let contents = "\
+Rust:
+safe, fast, productive.
+Pick three.";
+
+ assert_eq!(
+ vec!["safe, fast, productive."],
+ search(query, contents)
+ );
+ }
+}
```
<span class="caption">Listing 12-15: Creating a failing test for the `search`
@@ -61,7 +81,9 @@ containing the line `"safe, fast, productive."`
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-16/src/lib.rs:here}}
+fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+ vec![]
+}
```
<span class="caption">Listing 12-16: Defining just enough of the `search`
@@ -69,11 +91,10 @@ function so our test will compile</span>
Notice that we need an explicit lifetime `'a` defined in the signature of
`search` and used with the `contents` argument and the return value. Recall in
-[Chapter 10][ch10-lifetimes]<!-- ignore --> that the lifetime parameters
-specify which argument lifetime is connected to the lifetime of the return
-value. In this case, we indicate that the returned vector should contain string
-slices that reference slices of the argument `contents` (rather than the
-argument `query`).
+Chapter 10 that the lifetime parameters specify which argument lifetime is
+connected to the lifetime of the return value. In this case, we indicate that
+the returned vector should contain string slices that reference slices of the
+argument `contents` (rather than the argument `query`).
In other words, we tell Rust that the data returned by the `search` function
will live as long as the data passed into the `search` function in the
@@ -86,7 +107,15 @@ If we forget the lifetime annotations and try to compile this function, we’ll
get this error:
```text
-{{#include ../listings/ch12-an-io-project/output-only-02-missing-lifetimes/output.txt}}
+error[E0106]: missing lifetime specifier
+ --> src/lib.rs:5:51
+ |
+5 | fn search(query: &str, contents: &str) -> Vec<&str> {
+ | ^ expected lifetime
+parameter
+ |
+ = help: this function's return type contains a borrowed value, but the
+ signature does not say whether it is borrowed from `query` or `contents`
```
Rust can’t possibly know which of the two arguments we need, so we need to tell
@@ -95,15 +124,39 @@ want to return the parts of that text that match, we know `contents` is the
argument that should be connected to the return value using the lifetime syntax.
Other programming languages don’t require you to connect arguments to return
-values in the signature. Although this might seem strange, it will get easier
-over time. You might want to compare this example with the [“Validating
+values in the signature. So although this might seem strange, it will get
+easier over time. You might want to compare this example with the [“Validating
References with Lifetimes”][validating-references-with-lifetimes]<!-- ignore
--> section in Chapter 10.
Now let’s run the test:
```text
-{{#include ../listings/ch12-an-io-project/listing-12-16/output.txt}}
+$ cargo test
+ Compiling minigrep v0.1.0 (file:///projects/minigrep)
+--warnings--
+ Finished dev [unoptimized + debuginfo] target(s) in 0.43 secs
+ Running target/debug/deps/minigrep-abcabcabc
+
+running 1 test
+test tests::one_result ... FAILED
+
+failures:
+
+---- tests::one_result stdout ----
+ thread 'tests::one_result' panicked at 'assertion failed: `(left ==
+right)`
+left: `["safe, fast, productive."]`,
+right: `[]`)', src/lib.rs:48:8
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
+
+
+failures:
+ tests::one_result
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
+
+error: test failed, to rerun pass '--lib'
```
Great, the test fails, exactly as we expected. Let’s get the test to pass!
@@ -125,33 +178,43 @@ Let’s work through each step, starting with iterating through lines.
Rust has a helpful method to handle line-by-line iteration of strings,
conveniently named `lines`, that works as shown in Listing 12-17. Note this
-won’t compile yet.
+won’t compile yet:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-17/src/lib.rs:here}}
+fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+ for line in contents.lines() {
+ // do something with line
+ }
+}
```
<span class="caption">Listing 12-17: Iterating through each line in `contents`
</span>
The `lines` method returns an iterator. We’ll talk about iterators in depth in
-[Chapter 13][ch13-iterators]<!-- ignore -->, but recall that you saw this way of using an
-iterator in [Listing 3-5][ch3-iter]<!-- ignore -->, where we used a `for` loop
-with an iterator to run some code on each item in a collection.
+Chapter 13, but recall that you saw this way of using an iterator in Listing
+3-5, where we used a `for` loop with an iterator to run some code on each item
+in a collection.
#### Searching Each Line for the Query
Next, we’ll check whether the current line contains our query string.
Fortunately, strings have a helpful method named `contains` that does this for
us! Add a call to the `contains` method in the `search` function, as shown in
-Listing 12-18. Note this still won’t compile yet.
+Listing 12-18. Note this still won’t compile yet:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-18/src/lib.rs:here}}
+fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+ for line in contents.lines() {
+ if line.contains(query) {
+ // do something with line
+ }
+ }
+}
```
<span class="caption">Listing 12-18: Adding functionality to see whether the
@@ -162,12 +225,22 @@ line contains the string in `query`</span>
We also need a way to store the lines that contain our query string. For that,
we can make a mutable vector before the `for` loop and call the `push` method
to store a `line` in the vector. After the `for` loop, we return the vector, as
-shown in Listing 12-19.
+shown in Listing 12-19:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-19/src/lib.rs:here}}
+fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+ let mut results = Vec::new();
+
+ for line in contents.lines() {
+ if line.contains(query) {
+ results.push(line);
+ }
+ }
+
+ results
+}
```
<span class="caption">Listing 12-19: Storing the lines that match so we can
@@ -177,7 +250,12 @@ Now the `search` function should return only the lines that contain `query`,
and our test should pass. Let’s run the test:
```text
-{{#include ../listings/ch12-an-io-project/listing-12-19/output.txt}}
+$ cargo test
+--snip--
+running 1 test
+test tests::one_result ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
Our test passed, so we know it works!
@@ -186,8 +264,8 @@ At this point, we could consider opportunities for refactoring the
implementation of the search function while keeping the tests passing to
maintain the same functionality. The code in the search function isn’t too bad,
but it doesn’t take advantage of some useful features of iterators. We’ll
-return to this example in [Chapter 13][ch13-iterators]<!-- ignore -->, where we’ll
-explore iterators in detail, and look at how to improve it.
+return to this example in Chapter 13, where we’ll explore iterators in detail,
+and look at how to improve it.
#### Using the `search` Function in the `run` Function
@@ -199,7 +277,15 @@ will print each line returned from `search`:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/lib.rs:here}}
+pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
+ let contents = fs::read_to_string(config.filename)?;
+
+ for line in search(&config.query, &contents) {
+ println!("{}", line);
+ }
+
+ Ok(())
+}
```
We’re still using a `for` loop to return each line from `search` and print it.
@@ -208,20 +294,31 @@ Now the entire program should work! Let’s try it out, first with a word that
should return exactly one line from the Emily Dickinson poem, “frog”:
```text
-{{#include ../listings/ch12-an-io-project/no-listing-02-using-search-in-run/output.txt}}
+$ cargo run frog poem.txt
+ Compiling minigrep v0.1.0 (file:///projects/minigrep)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.38 secs
+ Running `target/debug/minigrep frog poem.txt`
+How public, like a frog
```
Cool! Now let’s try a word that will match multiple lines, like “body”:
```text
-{{#include ../listings/ch12-an-io-project/output-only-03-multiple-matches/output.txt}}
+$ cargo run body poem.txt
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
+ Running `target/debug/minigrep body poem.txt`
+I’m nobody! Who are you?
+Are you nobody, too?
+How dreary to be somebody!
```
And finally, let’s make sure that we don’t get any lines when we search for a
word that isn’t anywhere in the poem, such as “monomorphization”:
```text
-{{#include ../listings/ch12-an-io-project/output-only-04-no-matches/output.txt}}
+$ cargo run monomorphization poem.txt
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
+ Running `target/debug/minigrep monomorphization poem.txt`
```
Excellent! We’ve built our own mini version of a classic tool and learned a lot
@@ -234,7 +331,3 @@ useful when you’re writing command line programs.
[validating-references-with-lifetimes]:
ch10-03-lifetime-syntax.html#validating-references-with-lifetimes
-[ch11-anatomy]: ch11-01-writing-tests.html#the-anatomy-of-a-test-function
-[ch10-lifetimes]: ch10-03-lifetime-syntax.html
-[ch3-iter]: ch03-05-control-flow.html#looping-through-a-collection-with-for
-[ch13-iterators]: ch13-02-iterators.html
diff --git a/book-original/src/ch12-05-working-with-environment-variables.md b/book-pl-en/src/ch12-05-working-with-environment-variables.md
index 48b7162..50dfd05 100644
--- a/book-original/src/ch12-05-working-with-environment-variables.md
+++ b/book-pl-en/src/ch12-05-working-with-environment-variables.md
@@ -14,12 +14,45 @@ the environment variable is on. We’ll continue to follow the TDD process, so
the first step is again to write a failing test. We’ll add a new test for the
new `search_case_insensitive` function and rename our old test from
`one_result` to `case_sensitive` to clarify the differences between the two
-tests, as shown in Listing 12-20.
+tests, as shown in Listing 12-20:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-20/src/lib.rs:here}}
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn case_sensitive() {
+ let query = "duct";
+ let contents = "\
+Rust:
+safe, fast, productive.
+Pick three.
+Duct tape.";
+
+ assert_eq!(
+ vec!["safe, fast, productive."],
+ search(query, contents)
+ );
+ }
+
+ #[test]
+ fn case_insensitive() {
+ let query = "rUsT";
+ let contents = "\
+Rust:
+safe, fast, productive.
+Pick three.
+Trust me.";
+
+ assert_eq!(
+ vec!["Rust:", "Trust me."],
+ search_case_insensitive(query, contents)
+ );
+ }
+}
```
<span class="caption">Listing 12-20: Adding a new failing test for the
@@ -27,7 +60,7 @@ case-insensitive function we’re about to add</span>
Note that we’ve edited the old test’s `contents` too. We’ve added a new line
with the text `"Duct tape."` using a capital D that shouldn’t match the query
-`"duct"` when we’re searching in a case-sensitive manner. Changing the old test
+“duct” when we’re searching in a case-sensitive manner. Changing the old test
in this way helps ensure that we don’t accidentally break the case-sensitive
search functionality that we’ve already implemented. This test should pass now
and should continue to pass as we work on the case-insensitive search.
@@ -35,7 +68,7 @@ and should continue to pass as we work on the case-insensitive search.
The new test for the case-*insensitive* search uses `"rUsT"` as its query. In
the `search_case_insensitive` function we’re about to add, the query `"rUsT"`
should match the line containing `"Rust:"` with a capital R and match the line
-`"Trust me."` even though both have different casing from the query. This is
+`"Trust me."` even though both have different casing than the query. This is
our failing test, and it will fail to compile because we haven’t yet defined
the `search_case_insensitive` function. Feel free to add a skeleton
implementation that always returns an empty vector, similar to the way we did
@@ -51,7 +84,18 @@ they’ll be the same case when we check whether the line contains the query.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-21/src/lib.rs:here}}
+fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+ let query = query.to_lowercase();
+ let mut results = Vec::new();
+
+ for line in contents.lines() {
+ if line.to_lowercase().contains(&query) {
+ results.push(line);
+ }
+ }
+
+ results
+}
```
<span class="caption">Listing 12-21: Defining the `search_case_insensitive`
@@ -78,31 +122,71 @@ query is.
Let’s see if this implementation passes the tests:
```text
-{{#include ../listings/ch12-an-io-project/listing-12-21/output.txt}}
+running 2 tests
+test tests::case_insensitive ... ok
+test tests::case_sensitive ... ok
+
+test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
Great! They passed. Now, let’s call the new `search_case_insensitive` function
from the `run` function. First, we’ll add a configuration option to the
`Config` struct to switch between case-sensitive and case-insensitive search.
-Adding this field will cause compiler errors because we aren’t initializing
-this field anywhere yet:
+Adding this field will cause compiler errors since we aren’t initializing this
+field anywhere yet:
<span class="filename">Filename: src/lib.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-22/src/lib.rs:here}}
+```rust
+pub struct Config {
+ pub query: String,
+ pub filename: String,
+ pub case_sensitive: bool,
+}
```
Note that we added the `case_sensitive` field that holds a Boolean. Next, we
need the `run` function to check the `case_sensitive` field’s value and use
that to decide whether to call the `search` function or the
`search_case_insensitive` function, as shown in Listing 12-22. Note this still
-won’t compile yet.
+won’t compile yet:
<span class="filename">Filename: src/lib.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-22/src/lib.rs:there}}
+```rust
+# use std::error::Error;
+# use std::fs::{self, File};
+# use std::io::prelude::*;
+#
+# fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+# vec![]
+# }
+#
+# fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+# vec![]
+# }
+#
+# pub struct Config {
+# query: String,
+# filename: String,
+# case_sensitive: bool,
+# }
+#
+pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
+ let contents = fs::read_to_string(config.filename)?;
+
+ let results = if config.case_sensitive {
+ search(&config.query, &contents)
+ } else {
+ search_case_insensitive(&config.query, &contents)
+ };
+
+ for line in results {
+ println!("{}", line);
+ }
+
+ Ok(())
+}
```
<span class="caption">Listing 12-22: Calling either `search` or
@@ -111,14 +195,36 @@ won’t compile yet.
Finally, we need to check for the environment variable. The functions for
working with environment variables are in the `env` module in the standard
library, so we want to bring that module into scope with a `use std::env;` line
-at the top of *src/lib.rs*. Then we’ll use the `var` function from the `env`
+at the top of *src/lib.rs*. Then we’ll use the `var` method from the `env`
module to check for an environment variable named `CASE_INSENSITIVE`, as shown
-in Listing 12-23.
+in Listing 12-23:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-23/src/lib.rs:here}}
+use std::env;
+# struct Config {
+# query: String,
+# filename: String,
+# case_sensitive: bool,
+# }
+
+// --snip--
+
+impl Config {
+ pub fn new(args: &[String]) -> Result<Config, &'static str> {
+ if args.len() < 3 {
+ return Err("not enough arguments");
+ }
+
+ let query = args[1].clone();
+ let filename = args[2].clone();
+
+ let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
+
+ Ok(Config { query, filename, case_sensitive })
+ }
+}
```
<span class="caption">Listing 12-23: Checking for an environment variable named
@@ -126,7 +232,7 @@ in Listing 12-23.
Here, we create a new variable `case_sensitive`. To set its value, we call the
`env::var` function and pass it the name of the `CASE_INSENSITIVE` environment
-variable. The `env::var` function returns a `Result` that will be the successful
+variable. The `env::var` method returns a `Result` that will be the successful
`Ok` variant that contains the value of the environment variable if the
environment variable is set. It will return the `Err` variant if the
environment variable is not set.
@@ -148,7 +254,12 @@ variable set and with the query `to`, which should match any line that contains
the word “to” in all lowercase:
```text
-{{#include ../listings/ch12-an-io-project/listing-12-23/output.txt}}
+$ cargo run to poem.txt
+ Compiling minigrep v0.1.0 (file:///projects/minigrep)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
+ Running `target/debug/minigrep to poem.txt`
+Are you nobody, too?
+How dreary to be somebody!
```
Looks like that still works! Now, let’s run the program with `CASE_INSENSITIVE`
@@ -164,15 +275,9 @@ $ cargo run to poem.txt
We should get lines that contain “to” that might have uppercase letters:
-<!-- manual-regeneration
-cd listings/ch12-an-io-project/listing-12-23
-CASE_INSENSITIVE=1 cargo run to poem.txt
-can't extract because of the environment variable
--->
-
```text
$ CASE_INSENSITIVE=1 cargo run to poem.txt
- Finished dev [unoptimized + debuginfo] target(s) in 0.0s
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/minigrep to poem.txt`
Are you nobody, too?
How dreary to be somebody!
diff --git a/book-original/src/ch12-06-writing-to-stderr-instead-of-stdout.md b/book-pl-en/src/ch12-06-writing-to-stderr-instead-of-stdout.md
index ab10ab1..0fc1aa2 100644
--- a/book-original/src/ch12-06-writing-to-stderr-instead-of-stdout.md
+++ b/book-pl-en/src/ch12-06-writing-to-stderr-instead-of-stdout.md
@@ -1,13 +1,13 @@
## Writing Error Messages to Standard Error Instead of Standard Output
At the moment, we’re writing all of our output to the terminal using the
-`println!` macro. Most terminals provide two kinds of output: *standard
+`println!` function. Most terminals provide two kinds of output: *standard
output* (`stdout`) for general information and *standard error* (`stderr`)
for error messages. This distinction enables users to choose to direct the
successful output of a program to a file but still print error messages to the
screen.
-The `println!` macro is only capable of printing to standard output, so we
+The `println!` function is only capable of printing to standard output, so we
have to use something else to print to standard error.
### Checking Where Errors Are Written
@@ -57,7 +57,20 @@ instead.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-24/src/main.rs:here}}
+fn main() {
+ let args: Vec<String> = env::args().collect();
+
+ let config = Config::new(&args).unwrap_or_else(|err| {
+ eprintln!("Problem parsing arguments: {}", err);
+ process::exit(1);
+ });
+
+ if let Err(e) = minigrep::run(config) {
+ eprintln!("Application error: {}", e);
+
+ process::exit(1);
+ }
+}
```
<span class="caption">Listing 12-24: Writing error messages to standard error
diff --git a/book-original/src/ch13-01-closures.md b/book-pl-en/src/ch13-01-closures.md
index 09485da..6fd93a9 100644
--- a/book-original/src/ch13-01-closures.md
+++ b/book-pl-en/src/ch13-01-closures.md
@@ -25,12 +25,19 @@ it once so we don’t make the user wait more than necessary.
We’ll simulate calling this hypothetical algorithm with the function
`simulated_expensive_calculation` shown in Listing 13-1, which will print
`calculating slowly...`, wait for two seconds, and then return whatever number
-we passed in.
+we passed in:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-01/src/main.rs:here}}
+use std::thread;
+use std::time::Duration;
+
+fn simulated_expensive_calculation(intensity: u32) -> u32 {
+ println!("calculating slowly...");
+ thread::sleep(Duration::from_secs(2));
+ intensity
+}
```
<span class="caption">Listing 13-1: A function to stand in for a hypothetical
@@ -50,12 +57,21 @@ The required inputs are these:
* A random number that will generate some variety in the workout plans
The output will be the recommended workout plan. Listing 13-2 shows the `main`
-function we’ll use.
+function we’ll use:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-02/src/main.rs:here}}
+fn main() {
+ let simulated_user_specified_value = 10;
+ let simulated_random_number = 7;
+
+ generate_workout(
+ simulated_user_specified_value,
+ simulated_random_number
+ );
+}
+# fn generate_workout(intensity: u32, random_number: u32) {}
```
<span class="caption">Listing 13-2: A `main` function with hardcoded values to
@@ -76,7 +92,36 @@ changes in this example will be made to this function.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-03/src/main.rs:here}}
+# use std::thread;
+# use std::time::Duration;
+#
+# fn simulated_expensive_calculation(num: u32) -> u32 {
+# println!("calculating slowly...");
+# thread::sleep(Duration::from_secs(2));
+# num
+# }
+#
+fn generate_workout(intensity: u32, random_number: u32) {
+ if intensity < 25 {
+ println!(
+ "Today, do {} pushups!",
+ simulated_expensive_calculation(intensity)
+ );
+ println!(
+ "Next, do {} situps!",
+ simulated_expensive_calculation(intensity)
+ );
+ } else {
+ if random_number == 3 {
+ println!("Take a break today! Remember to stay hydrated!");
+ } else {
+ println!(
+ "Today, run for {} minutes!",
+ simulated_expensive_calculation(intensity)
+ );
+ }
+ }
+}
```
<span class="caption">Listing 13-3: The business logic that prints the workout
@@ -88,9 +133,11 @@ The first `if` block calls `simulated_expensive_calculation` twice, the `if`
inside the outer `else` doesn’t call it at all, and the code inside the
second `else` case calls it once.
+<!-- NEXT PARAGRAPH WRAPPED WEIRD INTENTIONALLY SEE #199 -->
+
The desired behavior of the `generate_workout` function is to first check
-whether the user wants a low-intensity workout (indicated by a number less than
-25) or a high-intensity workout (a number of 25 or greater).
+whether the user wants a low-intensity workout (indicated by a number less
+than 25) or a high-intensity workout (a number of 25 or greater).
Low-intensity workout plans will recommend a number of push-ups and sit-ups
based on the complex algorithm we’re simulating.
@@ -113,12 +160,44 @@ to call it if the result isn’t needed, and we still want to call it only once.
We could restructure the workout program in many ways. First, we’ll try
extracting the duplicated call to the `simulated_expensive_calculation`
-function into a variable, as shown in Listing 13-4.
+function into a variable, as shown in Listing 13-4:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-04/src/main.rs:here}}
+# use std::thread;
+# use std::time::Duration;
+#
+# fn simulated_expensive_calculation(num: u32) -> u32 {
+# println!("calculating slowly...");
+# thread::sleep(Duration::from_secs(2));
+# num
+# }
+#
+fn generate_workout(intensity: u32, random_number: u32) {
+ let expensive_result =
+ simulated_expensive_calculation(intensity);
+
+ if intensity < 25 {
+ println!(
+ "Today, do {} pushups!",
+ expensive_result
+ );
+ println!(
+ "Next, do {} situps!",
+ expensive_result
+ );
+ } else {
+ if random_number == 3 {
+ println!("Take a break today! Remember to stay hydrated!");
+ } else {
+ println!(
+ "Today, run for {} minutes!",
+ expensive_result
+ );
+ }
+ }
+}
```
<span class="caption">Listing 13-4: Extracting the calls to
@@ -140,12 +219,20 @@ Instead of always calling the `simulated_expensive_calculation` function before
the `if` blocks, we can define a closure and store the *closure* in a variable
rather than storing the result of the function call, as shown in Listing 13-5.
We can actually move the whole body of `simulated_expensive_calculation` within
-the closure we’re introducing here.
+the closure we’re introducing here:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-05/src/main.rs:here}}
+# use std::thread;
+# use std::time::Duration;
+#
+let expensive_closure = |num| {
+ println!("calculating slowly...");
+ thread::sleep(Duration::from_secs(2));
+ num
+};
+# expensive_closure(5);
```
<span class="caption">Listing 13-5: Defining a closure and storing it in the
@@ -163,7 +250,7 @@ closure—these are optional if the closure body is a single expression. The end
of the closure, after the curly brackets, needs a semicolon to complete the
`let` statement. The value returned from the last line in the closure body
(`num`) will be the value returned from the closure when it’s called, because
-that line doesn’t end in a semicolon; just as in function bodies.
+that line doesn’t end in a semicolon; just like in function bodies.
Note that this `let` statement means `expensive_closure` contains the
*definition* of an anonymous function, not the *resulting value* of calling the
@@ -175,12 +262,41 @@ With the closure defined, we can change the code in the `if` blocks to call the
closure to execute the code and get the resulting value. We call a closure like
we do a function: we specify the variable name that holds the closure
definition and follow it with parentheses containing the argument values we
-want to use, as shown in Listing 13-6.
+want to use, as shown in Listing 13-6:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-06/src/main.rs:here}}
+# use std::thread;
+# use std::time::Duration;
+#
+fn generate_workout(intensity: u32, random_number: u32) {
+ let expensive_closure = |num| {
+ println!("calculating slowly...");
+ thread::sleep(Duration::from_secs(2));
+ num
+ };
+
+ if intensity < 25 {
+ println!(
+ "Today, do {} pushups!",
+ expensive_closure(intensity)
+ );
+ println!(
+ "Next, do {} situps!",
+ expensive_closure(intensity)
+ );
+ } else {
+ if random_number == 3 {
+ println!("Take a break today! Remember to stay hydrated!");
+ } else {
+ println!(
+ "Today, run for {} minutes!",
+ expensive_closure(intensity)
+ );
+ }
+ }
+}
```
<span class="caption">Listing 13-6: Calling the `expensive_closure` we’ve
@@ -220,12 +336,19 @@ available.
As with variables, we can add type annotations if we want to increase
explicitness and clarity at the cost of being more verbose than is strictly
necessary. Annotating the types for the closure we defined in Listing 13-5
-would look like the definition shown in Listing 13-7.
+would look like the definition shown in Listing 13-7:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-07/src/main.rs:here}}
+# use std::thread;
+# use std::time::Duration;
+#
+let expensive_closure = |num: u32| -> u32 {
+ println!("calculating slowly...");
+ thread::sleep(Duration::from_secs(2));
+ num
+};
```
<span class="caption">Listing 13-7: Adding optional type annotations of the
@@ -249,9 +372,7 @@ The first line shows a function definition, and the second line shows a fully
annotated closure definition. The third line removes the type annotations from
the closure definition, and the fourth line removes the brackets, which are
optional because the closure body has only one expression. These are all valid
-definitions that will produce the same behavior when they’re called. Calling
-the closures is required for `add_one_v3` and `add_one_v4` to be able to
-compile because the types will be inferred from their usage.
+definitions that will produce the same behavior when they’re called.
Closure definitions will have one concrete type inferred for each of their
parameters and for their return value. For instance, Listing 13-8 shows the
@@ -264,7 +385,10 @@ first time and a `u32` the second time, we’ll get an error.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-08/src/main.rs:here}}
+let example_closure = |x| x;
+
+let s = example_closure(String::from("hello"));
+let n = example_closure(5);
```
<span class="caption">Listing 13-8: Attempting to call a closure whose types
@@ -273,7 +397,15 @@ are inferred with two different types</span>
The compiler gives us this error:
```text
-{{#include ../listings/ch13-functional-features/listing-13-08/output.txt}}
+error[E0308]: mismatched types
+ --> src/main.rs
+ |
+ | let n = example_closure(5);
+ | ^ expected struct `std::string::String`, found
+ integral variable
+ |
+ = note: expected type `std::string::String`
+ found type `{integer}`
```
The first time we call `example_closure` with the `String` value, the compiler
@@ -316,12 +448,17 @@ case, our closure has a parameter of type `u32` and returns a `u32`, so the
trait bound we specify is `Fn(u32) -> u32`.
Listing 13-9 shows the definition of the `Cacher` struct that holds a closure
-and an optional result value.
+and an optional result value:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-09/src/main.rs:here}}
+struct Cacher<T>
+ where T: Fn(u32) -> u32
+{
+ calculation: T,
+ value: Option<u32>,
+}
```
<span class="caption">Listing 13-9: Defining a `Cacher` struct that holds a
@@ -346,12 +483,39 @@ the result of the closure again, instead of executing the closure again, the
`Cacher` will return the result held in the `Some` variant.
The logic around the `value` field we’ve just described is defined in Listing
-13-10.
+13-10:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-10/src/main.rs:here}}
+# struct Cacher<T>
+# where T: Fn(u32) -> u32
+# {
+# calculation: T,
+# value: Option<u32>,
+# }
+#
+impl<T> Cacher<T>
+ where T: Fn(u32) -> u32
+{
+ fn new(calculation: T) -> Cacher<T> {
+ Cacher {
+ calculation,
+ value: None,
+ }
+ }
+
+ fn value(&mut self, arg: u32) -> u32 {
+ match self.value {
+ Some(v) => v,
+ None => {
+ let v = (self.calculation)(arg);
+ self.value = Some(v);
+ v
+ },
+ }
+ }
+}
```
<span class="caption">Listing 13-10: The caching logic of `Cacher`</span>
@@ -377,12 +541,70 @@ If `self.value` is `None`, the code calls the closure stored in
returns the value as well.
Listing 13-11 shows how we can use this `Cacher` struct in the function
-`generate_workout` from Listing 13-6.
+`generate_workout` from Listing 13-6:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-11/src/main.rs:here}}
+# use std::thread;
+# use std::time::Duration;
+#
+# struct Cacher<T>
+# where T: Fn(u32) -> u32
+# {
+# calculation: T,
+# value: Option<u32>,
+# }
+#
+# impl<T> Cacher<T>
+# where T: Fn(u32) -> u32
+# {
+# fn new(calculation: T) -> Cacher<T> {
+# Cacher {
+# calculation,
+# value: None,
+# }
+# }
+#
+# fn value(&mut self, arg: u32) -> u32 {
+# match self.value {
+# Some(v) => v,
+# None => {
+# let v = (self.calculation)(arg);
+# self.value = Some(v);
+# v
+# },
+# }
+# }
+# }
+#
+fn generate_workout(intensity: u32, random_number: u32) {
+ let mut expensive_result = Cacher::new(|num| {
+ println!("calculating slowly...");
+ thread::sleep(Duration::from_secs(2));
+ num
+ });
+
+ if intensity < 25 {
+ println!(
+ "Today, do {} pushups!",
+ expensive_result.value(intensity)
+ );
+ println!(
+ "Next, do {} situps!",
+ expensive_result.value(intensity)
+ );
+ } else {
+ if random_number == 3 {
+ println!("Take a break today! Remember to stay hydrated!");
+ } else {
+ println!(
+ "Today, run for {} minutes!",
+ expensive_result.value(intensity)
+ );
+ }
+ }
+}
```
<span class="caption">Listing 13-11: Using `Cacher` in the `generate_workout`
@@ -414,19 +636,29 @@ same value for the parameter `arg` to the `value` method. That is, this test of
`Cacher` will fail:
```rust,ignore,panics
-{{#rustdoc_include ../listings/ch13-functional-features/no-listing-01-failing-cacher-test/src/lib.rs:here}}
+#[test]
+fn call_with_different_values() {
+ let mut c = Cacher::new(|a| a);
+
+ let v1 = c.value(1);
+ let v2 = c.value(2);
+
+ assert_eq!(v2, 2);
+}
```
This test creates a new `Cacher` instance with a closure that returns the value
passed into it. We call the `value` method on this `Cacher` instance with an
`arg` value of 1 and then an `arg` value of 2, and we expect the call to
-`value` with the `arg` value of 2 to return 2.
+`value` with the `arg` value of 2 should return 2.
Run this test with the `Cacher` implementation in Listing 13-9 and Listing
13-10, and the test will fail on the `assert_eq!` with this message:
```text
-{{#include ../listings/ch13-functional-features/no-listing-01-failing-cacher-test/output.txt}}
+thread 'call_with_different_values' panicked at 'assertion failed: `(left == right)`
+ left: `1`,
+ right: `2`', src/main.rs
```
The problem is that the first time we called `c.value` with 1, the `Cacher`
@@ -455,12 +687,20 @@ have: they can capture their environment and access variables from the scope in
which they’re defined.
Listing 13-12 has an example of a closure stored in the `equal_to_x` variable
-that uses the `x` variable from the closure’s surrounding environment.
+that uses the `x` variable from the closure’s surrounding environment:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-12/src/main.rs}}
+fn main() {
+ let x = 4;
+
+ let equal_to_x = |z| z == x;
+
+ let y = 4;
+
+ assert!(equal_to_x(y));
+}
```
<span class="caption">Listing 13-12: Example of a closure that refers to a
@@ -476,13 +716,26 @@ code won’t compile:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch13-functional-features/no-listing-02-functions-cant-capture/src/main.rs}}
+fn main() {
+ let x = 4;
+
+ fn equal_to_x(z: i32) -> bool { z == x }
+
+ let y = 4;
+
+ assert!(equal_to_x(y));
+}
```
We get an error:
```text
-{{#include ../listings/ch13-functional-features/no-listing-02-functions-cant-capture/output.txt}}
+error[E0434]: can't capture dynamic environment in a fn item; use the || { ...
+} closure form instead
+ --> src/main.rs
+ |
+4 | fn equal_to_x(z: i32) -> bool { z == x }
+ | ^
```
The compiler even reminds us that this only works with closures!
@@ -529,13 +782,33 @@ yet compile.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch13-functional-features/no-listing-03-move-closures/src/main.rs}}
+fn main() {
+ let x = vec![1, 2, 3];
+
+ let equal_to_x = move |z| z == x;
+
+ println!("can't use x here: {:?}", x);
+
+ let y = vec![1, 2, 3];
+
+ assert!(equal_to_x(y));
+}
```
We receive the following error:
```text
-{{#include ../listings/ch13-functional-features/no-listing-03-move-closures/output.txt}}
+error[E0382]: use of moved value: `x`
+ --> src/main.rs:6:40
+ |
+4 | let equal_to_x = move |z| z == x;
+ | -------- value moved (into closure) here
+5 |
+6 | println!("can't use x here: {:?}", x);
+ | ^ value used here after move
+ |
+ = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not
+ implement the `Copy` trait
```
The `x` value is moved into the closure when the closure is defined, because we
diff --git a/book-original/src/ch13-02-iterators.md b/book-pl-en/src/ch13-02-iterators.md
index 0b40e88..0dfc6e3 100644
--- a/book-original/src/ch13-02-iterators.md
+++ b/book-pl-en/src/ch13-02-iterators.md
@@ -8,11 +8,13 @@ have to reimplement that logic yourself.
In Rust, iterators are *lazy*, meaning they have no effect until you call
methods that consume the iterator to use it up. For example, the code in
Listing 13-13 creates an iterator over the items in the vector `v1` by calling
-the `iter` method defined on `Vec<T>`. This code by itself doesn’t do anything
+the `iter` method defined on `Vec`. This code by itself doesn’t do anything
useful.
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-13/src/main.rs:here}}
+let v1 = vec![1, 2, 3];
+
+let v1_iter = v1.iter();
```
<span class="caption">Listing 13-13: Creating an iterator</span>
@@ -28,7 +30,13 @@ called using the iterator in `v1_iter`, each element in the iterator is used in
one iteration of the loop, which prints out each value.
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-14/src/main.rs:here}}
+let v1 = vec![1, 2, 3];
+
+let v1_iter = v1.iter();
+
+for val in v1_iter {
+ println!("Got: {}", val);
+}
```
<span class="caption">Listing 13-14: Using an iterator in a `for` loop</span>
@@ -50,7 +58,7 @@ All iterators implement a trait named `Iterator` that is defined in the
standard library. The definition of the trait looks like this:
```rust
-pub trait Iterator {
+trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
@@ -73,12 +81,22 @@ The `Iterator` trait only requires implementors to define one method: the
We can call the `next` method on iterators directly; Listing 13-15 demonstrates
what values are returned from repeated calls to `next` on the iterator created
-from the vector.
+from the vector:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-15/src/lib.rs:here}}
+#[test]
+fn iterator_demonstration() {
+ let v1 = vec![1, 2, 3];
+
+ let mut v1_iter = v1.iter();
+
+ assert_eq!(v1_iter.next(), Some(&1));
+ assert_eq!(v1_iter.next(), Some(&2));
+ assert_eq!(v1_iter.next(), Some(&3));
+ assert_eq!(v1_iter.next(), None);
+}
```
<span class="caption">Listing 13-15: Calling the `next` method on an
@@ -117,7 +135,16 @@ test illustrating a use of the `sum` method:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-16/src/lib.rs:here}}
+#[test]
+fn iterator_sum() {
+ let v1 = vec![1, 2, 3];
+
+ let v1_iter = v1.iter();
+
+ let total: i32 = v1_iter.sum();
+
+ assert_eq!(total, 6);
+}
```
<span class="caption">Listing 13-16: Calling the `sum` method to get the total
@@ -142,7 +169,9 @@ incremented by 1. However, this code produces a warning:
<span class="filename">Filename: src/main.rs</span>
```rust,not_desired_behavior
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-17/src/main.rs:here}}
+let v1: Vec<i32> = vec![1, 2, 3];
+
+v1.iter().map(|x| x + 1);
```
<span class="caption">Listing 13-17: Calling the iterator adaptor `map` to
@@ -151,7 +180,14 @@ create a new iterator</span>
The warning we get is this:
```text
-{{#include ../listings/ch13-functional-features/listing-13-17/output.txt}}
+warning: unused `std::iter::Map` which must be used: iterator adaptors are lazy
+and do nothing unless consumed
+ --> src/main.rs:4:5
+ |
+4 | v1.iter().map(|x| x + 1);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: #[warn(unused_must_use)] on by default
```
The code in Listing 13-17 doesn’t do anything; the closure we’ve specified
@@ -169,7 +205,11 @@ containing each item from the original vector incremented by 1.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-18/src/main.rs:here}}
+let v1: Vec<i32> = vec![1, 2, 3];
+
+let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();
+
+assert_eq!(v2, vec![2, 3, 4]);
```
<span class="caption">Listing 13-18: Calling the `map` method to create a new
@@ -197,7 +237,36 @@ instances. It will return only shoes that are the specified size.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-19/src/lib.rs}}
+#[derive(PartialEq, Debug)]
+struct Shoe {
+ size: u32,
+ style: String,
+}
+
+fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
+ shoes.into_iter()
+ .filter(|s| s.size == shoe_size)
+ .collect()
+}
+
+#[test]
+fn filters_by_size() {
+ let shoes = vec![
+ Shoe { size: 10, style: String::from("sneaker") },
+ Shoe { size: 13, style: String::from("sandal") },
+ Shoe { size: 10, style: String::from("boot") },
+ ];
+
+ let in_my_size = shoes_in_my_size(shoes, 10);
+
+ assert_eq!(
+ in_my_size,
+ vec![
+ Shoe { size: 10, style: String::from("sneaker") },
+ Shoe { size: 10, style: String::from("boot") },
+ ]
+ );
+}
```
<span class="caption">Listing 13-19: Using the `filter` method with a closure
@@ -242,7 +311,15 @@ Listing 13-20 has the definition of the `Counter` struct and an associated
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-20/src/lib.rs}}
+struct Counter {
+ count: u32,
+}
+
+impl Counter {
+ fn new() -> Counter {
+ Counter { count: 0 }
+ }
+}
```
<span class="caption">Listing 13-20: Defining the `Counter` struct and a `new`
@@ -262,7 +339,23 @@ iterator is used, as shown in Listing 13-21:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-21/src/lib.rs:here}}
+# struct Counter {
+# count: u32,
+# }
+#
+impl Iterator for Counter {
+ type Item = u32;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.count += 1;
+
+ if self.count < 6 {
+ Some(self.count)
+ } else {
+ None
+ }
+ }
+}
```
<span class="caption">Listing 13-21: Implementing the `Iterator` trait on our
@@ -273,10 +366,9 @@ iterator will return `u32` values. Again, don’t worry about associated types
yet, we’ll cover them in Chapter 19.
We want our iterator to add 1 to the current state, so we initialized `count`
-to 0 so it would return 1 first. If the value of `count` is less than 5, `next`
-will increment `count` and return the current value wrapped in `Some`. Once
-`count` is 5, our iterator will stop incrementing `count` and always return
-`None`.
+to 0 so it would return 1 first. If the value of `count` is less than 6, `next`
+will return the current value wrapped in `Some`, but if `count` is 6 or higher,
+our iterator will return `None`.
#### Using Our `Counter` Iterator’s `next` Method
@@ -288,7 +380,35 @@ with the iterator created from a vector in Listing 13-15.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-22/src/lib.rs:here}}
+# struct Counter {
+# count: u32,
+# }
+#
+# impl Iterator for Counter {
+# type Item = u32;
+#
+# fn next(&mut self) -> Option<Self::Item> {
+# self.count += 1;
+#
+# if self.count < 6 {
+# Some(self.count)
+# } else {
+# None
+# }
+# }
+# }
+#
+#[test]
+fn calling_next_directly() {
+ let mut counter = Counter::new();
+
+ assert_eq!(counter.next(), Some(1));
+ assert_eq!(counter.next(), Some(2));
+ assert_eq!(counter.next(), Some(3));
+ assert_eq!(counter.next(), Some(4));
+ assert_eq!(counter.next(), Some(5));
+ assert_eq!(counter.next(), None);
+}
```
<span class="caption">Listing 13-22: Testing the functionality of the `next`
@@ -313,7 +433,41 @@ together, we could do so, as shown in the test in Listing 13-23:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-23/src/lib.rs:here}}
+# struct Counter {
+# count: u32,
+# }
+#
+# impl Counter {
+# fn new() -> Counter {
+# Counter { count: 0 }
+# }
+# }
+#
+# impl Iterator for Counter {
+# // Our iterator will produce u32s
+# type Item = u32;
+#
+# fn next(&mut self) -> Option<Self::Item> {
+# // increment our count. This is why we started at zero.
+# self.count += 1;
+#
+# // check to see if we've finished counting or not.
+# if self.count < 6 {
+# Some(self.count)
+# } else {
+# None
+# }
+# }
+# }
+#
+#[test]
+fn using_other_iterator_trait_methods() {
+ let sum: u32 = Counter::new().zip(Counter::new().skip(1))
+ .map(|(a, b)| a * b)
+ .filter(|x| x % 3 == 0)
+ .sum();
+ assert_eq!(18, sum);
+}
```
<span class="caption">Listing 13-23: Using a variety of `Iterator` trait
diff --git a/book-original/src/ch13-03-improving-our-io-project.md b/book-pl-en/src/ch13-03-improving-our-io-project.md
index 0473b2c..e6ee68d 100644
--- a/book-original/src/ch13-03-improving-our-io-project.md
+++ b/book-pl-en/src/ch13-03-improving-our-io-project.md
@@ -5,6 +5,7 @@ Chapter 12 by using iterators to make places in the code clearer and more
concise. Let’s look at how iterators can improve our implementation of the
`Config::new` function and the `search` function.
+
### Removing a `clone` Using an Iterator
In Listing 12-6, we added code that took a slice of `String` values and created
@@ -16,7 +17,20 @@ Listing 12-23:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch13-functional-features/listing-12-23-reproduced/src/lib.rs:ch13}}
+impl Config {
+ pub fn new(args: &[String]) -> Result<Config, &'static str> {
+ if args.len() < 3 {
+ return Err("not enough arguments");
+ }
+
+ let query = args[1].clone();
+ let filename = args[2].clone();
+
+ let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
+
+ Ok(Config { query, filename, case_sensitive })
+ }
+}
```
<span class="caption">Listing 13-24: Reproduction of the `Config::new` function
@@ -47,7 +61,16 @@ Open your I/O project’s *src/main.rs* file, which should look like this:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch13-functional-features/listing-12-24-reproduced/src/main.rs:ch13}}
+fn main() {
+ let args: Vec<String> = env::args().collect();
+
+ let config = Config::new(&args).unwrap_or_else(|err| {
+ eprintln!("Problem parsing arguments: {}", err);
+ process::exit(1);
+ });
+
+ // --snip--
+}
```
We’ll change the start of the `main` function that we had in Listing 12-24 to
@@ -57,7 +80,14 @@ well.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-25/src/main.rs:here}}
+fn main() {
+ let config = Config::new(env::args()).unwrap_or_else(|err| {
+ eprintln!("Problem parsing arguments: {}", err);
+ process::exit(1);
+ });
+
+ // --snip--
+}
```
<span class="caption">Listing 13-25: Passing the return value of `env::args` to
@@ -76,7 +106,9 @@ body.
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-26/src/lib.rs:here}}
+impl Config {
+ pub fn new(mut args: std::env::Args) -> Result<Config, &'static str> {
+ // --snip--
```
<span class="caption">Listing 13-26: Updating the signature of `Config::new` to
@@ -99,7 +131,34 @@ Listing 12-23 to use the `next` method:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-27/src/lib.rs:here}}
+# fn main() {}
+# use std::env;
+#
+# struct Config {
+# query: String,
+# filename: String,
+# case_sensitive: bool,
+# }
+#
+impl Config {
+ pub fn new(mut args: std::env::Args) -> Result<Config, &'static str> {
+ args.next();
+
+ let query = match args.next() {
+ Some(arg) => arg,
+ None => return Err("Didn't get a query string"),
+ };
+
+ let filename = match args.next() {
+ Some(arg) => arg,
+ None => return Err("Didn't get a file name"),
+ };
+
+ let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
+
+ Ok(Config { query, filename, case_sensitive })
+ }
+}
```
<span class="caption">Listing 13-27: Changing the body of `Config::new` to use
@@ -121,7 +180,17 @@ project, which is reproduced here in Listing 13-28 as it was in Listing 12-19:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-19/src/lib.rs:ch13}}
+pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+ let mut results = Vec::new();
+
+ for line in contents.lines() {
+ if line.contains(query) {
+ results.push(line);
+ }
+ }
+
+ results
+}
```
<span class="caption">Listing 13-28: The implementation of the `search`
@@ -137,7 +206,11 @@ concurrent access to the `results` vector. Listing 13-29 shows this change:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch13-functional-features/listing-13-29/src/lib.rs:here}}
+pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+ contents.lines()
+ .filter(|line| line.contains(query))
+ .collect()
+}
```
<span class="caption">Listing 13-29: Using iterator adaptor methods in the
diff --git a/book-original/src/ch14-00-more-about-cargo.md b/book-pl-en/src/ch14-00-more-about-cargo.md
index d08d8cc..d5904b2 100644
--- a/book-original/src/ch14-00-more-about-cargo.md
+++ b/book-pl-en/src/ch14-00-more-about-cargo.md
@@ -5,9 +5,9 @@ our code, but it can do a lot more. In this chapter, we’ll discuss some of its
other, more advanced features to show you how to do the following:
* Customize your build through release profiles
-* Publish libraries on [crates.io](https://crates.io/)<!-- ignore -->
+* Publish libraries on [crates.io](https://crates.io)<!-- ignore -->
* Organize large projects with workspaces
-* Install binaries from [crates.io](https://crates.io/)<!-- ignore -->
+* Install binaries from [crates.io](https://crates.io)<!-- ignore -->
* Extend Cargo using custom commands
Cargo can do even more than what we cover in this chapter, so for a full
diff --git a/book-original/src/ch14-01-release-profiles.md b/book-pl-en/src/ch14-01-release-profiles.md
index 24a36ae..c150f6a 100644
--- a/book-original/src/ch14-01-release-profiles.md
+++ b/book-pl-en/src/ch14-01-release-profiles.md
@@ -12,18 +12,11 @@ and the `release` profile has good defaults for release builds.
These profile names might be familiar from the output of your builds:
-<!-- manual-regeneration
-anywhere, run:
-cargo build
-cargo build --release
-and ensure output below is accurate
--->
-
```text
$ cargo build
- Finished dev [unoptimized + debuginfo] target(s) in 0.0s
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
$ cargo build --release
- Finished release [optimized] target(s) in 0.0s
+ Finished release [optimized] target(s) in 0.0 secs
```
The `dev` and `release` shown in this build output indicate that the compiler
@@ -73,4 +66,4 @@ Cargo will use the defaults for the `dev` profile plus our customization to
optimizations than the default, but not as many as in a release build.
For the full list of configuration options and defaults for each profile, see
-[Cargo’s documentation](https://doc.rust-lang.org/cargo/reference/manifest.html#the-profile-sections).
+[Cargo’s documentation](https://doc.rust-lang.org/cargo/).
diff --git a/book-original/src/ch14-02-publishing-to-crates-io.md b/book-pl-en/src/ch14-02-publishing-to-crates-io.md
index 4e5c220..b67dd19 100644
--- a/book-original/src/ch14-02-publishing-to-crates-io.md
+++ b/book-pl-en/src/ch14-02-publishing-to-crates-io.md
@@ -1,9 +1,9 @@
## Publishing a Crate to Crates.io
-We’ve used packages from [crates.io](https://crates.io/)<!-- ignore --> as
+We’ve used packages from [crates.io](https://crates.io)<!-- ignore --> as
dependencies of our project, but you can also share your code with other people
by publishing your own packages. The crate registry at
-[crates.io](https://crates.io/)<!-- ignore --> distributes the source code of
+[crates.io](https://crates.io)<!-- ignore --> distributes the source code of
your packages, so it primarily hosts code that is open source.
Rust and Cargo have features that help make your published package easier for
@@ -29,7 +29,18 @@ for an `add_one` function in a crate named `my_crate`:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-01/src/lib.rs}}
+/// Adds one to the number given.
+///
+/// # Examples
+///
+/// ```
+/// let five = 5;
+///
+/// assert_eq!(6, my_crate::add_one(5));
+/// ```
+pub fn add_one(x: i32) -> i32 {
+ x + 1
+}
```
<span class="caption">Listing 14-1: A documentation comment for a
@@ -84,12 +95,6 @@ that don’t work because the code has changed since the documentation was
written. If we run `cargo test` with the documentation for the `add_one`
function from Listing 14-1, we will see a section in the test results like this:
-<!-- manual-regeneration
-cd listings/ch14-more-about-cargo/listing-14-01/
-cargo test
-copy just the doc-tests section below
--->
-
```text
Doc-tests my_crate
@@ -119,7 +124,13 @@ shown in Listing 14-2:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-02/src/lib.rs:here}}
+//! # My Crate
+//!
+//! `my_crate` is a collection of utilities to make performing certain
+//! calculations more convenient.
+
+/// Adds one to the number given.
+// --snip--
```
<span class="caption">Listing 14-2: Documentation for the `my_crate` crate as a
@@ -176,8 +187,36 @@ function named `mix`, as shown in Listing 14-3:
<span class="filename">Filename: src/lib.rs</span>
-```rust
-{{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-03/src/lib.rs:here}}
+```rust,ignore
+//! # Art
+//!
+//! A library for modeling artistic concepts.
+
+pub mod kinds {
+ /// The primary colors according to the RYB color model.
+ pub enum PrimaryColor {
+ Red,
+ Yellow,
+ Blue,
+ }
+
+ /// The secondary colors according to the RYB color model.
+ pub enum SecondaryColor {
+ Orange,
+ Green,
+ Purple,
+ }
+}
+
+pub mod utils {
+ use kinds::*;
+
+ /// Combines two primary colors in equal amounts to create
+ /// a secondary color.
+ pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
+ // --snip--
+ }
+}
```
<span class="caption">Listing 14-3: An `art` library with items organized into
@@ -203,7 +242,14 @@ currently defined. Listing 14-4 shows an example of a crate that uses the
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-04/src/main.rs}}
+use art::kinds::PrimaryColor;
+use art::utils::mix;
+
+fn main() {
+ let red = PrimaryColor::Red;
+ let yellow = PrimaryColor::Yellow;
+ mix(red, yellow);
+}
```
<span class="caption">Listing 14-4: A crate using the `art` crate’s items with
@@ -227,7 +273,21 @@ items at the top level, as shown in Listing 14-5:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-05/src/lib.rs:here}}
+//! # Art
+//!
+//! A library for modeling artistic concepts.
+
+pub use kinds::PrimaryColor;
+pub use kinds::SecondaryColor;
+pub use utils::mix;
+
+pub mod kinds {
+ // --snip--
+}
+
+pub mod utils {
+ // --snip--
+}
```
<span class="caption">Listing 14-5: Adding `pub use` statements to re-export
@@ -249,7 +309,12 @@ structure in Listing 14-5, as shown in Listing 14-6:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-06/src/main.rs:here}}
+use art::PrimaryColor;
+use art::mix;
+
+fn main() {
+ // --snip--
+}
```
<span class="caption">Listing 14-6: A program using the re-exported items from
@@ -269,8 +334,8 @@ differs from their public API.
### Setting Up a Crates.io Account
Before you can publish any crates, you need to create an account on
-[crates.io](https://crates.io/)<!-- ignore --> and get an API token. To do so,
-visit the home page at [crates.io](https://crates.io/)<!-- ignore --> and log in
+[crates.io](https://crates.io)<!-- ignore --> and get an API token. To do so,
+visit the home page at [crates.io](https://crates.io)<!-- ignore --> and log in
via a GitHub account. (The GitHub account is currently a requirement, but the
site might support other ways of creating an account in the future.) Once
you’re logged in, visit your account settings at
@@ -284,7 +349,7 @@ $ cargo login abcdefghijklmnopqrstuvwxyz012345
This command will inform Cargo of your API token and store it locally in
*~/.cargo/credentials*. Note that this token is a *secret*: do not share it
with anyone else. If you do share it with anyone for any reason, you should
-revoke it and generate a new token on [crates.io](https://crates.io/)<!-- ignore
+revoke it and generate a new token on [crates.io](https://crates.io)<!-- ignore
-->.
### Adding Metadata to a New Crate
@@ -295,7 +360,7 @@ to the `[package]` section of the crate’s *Cargo.toml* file.
Your crate will need a unique name. While you’re working on a crate locally,
you can name a crate whatever you’d like. However, crate names on
-[crates.io](https://crates.io/)<!-- ignore --> are allocated on a first-come,
+[crates.io](https://crates.io)<!-- ignore --> are allocated on a first-come,
first-served basis. Once a crate name is taken, no one else can publish a crate
with that name. Before attempting to publish a crate, search for the name you
want to use on the site. If the name has been used by another crate, you will
@@ -312,19 +377,13 @@ name = "guessing_game"
Even if you’ve chosen a unique name, when you run `cargo publish` to publish
the crate at this point, you’ll get a warning and then an error:
-<!-- manual-regeneration
-cd listings/ch14-more-about-cargo/listing-14-01/
-cargo publish
-copy just the relevant lines below
--->
-
```text
$ cargo publish
- Updating crates.io index
-warning: manifest has no description, license, license-file, documentation, homepage or repository.
-See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
+ Updating registry `https://github.com/rust-lang/crates.io-index`
+warning: manifest has no description, license, license-file, documentation,
+homepage or repository.
--snip--
-error: api errors (status 200 OK): missing or empty metadata fields: description, license. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for how to upload metadata
+error: api errors: missing or empty metadata fields: description, license.
```
The reason is that you’re missing some crucial information: a description and
@@ -387,33 +446,27 @@ easily.
Now that you’ve created an account, saved your API token, chosen a name for
your crate, and specified the required metadata, you’re ready to publish!
Publishing a crate uploads a specific version to
-[crates.io](https://crates.io/)<!-- ignore --> for others to use.
+[crates.io](https://crates.io)<!-- ignore --> for others to use.
Be careful when publishing a crate because a publish is *permanent*. The
version can never be overwritten, and the code cannot be deleted. One major
-goal of [crates.io](https://crates.io/)<!-- ignore --> is to act as a permanent
+goal of [crates.io](https://crates.io)<!-- ignore --> is to act as a permanent
archive of code so that builds of all projects that depend on crates from
-[crates.io](https://crates.io/)<!-- ignore --> will continue to work. Allowing
+[crates.io](https://crates.io)<!-- ignore --> will continue to work. Allowing
version deletions would make fulfilling that goal impossible. However, there is
no limit to the number of crate versions you can publish.
Run the `cargo publish` command again. It should succeed now:
-<!-- manual-regeneration
-go to some valid crate, publish a new version
-cargo publish
-copy just the relevant lines below
--->
-
```text
$ cargo publish
- Updating crates.io index
- Packaging guessing_game v0.1.0 (file:///projects/guessing_game)
- Verifying guessing_game v0.1.0 (file:///projects/guessing_game)
- Compiling guessing_game v0.1.0
+ Updating registry `https://github.com/rust-lang/crates.io-index`
+Packaging guessing_game v0.1.0 (file:///projects/guessing_game)
+Verifying guessing_game v0.1.0 (file:///projects/guessing_game)
+Compiling guessing_game v0.1.0
(file:///projects/guessing_game/target/package/guessing_game-0.1.0)
- Finished dev [unoptimized + debuginfo] target(s) in 0.19s
- Uploading guessing_game v0.1.0 (file:///projects/guessing_game)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.19 secs
+Uploading guessing_game v0.1.0 (file:///projects/guessing_game)
```
Congratulations! You’ve now shared your code with the Rust community, and
diff --git a/book-original/src/ch14-03-cargo-workspaces.md b/book-pl-en/src/ch14-03-cargo-workspaces.md
index 6054c73..07c8719 100644
--- a/book-original/src/ch14-03-cargo-workspaces.md
+++ b/book-pl-en/src/ch14-03-cargo-workspaces.md
@@ -33,22 +33,19 @@ by specifying the path to our binary crate; in this case, that path is *adder*:
<span class="filename">Filename: Cargo.toml</span>
```toml
-{{#include ../listings/ch14-more-about-cargo/no-listing-01-workspace-with-adder-crate/add/Cargo.toml}}
+[workspace]
+
+members = [
+ "adder",
+]
```
Next, we’ll create the `adder` binary crate by running `cargo new` within the
*add* directory:
-<!-- manual-regeneration
-cd listings/ch14-more-about-cargo/output-only-01-adder-crate/add
-rm -rf adder
-cargo new adder
-copy output below
--->
-
```text
$ cargo new adder
- Created binary (application) `adder` package
+ Created binary (application) `adder` project
```
At this point, we can build the workspace by running `cargo build`. The files
@@ -84,21 +81,19 @@ Change the top-level *Cargo.toml* to specify the *add-one* path in the
<span class="filename">Filename: Cargo.toml</span>
```toml
-{{#include ../listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/Cargo.toml}}
+[workspace]
+
+members = [
+ "adder",
+ "add-one",
+]
```
Then generate a new library crate named `add-one`:
-<!-- manual-regeneration
-cd listings/ch14-more-about-cargo/output-only-02-add-one/add
-rm -rf add-one
-cargo new add-one --lib
-copy output below
--->
-
```text
$ cargo new add-one --lib
- Created library `add-one` package
+ Created library `add-one` project
```
Your *add* directory should now have these directories and files:
@@ -122,7 +117,9 @@ In the *add-one/src/lib.rs* file, let’s add an `add_one` function:
<span class="filename">Filename: add-one/src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/add-one/src/lib.rs}}
+pub fn add_one(x: i32) -> i32 {
+ x + 1
+}
```
Now that we have a library crate in the workspace, we can have the binary crate
@@ -132,21 +129,28 @@ dependency on `add-one` to *adder/Cargo.toml*.
<span class="filename">Filename: adder/Cargo.toml</span>
```toml
-{{#include ../listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/adder/Cargo.toml:7:9}}
+[dependencies]
+
+add-one = { path = "../add-one" }
```
Cargo doesn’t assume that crates in a workspace will depend on each other, so
we need to be explicit about the dependency relationships between the crates.
Next, let’s use the `add_one` function from the `add-one` crate in the `adder`
-crate. Open the *adder/src/main.rs* file and add a `use` line at the top to
+crate. Open the *adder/src/main.rs* file and add an `use` line at the top to
bring the new `add-one` library crate into scope. Then change the `main`
-function to call the `add_one` function, as in Listing 14-7.
+function to call the `add_one` function, as in Listing 14-7:
<span class="filename">Filename: adder/src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-07/add/adder/src/main.rs}}
+use add_one;
+
+fn main() {
+ let num = 10;
+ println!("Hello, world! {} plus one is {}!", num, add_one::add_one(num));
+}
```
<span class="caption">Listing 14-7: Using the `add-one` library crate from the
@@ -155,32 +159,20 @@ function to call the `add_one` function, as in Listing 14-7.
Let’s build the workspace by running `cargo build` in the top-level *add*
directory!
-<!-- manual-regeneration
-cd listings/ch14-more-about-cargo/listing-14-07/add
-cargo build
-copy output below; the output updating script doesn't handle subdirectories in paths properly
--->
-
```text
$ cargo build
Compiling add-one v0.1.0 (file:///projects/add/add-one)
Compiling adder v0.1.0 (file:///projects/add/adder)
- Finished dev [unoptimized + debuginfo] target(s) in 0.68s
+ Finished dev [unoptimized + debuginfo] target(s) in 0.68 secs
```
To run the binary crate from the *add* directory, we need to specify which
package in the workspace we want to use by using the `-p` argument and the
package name with `cargo run`:
-<!-- manual-regeneration
-cd listings/ch14-more-about-cargo/listing-14-07/add
-cargo run -p adder
-copy output below; the output updating script doesn't handle subdirectories in paths properly
--->
-
```text
$ cargo run -p adder
- Finished dev [unoptimized + debuginfo] target(s) in 0.0s
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/adder`
Hello, world! 10 plus one is 11!
```
@@ -200,60 +192,44 @@ each other. Let’s add the `rand` crate to the `[dependencies]` section in the
*add-one/Cargo.toml* file to be able to use the `rand` crate in the `add-one`
crate:
-<!-- When updating the version of `rand` used, also update the version of
-`rand` used in these files so they all match:
-* ch02-00-guessing-game-tutorial.md
-* ch07-04-bringing-paths-into-scope-with-the-use-keyword.md
--->
-
<span class="filename">Filename: add-one/Cargo.toml</span>
```toml
-{{#include ../listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add-one/Cargo.toml:7:8}}
+[dependencies]
+
+rand = "0.3.14"
```
We can now add `use rand;` to the *add-one/src/lib.rs* file, and building the
whole workspace by running `cargo build` in the *add* directory will bring in
and compile the `rand` crate:
-<!-- manual-regeneration
-cd listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add
-cargo build
-copy output below; the output updating script doesn't handle subdirectories in paths properly
--->
-
```text
$ cargo build
- Updating crates.io index
- Downloaded rand v0.5.5
+ Updating registry `https://github.com/rust-lang/crates.io-index`
+ Downloading rand v0.3.14
--snip--
- Compiling rand v0.5.6
+ Compiling rand v0.3.14
Compiling add-one v0.1.0 (file:///projects/add/add-one)
Compiling adder v0.1.0 (file:///projects/add/adder)
- Finished dev [unoptimized + debuginfo] target(s) in 10.18s
+ Finished dev [unoptimized + debuginfo] target(s) in 10.18 secs
```
The top-level *Cargo.lock* now contains information about the dependency of
`add-one` on `rand`. However, even though `rand` is used somewhere in the
workspace, we can’t use it in other crates in the workspace unless we add
-`rand` to their *Cargo.toml* files as well. For example, if we add `use rand;`
-to the *adder/src/main.rs* file for the `adder` crate, we’ll get an error:
-
-<!-- manual-regeneration
-cd listings/ch14-more-about-cargo/output-only-03-use-rand/add
-cargo build
-copy output below; the output updating script doesn't handle subdirectories in paths properly
--->
+`rand` to their *Cargo.toml* files as well. For example, if we add `extern
+crate rand;` to the *adder/src/main.rs* file for the `adder` crate, we’ll get
+an error:
```text
$ cargo build
- --snip--
Compiling adder v0.1.0 (file:///projects/add/adder)
-error[E0432]: unresolved import `rand`
- --> adder/src/main.rs:2:5
+error: use of unstable library feature 'rand': use `rand` from crates.io (see
+issue #27703)
+ --> adder/src/main.rs:1:1
|
-2 | use rand;
- | ^^^^ no `rand` external crate
+1 | use rand;
```
To fix this, edit the *Cargo.toml* file for the `adder` crate and indicate that
@@ -273,22 +249,28 @@ within the `add_one` crate:
<span class="filename">Filename: add-one/src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch14-more-about-cargo/no-listing-04-workspace-with-tests/add/add-one/src/lib.rs}}
+pub fn add_one(x: i32) -> i32 {
+ x + 1
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ assert_eq!(3, add_one(2));
+ }
+}
```
Now run `cargo test` in the top-level *add* directory:
-<!-- manual-regeneration
-cd listings/ch14-more-about-cargo/no-listing-04-workspace-with-tests/add
-cargo test
-copy output below; the output updating script doesn't handle subdirectories in paths properly
--->
-
```text
$ cargo test
Compiling add-one v0.1.0 (file:///projects/add/add-one)
Compiling adder v0.1.0 (file:///projects/add/adder)
- Finished test [unoptimized + debuginfo] target(s) in 0.27s
+ Finished dev [unoptimized + debuginfo] target(s) in 0.27 secs
Running target/debug/deps/add_one-f0253159197f7841
running 1 test
@@ -296,7 +278,7 @@ test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
- Running target/debug/deps/adder-49979ff40686fa8e
+ Running target/debug/deps/adder-f88af9d2cc175a5e
running 0 tests
@@ -319,15 +301,9 @@ We can also run tests for one particular crate in a workspace from the
top-level directory by using the `-p` flag and specifying the name of the crate
we want to test:
-<!-- manual-regeneration
-cd listings/ch14-more-about-cargo/no-listing-04-workspace-with-tests/add
-cargo test -p add-one
-copy output below; the output updating script doesn't handle subdirectories in paths properly
--->
-
```text
$ cargo test -p add-one
- Finished test [unoptimized + debuginfo] target(s) in 0.00s
+ Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running target/debug/deps/add_one-b3235fea9a156f74
running 1 test
@@ -345,11 +321,11 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
This output shows `cargo test` only ran the tests for the `add-one` crate and
didn’t run the `adder` crate tests.
-If you publish the crates in the workspace to [crates.io](https://crates.io/),
-each crate in the workspace will need to be published separately. The `cargo
-publish` command does not have an `--all` flag or a `-p` flag, so you must
-change to each crate’s directory and run `cargo publish` on each crate in the
-workspace to publish the crates.
+If you publish the crates in the workspace to *https://crates.io/*, each crate
+in the workspace will need to be published separately. The `cargo publish`
+command does not have an `--all` flag or a `-p` flag, so you must change to
+each crate’s directory and run `cargo publish` on each crate in the workspace
+to publish the crates.
For additional practice, add an `add-two` crate to this workspace in a similar
way as the `add-one` crate!
diff --git a/book-original/src/ch14-04-installing-binaries.md b/book-pl-en/src/ch14-04-installing-binaries.md
index 6b2f58b..826b970 100644
--- a/book-original/src/ch14-04-installing-binaries.md
+++ b/book-pl-en/src/ch14-04-installing-binaries.md
@@ -3,7 +3,7 @@
The `cargo install` command allows you to install and use binary crates
locally. This isn’t intended to replace system packages; it’s meant to be a
convenient way for Rust developers to install tools that others have shared on
-[crates.io](https://crates.io/)<!-- ignore -->. Note that you can only install
+[crates.io](https://crates.io)<!-- ignore -->. Note that you can only install
packages that have binary targets. A *binary target* is the runnable program
that is created if the crate has a *src/main.rs* file or another file specified
as a binary, as opposed to a library target that isn’t runnable on its own but
@@ -21,24 +21,17 @@ For example, in Chapter 12 we mentioned that there’s a Rust implementation of
the `grep` tool called `ripgrep` for searching files. If we want to install
`ripgrep`, we can run the following:
-<!-- manual-regeneration
-cargo install something you don't have, copy relevant output below
--->
-
```text
$ cargo install ripgrep
- Updating crates.io index
- Downloaded ripgrep v11.0.2
- Downloaded 1 crate (243.3 KB) in 0.88s
- Installing ripgrep v11.0.2
---snip--
- Compiling ripgrep v11.0.2
- Finished release [optimized] target(s) in 3m 10s
+Updating registry `https://github.com/rust-lang/crates.io-index`
+ Downloading ripgrep v0.3.2
+ --snip--
+ Compiling ripgrep v0.3.2
+ Finished release [optimized + debuginfo] target(s) in 97.91 secs
Installing ~/.cargo/bin/rg
- Installed package `ripgrep v11.0.2` (executable `rg`)
```
-The second-to-last line of the output shows the location and the name of the
-installed binary, which in the case of `ripgrep` is `rg`. As long as the
-installation directory is in your `$PATH`, as mentioned previously, you can
-then run `rg --help` and start using a faster, rustier tool for searching files!
+The last line of the output shows the location and the name of the installed
+binary, which in the case of `ripgrep` is `rg`. As long as the installation
+directory is in your `$PATH`, as mentioned previously, you can then run `rg
+--help` and start using a faster, rustier tool for searching files!
diff --git a/book-original/src/ch14-05-extending-cargo.md b/book-pl-en/src/ch14-05-extending-cargo.md
index bd22871..d70d227 100644
--- a/book-original/src/ch14-05-extending-cargo.md
+++ b/book-pl-en/src/ch14-05-extending-cargo.md
@@ -9,9 +9,9 @@ built-in Cargo tools is a super convenient benefit of Cargo’s design!
## Summary
-Sharing code with Cargo and [crates.io](https://crates.io/)<!-- ignore --> is
+Sharing code with Cargo and [crates.io](https://crates.io)<!-- ignore --> is
part of what makes the Rust ecosystem useful for many different tasks. Rust’s
standard library is small and stable, but crates are easy to share, use, and
improve on a timeline different from that of the language. Don’t be shy about
-sharing code that’s useful to you on [crates.io](https://crates.io/)<!-- ignore
+sharing code that’s useful to you on [crates.io](https://crates.io)<!-- ignore
-->; it’s likely that it will be useful to someone else as well!
diff --git a/book-original/src/ch15-01-box.md b/book-pl-en/src/ch15-01-box.md
index 1605928..a5a71f0 100644
--- a/book-original/src/ch15-01-box.md
+++ b/book-pl-en/src/ch15-01-box.md
@@ -38,7 +38,10 @@ Listing 15-1 shows how to use a box to store an `i32` value on the heap:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-01/src/main.rs}}
+fn main() {
+ let b = Box::new(5);
+ println!("b = {}", b);
+}
```
<span class="caption">Listing 15-1: Storing an `i32` value on the heap using a
@@ -106,7 +109,10 @@ we’ll demonstrate.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-02/src/main.rs:here}}
+enum List {
+ Cons(i32, List),
+ Nil,
+}
```
<span class="caption">Listing 15-2: The first attempt at defining an enum to
@@ -122,8 +128,12 @@ Listing 15-3:
<span class="filename">Filename: src/main.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-03/src/main.rs:here}}
+```rust,ignore
+use List::{Cons, Nil};
+
+fn main() {
+ let list = Cons(1, Cons(2, Cons(3, Nil)));
+}
```
<span class="caption">Listing 15-3: Using the `List` enum to store the list `1,
@@ -138,7 +148,16 @@ If we try to compile the code in Listing 15-3, we get the error shown in
Listing 15-4:
```text
-{{#include ../listings/ch15-smart-pointers/listing-15-03/output.txt}}
+error[E0072]: recursive type `List` has infinite size
+ --> src/main.rs:1:1
+ |
+1 | enum List {
+ | ^^^^^^^^^ recursive type has infinite size
+2 | Cons(i32, List),
+ | ----- recursive without indirection
+ |
+ = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to
+ make `List` representable
```
<span class="caption">Listing 15-4: The error we get when attempting to define
@@ -157,7 +176,12 @@ Recall the `Message` enum we defined in Listing 6-2 when we discussed enum
definitions in Chapter 6:
```rust
-{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-02/src/main.rs:here}}
+enum Message {
+ Quit,
+ Move { x: i32, y: i32 },
+ Write(String),
+ ChangeColor(i32, i32, i32),
+}
```
To determine how much space to allocate for a `Message` value, Rust goes
@@ -187,12 +211,9 @@ Rust can’t figure out how much space to allocate for recursively defined types
so the compiler gives the error in Listing 15-4. But the error does include
this helpful suggestion:
-<!-- manual-regeneration
-after doing automatic regeneration, look at listings/ch15-smart-pointers/listing-15-03/output.txt and copy the relevant line
--->
-
```text
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable
+ = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to
+ make `List` representable
```
In this suggestion, “indirection” means that instead of storing a value
@@ -214,7 +235,19 @@ of the `List` in Listing 15-3 to the code in Listing 15-5, which will compile:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-05/src/main.rs}}
+enum List {
+ Cons(i32, Box<List>),
+ Nil,
+}
+
+use List::{Cons, Nil};
+
+fn main() {
+ let list = Cons(1,
+ Box::new(Cons(2,
+ Box::new(Cons(3,
+ Box::new(Nil))))));
+}
```
<span class="caption">Listing 15-5: Definition of `List` that uses `Box<T>` in
diff --git a/book-original/src/ch15-02-deref.md b/book-pl-en/src/ch15-02-deref.md
index b2f6081..d6457be 100644
--- a/book-original/src/ch15-02-deref.md
+++ b/book-pl-en/src/ch15-02-deref.md
@@ -10,13 +10,13 @@ Let’s first look at how the dereference operator works with regular references
Then we’ll try to define a custom type that behaves like `Box<T>`, and see why
the dereference operator doesn’t work like a reference on our newly defined
type. We’ll explore how implementing the `Deref` trait makes it possible for
-smart pointers to work in ways similar to references. Then we’ll look at
+smart pointers to work in a similar way as references. Then we’ll look at
Rust’s *deref coercion* feature and how it lets us work with either references
or smart pointers.
-> Note: there’s one big difference between the `MyBox<T>` type we’re about to
-> build and the real `Box<T>`: our version will not store its data on the heap.
-> We are focusing this example on `Deref`, so where the data is actually stored
+> There's one big difference between the `MyBox<T>` type we're about to build
+> and the real `Box<T>`: our version will not store its data on the heap. We
+> are focusing this example on `Deref`, and so where the data is actually stored
> is less important than the pointer-like behavior.
### Following the Pointer to the Value with the Dereference Operator
@@ -29,7 +29,13 @@ reference to the data:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-06/src/main.rs}}
+fn main() {
+ let x = 5;
+ let y = &x;
+
+ assert_eq!(5, x);
+ assert_eq!(5, *y);
+}
```
<span class="caption">Listing 15-6: Using the dereference operator to follow a
@@ -46,7 +52,13 @@ If we tried to write `assert_eq!(5, y);` instead, we would get this compilation
error:
```text
-{{#include ../listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt}}
+error[E0277]: can't compare `{integer}` with `&{integer}`
+ --> src/main.rs:6:5
+ |
+6 | assert_eq!(5, y);
+ | ^^^^^^^^^^^^^^^^^ no implementation for `{integer} == &{integer}`
+ |
+ = help: the trait `std::cmp::PartialEq<&{integer}>` is not implemented for `{integer}`
```
Comparing a number and a reference to a number isn’t allowed because they’re
@@ -61,7 +73,13 @@ reference; the dereference operator will work as shown in Listing 15-7:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-07/src/main.rs}}
+fn main() {
+ let x = 5;
+ let y = Box::new(x);
+
+ assert_eq!(5, x);
+ assert_eq!(5, *y);
+}
```
<span class="caption">Listing 15-7: Using the dereference operator on a
@@ -77,7 +95,7 @@ that enables us to use the dereference operator by defining our own box type.
### Defining Our Own Smart Pointer
Let’s build a smart pointer similar to the `Box<T>` type provided by the
-standard library to experience how smart pointers behave differently from
+standard library to experience how smart pointers behave differently than
references by default. Then we’ll look at how to add the ability to use the
dereference operator.
@@ -88,7 +106,13 @@ Listing 15-8 defines a `MyBox<T>` type in the same way. We’ll also define a
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-08/src/main.rs:here}}
+struct MyBox<T>(T);
+
+impl<T> MyBox<T> {
+ fn new(x: T) -> MyBox<T> {
+ MyBox(x)
+ }
+}
```
<span class="caption">Listing 15-8: Defining a `MyBox<T>` type</span>
@@ -106,7 +130,13 @@ code in Listing 15-9 won’t compile because Rust doesn’t know how to derefere
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-09/src/main.rs:here}}
+fn main() {
+ let x = 5;
+ let y = MyBox::new(x);
+
+ assert_eq!(5, x);
+ assert_eq!(5, *y);
+}
```
<span class="caption">Listing 15-9: Attempting to use `MyBox<T>` in the same
@@ -115,7 +145,11 @@ way we used references and `Box<T>`</span>
Here’s the resulting compilation error:
```text
-{{#include ../listings/ch15-smart-pointers/listing-15-09/output.txt}}
+error[E0614]: type `MyBox<{integer}>` cannot be dereferenced
+ --> src/main.rs:14:19
+ |
+14 | assert_eq!(5, *y);
+ | ^^
```
Our `MyBox<T>` type can’t be dereferenced because we haven’t implemented that
@@ -133,7 +167,16 @@ contains an implementation of `Deref` to add to the definition of `MyBox`:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-10/src/main.rs:here}}
+use std::ops::Deref;
+
+# struct MyBox<T>(T);
+impl<T> Deref for MyBox<T> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ &self.0
+ }
+}
```
<span class="caption">Listing 15-10: Implementing `Deref` on `MyBox<T>`</span>
@@ -182,14 +225,13 @@ Listing 15-9.
### Implicit Deref Coercions with Functions and Methods
*Deref coercion* is a convenience that Rust performs on arguments to functions
-and methods. Deref coercion works only on types that implement the `Deref`
-trait. Deref coercion converts such a type into a reference to another type.
-For example, deref coercion can convert `&String` to `&str` because `String`
-implements the `Deref` trait such that it returns `str`. Deref coercion happens
-automatically when we pass a reference to a particular type’s value as an
-argument to a function or method that doesn’t match the parameter type in the
-function or method definition. A sequence of calls to the `deref` method
-converts the type we provided into the type the parameter needs.
+and methods. Deref coercion converts a reference to a type that implements
+`Deref` into a reference to a type that `Deref` can convert the original type
+into. Deref coercion happens automatically when we pass a reference to a
+particular type’s value as an argument to a function or method that doesn’t
+match the parameter type in the function or method definition. A sequence of
+calls to the `deref` method converts the type we provided into the type the
+parameter needs.
Deref coercion was added to Rust so that programmers writing function and
method calls don’t need to add as many explicit references and dereferences
@@ -204,7 +246,9 @@ parameter:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-11/src/main.rs:here}}
+fn hello(name: &str) {
+ println!("Hello, {}!", name);
+}
```
<span class="caption">Listing 15-11: A `hello` function that has the parameter
@@ -217,7 +261,32 @@ with a reference to a value of type `MyBox<String>`, as shown in Listing 15-12:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-12/src/main.rs:here}}
+# use std::ops::Deref;
+#
+# struct MyBox<T>(T);
+#
+# impl<T> MyBox<T> {
+# fn new(x: T) -> MyBox<T> {
+# MyBox(x)
+# }
+# }
+#
+# impl<T> Deref for MyBox<T> {
+# type Target = T;
+#
+# fn deref(&self) -> &T {
+# &self.0
+# }
+# }
+#
+# fn hello(name: &str) {
+# println!("Hello, {}!", name);
+# }
+#
+fn main() {
+ let m = MyBox::new(String::from("Rust"));
+ hello(&m);
+}
```
<span class="caption">Listing 15-12: Calling `hello` with a reference to a
@@ -238,7 +307,32 @@ of type `&MyBox<String>`.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-13/src/main.rs:here}}
+# use std::ops::Deref;
+#
+# struct MyBox<T>(T);
+#
+# impl<T> MyBox<T> {
+# fn new(x: T) -> MyBox<T> {
+# MyBox(x)
+# }
+# }
+#
+# impl<T> Deref for MyBox<T> {
+# type Target = T;
+#
+# fn deref(&self) -> &T {
+# &self.0
+# }
+# }
+#
+# fn hello(name: &str) {
+# println!("Hello, {}!", name);
+# }
+#
+fn main() {
+ let m = MyBox::new(String::from("Rust"));
+ hello(&(*m)[..]);
+}
```
<span class="caption">Listing 15-13: The code we would have to write if Rust
@@ -280,8 +374,7 @@ never coerce to mutable references. Because of the borrowing rules, if you have
a mutable reference, that mutable reference must be the only reference to that
data (otherwise, the program wouldn’t compile). Converting one mutable
reference to one immutable reference will never break the borrowing rules.
-Converting an immutable reference to a mutable reference would require that the
-initial immutable reference is the only immutable reference to that data, but
-the borrowing rules don’t guarantee that. Therefore, Rust can’t make the
-assumption that converting an immutable reference to a mutable reference is
-possible.
+Converting an immutable reference to a mutable reference would require that
+there is only one immutable reference to that data, and the borrowing rules
+don’t guarantee that. Therefore, Rust can’t make the assumption that converting
+an immutable reference to a mutable reference is possible.
diff --git a/book-original/src/ch15-03-drop.md b/book-pl-en/src/ch15-03-drop.md
index 8566f03..2ce0b69 100644
--- a/book-original/src/ch15-03-drop.md
+++ b/book-pl-en/src/ch15-03-drop.md
@@ -30,7 +30,21 @@ function.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-14/src/main.rs}}
+struct CustomSmartPointer {
+ data: String,
+}
+
+impl Drop for CustomSmartPointer {
+ fn drop(&mut self) {
+ println!("Dropping CustomSmartPointer with data `{}`!", self.data);
+ }
+}
+
+fn main() {
+ let c = CustomSmartPointer { data: String::from("my stuff") };
+ let d = CustomSmartPointer { data: String::from("other stuff") };
+ println!("CustomSmartPointers created.");
+}
```
<span class="caption">Listing 15-14: A `CustomSmartPointer` struct that
@@ -44,7 +58,7 @@ an instance of your type goes out of scope. We’re printing some text here to
demonstrate when Rust will call `drop`.
In `main`, we create two instances of `CustomSmartPointer` and then print
-`CustomSmartPointers created`. At the end of `main`, our instances of
+`CustomSmartPointers created.`. At the end of `main`, our instances of
`CustomSmartPointer` will go out of scope, and Rust will call the code we put
in the `drop` method, printing our final message. Note that we didn’t need to
call the `drop` method explicitly.
@@ -52,7 +66,9 @@ call the `drop` method explicitly.
When we run this program, we’ll see the following output:
```text
-{{#include ../listings/ch15-smart-pointers/listing-15-14/output.txt}}
+CustomSmartPointers created.
+Dropping CustomSmartPointer with data `other stuff`!
+Dropping CustomSmartPointer with data `my stuff`!
```
Rust automatically called `drop` for us when our instances went out of scope,
@@ -68,7 +84,7 @@ functionality. Disabling `drop` isn’t usually necessary; the whole point of th
`Drop` trait is that it’s taken care of automatically. Occasionally, however,
you might want to clean up a value early. One example is when using smart
pointers that manage locks: you might want to force the `drop` method that
-releases the lock so that other code in the same scope can acquire the lock.
+releases the lock to run so other code in the same scope can acquire the lock.
Rust doesn’t let you call the `Drop` trait’s `drop` method manually; instead
you have to call the `std::mem::drop` function provided by the standard library
if you want to force a value to be dropped before the end of its scope.
@@ -80,7 +96,12 @@ compiler error:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-15/src/main.rs:here}}
+fn main() {
+ let c = CustomSmartPointer { data: String::from("some data") };
+ println!("CustomSmartPointer created.");
+ c.drop();
+ println!("CustomSmartPointer dropped before the end of main.");
+}
```
<span class="caption">Listing 15-15: Attempting to call the `drop` method from
@@ -89,7 +110,11 @@ the `Drop` trait manually to clean up early</span>
When we try to compile this code, we’ll get this error:
```text
-{{#include ../listings/ch15-smart-pointers/listing-15-15/output.txt}}
+error[E0040]: explicit use of destructor method
+ --> src/main.rs:14:7
+ |
+14 | c.drop();
+ | ^^^^ explicit destructor calls not allowed
```
This error message states that we’re not allowed to explicitly call `drop`. The
@@ -107,7 +132,7 @@ We can’t disable the automatic insertion of `drop` when a value goes out of
scope, and we can’t call the `drop` method explicitly. So, if we need to force
a value to be cleaned up early, we can use the `std::mem::drop` function.
-The `std::mem::drop` function is different from the `drop` method in the `Drop`
+The `std::mem::drop` function is different than the `drop` method in the `Drop`
trait. We call it by passing the value we want to force to be dropped early as
an argument. The function is in the prelude, so we can modify `main` in Listing
15-15 to call the `drop` function, as shown in Listing 15-16:
@@ -115,7 +140,22 @@ an argument. The function is in the prelude, so we can modify `main` in Listing
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-16/src/main.rs:here}}
+# struct CustomSmartPointer {
+# data: String,
+# }
+#
+# impl Drop for CustomSmartPointer {
+# fn drop(&mut self) {
+# println!("Dropping CustomSmartPointer!");
+# }
+# }
+#
+fn main() {
+ let c = CustomSmartPointer { data: String::from("some data") };
+ println!("CustomSmartPointer created.");
+ drop(c);
+ println!("CustomSmartPointer dropped before the end of main.");
+}
```
<span class="caption">Listing 15-16: Calling `std::mem::drop` to explicitly
@@ -124,7 +164,9 @@ drop a value before it goes out of scope</span>
Running this code will print the following:
```text
-{{#include ../listings/ch15-smart-pointers/listing-15-16/output.txt}}
+CustomSmartPointer created.
+Dropping CustomSmartPointer with data `some data`!
+CustomSmartPointer dropped before the end of main.
```
The text ```Dropping CustomSmartPointer with data `some data`!``` is printed
diff --git a/book-original/src/ch15-04-rc.md b/book-pl-en/src/ch15-04-rc.md
index 8990ca0..a81cd62 100644
--- a/book-original/src/ch15-04-rc.md
+++ b/book-pl-en/src/ch15-04-rc.md
@@ -51,7 +51,20 @@ won’t work, as shown in Listing 15-17:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-17/src/main.rs}}
+enum List {
+ Cons(i32, Box<List>),
+ Nil,
+}
+
+use List::{Cons, Nil};
+
+fn main() {
+ let a = Cons(5,
+ Box::new(Cons(10,
+ Box::new(Nil))));
+ let b = Cons(3, Box::new(a));
+ let c = Cons(4, Box::new(a));
+}
```
<span class="caption">Listing 15-17: Demonstrating we’re not allowed to have
@@ -60,7 +73,16 @@ two lists using `Box<T>` that try to share ownership of a third list</span>
When we compile this code, we get this error:
```text
-{{#include ../listings/ch15-smart-pointers/listing-15-17/output.txt}}
+error[E0382]: use of moved value: `a`
+ --> src/main.rs:13:30
+ |
+12 | let b = Cons(3, Box::new(a));
+ | - value moved here
+13 | let c = Cons(4, Box::new(a));
+ | ^ value used here after move
+ |
+ = note: move occurs because `a` has type `List`, which does not implement
+ the `Copy` trait
```
The `Cons` variants own the data they hold, so when we create the `b` list, `a`
@@ -88,7 +110,19 @@ it.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-18/src/main.rs}}
+enum List {
+ Cons(i32, Rc<List>),
+ Nil,
+}
+
+use List::{Cons, Nil};
+use std::rc::Rc;
+
+fn main() {
+ let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
+ let b = Cons(3, Rc::clone(&a));
+ let c = Cons(4, Rc::clone(&a));
+}
```
<span class="caption">Listing 15-18: A definition of `List` that uses
@@ -122,7 +156,25 @@ then we can see how the reference count changes when `c` goes out of scope.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-19/src/main.rs:here}}
+# enum List {
+# Cons(i32, Rc<List>),
+# Nil,
+# }
+#
+# use List::{Cons, Nil};
+# use std::rc::Rc;
+#
+fn main() {
+ let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
+ println!("count after creating a = {}", Rc::strong_count(&a));
+ let b = Cons(3, Rc::clone(&a));
+ println!("count after creating b = {}", Rc::strong_count(&a));
+ {
+ let c = Cons(4, Rc::clone(&a));
+ println!("count after creating c = {}", Rc::strong_count(&a));
+ }
+ println!("count after c goes out of scope = {}", Rc::strong_count(&a));
+}
```
<span class="caption">Listing 15-19: Printing the reference count</span>
@@ -137,7 +189,10 @@ type also has a `weak_count`; we’ll see what `weak_count` is used for in the
This code prints the following:
```text
-{{#include ../listings/ch15-smart-pointers/listing-15-19/output.txt}}
+count after creating a = 1
+count after creating b = 2
+count after creating c = 3
+count after c goes out of scope = 2
```
We can see that the `Rc<List>` in `a` has an initial reference count of 1; then
diff --git a/book-original/src/ch15-05-interior-mutability.md b/book-pl-en/src/ch15-05-interior-mutability.md
index 959d3eb..3c561b2 100644
--- a/book-original/src/ch15-05-interior-mutability.md
+++ b/book-pl-en/src/ch15-05-interior-mutability.md
@@ -1,14 +1,16 @@
## `RefCell<T>` and the Interior Mutability Pattern
+<!-- NEXT PARAGRAPH WRAPPED WEIRD INTENTIONALLY SEE #199 -->
+
*Interior mutability* is a design pattern in Rust that allows you to mutate
data even when there are immutable references to that data; normally, this
action is disallowed by the borrowing rules. To mutate data, the pattern uses
`unsafe` code inside a data structure to bend Rust’s usual rules that govern
-mutation and borrowing. We haven’t yet covered unsafe code; we will in Chapter
-19. We can use types that use the interior mutability pattern when we can
-ensure that the borrowing rules will be followed at runtime, even though the
-compiler can’t guarantee that. The `unsafe` code involved is then wrapped in a
-safe API, and the outer type is still immutable.
+mutation and borrowing. We haven’t yet covered unsafe code; we will in
+Chapter 19. We can use types that use the interior mutability pattern when we
+can ensure that the borrowing rules will be followed at runtime, even though
+the compiler can’t guarantee that. The `unsafe` code involved is then wrapped
+in a safe API, and the outer type is still immutable.
Let’s explore this concept by looking at the `RefCell<T>` type that follows the
interior mutability pattern.
@@ -76,13 +78,22 @@ A consequence of the borrowing rules is that when you have an immutable value,
you can’t borrow it mutably. For example, this code won’t compile:
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/src/main.rs}}
+fn main() {
+ let x = 5;
+ let y = &mut x;
+}
```
If you tried to compile this code, you’d get the following error:
```text
-{{#include ../listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/output.txt}}
+error[E0596]: cannot borrow immutable local variable `x` as mutable
+ --> src/main.rs:3:18
+ |
+2 | let x = 5;
+ | - consider changing this to `mut x`
+3 | let y = &mut x;
+ | ^ cannot borrow mutably
```
However, there are situations in which it would be useful for a value to mutate
@@ -125,7 +136,40 @@ called `Messenger`. Listing 15-20 shows the library code:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-20/src/lib.rs}}
+pub trait Messenger {
+ fn send(&self, msg: &str);
+}
+
+pub struct LimitTracker<'a, T: 'a + Messenger> {
+ messenger: &'a T,
+ value: usize,
+ max: usize,
+}
+
+impl<'a, T> LimitTracker<'a, T>
+ where T: Messenger {
+ pub fn new(messenger: &T, max: usize) -> LimitTracker<T> {
+ LimitTracker {
+ messenger,
+ value: 0,
+ max,
+ }
+ }
+
+ pub fn set_value(&mut self, value: usize) {
+ self.value = value;
+
+ let percentage_of_max = self.value as f64 / self.max as f64;
+
+ if percentage_of_max >= 1.0 {
+ self.messenger.send("Error: You are over your quota!");
+ } else if percentage_of_max >= 0.9 {
+ self.messenger.send("Urgent warning: You've used up over 90% of your quota!");
+ } else if percentage_of_max >= 0.75 {
+ self.messenger.send("Warning: You've used up over 75% of your quota!");
+ }
+ }
+}
```
<span class="caption">Listing 15-20: A library to keep track of how close a
@@ -151,8 +195,37 @@ implement a mock object to do just that, but the borrow checker won’t allow it
<span class="filename">Filename: src/lib.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-21/src/lib.rs:here}}
+```rust,does_not_compile
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ struct MockMessenger {
+ sent_messages: Vec<String>,
+ }
+
+ impl MockMessenger {
+ fn new() -> MockMessenger {
+ MockMessenger { sent_messages: vec![] }
+ }
+ }
+
+ impl Messenger for MockMessenger {
+ fn send(&self, message: &str) {
+ self.sent_messages.push(String::from(message));
+ }
+ }
+
+ #[test]
+ fn it_sends_an_over_75_percent_warning_message() {
+ let mock_messenger = MockMessenger::new();
+ let mut limit_tracker = LimitTracker::new(&mock_messenger, 100);
+
+ limit_tracker.set_value(80);
+
+ assert_eq!(mock_messenger.sent_messages.len(), 1);
+ }
+}
```
<span class="caption">Listing 15-21: An attempt to implement a `MockMessenger`
@@ -179,7 +252,13 @@ of should now have one message in it.
However, there’s one problem with this test, as shown here:
```text
-{{#include ../listings/ch15-smart-pointers/listing-15-21/output.txt}}
+error[E0596]: cannot borrow immutable field `self.sent_messages` as mutable
+ --> src/lib.rs:52:13
+ |
+51 | fn send(&self, message: &str) {
+ | ----- use `&mut self` here to make mutable
+52 | self.sent_messages.push(String::from(message));
+ | ^^^^^^^^^^^^^^^^^^ cannot mutably borrow immutable field
```
We can’t modify the `MockMessenger` to keep track of the messages, because the
@@ -196,7 +275,37 @@ shows what that looks like:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-22/src/lib.rs:here}}
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::cell::RefCell;
+
+ struct MockMessenger {
+ sent_messages: RefCell<Vec<String>>,
+ }
+
+ impl MockMessenger {
+ fn new() -> MockMessenger {
+ MockMessenger { sent_messages: RefCell::new(vec![]) }
+ }
+ }
+
+ impl Messenger for MockMessenger {
+ fn send(&self, message: &str) {
+ self.sent_messages.borrow_mut().push(String::from(message));
+ }
+ }
+
+ #[test]
+ fn it_sends_an_over_75_percent_warning_message() {
+ // --snip--
+# let mock_messenger = MockMessenger::new();
+# let mut limit_tracker = LimitTracker::new(&mock_messenger, 100);
+# limit_tracker.set_value(75);
+
+ assert_eq!(mock_messenger.sent_messages.borrow().len(), 1);
+ }
+}
```
<span class="caption">Listing 15-22: Using `RefCell<T>` to mutate an inner
@@ -245,7 +354,15 @@ at runtime.
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore,panics
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-23/src/lib.rs:here}}
+impl Messenger for MockMessenger {
+ fn send(&self, message: &str) {
+ let mut one_borrow = self.sent_messages.borrow_mut();
+ let mut two_borrow = self.sent_messages.borrow_mut();
+
+ one_borrow.push(String::from(message));
+ two_borrow.push(String::from(message));
+ }
+}
```
<span class="caption">Listing 15-23: Creating two mutable references in the
@@ -258,7 +375,10 @@ which isn’t allowed. When we run the tests for our library, the code in Listin
15-23 will compile without any errors, but the test will fail:
```text
-{{#include ../listings/ch15-smart-pointers/listing-15-23/output.txt}}
+---- tests::it_sends_an_over_75_percent_warning_message stdout ----
+ thread 'tests::it_sends_an_over_75_percent_warning_message' panicked at
+'already borrowed: BorrowMutError', src/libcore/result.rs:906:4
+note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
Notice that the code panicked with the message `already borrowed:
@@ -293,7 +413,30 @@ the lists:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-24/src/main.rs}}
+#[derive(Debug)]
+enum List {
+ Cons(Rc<RefCell<i32>>, Rc<List>),
+ Nil,
+}
+
+use List::{Cons, Nil};
+use std::rc::Rc;
+use std::cell::RefCell;
+
+fn main() {
+ let value = Rc::new(RefCell::new(5));
+
+ let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));
+
+ let b = Cons(Rc::new(RefCell::new(6)), Rc::clone(&a));
+ let c = Cons(Rc::new(RefCell::new(10)), Rc::clone(&a));
+
+ *value.borrow_mut() += 10;
+
+ println!("a after = {:?}", a);
+ println!("b after = {:?}", b);
+ println!("c after = {:?}", c);
+}
```
<span class="caption">Listing 15-24: Using `Rc<RefCell<i32>>` to create a
@@ -321,7 +464,9 @@ When we print `a`, `b`, and `c`, we can see that they all have the modified
value of 15 rather than 5:
```text
-{{#include ../listings/ch15-smart-pointers/listing-15-24/output.txt}}
+a after = Cons(RefCell { value: 15 }, Nil)
+b after = Cons(RefCell { value: 6 }, Cons(RefCell { value: 15 }, Nil))
+c after = Cons(RefCell { value: 10 }, Cons(RefCell { value: 15 }, Nil))
```
This technique is pretty neat! By using `RefCell<T>`, we have an outwardly
diff --git a/book-original/src/ch15-06-reference-cycles.md b/book-pl-en/src/ch15-06-reference-cycles.md
index a824ec3..8dc4c42 100644
--- a/book-original/src/ch15-06-reference-cycles.md
+++ b/book-pl-en/src/ch15-06-reference-cycles.md
@@ -17,14 +17,35 @@ starting with the definition of the `List` enum and a `tail` method in Listing
<span class="filename">Filename: src/main.rs</span>
+<!-- Hidden fn main is here to disable the automatic wrapping in fn main that
+doc tests do; the `use List` fails if this listing is put within a main -->
+
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-25/src/main.rs}}
+# fn main() {}
+use std::rc::Rc;
+use std::cell::RefCell;
+use List::{Cons, Nil};
+
+#[derive(Debug)]
+enum List {
+ Cons(i32, RefCell<Rc<List>>),
+ Nil,
+}
+
+impl List {
+ fn tail(&self) -> Option<&RefCell<Rc<List>>> {
+ match self {
+ Cons(_, item) => Some(item),
+ Nil => None,
+ }
+ }
+}
```
<span class="caption">Listing 15-25: A cons list definition that holds a
`RefCell<T>` so we can modify what a `Cons` variant is referring to</span>
-We’re using another variation of the `List` definition from Listing 15-5. The
+We’re using another variation of the `List` definition in Listing 15-25. The
second element in the `Cons` variant is now `RefCell<Rc<List>>`, meaning that
instead of having the ability to modify the `i32` value as we did in Listing
15-24, we want to modify which `List` value a `Cons` variant is pointing to.
@@ -40,7 +61,47 @@ reference counts are at various points in this process.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-26/src/main.rs:here}}
+# use List::{Cons, Nil};
+# use std::rc::Rc;
+# use std::cell::RefCell;
+# #[derive(Debug)]
+# enum List {
+# Cons(i32, RefCell<Rc<List>>),
+# Nil,
+# }
+#
+# impl List {
+# fn tail(&self) -> Option<&RefCell<Rc<List>>> {
+# match self {
+# Cons(_, item) => Some(item),
+# Nil => None,
+# }
+# }
+# }
+#
+fn main() {
+ let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));
+
+ println!("a initial rc count = {}", Rc::strong_count(&a));
+ println!("a next item = {:?}", a.tail());
+
+ let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));
+
+ println!("a rc count after b creation = {}", Rc::strong_count(&a));
+ println!("b initial rc count = {}", Rc::strong_count(&b));
+ println!("b next item = {:?}", b.tail());
+
+ if let Some(link) = a.tail() {
+ *link.borrow_mut() = Rc::clone(&b);
+ }
+
+ println!("b rc count after changing a = {}", Rc::strong_count(&b));
+ println!("a rc count after changing a = {}", Rc::strong_count(&a));
+
+ // Uncomment the next line to see that we have a cycle;
+ // it will overflow the stack
+ // println!("a next item = {:?}", a.tail());
+}
```
<span class="caption">Listing 15-26: Creating a reference cycle of two `List`
@@ -61,13 +122,19 @@ When we run this code, keeping the last `println!` commented out for the
moment, we’ll get this output:
```text
-{{#include ../listings/ch15-smart-pointers/listing-15-26/output.txt}}
+a initial rc count = 1
+a next item = Some(RefCell { value: Nil })
+a rc count after b creation = 2
+b initial rc count = 1
+b next item = Some(RefCell { value: Cons(5, RefCell { value: Nil }) })
+b rc count after changing a = 2
+a rc count after changing a = 2
```
The reference count of the `Rc<List>` instances in both `a` and `b` are 2
after we change the list in `a` to point to `b`. At the end of `main`, Rust
-will try to drop `b` first, which will decrease the count of the `Rc<List>`
-instance in `b` by 1.
+will try to drop `b` first, which will decrease the count in each of the
+`Rc<List>` instances in `a` and `b` by 1.
However, because `a` is still referencing the `Rc<List>` that was in `b`, that
`Rc<List>` has a count of 1 rather than 0, so the memory the `Rc<List>` has on
@@ -131,9 +198,9 @@ anything with the value that a `Weak<T>` is pointing to, you must make sure the
value still exists. Do this by calling the `upgrade` method on a `Weak<T>`
instance, which will return an `Option<Rc<T>>`. You’ll get a result of `Some`
if the `Rc<T>` value has not been dropped yet and a result of `None` if the
-`Rc<T>` value has been dropped. Because `upgrade` returns an `Option<Rc<T>>`,
-Rust will ensure that the `Some` case and the `None` case are handled, and
-there won’t be an invalid pointer.
+`Rc<T>` value has been dropped. Because `upgrade` returns an `Option<T>`, Rust
+will ensure that the `Some` case and the `None` case are handled, and there
+won’t be an invalid pointer.
As an example, rather than using a list whose items know only about the next
item, we’ll create a tree whose items know about their children items *and*
@@ -148,7 +215,14 @@ references to its children `Node` values:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-27/src/main.rs:here}}
+use std::rc::Rc;
+use std::cell::RefCell;
+
+#[derive(Debug)]
+struct Node {
+ value: i32,
+ children: RefCell<Vec<Rc<Node>>>,
+}
```
We want a `Node` to own its children, and we want to share that ownership with
@@ -164,7 +238,26 @@ with the value 5 and `leaf` as one of its children, as shown in Listing 15-27:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-27/src/main.rs:there}}
+# use std::rc::Rc;
+# use std::cell::RefCell;
+#
+# #[derive(Debug)]
+# struct Node {
+# value: i32,
+# children: RefCell<Vec<Rc<Node>>>,
+# }
+#
+fn main() {
+ let leaf = Rc::new(Node {
+ value: 3,
+ children: RefCell::new(vec![]),
+ });
+
+ let branch = Rc::new(Node {
+ value: 5,
+ children: RefCell::new(vec![Rc::clone(&leaf)]),
+ });
+}
```
<span class="caption">Listing 15-27: Creating a `leaf` node with no children
@@ -198,7 +291,15 @@ like this:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-28/src/main.rs:here}}
+use std::rc::{Rc, Weak};
+use std::cell::RefCell;
+
+#[derive(Debug)]
+struct Node {
+ value: i32,
+ parent: RefCell<Weak<Node>>,
+ children: RefCell<Vec<Rc<Node>>>,
+}
```
A node will be able to refer to its parent node but doesn’t own its parent.
@@ -208,7 +309,35 @@ node will have a way to refer to its parent, `branch`:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-28/src/main.rs:there}}
+# use std::rc::{Rc, Weak};
+# use std::cell::RefCell;
+#
+# #[derive(Debug)]
+# struct Node {
+# value: i32,
+# parent: RefCell<Weak<Node>>,
+# children: RefCell<Vec<Rc<Node>>>,
+# }
+#
+fn main() {
+ let leaf = Rc::new(Node {
+ value: 3,
+ parent: RefCell::new(Weak::new()),
+ children: RefCell::new(vec![]),
+ });
+
+ println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
+
+ let branch = Rc::new(Node {
+ value: 5,
+ parent: RefCell::new(Weak::new()),
+ children: RefCell::new(vec![Rc::clone(&leaf)]),
+ });
+
+ *leaf.parent.borrow_mut() = Rc::downgrade(&branch);
+
+ println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
+}
```
<span class="caption">Listing 15-28: A `leaf` node with a weak reference to its
@@ -261,7 +390,58 @@ in Listing 15-29:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-29/src/main.rs:here}}
+# use std::rc::{Rc, Weak};
+# use std::cell::RefCell;
+#
+# #[derive(Debug)]
+# struct Node {
+# value: i32,
+# parent: RefCell<Weak<Node>>,
+# children: RefCell<Vec<Rc<Node>>>,
+# }
+#
+fn main() {
+ let leaf = Rc::new(Node {
+ value: 3,
+ parent: RefCell::new(Weak::new()),
+ children: RefCell::new(vec![]),
+ });
+
+ println!(
+ "leaf strong = {}, weak = {}",
+ Rc::strong_count(&leaf),
+ Rc::weak_count(&leaf),
+ );
+
+ {
+ let branch = Rc::new(Node {
+ value: 5,
+ parent: RefCell::new(Weak::new()),
+ children: RefCell::new(vec![Rc::clone(&leaf)]),
+ });
+
+ *leaf.parent.borrow_mut() = Rc::downgrade(&branch);
+
+ println!(
+ "branch strong = {}, weak = {}",
+ Rc::strong_count(&branch),
+ Rc::weak_count(&branch),
+ );
+
+ println!(
+ "leaf strong = {}, weak = {}",
+ Rc::strong_count(&leaf),
+ Rc::weak_count(&leaf),
+ );
+ }
+
+ println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
+ println!(
+ "leaf strong = {}, weak = {}",
+ Rc::strong_count(&leaf),
+ Rc::weak_count(&leaf),
+ );
+}
```
<span class="caption">Listing 15-29: Creating `branch` in an inner scope and
@@ -296,7 +476,7 @@ and memory leaks.
## Summary
This chapter covered how to use smart pointers to make different guarantees and
-trade-offs from those Rust makes by default with regular references. The
+trade-offs than those Rust makes by default with regular references. The
`Box<T>` type has a known size and points to data allocated on the heap. The
`Rc<T>` type keeps track of the number of references to data on the heap so
that data can have multiple owners. The `RefCell<T>` type with its interior
@@ -312,7 +492,7 @@ If this chapter has piqued your interest and you want to implement your own
smart pointers, check out [“The Rustonomicon”][nomicon] for more useful
information.
+[nomicon]: https://doc.rust-lang.org/stable/nomicon/
+
Next, we’ll talk about concurrency in Rust. You’ll even learn about a few new
smart pointers.
-
-[nomicon]: ../nomicon/index.html
diff --git a/book-original/src/ch16-01-threads.md b/book-pl-en/src/ch16-01-threads.md
index 6cec741..5f6eb41 100644
--- a/book-original/src/ch16-01-threads.md
+++ b/book-pl-en/src/ch16-01-threads.md
@@ -71,7 +71,22 @@ thread and other text from a new thread:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-01/src/main.rs}}
+use std::thread;
+use std::time::Duration;
+
+fn main() {
+ thread::spawn(|| {
+ for i in 1..10 {
+ println!("hi number {} from the spawned thread!", i);
+ thread::sleep(Duration::from_millis(1));
+ }
+ });
+
+ for i in 1..5 {
+ println!("hi number {} from the main thread!", i);
+ thread::sleep(Duration::from_millis(1));
+ }
+}
```
<span class="caption">Listing 16-1: Creating a new thread to print one thing
@@ -82,10 +97,6 @@ thread ends, whether or not it has finished running. The output from this
program might be a little different every time, but it will look similar to the
following:
-<!-- Not extracting output because changes to this output aren't significant;
-the changes are likely to be due to the threads running differently rather than
-changes in the compiler -->
-
```text
hi number 1 from the main thread!
hi number 1 from the spawned thread!
@@ -128,7 +139,24 @@ in Listing 16-1 and call `join` to make sure the spawned thread finishes before
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-02/src/main.rs}}
+use std::thread;
+use std::time::Duration;
+
+fn main() {
+ let handle = thread::spawn(|| {
+ for i in 1..10 {
+ println!("hi number {} from the spawned thread!", i);
+ thread::sleep(Duration::from_millis(1));
+ }
+ });
+
+ for i in 1..5 {
+ println!("hi number {} from the main thread!", i);
+ thread::sleep(Duration::from_millis(1));
+ }
+
+ handle.join().unwrap();
+}
```
<span class="caption">Listing 16-2: Saving a `JoinHandle` from `thread::spawn`
@@ -140,10 +168,6 @@ thread is prevented from performing work or exiting. Because we’ve put the cal
to `join` after the main thread’s `for` loop, running Listing 16-2 should
produce output similar to this:
-<!-- Not extracting output because changes to this output aren't significant;
-the changes are likely to be due to the threads running differently rather than
-changes in the compiler -->
-
```text
hi number 1 from the main thread!
hi number 2 from the main thread!
@@ -169,16 +193,29 @@ But let’s see what happens when we instead move `handle.join()` before the
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/no-listing-01-join-too-early/src/main.rs}}
+use std::thread;
+use std::time::Duration;
+
+fn main() {
+ let handle = thread::spawn(|| {
+ for i in 1..10 {
+ println!("hi number {} from the spawned thread!", i);
+ thread::sleep(Duration::from_millis(1));
+ }
+ });
+
+ handle.join().unwrap();
+
+ for i in 1..5 {
+ println!("hi number {} from the main thread!", i);
+ thread::sleep(Duration::from_millis(1));
+ }
+}
```
The main thread will wait for the spawned thread to finish and then run its
`for` loop, so the output won’t be interleaved anymore, as shown here:
-<!-- Not extracting output because changes to this output aren't significant;
-the changes are likely to be due to the threads running differently rather than
-changes in the compiler -->
-
```text
hi number 1 from the spawned thread!
hi number 2 from the spawned thread!
@@ -218,7 +255,17 @@ thread. However, this won’t yet work, as you’ll see in a moment.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-03/src/main.rs}}
+use std::thread;
+
+fn main() {
+ let v = vec![1, 2, 3];
+
+ let handle = thread::spawn(|| {
+ println!("Here's a vector: {:?}", v);
+ });
+
+ handle.join().unwrap();
+}
```
<span class="caption">Listing 16-3: Attempting to use a vector created by the
@@ -230,7 +277,20 @@ should be able to access `v` inside that new thread. But when we compile this
example, we get the following error:
```text
-{{#include ../listings/ch16-fearless-concurrency/listing-16-03/output.txt}}
+error[E0373]: closure may outlive the current function, but it borrows `v`,
+which is owned by the current function
+ --> src/main.rs:6:32
+ |
+6 | let handle = thread::spawn(|| {
+ | ^^ may outlive borrowed value `v`
+7 | println!("Here's a vector: {:?}", v);
+ | - `v` is borrowed here
+ |
+help: to force the closure to take ownership of `v` (and any other referenced
+variables), use the `move` keyword
+ |
+6 | let handle = thread::spawn(move || {
+ | ^^^^^^^
```
Rust *infers* how to capture `v`, and because `println!` only needs a reference
@@ -244,7 +304,19 @@ that won’t be valid:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-04/src/main.rs}}
+use std::thread;
+
+fn main() {
+ let v = vec![1, 2, 3];
+
+ let handle = thread::spawn(|| {
+ println!("Here's a vector: {:?}", v);
+ });
+
+ drop(v); // oh no!
+
+ handle.join().unwrap();
+}
```
<span class="caption">Listing 16-4: A thread with a closure that attempts to
@@ -260,12 +332,9 @@ is also invalid. Oh no!
To fix the compiler error in Listing 16-3, we can use the error message’s
advice:
-<!-- manual-regeneration
-after automatic regeneration, look at listings/ch16-fearless-concurrency/listing-16-03/output.txt and copy the relevant part
--->
-
```text
-help: to force the closure to take ownership of `v` (and any other referenced variables), use the `move` keyword
+help: to force the closure to take ownership of `v` (and any other referenced
+variables), use the `move` keyword
|
6 | let handle = thread::spawn(move || {
| ^^^^^^^
@@ -279,7 +348,17 @@ should borrow the values. The modification to Listing 16-3 shown in Listing
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-05/src/main.rs}}
+use std::thread;
+
+fn main() {
+ let v = vec![1, 2, 3];
+
+ let handle = thread::spawn(move || {
+ println!("Here's a vector: {:?}", v);
+ });
+
+ handle.join().unwrap();
+}
```
<span class="caption">Listing 16-5: Using the `move` keyword to force a closure
@@ -293,7 +372,17 @@ would move `v` into the closure’s environment, and we could no longer call
`drop` on it in the main thread. We would get this compiler error instead:
```text
-{{#include ../listings/ch16-fearless-concurrency/output-only-01-move-drop/output.txt}}
+error[E0382]: use of moved value: `v`
+ --> src/main.rs:10:10
+ |
+6 | let handle = thread::spawn(move || {
+ | ------- value moved (into closure) here
+...
+10 | drop(v); // oh no!
+ | ^ value used here after move
+ |
+ = note: move occurs because `v` has type `std::vec::Vec<i32>`, which does
+ not implement the `Copy` trait
```
Rust’s ownership rules have saved us again! We got an error from the code in
diff --git a/book-original/src/ch16-02-message-passing.md b/book-pl-en/src/ch16-02-message-passing.md
index 7fdbccc..7cb4cfa 100644
--- a/book-original/src/ch16-02-message-passing.md
+++ b/book-pl-en/src/ch16-02-message-passing.md
@@ -35,8 +35,13 @@ want to send over the channel.
<span class="filename">Filename: src/main.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-06/src/main.rs}}
+```rust
+use std::sync::mpsc;
+
+fn main() {
+ let (tx, rx) = mpsc::channel();
+# tx.send(()).unwrap();
+}
```
<span class="caption">Listing 16-6: Creating a channel and assigning the two
@@ -51,14 +56,16 @@ of the streams will end up in one river at the end. We’ll start with a single
producer for now, but we’ll add multiple producers when we get this example
working.
+<!-- NEXT PARAGRAPH WRAPPED WEIRD INTENTIONALLY SEE #199 -->
+
The `mpsc::channel` function returns a tuple, the first element of which is the
sending end and the second element is the receiving end. The abbreviations `tx`
and `rx` are traditionally used in many fields for *transmitter* and *receiver*
respectively, so we name our variables as such to indicate each end. We’re
using a `let` statement with a pattern that destructures the tuples; we’ll
-discuss the use of patterns in `let` statements and destructuring in Chapter
-18. Using a `let` statement this way is a convenient approach to extract the
-pieces of the tuple returned by `mpsc::channel`.
+discuss the use of patterns in `let` statements and destructuring in
+Chapter 18. Using a `let` statement this way is a convenient approach to
+extract the pieces of the tuple returned by `mpsc::channel`.
Let’s move the transmitting end into a spawned thread and have it send one
string so the spawned thread is communicating with the main thread, as shown in
@@ -68,7 +75,17 @@ sending a chat message from one thread to another.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-07/src/main.rs}}
+use std::thread;
+use std::sync::mpsc;
+
+fn main() {
+ let (tx, rx) = mpsc::channel();
+
+ thread::spawn(move || {
+ let val = String::from("hi");
+ tx.send(val).unwrap();
+ });
+}
```
<span class="caption">Listing 16-7: Moving `tx` to a spawned thread and sending
@@ -93,7 +110,20 @@ end of the river or like getting a chat message.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-08/src/main.rs}}
+use std::thread;
+use std::sync::mpsc;
+
+fn main() {
+ let (tx, rx) = mpsc::channel();
+
+ thread::spawn(move || {
+ let val = String::from("hi");
+ tx.send(val).unwrap();
+ });
+
+ let received = rx.recv().unwrap();
+ println!("Got: {}", received);
+}
```
<span class="caption">Listing 16-8: Receiving the value “hi” in the main thread
@@ -121,10 +151,6 @@ thread is appropriate.
When we run the code in Listing 16-8, we’ll see the value printed from the main
thread:
-<!-- Not extracting output because changes to this output aren't significant;
-the changes are likely to be due to the threads running differently rather than
-changes in the compiler -->
-
```text
Got: hi
```
@@ -144,7 +170,21 @@ this code isn’t allowed:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-09/src/main.rs}}
+use std::thread;
+use std::sync::mpsc;
+
+fn main() {
+ let (tx, rx) = mpsc::channel();
+
+ thread::spawn(move || {
+ let val = String::from("hi");
+ tx.send(val).unwrap();
+ println!("val is {}", val);
+ });
+
+ let received = rx.recv().unwrap();
+ println!("Got: {}", received);
+}
```
<span class="caption">Listing 16-9: Attempting to use `val` after we’ve sent it
@@ -158,7 +198,16 @@ unexpected results due to inconsistent or nonexistent data. However, Rust gives
us an error if we try to compile the code in Listing 16-9:
```text
-{{#include ../listings/ch16-fearless-concurrency/listing-16-09/output.txt}}
+error[E0382]: use of moved value: `val`
+ --> src/main.rs:10:31
+ |
+9 | tx.send(val).unwrap();
+ | --- value moved here
+10 | println!("val is {}", val);
+ | ^^^ value used here after move
+ |
+ = note: move occurs because `val` has type `std::string::String`, which does
+not implement the `Copy` trait
```
Our concurrency mistake has caused a compile time error. The `send` function
@@ -177,7 +226,31 @@ pause for a second between each message.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-10/src/main.rs}}
+use std::thread;
+use std::sync::mpsc;
+use std::time::Duration;
+
+fn main() {
+ let (tx, rx) = mpsc::channel();
+
+ thread::spawn(move || {
+ let vals = vec![
+ String::from("hi"),
+ String::from("from"),
+ String::from("the"),
+ String::from("thread"),
+ ];
+
+ for val in vals {
+ tx.send(val).unwrap();
+ thread::sleep(Duration::from_secs(1));
+ }
+ });
+
+ for received in rx {
+ println!("Got: {}", received);
+ }
+}
```
<span class="caption">Listing 16-10: Sending multiple messages and pausing
@@ -195,10 +268,6 @@ printing it. When the channel is closed, iteration will end.
When running the code in Listing 16-10, you should see the following output
with a 1-second pause in between each line:
-<!-- Not extracting output because changes to this output aren't significant;
-the changes are likely to be due to the threads running differently rather than
-changes in the compiler -->
-
```text
Got: hi
Got: from
@@ -220,7 +289,50 @@ so by cloning the transmitting half of the channel, as shown in Listing 16-11:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-11/src/main.rs:here}}
+# use std::thread;
+# use std::sync::mpsc;
+# use std::time::Duration;
+#
+# fn main() {
+// --snip--
+
+let (tx, rx) = mpsc::channel();
+
+let tx1 = mpsc::Sender::clone(&tx);
+thread::spawn(move || {
+ let vals = vec![
+ String::from("hi"),
+ String::from("from"),
+ String::from("the"),
+ String::from("thread"),
+ ];
+
+ for val in vals {
+ tx1.send(val).unwrap();
+ thread::sleep(Duration::from_secs(1));
+ }
+});
+
+thread::spawn(move || {
+ let vals = vec![
+ String::from("more"),
+ String::from("messages"),
+ String::from("for"),
+ String::from("you"),
+ ];
+
+ for val in vals {
+ tx.send(val).unwrap();
+ thread::sleep(Duration::from_secs(1));
+ }
+});
+
+for received in rx {
+ println!("Got: {}", received);
+}
+
+// --snip--
+# }
```
<span class="caption">Listing 16-11: Sending multiple messages from multiple
@@ -234,10 +346,6 @@ messages to the receiving end of the channel.
When you run the code, your output should look something like this:
-<!-- Not extracting output because changes to this output aren't significant;
-the changes are likely to be due to the threads running differently rather than
-changes in the compiler -->
-
```text
Got: hi
Got: more
diff --git a/book-original/src/ch16-03-shared-state.md b/book-pl-en/src/ch16-03-shared-state.md
index 50ce56c..ea6e481 100644
--- a/book-original/src/ch16-03-shared-state.md
+++ b/book-pl-en/src/ch16-03-shared-state.md
@@ -2,7 +2,7 @@
Message passing is a fine way of handling concurrency, but it’s not the only
one. Consider this part of the slogan from the Go language documentation again:
-“do not communicate by sharing memory.”
+“communicate by sharing memory.”
What would communicating by sharing memory look like? In addition, why would
message-passing enthusiasts not use it and do the opposite instead?
@@ -54,7 +54,18 @@ single-threaded context, as shown in Listing 16-12:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-12/src/main.rs}}
+use std::sync::Mutex;
+
+fn main() {
+ let m = Mutex::new(5);
+
+ {
+ let mut num = m.lock().unwrap();
+ *num = 6;
+ }
+
+ println!("m = {:?}", m);
+}
```
<span class="caption">Listing 16-12: Exploring the API of `Mutex<T>` in a
@@ -76,14 +87,13 @@ that we acquire a lock before using the value in `m`: `Mutex<i32>` is not an
can’t forget; the type system won’t let us access the inner `i32` otherwise.
As you might suspect, `Mutex<T>` is a smart pointer. More accurately, the call
-to `lock` *returns* a smart pointer called `MutexGuard`, wrapped in a
-`LockResult` that we handled with the call to `unwrap`. The `MutexGuard` smart
-pointer implements `Deref` to point at our inner data; the smart pointer also
-has a `Drop` implementation that releases the lock automatically when a
-`MutexGuard` goes out of scope, which happens at the end of the inner scope in
-Listing 16-12. As a result, we don’t risk forgetting to release the lock and
-blocking the mutex from being used by other threads because the lock release
-happens automatically.
+to `lock` *returns* a smart pointer called `MutexGuard`. This smart pointer
+implements `Deref` to point at our inner data; the smart pointer also has a
+`Drop` implementation that releases the lock automatically when a `MutexGuard`
+goes out of scope, which happens at the end of the inner scope in Listing
+16-12. As a result, we don’t risk forgetting to release the lock and blocking
+the mutex from being used by other threads because the lock release happens
+automatically.
After dropping the lock, we can print the mutex value and see that we were able
to change the inner `i32` to 6.
@@ -92,14 +102,36 @@ to change the inner `i32` to 6.
Now, let’s try to share a value between multiple threads using `Mutex<T>`.
We’ll spin up 10 threads and have them each increment a counter value by 1, so
-the counter goes from 0 to 10. The next example in Listing 16-13 will have
-a compiler error, and we’ll use that error to learn more about using
-`Mutex<T>` and how Rust helps us use it correctly.
+the counter goes from 0 to 10. Note that the next few examples will have
+compiler errors, and we’ll use those errors to learn more about using
+`Mutex<T>` and how Rust helps us use it correctly. Listing 16-13 has our
+starting example:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-13/src/main.rs}}
+use std::sync::Mutex;
+use std::thread;
+
+fn main() {
+ let counter = Mutex::new(0);
+ let mut handles = vec![];
+
+ for _ in 0..10 {
+ let handle = thread::spawn(move || {
+ let mut num = counter.lock().unwrap();
+
+ *num += 1;
+ });
+ handles.push(handle);
+ }
+
+ for handle in handles {
+ handle.join().unwrap();
+ }
+
+ println!("Result: {}", *counter.lock().unwrap());
+}
```
<span class="caption">Listing 16-13: Ten threads each increment a counter
@@ -121,13 +153,110 @@ program.
We hinted that this example wouldn’t compile. Now let’s find out why!
```text
-{{#include ../listings/ch16-fearless-concurrency/listing-16-13/output.txt}}
+error[E0382]: capture of moved value: `counter`
+ --> src/main.rs:10:27
+ |
+9 | let handle = thread::spawn(move || {
+ | ------- value moved (into closure) here
+10 | let mut num = counter.lock().unwrap();
+ | ^^^^^^^ value captured here after move
+ |
+ = note: move occurs because `counter` has type `std::sync::Mutex<i32>`,
+ which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `counter`
+ --> src/main.rs:21:29
+ |
+9 | let handle = thread::spawn(move || {
+ | ------- value moved (into closure) here
+...
+21 | println!("Result: {}", *counter.lock().unwrap());
+ | ^^^^^^^ value used here after move
+ |
+ = note: move occurs because `counter` has type `std::sync::Mutex<i32>`,
+ which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+```
+
+The error message states that the `counter` value is moved into the closure and
+then captured when we call `lock`. That description sounds like what we wanted,
+but it’s not allowed!
+
+Let’s figure this out by simplifying the program. Instead of making 10 threads
+in a `for` loop, let’s just make two threads without a loop and see what
+happens. Replace the first `for` loop in Listing 16-13 with this code instead:
+
+```rust,ignore,does_not_compile
+use std::sync::Mutex;
+use std::thread;
+
+fn main() {
+ let counter = Mutex::new(0);
+ let mut handles = vec![];
+
+ let handle = thread::spawn(move || {
+ let mut num = counter.lock().unwrap();
+
+ *num += 1;
+ });
+ handles.push(handle);
+
+ let handle2 = thread::spawn(move || {
+ let mut num2 = counter.lock().unwrap();
+
+ *num2 += 1;
+ });
+ handles.push(handle2);
+
+ for handle in handles {
+ handle.join().unwrap();
+ }
+
+ println!("Result: {}", *counter.lock().unwrap());
+}
+```
+
+We make two threads and change the variable names used with the second thread
+to `handle2` and `num2`. When we run the code this time, compiling gives us the
+following:
+
+```text
+error[E0382]: capture of moved value: `counter`
+ --> src/main.rs:16:24
+ |
+8 | let handle = thread::spawn(move || {
+ | ------- value moved (into closure) here
+...
+16 | let mut num2 = counter.lock().unwrap();
+ | ^^^^^^^ value captured here after move
+ |
+ = note: move occurs because `counter` has type `std::sync::Mutex<i32>`,
+ which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `counter`
+ --> src/main.rs:26:29
+ |
+8 | let handle = thread::spawn(move || {
+ | ------- value moved (into closure) here
+...
+26 | println!("Result: {}", *counter.lock().unwrap());
+ | ^^^^^^^ value used here after move
+ |
+ = note: move occurs because `counter` has type `std::sync::Mutex<i32>`,
+ which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
```
-The error message states that the `counter` value was moved in the previous
-iteration of the loop. So Rust is telling us that we can’t move the ownership
-of lock `counter` into multiple threads. Let’s fix the compiler error with a
-multiple-ownership method we discussed in Chapter 15.
+Aha! The first error message indicates that `counter` is moved into the closure
+for the thread associated with `handle`. That move is preventing us from
+capturing `counter` when we try to call `lock` on it and store the result in
+`num2` in the second thread! So Rust is telling us that we can’t move ownership
+of `counter` into multiple threads. This was hard to see earlier because our
+threads were in a loop, and Rust can’t point to different threads in different
+iterations of the loop. Let’s fix the compiler error with a multiple-ownership
+method we discussed in Chapter 15.
#### Multiple Ownership with Multiple Threads
@@ -141,7 +270,30 @@ errors, we’ll also switch back to using the `for` loop, and we’ll keep the
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-14/src/main.rs}}
+use std::rc::Rc;
+use std::sync::Mutex;
+use std::thread;
+
+fn main() {
+ let counter = Rc::new(Mutex::new(0));
+ let mut handles = vec![];
+
+ for _ in 0..10 {
+ let counter = Rc::clone(&counter);
+ let handle = thread::spawn(move || {
+ let mut num = counter.lock().unwrap();
+
+ *num += 1;
+ });
+ handles.push(handle);
+ }
+
+ for handle in handles {
+ handle.join().unwrap();
+ }
+
+ println!("Result: {}", *counter.lock().unwrap());
+}
```
<span class="caption">Listing 16-14: Attempting to use `Rc<T>` to allow
@@ -151,15 +303,30 @@ Once again, we compile and get... different errors! The compiler is teaching us
a lot.
```text
-{{#include ../listings/ch16-fearless-concurrency/listing-16-14/output.txt}}
+error[E0277]: the trait bound `std::rc::Rc<std::sync::Mutex<i32>>:
+std::marker::Send` is not satisfied in `[closure@src/main.rs:11:36:
+15:10 counter:std::rc::Rc<std::sync::Mutex<i32>>]`
+ --> src/main.rs:11:22
+ |
+11 | let handle = thread::spawn(move || {
+ | ^^^^^^^^^^^^^ `std::rc::Rc<std::sync::Mutex<i32>>`
+cannot be sent between threads safely
+ |
+ = help: within `[closure@src/main.rs:11:36: 15:10
+counter:std::rc::Rc<std::sync::Mutex<i32>>]`, the trait `std::marker::Send` is
+not implemented for `std::rc::Rc<std::sync::Mutex<i32>>`
+ = note: required because it appears within the type
+`[closure@src/main.rs:11:36: 15:10 counter:std::rc::Rc<std::sync::Mutex<i32>>]`
+ = note: required by `std::thread::spawn`
```
-Wow, that error message is very wordy! Here’s the important part to focus
-on: `` `Rc<Mutex<i32>>` cannot be sent between threads safely ``. The compiler
-is also telling us the reason why: ``the trait `Send` is not implemented for
-`Rc<Mutex<i32>>` ``. We’ll talk about `Send` in the next section: it’s one of
-the traits that ensures the types we use with threads are meant for use in
-concurrent situations.
+Wow, that error message is very wordy! Here are some important parts to focus
+on: the first inline error says `` `std::rc::Rc<std::sync::Mutex<i32>>` cannot
+be sent between threads safely ``. The reason for this is in the next important
+part to focus on, the error message. The distilled error message says `` the
+trait bound `Send` is not satisfied ``. We’ll talk about `Send` in the next
+section: it’s one of the traits that ensures the types we use with threads are
+meant for use in concurrent situations.
Unfortunately, `Rc<T>` is not safe to share across threads. When `Rc<T>`
manages the reference count, it adds to the count for each call to `clone` and
@@ -194,7 +361,29 @@ our program by changing the `use` line, the call to `new`, and the call to
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-15/src/main.rs}}
+use std::sync::{Mutex, Arc};
+use std::thread;
+
+fn main() {
+ let counter = Arc::new(Mutex::new(0));
+ let mut handles = vec![];
+
+ for _ in 0..10 {
+ let counter = Arc::clone(&counter);
+ let handle = thread::spawn(move || {
+ let mut num = counter.lock().unwrap();
+
+ *num += 1;
+ });
+ handles.push(handle);
+ }
+
+ for handle in handles {
+ handle.join().unwrap();
+ }
+
+ println!("Result: {}", *counter.lock().unwrap());
+}
```
<span class="caption">Listing 16-15: Using an `Arc<T>` to wrap the `Mutex<T>`
@@ -202,10 +391,6 @@ to be able to share ownership across multiple threads</span>
This code will print the following:
-<!-- Not extracting output because changes to this output aren't significant;
-the changes are likely to be due to the threads running differently rather than
-changes in the compiler -->
-
```text
Result: 10
```
diff --git a/book-original/src/ch16-04-extensible-concurrency-sync-and-send.md b/book-pl-en/src/ch16-04-extensible-concurrency-sync-and-send.md
index 797f69a..7ec5d79 100644
--- a/book-original/src/ch16-04-extensible-concurrency-sync-and-send.md
+++ b/book-pl-en/src/ch16-04-extensible-concurrency-sync-and-send.md
@@ -42,8 +42,8 @@ The smart pointer `Rc<T>` is also not `Sync` for the same reasons that it’s no
family of related `Cell<T>` types are not `Sync`. The implementation of borrow
checking that `RefCell<T>` does at runtime is not thread-safe. The smart
pointer `Mutex<T>` is `Sync` and can be used to share access with multiple
-threads as you saw in the [“Sharing a `Mutex<T>` Between Multiple
-Threads”][sharing-a-mutext-between-multiple-threads]<!-- ignore --> section.
+threads as you saw in the [“Sharing a `Mutex<T>` Between Multiple Threads”]
+[sharing-a-mutext-between-multiple-threads]<!-- ignore --> section.
### Implementing `Send` and `Sync` Manually Is Unsafe
@@ -55,10 +55,12 @@ useful for enforcing invariants related to concurrency.
Manually implementing these traits involves implementing unsafe Rust code.
We’ll talk about using unsafe Rust code in Chapter 19; for now, the important
information is that building new concurrent types not made up of `Send` and
-`Sync` parts requires careful thought to uphold the safety guarantees. [“The
-Rustonomicon”][nomicon] has more information about these guarantees and how to
+`Sync` parts requires careful thought to uphold the safety guarantees.
+[The Rustonomicon] has more information about these guarantees and how to
uphold them.
+[The Rustonomicon]: https://doc.rust-lang.org/stable/nomicon/
+
## Summary
This isn’t the last you’ll see of concurrency in this book: the project in
@@ -86,4 +88,3 @@ relate to those you might be familiar with from object-oriented programming.
[sharing-a-mutext-between-multiple-threads]:
ch16-03-shared-state.html#sharing-a-mutext-between-multiple-threads
-[nomicon]: ../nomicon/index.html
diff --git a/book-original/src/ch17-01-what-is-oo.md b/book-pl-en/src/ch17-01-what-is-oo.md
index e197cbf..b35f74d 100644
--- a/book-original/src/ch17-01-what-is-oo.md
+++ b/book-pl-en/src/ch17-01-what-is-oo.md
@@ -47,7 +47,10 @@ cache the calculated average for us. Listing 17-1 has the definition of the
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-01/src/lib.rs}}
+pub struct AveragedCollection {
+ list: Vec<i32>,
+ average: f64,
+}
```
<span class="caption">Listing 17-1: An `AveragedCollection` struct that
@@ -63,7 +66,36 @@ on the struct, as shown in Listing 17-2:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-02/src/lib.rs:here}}
+# pub struct AveragedCollection {
+# list: Vec<i32>,
+# average: f64,
+# }
+impl AveragedCollection {
+ pub fn add(&mut self, value: i32) {
+ self.list.push(value);
+ self.update_average();
+ }
+
+ pub fn remove(&mut self) -> Option<i32> {
+ let result = self.list.pop();
+ match result {
+ Some(value) => {
+ self.update_average();
+ Some(value)
+ },
+ None => None,
+ }
+ }
+
+ pub fn average(&self) -> f64 {
+ self.average
+ }
+
+ fn update_average(&mut self) {
+ let total: i32 = self.list.iter().sum();
+ self.average = total as f64 / self.list.len() as f64;
+ }
+}
```
<span class="caption">Listing 17-2: Implementations of the public methods
@@ -83,13 +115,13 @@ code to read the `average` but not modify it.
Because we’ve encapsulated the implementation details of the struct
`AveragedCollection`, we can easily change aspects, such as the data structure,
-in the future. For instance, we could use a `HashSet<i32>` instead of a
-`Vec<i32>` for the `list` field. As long as the signatures of the `add`,
-`remove`, and `average` public methods stay the same, code using
-`AveragedCollection` wouldn’t need to change. If we made `list` public instead,
-this wouldn’t necessarily be the case: `HashSet<i32>` and `Vec<i32>` have
-different methods for adding and removing items, so the external code would
-likely have to change if it were modifying `list` directly.
+in the future. For instance, we could use a `HashSet` instead of a `Vec` for
+the `list` field. As long as the signatures of the `add`, `remove`, and
+`average` public methods stay the same, code using `AveragedCollection`
+wouldn’t need to change. If we made `list` public instead, this wouldn’t
+necessarily be the case: `HashSet` and `Vec` have different methods for adding
+and removing items, so the external code would likely have to change if it were
+modifying `list` directly.
If encapsulation is a required aspect for a language to be considered object
oriented, then Rust meets that requirement. The option to use `pub` or not for
diff --git a/book-original/src/ch17-02-trait-objects.md b/book-pl-en/src/ch17-02-trait-objects.md
index b4f7e42..008158f 100644
--- a/book-original/src/ch17-02-trait-objects.md
+++ b/book-pl-en/src/ch17-02-trait-objects.md
@@ -40,11 +40,10 @@ allow users to extend it with new types.
To implement the behavior we want `gui` to have, we’ll define a trait named
`Draw` that will have one method named `draw`. Then we can define a vector that
-takes a *trait object*. A trait object points to both an instance of a type
-implementing our specified trait as well as a table used to look up trait
-methods on that type at runtime. We create a trait object by specifying some
-sort of pointer, such as a `&` reference or a `Box<T>` smart pointer, then the
-`dyn` keyword, and then specifying the relevant trait. (We’ll talk about the
+takes a *trait object*. A trait object points to an instance of a type that
+implements the trait we specify. We create a trait object by specifying some
+sort of pointer, such as a `&` reference or a `Box<T>` smart pointer, and then
+specifying the relevant trait, and add a `dyn` keyword. (We’ll talk about the
reason trait objects must use a pointer in Chapter 19 in the section
[“Dynamically Sized Types and the `Sized` Trait.”][dynamically-sized]<!--
ignore -->) We can use trait objects in place of a generic or concrete type.
@@ -69,7 +68,9 @@ Listing 17-3 shows how to define a trait named `Draw` with one method named
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-03/src/lib.rs}}
+pub trait Draw {
+ fn draw(&self);
+}
```
<span class="caption">Listing 17-3: Definition of the `Draw` trait</span>
@@ -83,7 +84,13 @@ a `Box` that implements the `Draw` trait.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-04/src/lib.rs:here}}
+# pub trait Draw {
+# fn draw(&self);
+# }
+#
+pub struct Screen {
+ pub components: Vec<Box<dyn Draw>>,
+}
```
<span class="caption">Listing 17-4: Definition of the `Screen` struct with a
@@ -96,13 +103,27 @@ On the `Screen` struct, we’ll define a method named `run` that will call the
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-05/src/lib.rs:here}}
+# pub trait Draw {
+# fn draw(&self);
+# }
+#
+# pub struct Screen {
+# pub components: Vec<Box<dyn Draw>>,
+# }
+#
+impl Screen {
+ pub fn run(&self) {
+ for component in self.components.iter() {
+ component.draw();
+ }
+ }
+}
```
<span class="caption">Listing 17-5: A `run` method on `Screen` that calls the
`draw` method on each component</span>
-This works differently from defining a struct that uses a generic type
+This works differently than defining a struct that uses a generic type
parameter with trait bounds. A generic type parameter can only be substituted
with one concrete type at a time, whereas trait objects allow for multiple
concrete types to fill in for the trait object at runtime. For example, we
@@ -112,7 +133,22 @@ as in Listing 17-6:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-06/src/lib.rs:here}}
+# pub trait Draw {
+# fn draw(&self);
+# }
+#
+pub struct Screen<T: Draw> {
+ pub components: Vec<T>,
+}
+
+impl<T> Screen<T>
+ where T: Draw {
+ pub fn run(&self) {
+ for component in self.components.iter() {
+ component.draw();
+ }
+ }
+}
```
<span class="caption">Listing 17-6: An alternate implementation of the `Screen`
@@ -124,9 +160,9 @@ collections, using generics and trait bounds is preferable because the
definitions will be monomorphized at compile time to use the concrete types.
On the other hand, with the method using trait objects, one `Screen` instance
-can hold a `Vec<T>` that contains a `Box<Button>` as well as a
-`Box<TextField>`. Let’s look at how this works, and then we’ll talk about the
-runtime performance implications.
+can hold a `Vec` that contains a `Box<Button>` as well as a `Box<TextField>`.
+Let’s look at how this works, and then we’ll talk about the runtime performance
+implications.
### Implementing the Trait
@@ -139,7 +175,21 @@ might have fields for `width`, `height`, and `label`, as shown in Listing 17-7:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-07/src/lib.rs:here}}
+# pub trait Draw {
+# fn draw(&self);
+# }
+#
+pub struct Button {
+ pub width: u32,
+ pub height: u32,
+ pub label: String,
+}
+
+impl Draw for Button {
+ fn draw(&self) {
+ // code to actually draw a button
+ }
+}
```
<span class="caption">Listing 17-7: A `Button` struct that implements the
@@ -162,7 +212,19 @@ If someone using our library decides to implement a `SelectBox` struct that has
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch17-oop/listing-17-08/src/main.rs:here}}
+use gui::Draw;
+
+struct SelectBox {
+ width: u32,
+ height: u32,
+ options: Vec<String>,
+}
+
+impl Draw for SelectBox {
+ fn draw(&self) {
+ // code to actually draw a select box
+ }
+}
```
<span class="caption">Listing 17-8: Another crate using `gui` and implementing
@@ -177,7 +239,30 @@ components. Listing 17-9 shows this implementation:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch17-oop/listing-17-09/src/main.rs:here}}
+use gui::{Screen, Button};
+
+fn main() {
+ let screen = Screen {
+ components: vec![
+ Box::new(SelectBox {
+ width: 75,
+ height: 10,
+ options: vec![
+ String::from("Yes"),
+ String::from("Maybe"),
+ String::from("No")
+ ],
+ }),
+ Box::new(Button {
+ width: 50,
+ height: 10,
+ label: String::from("OK"),
+ }),
+ ],
+ };
+
+ screen.run();
+}
```
<span class="caption">Listing 17-9: Using trait objects to store values of
@@ -189,15 +274,14 @@ new type and draw it because `SelectBox` implements the `Draw` trait, which
means it implements the `draw` method.
This concept—of being concerned only with the messages a value responds to
-rather than the value’s concrete type—is similar to the concept of *duck
-typing* in dynamically typed languages: if it walks like a duck and quacks
-like a duck, then it must be a duck! In the implementation of `run` on `Screen`
-in Listing 17-5, `run` doesn’t need to know what the concrete type of each
-component is. It doesn’t check whether a component is an instance of a `Button`
-or a `SelectBox`, it just calls the `draw` method on the component. By
-specifying `Box<dyn Draw>` as the type of the values in the `components`
-vector, we’ve defined `Screen` to need values that we can call the `draw`
-method on.
+rather than the value’s concrete type—is similar to the concept *duck typing*
+in dynamically typed languages: if it walks like a duck and quacks like a duck,
+then it must be a duck! In the implementation of `run` on `Screen` in Listing
+17-5, `run` doesn’t need to know what the concrete type of each component is.
+It doesn’t check whether a component is an instance of a `Button` or a
+`SelectBox`, it just calls the `draw` method on the component. By specifying
+`Box<dyn Draw>` as the type of the values in the `components` vector, we’ve
+defined `Screen` to need values that we can call the `draw` method on.
The advantage of using trait objects and Rust’s type system to write code
similar to code using duck typing is that we never have to check whether a
@@ -211,7 +295,17 @@ with a `String` as a component:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch17-oop/listing-17-10/src/main.rs}}
+use gui::Screen;
+
+fn main() {
+ let screen = Screen {
+ components: vec![
+ Box::new(String::from("Hi")),
+ ],
+ };
+
+ screen.run();
+}
```
<span class="caption">Listing 17-10: Attempting to use a type that doesn’t
@@ -220,7 +314,14 @@ implement the trait object’s trait</span>
We’ll get this error because `String` doesn’t implement the `Draw` trait:
```text
-{{#include ../listings/ch17-oop/listing-17-10/output.txt}}
+error[E0277]: the trait bound `std::string::String: gui::Draw` is not satisfied
+ --> src/main.rs:7:13
+ |
+ 7 | Box::new(String::from("Hi")),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait gui::Draw is not
+ implemented for `std::string::String`
+ |
+ = note: required for the cast to the object type `gui::Draw`
```
This error lets us know that either we’re passing something to `Screen` we
@@ -229,17 +330,17 @@ didn’t mean to pass and we should pass a different type or we should implement
### Trait Objects Perform Dynamic Dispatch
-Recall in the [“Performance of Code Using
-Generics”][performance-of-code-using-generics]<!-- ignore --> section in
-Chapter 10 our discussion on the monomorphization process performed by the
-compiler when we use trait bounds on generics: the compiler generates
-nongeneric implementations of functions and methods for each concrete type
-that we use in place of a generic type parameter. The code that results from
-monomorphization is doing *static dispatch*, which is when the compiler knows
-what method you’re calling at compile time. This is opposed to *dynamic
-dispatch*, which is when the compiler can’t tell at compile time which method
-you’re calling. In dynamic dispatch cases, the compiler emits code that at
-runtime will figure out which method to call.
+Recall in the [“Performance of Code Using Generics”]
+[performance-of-code-using-generics]<!-- ignore --> section in Chapter 10 our
+discussion on the monomorphization process performed by the compiler when we
+use trait bounds on generics: the compiler generates nongeneric implementations
+of functions and methods for each concrete type that we use in place of a
+generic type parameter. The code that results from monomorphization is doing
+*static dispatch*, which is when the compiler knows what method you’re calling
+at compile time. This is opposed to *dynamic dispatch*, which is when the
+compiler can’t tell at compile time which method you’re calling. In dynamic
+dispatch cases, the compiler emits code that at runtime will figure out which
+method to call.
When we use trait objects, Rust must use dynamic dispatch. The compiler doesn’t
know all the types that might be used with the code that is using trait
@@ -285,9 +386,9 @@ pub trait Clone {
The `String` type implements the `Clone` trait, and when we call the `clone`
method on an instance of `String` we get back an instance of `String`.
-Similarly, if we call `clone` on an instance of `Vec<T>`, we get back an
-instance of `Vec<T>`. The signature of `clone` needs to know what type will
-stand in for `Self`, because that’s the return type.
+Similarly, if we call `clone` on an instance of `Vec`, we get back an instance
+of `Vec`. The signature of `clone` needs to know what type will stand in for
+`Self`, because that’s the return type.
The compiler will indicate when you’re trying to do something that violates the
rules of object safety in regard to trait objects. For example, let’s say we
@@ -295,13 +396,22 @@ tried to implement the `Screen` struct in Listing 17-4 to hold types that
implement the `Clone` trait instead of the `Draw` trait, like this:
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch17-oop/no-listing-01-trait-object-of-clone/src/lib.rs}}
+pub struct Screen {
+ pub components: Vec<Box<dyn Clone>>,
+}
```
We would get this error:
```text
-{{#include ../listings/ch17-oop/no-listing-01-trait-object-of-clone/output.txt}}
+error[E0038]: the trait `std::clone::Clone` cannot be made into an object
+ --> src/lib.rs:2:5
+ |
+2 | pub components: Vec<Box<dyn Clone>>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` cannot be
+made into an object
+ |
+ = note: the trait cannot require that `Self : Sized`
```
This error means you can’t use this trait as a trait object in this way. If
diff --git a/book-original/src/ch17-03-oo-design-patterns.md b/book-pl-en/src/ch17-03-oo-design-patterns.md
index 8807541..e2d50b8 100644
--- a/book-original/src/ch17-03-oo-design-patterns.md
+++ b/book-pl-en/src/ch17-03-oo-design-patterns.md
@@ -34,8 +34,21 @@ because we haven’t implemented the `blog` crate yet.
<span class="filename">Filename: src/main.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch17-oop/listing-17-11/src/main.rs:all}}
+```rust,ignore
+use blog::Post;
+
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+ assert_eq!("", post.content());
+
+ post.request_review();
+ assert_eq!("", post.content());
+
+ post.approve();
+ assert_eq!("I ate a salad for lunch today", post.content());
+}
```
<span class="caption">Listing 17-11: Code that demonstrates the desired
@@ -76,7 +89,25 @@ inside an `Option<T>` in a private field named `state`. You’ll see why the
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-12/src/lib.rs}}
+pub struct Post {
+ state: Option<Box<dyn State>>,
+ content: String,
+}
+
+impl Post {
+ pub fn new() -> Post {
+ Post {
+ state: Some(Box::new(Draft {})),
+ content: String::new(),
+ }
+ }
+}
+
+trait State {}
+
+struct Draft {}
+
+impl State for Draft {}
```
<span class="caption">Listing 17-12: Definition of a `Post` struct and a `new`
@@ -108,7 +139,16 @@ Post` block:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-13/src/lib.rs:here}}
+# pub struct Post {
+# content: String,
+# }
+#
+impl Post {
+ // --snip--
+ pub fn add_text(&mut self, text: &str) {
+ self.content.push_str(text);
+ }
+}
```
<span class="caption">Listing 17-13: Implementing the `add_text` method to add
@@ -126,7 +166,7 @@ support.
Even after we’ve called `add_text` and added some content to our post, we still
want the `content` method to return an empty string slice because the post is
-still in the draft state, as shown on line 7 of Listing 17-11. For now, let’s
+still in the draft state, as shown on line 8 of Listing 17-11. For now, let’s
implement the `content` method with the simplest thing that will fulfill this
requirement: always returning an empty string slice. We’ll change this later
once we implement the ability to change a post’s state so it can be published.
@@ -136,13 +176,22 @@ be empty. Listing 17-14 shows this placeholder implementation:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-14/src/lib.rs:here}}
+# pub struct Post {
+# content: String,
+# }
+#
+impl Post {
+ // --snip--
+ pub fn content(&self) -> &str {
+ ""
+ }
+}
```
<span class="caption">Listing 17-14: Adding a placeholder implementation for
the `content` method on `Post` that always returns an empty string slice</span>
-With this added `content` method, everything in Listing 17-11 up to line 7
+With this added `content` method, everything in Listing 17-11 up to line 8
works as intended.
### Requesting a Review of the Post Changes Its State
@@ -153,7 +202,39 @@ change its state from `Draft` to `PendingReview`. Listing 17-15 shows this code:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-15/src/lib.rs:here}}
+# pub struct Post {
+# state: Option<Box<dyn State>>,
+# content: String,
+# }
+#
+impl Post {
+ // --snip--
+ pub fn request_review(&mut self) {
+ if let Some(s) = self.state.take() {
+ self.state = Some(s.request_review())
+ }
+ }
+}
+
+trait State {
+ fn request_review(self: Box<Self>) -> Box<dyn State>;
+}
+
+struct Draft {}
+
+impl State for Draft {
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ Box::new(PendingReview {})
+ }
+}
+
+struct PendingReview {}
+
+impl State for PendingReview {
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+}
```
<span class="caption">Listing 17-15: Implementing `request_review` methods on
@@ -199,7 +280,7 @@ state is responsible for its own rules.
We’ll leave the `content` method on `Post` as is, returning an empty string
slice. We can now have a `Post` in the `PendingReview` state as well as in the
`Draft` state, but we want the same behavior in the `PendingReview` state.
-Listing 17-11 now works up to line 10!
+Listing 17-11 now works up to line 11!
### Adding the `approve` Method that Changes the Behavior of `content`
@@ -210,7 +291,62 @@ state is approved, as shown in Listing 17-16:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-16/src/lib.rs:here}}
+# pub struct Post {
+# state: Option<Box<dyn State>>,
+# content: String,
+# }
+#
+impl Post {
+ // --snip--
+ pub fn approve(&mut self) {
+ if let Some(s) = self.state.take() {
+ self.state = Some(s.approve())
+ }
+ }
+}
+
+trait State {
+ fn request_review(self: Box<Self>) -> Box<dyn State>;
+ fn approve(self: Box<Self>) -> Box<dyn State>;
+}
+
+struct Draft {}
+
+impl State for Draft {
+# fn request_review(self: Box<Self>) -> Box<dyn State> {
+# Box::new(PendingReview {})
+# }
+#
+ // --snip--
+ fn approve(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+}
+
+struct PendingReview {}
+
+impl State for PendingReview {
+# fn request_review(self: Box<Self>) -> Box<dyn State> {
+# self
+# }
+#
+ // --snip--
+ fn approve(self: Box<Self>) -> Box<dyn State> {
+ Box::new(Published {})
+ }
+}
+
+struct Published {}
+
+impl State for Published {
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+
+ fn approve(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+}
```
<span class="caption">Listing 17-16: Implementing the `approve` method on
@@ -232,8 +368,22 @@ otherwise, we want to return an empty string slice, as shown in Listing 17-17:
<span class="filename">Filename: src/lib.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch17-oop/listing-17-17/src/lib.rs:here}}
+```rust
+# trait State {
+# fn content<'a>(&self, post: &'a Post) -> &'a str;
+# }
+# pub struct Post {
+# state: Option<Box<dyn State>>,
+# content: String,
+# }
+#
+impl Post {
+ // --snip--
+ pub fn content(&self) -> &str {
+ self.state.as_ref().unwrap().content(&self)
+ }
+ // --snip--
+}
```
<span class="caption">Listing 17-17: Updating the `content` method on `Post` to
@@ -268,7 +418,25 @@ Listing 17-18:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-18/src/lib.rs:here}}
+# pub struct Post {
+# content: String
+# }
+trait State {
+ // --snip--
+ fn content<'a>(&self, post: &'a Post) -> &'a str {
+ ""
+ }
+}
+
+// --snip--
+struct Published {}
+
+impl State for Published {
+ // --snip--
+ fn content<'a>(&self, post: &'a Post) -> &'a str {
+ &post.content
+ }
+}
```
<span class="caption">Listing 17-18: Adding the `content` method to the `State`
@@ -360,7 +528,14 @@ Let’s consider the first part of `main` in Listing 17-11:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch17-oop/listing-17-11/src/main.rs:here}}
+# use blog::Post;
+
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+ assert_eq!("", post.content());
+}
```
We still enable the creation of new posts in the draft state using `Post::new`
@@ -376,7 +551,31 @@ as well as methods on each:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-19/src/lib.rs}}
+pub struct Post {
+ content: String,
+}
+
+pub struct DraftPost {
+ content: String,
+}
+
+impl Post {
+ pub fn new() -> DraftPost {
+ DraftPost {
+ content: String::new(),
+ }
+ }
+
+ pub fn content(&self) -> &str {
+ &self.content
+ }
+}
+
+impl DraftPost {
+ pub fn add_text(&mut self, text: &str) {
+ self.content.push_str(text);
+ }
+}
```
<span class="caption">Listing 17-19: A `Post` with a `content` method and a
@@ -412,7 +611,35 @@ shown in Listing 17-20:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch17-oop/listing-17-20/src/lib.rs:here}}
+# pub struct Post {
+# content: String,
+# }
+#
+# pub struct DraftPost {
+# content: String,
+# }
+#
+impl DraftPost {
+ // --snip--
+
+ pub fn request_review(self) -> PendingReviewPost {
+ PendingReviewPost {
+ content: self.content,
+ }
+ }
+}
+
+pub struct PendingReviewPost {
+ content: String,
+}
+
+impl PendingReviewPost {
+ pub fn approve(self) -> Post {
+ Post {
+ content: self.content,
+ }
+ }
+}
```
<span class="caption">Listing 17-20: A `PendingReviewPost` that gets created by
@@ -442,7 +669,19 @@ The updated code in `main` is shown in Listing 17-21:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch17-oop/listing-17-21/src/main.rs}}
+use blog::Post;
+
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+
+ let post = post.request_review();
+
+ let post = post.approve();
+
+ assert_eq!("I ate a salad for lunch today", post.content());
+}
```
<span class="caption">Listing 17-21: Modifications to `main` to use the new
diff --git a/book-original/src/ch18-01-all-the-places-for-patterns.md b/book-pl-en/src/ch18-01-all-the-places-for-patterns.md
index ec0389a..f14e0c9 100644
--- a/book-original/src/ch18-01-all-the-places-for-patterns.md
+++ b/book-pl-en/src/ch18-01-all-the-places-for-patterns.md
@@ -28,9 +28,8 @@ value can never fail and thus covers every remaining case.
A particular pattern `_` will match anything, but it never binds to a variable,
so it’s often used in the last match arm. The `_` pattern can be useful when
you want to ignore any value not specified, for example. We’ll cover the `_`
-pattern in more detail in the [“Ignoring Values in a
-Pattern”][ignoring-values-in-a-pattern]<!-- ignore --> section later in this
-chapter.
+pattern in more detail in the [“Ignoring Values in a Pattern”]
+[ignoring-values-in-a-pattern]<!-- ignore --> section later in this chapter.
### Conditional `if let` Expressions
@@ -53,7 +52,25 @@ input.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-01/src/main.rs}}
+fn main() {
+ let favorite_color: Option<&str> = None;
+ let is_tuesday = false;
+ let age: Result<u8, _> = "34".parse();
+
+ if let Some(color) = favorite_color {
+ println!("Using your favorite color, {}, as the background", color);
+ } else if is_tuesday {
+ println!("Tuesday is green day!");
+ } else if let Ok(age) = age {
+ if age > 30 {
+ println!("Using purple as the background color");
+ } else {
+ println!("Using orange as the background color");
+ }
+ } else {
+ println!("Using blue as the background color");
+ }
+}
```
<span class="caption">Listing 18-1: Mixing `if let`, `else if`, `else if let`,
@@ -90,7 +107,15 @@ Listing 18-2 shows a `while let` loop that uses a vector as a stack and prints
the values in the vector in the opposite order in which they were pushed.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-02/src/main.rs:here}}
+let mut stack = Vec::new();
+
+stack.push(1);
+stack.push(2);
+stack.push(3);
+
+while let Some(top) = stack.pop() {
+ println!("{}", top);
+}
```
<span class="caption">Listing 18-2: Using a `while let` loop to print values
@@ -113,7 +138,11 @@ Listing 18-3 demonstrates how to use a pattern in a `for` loop to destructure,
or break apart, a tuple as part of the `for` loop.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-03/src/main.rs:here}}
+let v = vec!['a', 'b', 'c'];
+
+for (index, value) in v.iter().enumerate() {
+ println!("{} is at index {}", value, index);
+}
```
<span class="caption">Listing 18-3: Using a pattern in a `for` loop to
@@ -122,7 +151,9 @@ destructure a tuple</span>
The code in Listing 18-3 will print the following:
```text
-{{#include ../listings/ch18-patterns-and-matching/listing-18-03/output.txt}}
+a is at index 0
+b is at index 1
+c is at index 2
```
We use the `enumerate` method to adapt an iterator to produce a value and that
@@ -161,7 +192,7 @@ To see the pattern matching aspect of `let` more clearly, consider Listing
18-4, which uses a pattern with `let` to destructure a tuple.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-04/src/main.rs:here}}
+let (x, y, z) = (1, 2, 3);
```
<span class="caption">Listing 18-4: Using a pattern to destructure a tuple and
@@ -178,7 +209,7 @@ example, Listing 18-5 shows an attempt to destructure a tuple with three
elements into two variables, which won’t work.
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-05/src/main.rs:here}}
+let (x, y) = (1, 2, 3);
```
<span class="caption">Listing 18-5: Incorrectly constructing a pattern whose
@@ -187,15 +218,22 @@ variables don’t match the number of elements in the tuple</span>
Attempting to compile this code results in this type error:
```text
-{{#include ../listings/ch18-patterns-and-matching/listing-18-05/output.txt}}
+error[E0308]: mismatched types
+ --> src/main.rs:2:9
+ |
+2 | let (x, y) = (1, 2, 3);
+ | ^^^^^^ expected a tuple with 3 elements, found one with 2 elements
+ |
+ = note: expected type `({integer}, {integer}, {integer})`
+ found type `(_, _)`
```
If we wanted to ignore one or more of the values in the tuple, we could use `_`
-or `..`, as you’ll see in the [“Ignoring Values in a
-Pattern”][ignoring-values-in-a-pattern]<!-- ignore --> section. If the problem
-is that we have too many variables in the pattern, the solution is to make the
-types match by removing variables so the number of variables equals the number
-of elements in the tuple.
+or `..`, as you’ll see in the [“Ignoring Values in a Pattern”]
+[ignoring-values-in-a-pattern]<!-- ignore --> section. If the problem is that
+we have too many variables in the pattern, the solution is to make the types
+match by removing variables so the number of variables equals the number of
+elements in the tuple.
### Function Parameters
@@ -204,7 +242,9 @@ declares a function named `foo` that takes one parameter named `x` of type
`i32`, should by now look familiar.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-06/src/main.rs:here}}
+fn foo(x: i32) {
+ // code goes here
+}
```
<span class="caption">Listing 18-6: A function signature uses patterns in the
@@ -217,7 +257,14 @@ as we pass it to a function.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-07/src/main.rs}}
+fn print_coordinates(&(x, y): &(i32, i32)) {
+ println!("Current location: ({}, {})", x, y);
+}
+
+fn main() {
+ let point = (3, 5);
+ print_coordinates(&point);
+}
```
<span class="caption">Listing 18-7: A function with parameters that destructure
diff --git a/book-original/src/ch18-02-refutability.md b/book-pl-en/src/ch18-02-refutability.md
index 029547f..55cb038 100644
--- a/book-original/src/ch18-02-refutability.md
+++ b/book-pl-en/src/ch18-02-refutability.md
@@ -10,9 +10,8 @@ a_value` because if the value in the `a_value` variable is `None` rather than
Function parameters, `let` statements, and `for` loops can only accept
irrefutable patterns, because the program cannot do anything meaningful when
-values don’t match. The `if let` and `while let` expressions accept
-refutable and irrefutable patterns, but the compiler warns against
-irrefutable patterns because by definition they’re intended to handle possible
+values don’t match. The `if let` and `while let` expressions only accept
+refutable patterns, because by definition they’re intended to handle possible
failure: the functionality of a conditional is in its ability to perform
differently depending on success or failure.
@@ -28,7 +27,7 @@ where Rust requires an irrefutable pattern and vice versa. Listing 18-8 shows a
pattern. As you might expect, this code will not compile.
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-08/src/main.rs:here}}
+let Some(x) = some_option_value;
```
<span class="caption">Listing 18-8: Attempting to use a refutable pattern with
@@ -41,7 +40,11 @@ do with a `None` value. At compile time, Rust will complain that we’ve tried t
use a refutable pattern where an irrefutable pattern is required:
```text
-{{#include ../listings/ch18-patterns-and-matching/listing-18-08/output.txt}}
+error[E0005]: refutable pattern in local binding: `None` not covered
+ -->
+ |
+3 | let Some(x) = some_option_value;
+ | ^^^^^^^ pattern `None` not covered
```
Because we didn’t cover (and couldn’t cover!) every valid value with the
@@ -54,7 +57,10 @@ will just skip the code in the curly brackets, giving it a way to continue
validly. Listing 18-9 shows how to fix the code in Listing 18-8.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-09/src/main.rs:here}}
+# let some_option_value: Option<i32> = None;
+if let Some(x) = some_option_value {
+ println!("{}", x);
+}
```
<span class="caption">Listing 18-9: Using `if let` and a block with refutable
@@ -63,10 +69,12 @@ patterns instead of `let`</span>
We’ve given the code an out! This code is perfectly valid, although it means we
cannot use an irrefutable pattern without receiving an error. If we give `if
let` a pattern that will always match, such as `x`, as shown in Listing 18-10,
-the compiler will give a warning.
+it will not compile.
-```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-10/src/main.rs:here}}
+```rust,ignore,does_not_compile
+if let x = 5 {
+ println!("{}", x);
+};
```
<span class="caption">Listing 18-10: Attempting to use an irrefutable pattern
@@ -76,7 +84,11 @@ Rust complains that it doesn’t make sense to use `if let` with an irrefutable
pattern:
```text
-{{#include ../listings/ch18-patterns-and-matching/listing-18-10/output.txt}}
+error[E0162]: irrefutable if-let pattern
+ --> <anon>:2:8
+ |
+2 | if let x = 5 {
+ | ^ irrefutable pattern
```
For this reason, match arms must use refutable patterns, except for the last
diff --git a/book-original/src/ch18-03-pattern-syntax.md b/book-pl-en/src/ch18-03-pattern-syntax.md
index d0b2818..1ff1a1c 100644
--- a/book-original/src/ch18-03-pattern-syntax.md
+++ b/book-pl-en/src/ch18-03-pattern-syntax.md
@@ -10,7 +10,14 @@ As you saw in Chapter 6, you can match patterns against literals directly. The
following code gives some examples:
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-01-literals/src/main.rs:here}}
+let x = 1;
+
+match x {
+ 1 => println!("one"),
+ 2 => println!("two"),
+ 3 => println!("three"),
+ _ => println!("anything"),
+}
```
This code prints `one` because the value in `x` is 1. This syntax is useful
@@ -33,7 +40,18 @@ running this code or reading further.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-11/src/main.rs:here}}
+fn main() {
+ let x = Some(5);
+ let y = 10;
+
+ match x {
+ Some(50) => println!("Got 50"),
+ Some(y) => println!("Matched, y = {:?}", y),
+ _ => println!("Default case, x = {:?}", x),
+ }
+
+ println!("at the end: x = {:?}, y = {:?}", x, y);
+}
```
<span class="caption">Listing 18-11: A `match` expression with an arm that
@@ -76,26 +94,37 @@ value of `x` matches either of the values in that arm, that arm’s code will
run:
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/src/main.rs:here}}
+let x = 1;
+
+match x {
+ 1 | 2 => println!("one or two"),
+ 3 => println!("three"),
+ _ => println!("anything"),
+}
```
This code prints `one or two`.
-### Matching Ranges of Values with `..=`
+### Matching Ranges of Values with `...`
-The `..=` syntax allows us to match to an inclusive range of values. In the
+The `...` syntax allows us to match to an inclusive range of values. In the
following code, when a pattern matches any of the values within the range, that
arm will execute:
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-03-ranges/src/main.rs:here}}
+let x = 5;
+
+match x {
+ 1 ... 5 => println!("one through five"),
+ _ => println!("something else"),
+}
```
If `x` is 1, 2, 3, 4, or 5, the first arm will match. This syntax is more
-convenient than using the `|` operator to express the same idea; instead of
-`1..=5`, we would have to specify `1 | 2 | 3 | 4 | 5` if we used `|`.
-Specifying a range is much shorter, especially if we want to match, say, any
-number between 1 and 1,000!
+convenient than using the `|` operator to express the same idea; instead of `1
+... 5`, we would have to specify `1 | 2 | 3 | 4 | 5` if we used `|`. Specifying
+a range is much shorter, especially if we want to match, say, any number
+between 1 and 1,000!
Ranges are only allowed with numeric values or `char` values, because the
compiler checks that the range isn’t empty at compile time. The only types for
@@ -104,7 +133,13 @@ which Rust can tell if a range is empty or not are `char` and numeric values.
Here is an example using ranges of `char` values:
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/src/main.rs:here}}
+let x = 'c';
+
+match x {
+ 'a' ... 'j' => println!("early ASCII letter"),
+ 'k' ... 'z' => println!("late ASCII letter"),
+ _ => println!("something else"),
+}
```
Rust can tell that `c` is within the first pattern’s range and prints `early
@@ -123,7 +158,18 @@ break apart using a pattern with a `let` statement.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-12/src/main.rs}}
+struct Point {
+ x: i32,
+ y: i32,
+}
+
+fn main() {
+ let p = Point { x: 0, y: 7 };
+
+ let Point { x: a, y: b } = p;
+ assert_eq!(0, a);
+ assert_eq!(7, b);
+}
```
<span class="caption">Listing 18-12: Destructuring a struct’s fields into
@@ -146,7 +192,18 @@ in Listing 18-12, but the variables created in the `let` pattern are `x` and
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-13/src/main.rs}}
+struct Point {
+ x: i32,
+ y: i32,
+}
+
+fn main() {
+ let p = Point { x: 0, y: 7 };
+
+ let Point { x, y } = p;
+ assert_eq!(0, x);
+ assert_eq!(7, y);
+}
```
<span class="caption">Listing 18-13: Destructuring struct fields using struct
@@ -168,7 +225,20 @@ three cases: points that lie directly on the `x` axis (which is true when `y =
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-14/src/main.rs:here}}
+# struct Point {
+# x: i32,
+# y: i32,
+# }
+#
+fn main() {
+ let p = Point { x: 0, y: 7 };
+
+ match p {
+ Point { x, y: 0 } => println!("On the x axis at {}", x),
+ Point { x: 0, y } => println!("On the y axis at {}", y),
+ Point { x, y } => println!("On neither axis: ({}, {})", x, y),
+ }
+}
```
<span class="caption">Listing 18-14: Destructuring and matching literal values
@@ -198,7 +268,38 @@ a `match` with patterns that will destructure each inner value.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-15/src/main.rs}}
+enum Message {
+ Quit,
+ Move { x: i32, y: i32 },
+ Write(String),
+ ChangeColor(i32, i32, i32),
+}
+
+fn main() {
+ let msg = Message::ChangeColor(0, 160, 255);
+
+ match msg {
+ Message::Quit => {
+ println!("The Quit variant has no data to destructure.")
+ },
+ Message::Move { x, y } => {
+ println!(
+ "Move in the x direction {} and in the y direction {}",
+ x,
+ y
+ );
+ }
+ Message::Write(text) => println!("Text message: {}", text),
+ Message::ChangeColor(r, g, b) => {
+ println!(
+ "Change the color to red {}, green {}, and blue {}",
+ r,
+ g,
+ b
+ )
+ }
+ }
+}
```
<span class="caption">Listing 18-15: Destructuring enum variants that hold
@@ -223,26 +324,108 @@ pattern is similar to the pattern we specify to match tuples. The number of
variables in the pattern must match the number of elements in the variant we’re
matching.
-#### Destructuring Nested Structs and Enums
+#### Destructuring Nested Structs & Enums
+
+Up until now, all of our examples have been matching structures that were one
+level deep. Matching can work on nested structures too!
+
+We can refactor the example above to support both RGB and HSV colors:
+
+```rust
+enum Color {
+ Rgb(i32, i32, i32),
+ Hsv(i32, i32, i32)
+}
+
+enum Message {
+ Quit,
+ Move { x: i32, y: i32 },
+ Write(String),
+ ChangeColor(Color),
+}
+
+fn main() {
+ let msg = Message::ChangeColor(Color::Hsv(0, 160, 255));
+
+ match msg {
+ Message::ChangeColor(Color::Rgb(r, g, b)) => {
+ println!(
+ "Change the color to red {}, green {}, and blue {}",
+ r,
+ g,
+ b
+ )
+ },
+ Message::ChangeColor(Color::Hsv(h, s, v)) => {
+ println!(
+ "Change the color to hue {}, saturation {}, and value {}",
+ h,
+ s,
+ v
+ )
+ }
+ _ => ()
+ }
+}
+```
+
+#### Destructuring References
-Until now, all our examples have been matching structs or enums that were one
-level deep. Matching can work on nested items too!
+When the value we’re matching to our pattern contains a reference, we need to
+destructure the reference from the value, which we can do by specifying a `&`
+in the pattern. Doing so lets us get a variable holding the value that the
+reference points to rather than getting a variable that holds the reference.
+This technique is especially useful in closures where we have iterators that
+iterate over references, but we want to use the values in the closure rather
+than the references.
-For example, we can refactor the code in Listing 18-15 to support RGB and HSV
-colors in the `ChangeColor` message, as shown in Listing 18-16.
+The example in Listing 18-16 iterates over references to `Point` instances in a
+vector, destructuring the reference and the struct so we can perform
+calculations on the `x` and `y` values easily.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-16/src/main.rs}}
+# struct Point {
+# x: i32,
+# y: i32,
+# }
+#
+let points = vec![
+ Point { x: 0, y: 0 },
+ Point { x: 1, y: 5 },
+ Point { x: 10, y: -3 },
+];
+
+let sum_of_squares: i32 = points
+ .iter()
+ .map(|&Point { x, y }| x * x + y * y)
+ .sum();
```
-<span class="caption">Listing 18-16: Matching on nested enums</span>
+<span class="caption">Listing 18-16: Destructuring a reference to a struct into
+the struct field values</span>
-The pattern of the first arm in the `match` expression matches a
-`Message::ChangeColor` enum variant that contains a `Color::Rgb` variant; then
-the pattern binds to the three inner `i32` values. The pattern of the second
-arm also matches a `Message::ChangeColor` enum variant, but the inner enum
-matches the `Color::Hsv` variant instead. We can specify these complex
-conditions in one `match` expression, even though two enums are involved.
+This code gives us the variable `sum_of_squares` holding the value 135, which
+is the result of squaring the `x` value and the `y` value, adding those
+together, and then adding the result for each `Point` in the `points` vector to
+get one number.
+
+If we had not included the `&` in `&Point { x, y }`, we’d get a type mismatch
+error, because `iter` would then iterate over references to the items in the
+vector rather than the actual values. The error would look like this:
+
+```text
+error[E0308]: mismatched types
+ -->
+ |
+14 | .map(|Point { x, y }| x * x + y * y)
+ | ^^^^^^^^^^^^ expected &Point, found struct `Point`
+ |
+ = note: expected type `&Point`
+ found type `Point`
+```
+
+This error indicates that Rust was expecting our closure to match `&Point`, but
+we tried to match directly to a `Point` value, not a reference to a `Point`.
#### Destructuring Structs and Tuples
@@ -251,7 +434,12 @@ The following example shows a complicated destructure where we nest structs and
tuples inside a tuple and destructure all the primitive values out:
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/src/main.rs:here}}
+# struct Point {
+# x: i32,
+# y: i32,
+# }
+#
+let ((feet, inches), Point {x, y}) = ((3, 10), Point { x: 3, y: -10 });
```
This code lets us break complex types into their component parts so we can use
@@ -280,7 +468,13 @@ including function parameters, as shown in Listing 18-17.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-17/src/main.rs}}
+fn foo(_: i32, y: i32) {
+ println!("This code only uses the y parameter: {}", y);
+}
+
+fn main() {
+ foo(3, 4);
+}
```
<span class="caption">Listing 18-17: Using `_` in a function signature</span>
@@ -303,10 +497,23 @@ example, when we want to test for only part of a value but have no use for the
other parts in the corresponding code we want to run. Listing 18-18 shows code
responsible for managing a setting’s value. The business requirements are that
the user should not be allowed to overwrite an existing customization of a
-setting but can unset the setting and give it a value if it is currently unset.
+setting but can unset the setting and can give the setting a value if it is
+currently unset.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-18/src/main.rs:here}}
+let mut setting_value = Some(5);
+let new_setting_value = Some(10);
+
+match (setting_value, new_setting_value) {
+ (Some(_), Some(_)) => {
+ println!("Can't overwrite an existing customized value");
+ }
+ _ => {
+ setting_value = new_setting_value;
+ }
+}
+
+println!("setting is {:?}", setting_value);
```
<span class="caption">Listing 18-18: Using an underscore within patterns that
@@ -329,7 +536,13 @@ particular values. Listing 18-19 shows an example of ignoring the second and
fourth values in a tuple of five items.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-19/src/main.rs:here}}
+let numbers = (2, 4, 8, 16, 32);
+
+match numbers {
+ (first, _, third, _, fifth) => {
+ println!("Some numbers: {}, {}, {}", first, third, fifth)
+ },
+}
```
<span class="caption">Listing 18-19: Ignoring multiple parts of a tuple</span>
@@ -350,7 +563,10 @@ only get a warning about one of them.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-20/src/main.rs}}
+fn main() {
+ let _x = 5;
+ let y = 10;
+}
```
<span class="caption">Listing 18-20: Starting a variable name with an
@@ -365,7 +581,13 @@ variable, whereas `_` doesn’t bind at all. To show a case where this
distinction matters, Listing 18-21 will provide us with an error.
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-21/src/main.rs:here}}
+let s = Some(String::from("Hello!"));
+
+if let Some(_s) = s {
+ println!("found a string");
+}
+
+println!("{:?}", s);
```
<span class="caption">Listing 18-21: An unused variable starting with an
@@ -377,7 +599,13 @@ doesn’t ever bind to the value. Listing 18-22 will compile without any errors
because `s` doesn’t get moved into `_`.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-22/src/main.rs:here}}
+let s = Some(String::from("Hello!"));
+
+if let Some(_) = s {
+ println!("found a string");
+}
+
+println!("{:?}", s);
```
<span class="caption">Listing 18-22: Using an underscore does not bind the
@@ -396,7 +624,17 @@ explicitly matched in the rest of the pattern. In Listing 18-23, we have a
the values in the `y` and `z` fields.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-23/src/main.rs:here}}
+struct Point {
+ x: i32,
+ y: i32,
+ z: i32,
+}
+
+let origin = Point { x: 0, y: 0, z: 0 };
+
+match origin {
+ Point { x, .. } => println!("x is {}", x),
+}
```
<span class="caption">Listing 18-23: Ignoring all fields of a `Point` except
@@ -413,7 +651,15 @@ shows how to use `..` with a tuple.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-24/src/main.rs}}
+fn main() {
+ let numbers = (2, 4, 8, 16, 32);
+
+ match numbers {
+ (first, .., last) => {
+ println!("Some numbers: {}, {}", first, last);
+ },
+ }
+}
```
<span class="caption">Listing 18-24: Matching only the first and last values in
@@ -430,7 +676,15 @@ compile.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-25/src/main.rs}}
+fn main() {
+ let numbers = (2, 4, 8, 16, 32);
+
+ match numbers {
+ (.., second, ..) => {
+ println!("Some numbers: {}", second)
+ },
+ }
+}
```
<span class="caption">Listing 18-25: An attempt to use `..` in an ambiguous
@@ -439,7 +693,11 @@ way</span>
When we compile this example, we get this error:
```text
-{{#include ../listings/ch18-patterns-and-matching/listing-18-25/output.txt}}
+error: `..` can only be used once per tuple or tuple struct pattern
+ --> src/main.rs:5:22
+ |
+5 | (.., second, ..) => {
+ | ^^
```
It’s impossible for Rust to determine how many values in the tuple to ignore
@@ -462,7 +720,13 @@ The condition can use variables created in the pattern. Listing 18-26 shows a
guard of `if x < 5`.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-26/src/main.rs:here}}
+let num = Some(4);
+
+match num {
+ Some(x) if x < 5 => println!("less than five: {}", x),
+ Some(x) => println!("{}", x),
+ None => (),
+}
```
<span class="caption">Listing 18-26: Adding a match guard to a pattern</span>
@@ -490,7 +754,18 @@ problem.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-27/src/main.rs}}
+fn main() {
+ let x = Some(5);
+ let y = 10;
+
+ match x {
+ Some(50) => println!("Got 50"),
+ Some(n) if n == y => println!("Matched, n = {:?}", n),
+ _ => println!("Default case, x = {:?}", x),
+ }
+
+ println!("at the end: x = {:?}, y = {:?}", x, y);
+}
```
<span class="caption">Listing 18-27: Using a match guard to test for equality
@@ -516,7 +791,13 @@ to `4`, `5`, *and* `6`, even though it might look like `if y` only applies to
`6`.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-28/src/main.rs:here}}
+let x = 4;
+let y = false;
+
+match x {
+ 4 | 5 | 6 if y => println!("yes"),
+ _ => println!("no"),
+}
```
<span class="caption">Listing 18-28: Combining multiple patterns with a match
@@ -551,20 +832,36 @@ were applied only to the final value in the list of values specified using the
The *at* operator (`@`) lets us create a variable that holds a value at the
same time we’re testing that value to see whether it matches a pattern. Listing
18-29 shows an example where we want to test that a `Message::Hello` `id` field
-is within the range `3..=7`. But we also want to bind the value to the variable
+is within the range `3...7`. But we also want to bind the value to the variable
`id_variable` so we can use it in the code associated with the arm. We could
name this variable `id`, the same as the field, but for this example we’ll use
a different name.
```rust
-{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-29/src/main.rs:here}}
+enum Message {
+ Hello { id: i32 },
+}
+
+let msg = Message::Hello { id: 5 };
+
+match msg {
+ Message::Hello { id: id_variable @ 3...7 } => {
+ println!("Found an id in range: {}", id_variable)
+ },
+ Message::Hello { id: 10...12 } => {
+ println!("Found an id in another range")
+ },
+ Message::Hello { id } => {
+ println!("Found some other id: {}", id)
+ },
+}
```
<span class="caption">Listing 18-29: Using `@` to bind to a value in a pattern
while also testing it</span>
This example will print `Found an id in range: 5`. By specifying `id_variable
-@` before the range `3..=7`, we’re capturing whatever value matched the range
+@` before the range `3...7`, we’re capturing whatever value matched the range
while also testing that the value matched the range pattern.
In the second arm, where we only have a range specified in the pattern, the code
@@ -582,6 +879,66 @@ first two arms: any value would match this pattern.
Using `@` lets us test a value and save it in a variable within one pattern.
+### Legacy patterns: `ref` and `ref mut`
+
+In older versions of Rust, `match` would assume that you want to move what is
+matched. But sometimes, that’s not what you wanted. For example:
+
+```rust
+let robot_name = &Some(String::from("Bors"));
+
+match robot_name {
+ Some(name) => println!("Found a name: {}", name),
+ None => (),
+}
+
+println!("robot_name is: {:?}", robot_name);
+```
+
+Here, `robot_name` is a `&Option<String>`. Rust would then complain that
+`Some(name)` doesn’t match up with `&Option<T>`, so you’d have to write this:
+
+```rust,ignore
+let robot_name = &Some(String::from("Bors"));
+
+match robot_name {
+ &Some(name) => println!("Found a name: {}", name),
+ None => (),
+}
+
+println!("robot_name is: {:?}", robot_name);
+```
+
+Next, Rust would complain that `name` is trying to move the `String` out of
+the option, but because it’s a reference to an option, it’s borrowed, and so
+can’t be moved out of. This is where the `ref` keyword comes into play:
+
+```rust
+let robot_name = &Some(String::from("Bors"));
+
+match robot_name {
+ &Some(ref name) => println!("Found a name: {}", name),
+ None => (),
+}
+
+println!("robot_name is: {:?}", robot_name);
+```
+
+The `ref` keyword is like the opposite of `&` in patterns; this says “please
+bind `ref` to be a `&String`, don’t try to move it out. In other words, the
+`&` in `&Some` is matching against a reference, but `ref` *creates* a
+reference. `ref mut` is like `ref`, but for mutable references.
+
+Anyway, today’s Rust doesn’t work like this. If you try to `match` on
+something borrowed, then all of the bindings you create will attempt to
+borrow as well. This means that the original code works as you’d expect.
+
+Because Rust is backwards compatible, we couldn’t remove `ref` and `ref mut`,
+and they’re sometimes useful in obscure situations, where you want to
+partially borrow part of a struct as mutable and another part as immutable.
+But you may see them in older Rust code, so knowing what they do is still
+useful.
+
## Summary
Rust’s patterns are very useful in that they help distinguish between different
diff --git a/book-original/src/ch19-00-advanced-features.md b/book-pl-en/src/ch19-00-advanced-features.md
index 270d6da..0b7f987 100644
--- a/book-original/src/ch19-00-advanced-features.md
+++ b/book-pl-en/src/ch19-00-advanced-features.md
@@ -12,6 +12,7 @@ In this chapter, we’ll cover:
* Unsafe Rust: how to opt out of some of Rust’s guarantees and take
responsibility for manually upholding those guarantees
+* Advanced lifetimes: syntax for complex lifetime situations
* Advanced traits: associated types, default type parameters, fully qualified
syntax, supertraits, and the newtype pattern in relation to traits
* Advanced types: more about the newtype pattern, type aliases, the never type,
diff --git a/book-original/src/ch19-01-unsafe-rust.md b/book-pl-en/src/ch19-01-unsafe-rust.md
index 653bf88..bdbd473 100644
--- a/book-original/src/ch19-01-unsafe-rust.md
+++ b/book-pl-en/src/ch19-01-unsafe-rust.md
@@ -25,7 +25,7 @@ Rust and how to do it.
### Unsafe Superpowers
To switch to unsafe Rust, use the `unsafe` keyword and then start a new block
-that holds the unsafe code. You can take five actions in unsafe Rust, called
+that holds the unsafe code. You can take four actions in unsafe Rust, called
*unsafe superpowers*, that you can’t in safe Rust. Those superpowers include
the ability to:
@@ -33,12 +33,11 @@ the ability to:
* Call an unsafe function or method
* Access or modify a mutable static variable
* Implement an unsafe trait
-* Access fields of `union`s
It’s important to understand that `unsafe` doesn’t turn off the borrow checker
or disable any other of Rust’s safety checks: if you use a reference in unsafe
code, it will still be checked. The `unsafe` keyword only gives you access to
-these five features that are then not checked by the compiler for memory
+these four features that are then not checked by the compiler for memory
safety. You’ll still get some degree of safety inside of an unsafe block.
In addition, `unsafe` does not mean the code inside the block is necessarily
@@ -46,7 +45,7 @@ dangerous or that it will definitely have memory safety problems: the intent is
that as the programmer, you’ll ensure the code inside an `unsafe` block will
access memory in a valid way.
-People are fallible, and mistakes will happen, but by requiring these five
+People are fallible, and mistakes will happen, but by requiring these four
unsafe operations to be inside blocks annotated with `unsafe` you’ll know that
any errors related to memory safety must be within an `unsafe` block. Keep
`unsafe` blocks small; you’ll be thankful later when you investigate memory
@@ -61,7 +60,7 @@ from leaking out into all the places that you or your users might want to use
the functionality implemented with `unsafe` code, because using a safe
abstraction is safe.
-Let’s look at each of the five unsafe superpowers in turn. We’ll also look at
+Let’s look at each of the four unsafe superpowers in turn. We’ll also look at
some abstractions that provide a safe interface to unsafe code.
### Dereferencing a Raw Pointer
@@ -91,7 +90,10 @@ Listing 19-1 shows how to create an immutable and a mutable raw pointer from
references.
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-01/src/main.rs:here}}
+let mut num = 5;
+
+let r1 = &num as *const i32;
+let r2 = &mut num as *mut i32;
```
<span class="caption">Listing 19-1: Creating raw pointers from references</span>
@@ -114,7 +116,8 @@ is no memory access, or the program might error with a segmentation fault.
Usually, there is no good reason to write code like this, but it is possible.
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-02/src/main.rs:here}}
+let address = 0x012345usize;
+let r = address as *const i32;
```
<span class="caption">Listing 19-2: Creating a raw pointer to an arbitrary
@@ -125,7 +128,15 @@ raw pointers and read the data being pointed to. In Listing 19-3, we use the
dereference operator `*` on a raw pointer that requires an `unsafe` block.
```rust,unsafe
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-03/src/main.rs:here}}
+let mut num = 5;
+
+let r1 = &num as *const i32;
+let r2 = &mut num as *mut i32;
+
+unsafe {
+ println!("r1 is: {}", *r1);
+ println!("r2 is: {}", *r2);
+}
```
<span class="caption">Listing 19-3: Dereferencing raw pointers within an
@@ -166,14 +177,22 @@ Here is an unsafe function named `dangerous` that doesn’t do anything in its
body:
```rust,unsafe
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-01-unsafe-fn/src/main.rs:here}}
+unsafe fn dangerous() {}
+
+unsafe {
+ dangerous();
+}
```
We must call the `dangerous` function within a separate `unsafe` block. If we
try to call `dangerous` without the `unsafe` block, we’ll get an error:
```text
-{{#include ../listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt}}
+error[E0133]: call to unsafe function requires unsafe function or block
+ -->
+ |
+4 | dangerous();
+ | ^^^^^^^^^^^ call to unsafe function
```
By inserting the `unsafe` block around our call to `dangerous`, we’re asserting
@@ -196,7 +215,14 @@ slice and makes it two by splitting the slice at the index given as an
argument. Listing 19-4 shows how to use `split_at_mut`.
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-04/src/main.rs:here}}
+let mut v = vec![1, 2, 3, 4, 5, 6];
+
+let r = &mut v[..];
+
+let (a, b) = r.split_at_mut(3);
+
+assert_eq!(a, &mut [1, 2, 3]);
+assert_eq!(b, &mut [4, 5, 6]);
```
<span class="caption">Listing 19-4: Using the safe `split_at_mut`
@@ -208,7 +234,14 @@ implement `split_at_mut` as a function rather than a method and only for slices
of `i32` values rather than for a generic type `T`.
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-05/src/main.rs:here}}
+fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
+ let len = slice.len();
+
+ assert!(mid <= len);
+
+ (&mut slice[..mid],
+ &mut slice[mid..])
+}
```
<span class="caption">Listing 19-5: An attempted implementation of
@@ -217,7 +250,7 @@ of `i32` values rather than for a generic type `T`.
This function first gets the total length of the slice. Then it asserts that
the index given as a parameter is within the slice by checking whether it’s
less than or equal to the length. The assertion means that if we pass an index
-that is greater than the length to split the slice at, the function will panic
+that is greater than the index to split the slice at, the function will panic
before it attempts to use that index.
Then we return two mutable slices in a tuple: one from the start of the
@@ -227,7 +260,15 @@ slice.
When we try to compile the code in Listing 19-5, we’ll get an error.
```text
-{{#include ../listings/ch19-advanced-features/listing-19-05/output.txt}}
+error[E0499]: cannot borrow `*slice` as mutable more than once at a time
+ -->
+ |
+6 | (&mut slice[..mid],
+ | ----- first mutable borrow occurs here
+7 | &mut slice[mid..])
+ | ^^^^^ second mutable borrow occurs here
+8 | }
+ | - first borrow ends here
```
Rust’s borrow checker can’t understand that we’re borrowing different parts of
@@ -240,7 +281,19 @@ Listing 19-6 shows how to use an `unsafe` block, a raw pointer, and some calls
to unsafe functions to make the implementation of `split_at_mut` work.
```rust,unsafe
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-06/src/main.rs:here}}
+use std::slice;
+
+fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
+ let len = slice.len();
+ let ptr = slice.as_mut_ptr();
+
+ assert!(mid <= len);
+
+ unsafe {
+ (slice::from_raw_parts_mut(ptr, mid),
+ slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
+ }
+}
```
<span class="caption">Listing 19-6: Using unsafe code in the implementation of
@@ -256,16 +309,16 @@ mutable slice to `i32` values, `as_mut_ptr` returns a raw pointer with the type
We keep the assertion that the `mid` index is within the slice. Then we get to
the unsafe code: the `slice::from_raw_parts_mut` function takes a raw pointer
and a length, and it creates a slice. We use this function to create a slice
-that starts from `ptr` and is `mid` items long. Then we call the `add`
+that starts from `ptr` and is `mid` items long. Then we call the `offset`
method on `ptr` with `mid` as an argument to get a raw pointer that starts at
`mid`, and we create a slice using that pointer and the remaining number of
items after `mid` as the length.
The function `slice::from_raw_parts_mut` is unsafe because it takes a raw
-pointer and must trust that this pointer is valid. The `add` method on raw
+pointer and must trust that this pointer is valid. The `offset` method on raw
pointers is also unsafe, because it must trust that the offset location is also
a valid pointer. Therefore, we had to put an `unsafe` block around our calls to
-`slice::from_raw_parts_mut` and `add` so we could call them. By looking at
+`slice::from_raw_parts_mut` and `offset` so we could call them. By looking at
the code and by adding the assertion that `mid` must be less than or equal to
`len`, we can tell that all the raw pointers used within the `unsafe` block
will be valid pointers to data within the slice. This is an acceptable and
@@ -282,7 +335,14 @@ likely crash when the slice is used. This code takes an arbitrary memory
location and creates a slice 10,000 items long.
```rust,unsafe
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-07/src/main.rs:here}}
+use std::slice;
+
+let address = 0x01234usize;
+let r = address as *mut i32;
+
+let slice : &[i32] = unsafe {
+ slice::from_raw_parts_mut(r, 10000)
+};
```
<span class="caption">Listing 19-7: Creating a slice from an arbitrary memory
@@ -290,7 +350,11 @@ location</span>
We don’t own the memory at this arbitrary location, and there is no guarantee
that the slice this code creates contains valid `i32` values. Attempting to use
-`slice` as though it’s a valid slice results in undefined behavior.
+`slice` as though it’s a valid slice results in undefined behavior. If we would
+not have taken care to align `address` to 4 (the alignment of `i32`), then even
+just calling `slice::from_raw_parts_mut` would already be undefined behavior --
+slices must always be aligned, even if they are not used (and even if they are
+empty).
#### Using `extern` Functions to Call External Code
@@ -309,7 +373,15 @@ responsibility falls on the programmer to ensure safety.
<span class="filename">Filename: src/main.rs</span>
```rust,unsafe
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-08/src/main.rs}}
+extern "C" {
+ fn abs(input: i32) -> i32;
+}
+
+fn main() {
+ unsafe {
+ println!("Absolute value of -3 according to C: {}", abs(-3));
+ }
+}
```
<span class="caption">Listing 19-8: Declaring and calling an `extern` function
@@ -359,21 +431,26 @@ value.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-09/src/main.rs}}
+static HELLO_WORLD: &str = "Hello, world!";
+
+fn main() {
+ println!("name is: {}", HELLO_WORLD);
+}
```
<span class="caption">Listing 19-9: Defining and using an immutable static
variable</span>
+<!-- NEXT PARAGRAPH WRAPPED WEIRD INTENTIONALLY SEE #199 -->
+
Static variables are similar to constants, which we discussed in the
-[“Differences Between Variables and
-Constants”][differences-between-variables-and-constants]<!-- ignore -->
-section in Chapter 3. The names of static variables are in
-`SCREAMING_SNAKE_CASE` by convention, and we *must* annotate the variable’s
-type, which is `&'static str` in this example. Static variables can only store
-references with the `'static` lifetime, which means the Rust compiler can
-figure out the lifetime; we don’t need to annotate it explicitly. Accessing an
-immutable static variable is safe.
+[“Differences Between Variables and Constants”]
+[differences-between-variables-and-constants]<!-- ignore --> section in
+Chapter 3. The names of static variables are in `SCREAMING_SNAKE_CASE` by
+convention, and we *must* annotate the variable’s type, which is `&'static str`
+in this example. Static variables can only store references with the `'static`
+lifetime, which means the Rust compiler can figure out the lifetime; we don’t
+need to annotate it explicitly. Accessing an immutable static variable is safe.
Constants and immutable static variables might seem similar, but a subtle
difference is that values in a static variable have a fixed address in memory.
@@ -388,7 +465,21 @@ static variable named `COUNTER`.
<span class="filename">Filename: src/main.rs</span>
```rust,unsafe
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-10/src/main.rs}}
+static mut COUNTER: u32 = 0;
+
+fn add_to_count(inc: u32) {
+ unsafe {
+ COUNTER += inc;
+ }
+}
+
+fn main() {
+ add_to_count(3);
+
+ unsafe {
+ println!("COUNTER: {}", COUNTER);
+ }
+}
```
<span class="caption">Listing 19-10: Reading from or writing to a mutable
@@ -415,7 +506,13 @@ compiler can’t verify. We can declare that a trait is `unsafe` by adding the
`unsafe` too, as shown in Listing 19-11.
```rust,unsafe
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-11/src/main.rs}}
+unsafe trait Foo {
+ // methods go here
+}
+
+unsafe impl Foo for i32 {
+ // method implementations go here
+}
```
<span class="caption">Listing 19-11: Defining and implementing an unsafe
@@ -425,37 +522,28 @@ By using `unsafe impl`, we’re promising that we’ll uphold the invariants tha
the compiler can’t verify.
As an example, recall the `Sync` and `Send` marker traits we discussed in the
-[“Extensible Concurrency with the `Sync` and `Send`
-Traits”][extensible-concurrency-with-the-sync-and-send-traits]<!-- ignore -->
-section in Chapter 16: the compiler implements these traits automatically if
-our types are composed entirely of `Send` and `Sync` types. If we implement a
-type that contains a type that is not `Send` or `Sync`, such as raw pointers,
-and we want to mark that type as `Send` or `Sync`, we must use `unsafe`. Rust
-can’t verify that our type upholds the guarantees that it can be safely sent
-across threads or accessed from multiple threads; therefore, we need to do
-those checks manually and indicate as such with `unsafe`.
-
-### Accessing Fields of a Union
-
-A `union` is similar to a `struct`, but only one declared field is used in a
-particular instance at one time. Unions are primarily used to interface with
-unions in C code. Accessing union fields is unsafe because Rust can’t guarantee
-the type of the data currently being stored in the union instance. You can
-learn more about unions in [the reference][reference].
+[“Extensible Concurrency with the `Sync` and `Send` Traits”]
+[extensible-concurrency-with-the-sync-and-send-traits]<!-- ignore --> section
+in Chapter 16: the compiler implements these traits automatically if our types
+are composed entirely of `Send` and `Sync` types. If we implement a type that
+contains a type that is not `Send` or `Sync`, such as raw pointers, and we want
+to mark that type as `Send` or `Sync`, we must use `unsafe`. Rust can’t verify
+that our type upholds the guarantees that it can be safely sent across threads
+or accessed from multiple threads; therefore, we need to do those checks
+manually and indicate as such with `unsafe`.
### When to Use Unsafe Code
-Using `unsafe` to take one of the five actions (superpowers) just discussed
+Using `unsafe` to take one of the four actions (superpowers) just discussed
isn’t wrong or even frowned upon. But it is trickier to get `unsafe` code
correct because the compiler can’t help uphold memory safety. When you have a
reason to use `unsafe` code, you can do so, and having the explicit `unsafe`
-annotation makes it easier to track down the source of problems when they occur.
+annotation makes it easier to track down the source of problems if they occur.
[dangling-references]:
ch04-02-references-and-borrowing.html#dangling-references
[differences-between-variables-and-constants]:
ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
[extensible-concurrency-with-the-sync-and-send-traits]:
-ch16-04-extensible-concurrency-sync-and-send.html#extensible-concurrency-with-the-sync-and-send-traits
+ch16-04-extensible-concurrency-sync-and-sen.html#extensible-concurrency-with-the-sync-and-send-traits
[the-slice-type]: ch04-03-slices.html#the-slice-type
-[reference]: ../reference/items/unions.html
diff --git a/book-pl-en/src/ch19-02-advanced-lifetimes.md b/book-pl-en/src/ch19-02-advanced-lifetimes.md
new file mode 100644
index 0000000..df53653
--- /dev/null
+++ b/book-pl-en/src/ch19-02-advanced-lifetimes.md
@@ -0,0 +1,502 @@
+## Advanced Lifetimes
+
+In Chapter 10 in the [“Validating References with Lifetimes”]
+[validating-references-with-lifetimes]<!-- ignore --> section, you learned how
+to annotate references with lifetime parameters to tell Rust how lifetimes of
+different references relate. You saw how every reference has a lifetime, but
+most of the time, Rust will let you elide lifetimes. Now we’ll look at three
+advanced features of lifetimes that we haven’t covered yet:
+
+* Lifetime subtyping: ensures that one lifetime outlives another lifetime
+* Lifetime bounds: specifies a lifetime for a reference to a generic type
+* Inference of trait object lifetimes: allows the compiler to infer trait
+ object lifetimes and when they need to be specified
+* The anonymous lifetime: making elision more obvious
+
+### Ensuring One Lifetime Outlives Another with Lifetime Subtyping
+
+*Lifetime subtyping* specifies that one lifetime should outlive another
+lifetime. To explore lifetime subtyping, imagine we want to write a parser.
+We’ll use a structure called `Context` that holds a reference to the string
+we’re parsing. We’ll write a parser that will parse this string and return
+success or failure. The parser will need to borrow the `Context` to do the
+parsing. Listing 19-12 implements this parser code, except the code doesn’t
+have the required lifetime annotations, so it won’t compile.
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust,ignore,does_not_compile
+struct Context(&str);
+
+struct Parser {
+ context: &Context,
+}
+
+impl Parser {
+ fn parse(&self) -> Result<(), &str> {
+ Err(&self.context.0[1..])
+ }
+}
+```
+
+<span class="caption">Listing 19-12: Defining a parser without lifetime
+annotations</span>
+
+Compiling the code results in errors because Rust expects lifetime parameters
+on the string slice in `Context` and the reference to a `Context` in `Parser`.
+
+For simplicity’s sake, the `parse` function returns `Result<(), &str>`. That
+is, the function will do nothing on success and, on failure, will return the
+part of the string slice that didn’t parse correctly. A real implementation
+would provide more error information and would return a structured data type
+when parsing succeeds. We won’t be discussing those details because they aren’t
+relevant to the lifetimes part of this example.
+
+To keep this code simple, we won’t write any parsing logic. However, it’s very
+likely that somewhere in the parsing logic we would handle invalid input by
+returning an error that references the part of the input that is invalid; this
+reference is what makes the code example interesting in regard to lifetimes.
+Let’s pretend that the logic of our parser is that the input is invalid after
+the first byte. Note that this code might panic if the first byte is not on a
+valid character boundary; again, we’re simplifying the example to focus on the
+lifetimes involved.
+
+To get this code to compile, we need to fill in the lifetime parameters for the
+string slice in `Context` and the reference to the `Context` in `Parser`. The
+most straightforward way to do this is to use the same lifetime name
+everywhere, as shown in Listing 19-13. Recall from the [“Lifetime Annotations
+in Struct Definitions”][lifetime-annotations-in-struct-definitions]<!-- ignore
+--> section in Chapter 10 that each of `struct Context<'a>`, `struct
+Parser<'a>`, and `impl<'a>` is declaring a new lifetime parameter. While their
+names happen to all be the same, the three lifetime parameters declared in this
+example aren’t related.
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust
+struct Context<'a>(&'a str);
+
+struct Parser<'a> {
+ context: &'a Context<'a>,
+}
+
+impl<'a> Parser<'a> {
+ fn parse(&self) -> Result<(), &str> {
+ Err(&self.context.0[1..])
+ }
+}
+```
+
+<span class="caption">Listing 19-13: Annotating all references in `Context` and
+`Parser` with lifetime parameters</span>
+
+This code compiles just fine. It tells Rust that a `Parser` holds a reference
+to a `Context` with lifetime `'a` and that `Context` holds a string slice that
+also lives as long as the reference to the `Context` in `Parser`. Rust’s
+compiler error message stated that lifetime parameters were required for these
+references, and we’ve now added lifetime parameters.
+
+Next, in Listing 19-14, we’ll add a function that takes an instance of
+`Context`, uses a `Parser` to parse that context, and returns what `parse`
+returns. This code doesn’t quite work.
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust,ignore,does_not_compile
+fn parse_context(context: Context) -> Result<(), &str> {
+ Parser { context: &context }.parse()
+}
+```
+
+<span class="caption">Listing 19-14: An attempt to add a `parse_context`
+function that takes a `Context` and uses a `Parser`</span>
+
+We get two verbose errors when we try to compile the code with the addition of
+the `parse_context` function:
+
+```text
+error[E0597]: borrowed value does not live long enough
+ --> src/lib.rs:14:5
+ |
+14 | Parser { context: &context }.parse()
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ does not live long enough
+15 | }
+ | - temporary value only lives until here
+ |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 13:1...
+ --> src/lib.rs:13:1
+ |
+13 | / fn parse_context(context: Context) -> Result<(), &str> {
+14 | | Parser { context: &context }.parse()
+15 | | }
+ | |_^
+
+error[E0597]: `context` does not live long enough
+ --> src/lib.rs:14:24
+ |
+14 | Parser { context: &context }.parse()
+ | ^^^^^^^ does not live long enough
+15 | }
+ | - borrowed value only lives until here
+ |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 13:1...
+ --> src/lib.rs:13:1
+ |
+13 | / fn parse_context(context: Context) -> Result<(), &str> {
+14 | | Parser { context: &context }.parse()
+15 | | }
+ | |_^
+```
+
+These errors state that the `Parser` instance that is created and the `context`
+parameter live only until the end of the `parse_context` function. But they
+both need to live for the entire lifetime of the function.
+
+In other words, `Parser` and `context` need to *outlive* the entire function
+and be valid before the function starts as well as after it ends for all the
+references in this code to always be valid. The `Parser` we’re creating and the
+`context` parameter go out of scope at the end of the function, because
+`parse_context` takes ownership of `context`.
+
+To figure out why these errors occur, let’s look at the definitions in Listing
+19-13 again, specifically the references in the signature of the `parse` method:
+
+```rust,ignore
+ fn parse(&self) -> Result<(), &str> {
+```
+
+Remember the elision rules? If we annotate the lifetimes of the references
+rather than eliding, the signature would be as follows:
+
+```rust,ignore
+ fn parse<'a>(&'a self) -> Result<(), &'a str> {
+```
+
+That is, the error part of the return value of `parse` has a lifetime that is
+tied to the lifetime of the `Parser` instance (that of `&self` in the `parse`
+method signature). That makes sense: the returned string slice references the
+string slice in the `Context` instance held by the `Parser`, and the definition
+of the `Parser` struct specifies that the lifetime of the reference to
+`Context` and the lifetime of the string slice that `Context` holds should be
+the same.
+
+The problem is that the `parse_context` function returns the value returned
+from `parse`, so the lifetime of the return value of `parse_context` is tied to
+the lifetime of the `Parser` as well. But the `Parser` instance created in the
+`parse_context` function won’t live past the end of the function (it’s
+temporary), and `context` will go out of scope at the end of the function
+(`parse_context` takes ownership of it).
+
+Rust thinks we’re trying to return a reference to a value that goes out of
+scope at the end of the function, because we annotated all the lifetimes with
+the same lifetime parameter. The annotations told Rust the lifetime of the
+string slice that `Context` holds is the same as that of the lifetime of the
+reference to `Context` that `Parser` holds.
+
+The `parse_context` function can’t see that within the `parse` function, the
+string slice returned will outlive `Context` and `Parser` and that the
+reference `parse_context` returns refers to the string slice, not to `Context`
+or `Parser`.
+
+By knowing what the implementation of `parse` does, we know that the only
+reason the return value of `parse` is tied to the `Parser` instance is that
+it’s referencing the `Parser` instance’s `Context`, which is referencing the
+string slice. So, it’s really the lifetime of the string slice that
+`parse_context` needs to care about. We need a way to tell Rust that the string
+slice in `Context` and the reference to the `Context` in `Parser` have
+different lifetimes and that the return value of `parse_context` is tied to the
+lifetime of the string slice in `Context`.
+
+First, we’ll try giving `Parser` and `Context` different lifetime parameters,
+as shown in Listing 19-15. We’ll use `'s` and `'c` as lifetime parameter names
+to clarify which lifetime goes with the string slice in `Context` and which
+goes with the reference to `Context` in `Parser`. Note that this solution won’t
+completely fix the problem, but it’s a start. We’ll look at why this fix isn’t
+sufficient when we try to compile.
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust,ignore,does_not_compile
+struct Context<'s>(&'s str);
+
+struct Parser<'c, 's> {
+ context: &'c Context<'s>,
+}
+
+impl<'c, 's> Parser<'c, 's> {
+ fn parse(&self) -> Result<(), &'s str> {
+ Err(&self.context.0[1..])
+ }
+}
+
+fn parse_context(context: Context) -> Result<(), &str> {
+ Parser { context: &context }.parse()
+}
+```
+
+<span class="caption">Listing 19-15: Specifying different lifetime parameters
+for the references to the string slice and to `Context`</span>
+
+We’ve annotated the lifetimes of the references in all the same places that we
+annotated them in Listing 19-13. But this time we used different parameters
+depending on whether the reference goes with the string slice or with
+`Context`. We’ve also added an annotation to the string slice part of the
+return value of `parse` to indicate that it goes with the lifetime of the
+string slice in `Context`.
+
+When we try to compile now, we get the following error:
+
+```text
+error[E0491]: in type `&'c Context<'s>`, reference has a longer lifetime than the data it references
+ --> src/lib.rs:4:5
+ |
+4 | context: &'c Context<'s>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the pointer is valid for the lifetime 'c as defined on the struct at 3:1
+ --> src/lib.rs:3:1
+ |
+3 | / struct Parser<'c, 's> {
+4 | | context: &'c Context<'s>,
+5 | | }
+ | |_^
+note: but the referenced data is only valid for the lifetime 's as defined on the struct at 3:1
+ --> src/lib.rs:3:1
+ |
+3 | / struct Parser<'c, 's> {
+4 | | context: &'c Context<'s>,
+5 | | }
+ | |_^
+```
+
+Rust doesn’t know of any relationship between `'c` and `'s`. To be valid, the
+referenced data in `Context` with lifetime `'s` needs to be constrained to
+guarantee that it lives longer than the reference with lifetime `'c`. If `'s`
+is not longer than `'c`, the reference to `Context` might not be valid.
+
+Now we get to the point of this section: the Rust feature *lifetime
+subtyping* specifies that one lifetime parameter lives at least as long as
+another one. In the angle brackets where we declare lifetime parameters, we can
+declare a lifetime `'a` as usual and declare a lifetime `'b` that lives at
+least as long as `'a` by declaring `'b` using the syntax `'b: 'a`.
+
+In our definition of `Parser`, to say that `'s` (the lifetime of the string
+slice) is guaranteed to live at least as long as `'c` (the lifetime of the
+reference to `Context`), we change the lifetime declarations to look like this:
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust
+# struct Context<'a>(&'a str);
+#
+struct Parser<'c, 's: 'c> {
+ context: &'c Context<'s>,
+}
+```
+
+Now the reference to `Context` in the `Parser` and the reference to the string
+slice in the `Context` have different lifetimes; we’ve ensured that the
+lifetime of the string slice is longer than the reference to the `Context`.
+
+That was a very long-winded example, but as we mentioned at the start of this
+chapter, Rust’s advanced features are very specific. You won’t often need the
+syntax we described in this example, but in such situations, you’ll know how to
+refer to something and give it the necessary lifetime.
+
+### Lifetime Bounds on References to Generic Types
+
+In the [“Trait Bounds”][trait-bounds]<!-- ignore --> section in Chapter 10, we
+discussed using trait bounds on generic types. We can also add lifetime
+parameters as constraints on generic types; these are called *lifetime bounds*.
+Lifetime bounds help Rust verify that references in generic types won’t outlive
+the data they’re referencing.
+
+As an example, consider a type that is a wrapper over references. Recall the
+`RefCell<T>` type from the [“`RefCell<T>` and the Interior Mutability Pattern”]
+[refcellt-and-the-interior-mutability-pattern]<!-- ignore --> section in
+Chapter 15: its `borrow` and `borrow_mut` methods return the types `Ref` and
+`RefMut`, respectively. These types are wrappers over references that keep
+track of the borrowing rules at runtime. The definition of the `Ref` struct is
+shown in Listing 19-16, without lifetime bounds for now.
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust,ignore,does_not_compile
+struct Ref<'a, T>(&'a T);
+```
+
+<span class="caption">Listing 19-16: Defining a struct to wrap a reference to a
+generic type, without lifetime bounds</span>
+
+Without explicitly constraining the lifetime `'a` in relation to the generic
+parameter `T`, Rust will error because it doesn’t know how long the generic
+type `T` will live:
+
+```text
+error[E0309]: the parameter type `T` may not live long enough
+ --> src/lib.rs:1:19
+ |
+1 | struct Ref<'a, T>(&'a T);
+ | ^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `T: 'a`...
+note: ...so that the reference type `&'a T` does not outlive the data it points at
+ --> src/lib.rs:1:19
+ |
+1 | struct Ref<'a, T>(&'a T);
+ | ^^^^^^
+```
+
+Because `T` can be any type, `T` could be a reference or a type that holds one
+or more references, each of which could have their own lifetimes. Rust can’t be
+sure `T` will live as long as `'a`.
+
+Fortunately, the error provides helpful advice on how to specify the lifetime
+bound in this case:
+
+```text
+consider adding an explicit lifetime bound `T: 'a` so that the reference type
+`&'a T` does not outlive the data it points at
+```
+
+Listing 19-17 shows how to apply this advice by specifying the lifetime bound
+when we declare the generic type `T`.
+
+```rust
+struct Ref<'a, T: 'a>(&'a T);
+```
+
+<span class="caption">Listing 19-17: Adding lifetime bounds on `T` to specify
+that any references in `T` live at least as long as `'a`</span>
+
+This code now compiles because the `T: 'a` syntax specifies that `T` can be any
+type, but if it contains any references, the references must live at least as
+long as `'a`.
+
+We could solve this problem in a different way, as shown in the definition of a
+`StaticRef` struct in Listing 19-18, by adding the `'static` lifetime bound on
+`T`. This means if `T` contains any references, they must have the `'static`
+lifetime.
+
+```rust
+struct StaticRef<T: 'static>(&'static T);
+```
+
+<span class="caption">Listing 19-18: Adding a `'static` lifetime bound to `T`
+to constrain `T` to types that have only `'static` references or no
+references</span>
+
+Because `'static` means the reference must live as long as the entire program,
+a type that contains no references meets the criteria of all references living
+as long as the entire program (because there are no references). For the borrow
+checker concerned about references living long enough, there is no real
+distinction between a type that has no references and a type that has
+references that live forever: both are the same for determining whether or not
+a reference has a shorter lifetime than what it refers to.
+
+### Inference of Trait Object Lifetimes
+
+In Chapter 17 in the [“Using Trait Objects That Allow for Values of Different
+Types”][using-trait-objects-that-allow-for-values-of-different-types]<!--
+ignore --> section, we discussed trait objects, consisting of a trait behind a
+reference, that allow us to use dynamic dispatch. We haven’t yet discussed what
+happens if the type implementing the trait in the trait object has a lifetime
+of its own. Consider Listing 19-19 where we have a trait `Red` and a struct
+`Ball`. The `Ball` struct holds a reference (and thus has a lifetime parameter)
+and also implements trait `Red`. We want to use an instance of `Ball` as the
+trait object `Box<dyn Red>`.
+
+<span class="filename">Filename: src/main.rs</span>
+
+```rust
+trait Red { }
+
+struct Ball<'a> {
+ diameter: &'a i32,
+}
+
+impl<'a> Red for Ball<'a> { }
+
+fn main() {
+ let num = 5;
+
+ let obj = Box::new(Ball { diameter: &num }) as Box<dyn Red>;
+}
+```
+
+<span class="caption">Listing 19-19: Using a type that has a lifetime parameter
+with a trait object</span>
+
+This code compiles without any errors, even though we haven’t explicitly
+annotated the lifetimes involved in `obj`. This code works because there are
+rules for working with lifetimes and trait objects:
+
+* The default lifetime of a trait object is `'static`.
+* With `&'a Trait` or `&'a mut Trait`, the default lifetime of the trait object
+ is `'a`.
+* With a single `T: 'a` clause, the default lifetime of the trait object is
+ `'a`.
+* With multiple clauses like `T: 'a`, there is no default lifetime; we must be
+ explicit.
+
+When we must be explicit, we can add a lifetime bound on a trait object like
+`Box<dyn Red>` using the syntax `Box<dyn Red + 'static>` or `Box<dyn Red +
+'a>`, depending on whether the reference lives for the entire program or not.
+As with the other bounds, the syntax adding a lifetime bound means that any
+implementor of the `Red` trait that has references inside the type must have
+the same lifetime specified in the trait object bounds as those references.
+
+### The anonymous lifetime
+
+Let’s say that we have a struct that’s a wrapper around a string slice, like
+this:
+
+```rust
+struct StrWrap<'a>(&'a str);
+```
+
+We can write a function that returns one of these like this:
+
+```rust
+# struct StrWrap<'a>(&'a str);
+fn foo<'a>(string: &'a str) -> StrWrap<'a> {
+ StrWrap(string)
+}
+```
+
+But that’s a lot of `'a`s! To cut down on some of this noise, we can use the
+anonymous lifetime, `'_`, like this:
+
+```rust
+# struct StrWrap<'a>(&'a str);
+fn foo(string: &str) -> StrWrap<'_> {
+ StrWrap(string)
+}
+```
+
+The `'_` says “use the elidied lifetime here.” This means that we can still see
+that `StrWrap` contains a reference, but we don’t need all of the lifetime
+annotations to make sense of it.
+
+It works in `impl` headers too; for example:
+
+```rust,ignore
+// verbose
+impl<'a> fmt::Debug for StrWrap<'a> {
+
+// elided
+impl fmt::Debug for StrWrap<'_> {
+
+```
+
+Next, let’s look at some other advanced features that manage traits.
+
+[lifetime-annotations-in-struct-definitions]:
+ch10-03-lifetime-syntax.html#lifetime-annotations-in-struct-definitions
+[refcellt-and-the-interior-mutability-pattern]:
+ch15-05-interior-mutability.html#refcellt-and-the-interior-mutability-pattern
+[trait-bounds]: ch10-02-traits.html#trait-bounds
+[using-trait-objects-that-allow-for-values-of-different-types]:
+ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
+[validating-references-with-lifetimes]:
+ch10-03-lifetime-syntax.html#validating-references-with-lifetimes
diff --git a/book-original/src/ch19-03-advanced-traits.md b/book-pl-en/src/ch19-03-advanced-traits.md
index 9c33428..7bd4188 100644
--- a/book-original/src/ch19-03-advanced-traits.md
+++ b/book-pl-en/src/ch19-03-advanced-traits.md
@@ -1,9 +1,9 @@
## Advanced Traits
-We first covered traits in the [“Traits: Defining Shared
-Behavior”][traits-defining-shared-behavior]<!-- ignore --> section of Chapter
-10, but as with lifetimes, we didn’t discuss the more advanced details. Now
-that you know more about Rust, we can get into the nitty-gritty.
+We first covered traits in the [“Traits: Defining Shared Behavior”]
+[traits-defining-shared-behavior]<!-- ignore --> section of Chapter 10, but as
+with lifetimes, we didn’t discuss the more advanced details. Now that you know
+more about Rust, we can get into the nitty-gritty.
### Specifying Placeholder Types in Trait Definitions with Associated Types
@@ -22,16 +22,20 @@ the other features discussed in this chapter.
One example of a trait with an associated type is the `Iterator` trait that the
standard library provides. The associated type is named `Item` and stands in
for the type of the values the type implementing the `Iterator` trait is
-iterating over. In [“The `Iterator` Trait and the `next`
-Method”][the-iterator-trait-and-the-next-method]<!-- ignore --> section of
-Chapter 13, we mentioned that the definition of the `Iterator` trait is as
-shown in Listing 19-12.
+iterating over. In [“The `Iterator` Trait and the `next` Method”]
+[the-iterator-trait-and-the-next-method]<!-- ignore --> section of Chapter 13,
+we mentioned that the definition of the `Iterator` trait is as shown in Listing
+19-20.
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-12/src/lib.rs}}
+pub trait Iterator {
+ type Item;
+
+ fn next(&mut self) -> Option<Self::Item>;
+}
```
-<span class="caption">Listing 19-12: The definition of the `Iterator` trait
+<span class="caption">Listing 19-20: The definition of the `Iterator` trait
that has an associated type `Item`</span>
The type `Item` is a placeholder type, and the `next` method’s definition shows
@@ -50,20 +54,26 @@ Listing 13-21, we specified that the `Item` type was `u32`:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-13-21-reproduced/src/lib.rs:ch19}}
+impl Iterator for Counter {
+ type Item = u32;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ // --snip--
```
This syntax seems comparable to that of generics. So why not just define the
-`Iterator` trait with generics, as shown in Listing 19-13?
+`Iterator` trait with generics, as shown in Listing 19-21?
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-13/src/lib.rs}}
+pub trait Iterator<T> {
+ fn next(&mut self) -> Option<T>;
+}
```
-<span class="caption">Listing 19-13: A hypothetical definition of the
+<span class="caption">Listing 19-21: A hypothetical definition of the
`Iterator` trait using generics</span>
-The difference is that when using generics, as in Listing 19-13, we must
+The difference is that when using generics, as in Listing 19-21, we must
annotate the types in each implementation; because we can also implement
`Iterator<String> for Counter` or any other type, we could have multiple
implementations of `Iterator` for `Counter`. In other words, when a trait has a
@@ -73,7 +83,7 @@ the concrete types of the generic type parameters each time. When we use the
indicate which implementation of `Iterator` we want to use.
With associated types, we don’t need to annotate types because we can’t
-implement a trait on a type multiple times. In Listing 19-12 with the
+implement a trait on a type multiple times. In Listing 19-20 with the
definition that uses associated types, we can only choose what the type of
`Item` will be once, because there can only be one `impl Iterator for Counter`.
We don’t have to specify that we want an iterator of `u32` values everywhere
@@ -94,17 +104,39 @@ overloading. *Operator overloading* is customizing the behavior of an operator
Rust doesn’t allow you to create your own operators or overload arbitrary
operators. But you can overload the operations and corresponding traits listed
in `std::ops` by implementing the traits associated with the operator. For
-example, in Listing 19-14 we overload the `+` operator to add two `Point`
+example, in Listing 19-22 we overload the `+` operator to add two `Point`
instances together. We do this by implementing the `Add` trait on a `Point`
struct:
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-14/src/main.rs}}
+use std::ops::Add;
+
+#[derive(Debug, PartialEq)]
+struct Point {
+ x: i32,
+ y: i32,
+}
+
+impl Add for Point {
+ type Output = Point;
+
+ fn add(self, other: Point) -> Point {
+ Point {
+ x: self.x + other.x,
+ y: self.y + other.y,
+ }
+ }
+}
+
+fn main() {
+ assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
+ Point { x: 3, y: 3 });
+}
```
-<span class="caption">Listing 19-14: Implementing the `Add` trait to overload
+<span class="caption">Listing 19-22: Implementing the `Add` trait to overload
the `+` operator for `Point` instances</span>
The `add` method adds the `x` values of two `Point` instances and the `y`
@@ -139,15 +171,26 @@ default.
We have two structs, `Millimeters` and `Meters`, holding values in different
units. We want to add values in millimeters to values in meters and have the
implementation of `Add` do the conversion correctly. We can implement `Add` for
-`Millimeters` with `Meters` as the `RHS`, as shown in Listing 19-15.
+`Millimeters` with `Meters` as the `RHS`, as shown in Listing 19-23.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-15/src/lib.rs}}
+use std::ops::Add;
+
+struct Millimeters(u32);
+struct Meters(u32);
+
+impl Add<Meters> for Millimeters {
+ type Output = Millimeters;
+
+ fn add(self, other: Meters) -> Millimeters {
+ Millimeters(self.0 + (other.0 * 1000))
+ }
+}
```
-<span class="caption">Listing 19-15: Implementing the `Add` trait on
+<span class="caption">Listing 19-23: Implementing the `Add` trait on
`Millimeters` to add `Millimeters` to `Meters`</span>
To add `Millimeters` and `Meters`, we specify `impl Add<Meters>` to set the
@@ -178,7 +221,7 @@ on one type. It’s also possible to implement a method directly on the type wit
the same name as methods from traits.
When calling methods with the same name, you’ll need to tell Rust which one you
-want to use. Consider the code in Listing 19-16 where we’ve defined two traits,
+want to use. Consider the code in Listing 19-24 where we’ve defined two traits,
`Pilot` and `Wizard`, that both have a method called `fly`. We then implement
both traits on a type `Human` that already has a method named `fly` implemented
on it. Each `fly` method does something different.
@@ -186,23 +229,80 @@ on it. Each `fly` method does something different.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-16/src/main.rs:here}}
+trait Pilot {
+ fn fly(&self);
+}
+
+trait Wizard {
+ fn fly(&self);
+}
+
+struct Human;
+
+impl Pilot for Human {
+ fn fly(&self) {
+ println!("This is your captain speaking.");
+ }
+}
+
+impl Wizard for Human {
+ fn fly(&self) {
+ println!("Up!");
+ }
+}
+
+impl Human {
+ fn fly(&self) {
+ println!("*waving arms furiously*");
+ }
+}
```
-<span class="caption">Listing 19-16: Two traits are defined to have a `fly`
+<span class="caption">Listing 19-24: Two traits are defined to have a `fly`
method and are implemented on the `Human` type, and a `fly` method is
implemented on `Human` directly</span>
When we call `fly` on an instance of `Human`, the compiler defaults to calling
-the method that is directly implemented on the type, as shown in Listing 19-17.
+the method that is directly implemented on the type, as shown in Listing 19-25.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-17/src/main.rs:here}}
+# trait Pilot {
+# fn fly(&self);
+# }
+#
+# trait Wizard {
+# fn fly(&self);
+# }
+#
+# struct Human;
+#
+# impl Pilot for Human {
+# fn fly(&self) {
+# println!("This is your captain speaking.");
+# }
+# }
+#
+# impl Wizard for Human {
+# fn fly(&self) {
+# println!("Up!");
+# }
+# }
+#
+# impl Human {
+# fn fly(&self) {
+# println!("*waving arms furiously*");
+# }
+# }
+#
+fn main() {
+ let person = Human;
+ person.fly();
+}
```
-<span class="caption">Listing 19-17: Calling `fly` on an instance of
+<span class="caption">Listing 19-25: Calling `fly` on an instance of
`Human`</span>
Running this code will print `*waving arms furiously*`, showing that Rust
@@ -210,27 +310,62 @@ called the `fly` method implemented on `Human` directly.
To call the `fly` methods from either the `Pilot` trait or the `Wizard` trait,
we need to use more explicit syntax to specify which `fly` method we mean.
-Listing 19-18 demonstrates this syntax.
+Listing 19-26 demonstrates this syntax.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-18/src/main.rs:here}}
+# trait Pilot {
+# fn fly(&self);
+# }
+#
+# trait Wizard {
+# fn fly(&self);
+# }
+#
+# struct Human;
+#
+# impl Pilot for Human {
+# fn fly(&self) {
+# println!("This is your captain speaking.");
+# }
+# }
+#
+# impl Wizard for Human {
+# fn fly(&self) {
+# println!("Up!");
+# }
+# }
+#
+# impl Human {
+# fn fly(&self) {
+# println!("*waving arms furiously*");
+# }
+# }
+#
+fn main() {
+ let person = Human;
+ Pilot::fly(&person);
+ Wizard::fly(&person);
+ person.fly();
+}
```
-<span class="caption">Listing 19-18: Specifying which trait’s `fly` method we
+<span class="caption">Listing 19-26: Specifying which trait’s `fly` method we
want to call</span>
Specifying the trait name before the method name clarifies to Rust which
implementation of `fly` we want to call. We could also write
`Human::fly(&person)`, which is equivalent to the `person.fly()` that we used
-in Listing 19-18, but this is a bit longer to write if we don’t need to
+in Listing 19-26, but this is a bit longer to write if we don’t need to
disambiguate.
Running this code prints the following:
```text
-{{#include ../listings/ch19-advanced-features/listing-19-18/output.txt}}
+This is your captain speaking.
+Up!
+*waving arms furiously*
```
Because the `fly` method takes a `self` parameter, if we had two *types* that
@@ -240,17 +375,37 @@ trait to use based on the type of `self`.
However, associated functions that are part of traits don’t have a `self`
parameter. When two types in the same scope implement that trait, Rust can’t
figure out which type you mean unless you use *fully qualified syntax*. For
-example, the `Animal` trait in Listing 19-19 has the associated function
+example, the `Animal` trait in Listing 19-27 has the associated function
`baby_name`, the implementation of `Animal` for the struct `Dog`, and the
associated function `baby_name` defined on `Dog` directly.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-19/src/main.rs}}
+trait Animal {
+ fn baby_name() -> String;
+}
+
+struct Dog;
+
+impl Dog {
+ fn baby_name() -> String {
+ String::from("Spot")
+ }
+}
+
+impl Animal for Dog {
+ fn baby_name() -> String {
+ String::from("puppy")
+ }
+}
+
+fn main() {
+ println!("A baby dog is called a {}", Dog::baby_name());
+}
```
-<span class="caption">Listing 19-19: A trait with an associated function and a
+<span class="caption">Listing 19-27: A trait with an associated function and a
type with an associated function of the same name that also implements the
trait</span>
@@ -265,22 +420,24 @@ In `main`, we call the `Dog::baby_name` function, which calls the associated
function defined on `Dog` directly. This code prints the following:
```text
-{{#include ../listings/ch19-advanced-features/listing-19-19/output.txt}}
+A baby dog is called a Spot
```
This output isn’t what we wanted. We want to call the `baby_name` function that
is part of the `Animal` trait that we implemented on `Dog` so the code prints
`A baby dog is called a puppy`. The technique of specifying the trait name that
-we used in Listing 19-18 doesn’t help here; if we change `main` to the code in
-Listing 19-20, we’ll get a compilation error.
+we used in Listing 19-26 doesn’t help here; if we change `main` to the code in
+Listing 19-28, we’ll get a compilation error.
<span class="filename">Filename: src/main.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-20/src/main.rs:here}}
+fn main() {
+ println!("A baby dog is called a {}", Animal::baby_name());
+}
```
-<span class="caption">Listing 19-20: Attempting to call the `baby_name`
+<span class="caption">Listing 19-28: Attempting to call the `baby_name`
function from the `Animal` trait, but Rust doesn’t know which implementation to
use</span>
@@ -289,20 +446,46 @@ thus doesn’t have a `self` parameter, Rust can’t figure out which
implementation of `Animal::baby_name` we want. We’ll get this compiler error:
```text
-{{#include ../listings/ch19-advanced-features/listing-19-20/output.txt}}
+error[E0283]: type annotations required: cannot resolve `_: Animal`
+ --> src/main.rs:20:43
+ |
+20 | println!("A baby dog is called a {}", Animal::baby_name());
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: required by `Animal::baby_name`
```
To disambiguate and tell Rust that we want to use the implementation of
-`Animal` for `Dog`, we need to use fully qualified syntax. Listing 19-21
+`Animal` for `Dog`, we need to use fully qualified syntax. Listing 19-29
demonstrates how to use fully qualified syntax.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-21/src/main.rs:here}}
+# trait Animal {
+# fn baby_name() -> String;
+# }
+#
+# struct Dog;
+#
+# impl Dog {
+# fn baby_name() -> String {
+# String::from("Spot")
+# }
+# }
+#
+# impl Animal for Dog {
+# fn baby_name() -> String {
+# String::from("puppy")
+# }
+# }
+#
+fn main() {
+ println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
+}
```
-<span class="caption">Listing 19-21: Using fully qualified syntax to specify
+<span class="caption">Listing 19-29: Using fully qualified syntax to specify
that we want to call the `baby_name` function from the `Animal` trait as
implemented on `Dog`</span>
@@ -312,7 +495,7 @@ implemented on `Dog` by saying that we want to treat the `Dog` type as an
`Animal` for this function call. This code will now print what we want:
```text
-{{#include ../listings/ch19-advanced-features/listing-19-21/output.txt}}
+A baby dog is called a puppy
```
In general, fully qualified syntax is defined as follows:
@@ -332,7 +515,7 @@ implementation you want to call.
### Using Supertraits to Require One Trait’s Functionality Within Another Trait
Sometimes, you might need one trait to use another trait’s functionality. In
-this case, you need to rely on the dependent trait also being implemented.
+this case, you need to rely on the dependent traits also being implemented.
The trait you rely on is a *supertrait* of the trait you’re implementing.
For example, let’s say we want to make an `OutlinePrint` trait with an
@@ -354,15 +537,27 @@ functionality. Therefore, we need to specify that the `OutlinePrint` trait will
work only for types that also implement `Display` and provide the functionality
that `OutlinePrint` needs. We can do that in the trait definition by specifying
`OutlinePrint: Display`. This technique is similar to adding a trait bound to
-the trait. Listing 19-22 shows an implementation of the `OutlinePrint` trait.
+the trait. Listing 19-30 shows an implementation of the `OutlinePrint` trait.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-22/src/main.rs:here}}
+use std::fmt;
+
+trait OutlinePrint: fmt::Display {
+ fn outline_print(&self) {
+ let output = self.to_string();
+ let len = output.len();
+ println!("{}", "*".repeat(len + 4));
+ println!("*{}*", " ".repeat(len + 2));
+ println!("* {} *", output);
+ println!("*{}*", " ".repeat(len + 2));
+ println!("{}", "*".repeat(len + 4));
+ }
+}
```
-<span class="caption">Listing 19-22: Implementing the `OutlinePrint` trait that
+<span class="caption">Listing 19-30: Implementing the `OutlinePrint` trait that
requires the functionality from `Display`</span>
Because we’ve specified that `OutlinePrint` requires the `Display` trait, we
@@ -377,14 +572,27 @@ doesn’t implement `Display`, such as the `Point` struct:
<span class="filename">Filename: src/main.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/src/main.rs:here}}
+```rust
+# trait OutlinePrint {}
+struct Point {
+ x: i32,
+ y: i32,
+}
+
+impl OutlinePrint for Point {}
```
We get an error saying that `Display` is required but not implemented:
```text
-{{#include ../listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt}}
+error[E0277]: the trait bound `Point: std::fmt::Display` is not satisfied
+ --> src/main.rs:20:6
+ |
+20 | impl OutlinePrint for Point {}
+ | ^^^^^^^^^^^^ `Point` cannot be formatted with the default formatter;
+try using `:?` instead if you are using a format string
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `Point`
```
To fix this, we implement `Display` on `Point` and satisfy the constraint that
@@ -393,7 +601,18 @@ To fix this, we implement `Display` on `Point` and satisfy the constraint that
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-03-impl-display-for-point/src/main.rs:here}}
+# struct Point {
+# x: i32,
+# y: i32,
+# }
+#
+use std::fmt;
+
+impl fmt::Display for Point {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "({}, {})", self.x, self.y)
+ }
+}
```
Then implementing the `OutlinePrint` trait on `Point` will compile
@@ -402,33 +621,46 @@ it within an outline of asterisks.
### Using the Newtype Pattern to Implement External Traits on External Types
-In Chapter 10 in the [“Implementing a Trait on a
-Type”][implementing-a-trait-on-a-type]<!-- ignore --> section, we mentioned
-the orphan rule that states we’re allowed to implement a trait on a type as
-long as either the trait or the type are local to our crate. It’s possible to
-get around this restriction using the *newtype pattern*, which involves
-creating a new type in a tuple struct. (We covered tuple structs in the
-[“Using Tuple Structs without Named Fields to Create Different
-Types”][tuple-structs]<!-- ignore --> section of Chapter 5.) The tuple struct
-will have one field and be a thin wrapper around the type we want to implement
-a trait for. Then the wrapper type is local to our crate, and we can implement
-the trait on the wrapper. *Newtype* is a term that originates from the Haskell
-programming language. There is no runtime performance penalty for using this
-pattern, and the wrapper type is elided at compile time.
+In Chapter 10 in the [“Implementing a Trait on a Type”]
+[implementing-a-trait-on-a-type]<!-- ignore --> section, we mentioned the
+orphan rule that states we’re allowed to implement a trait on a type as long as
+either the trait or the type are local to our crate. It’s possible to get
+around this restriction using the *newtype pattern*, which involves creating a
+new type in a tuple struct. (We covered tuple structs in the [“Using Tuple
+Structs without Named Fields to Create Different Types”][tuple-structs]<!--
+ignore --> section of Chapter 5.) The tuple struct will have one field and be a
+thin wrapper around the type we want to implement a trait for. Then the wrapper
+type is local to our crate, and we can implement the trait on the wrapper.
+*Newtype* is a term that originates from the Haskell programming language.
+There is no runtime performance penalty for using this pattern, and the wrapper
+type is elided at compile time.
As an example, let’s say we want to implement `Display` on `Vec<T>`, which the
orphan rule prevents us from doing directly because the `Display` trait and the
`Vec<T>` type are defined outside our crate. We can make a `Wrapper` struct
that holds an instance of `Vec<T>`; then we can implement `Display` on
-`Wrapper` and use the `Vec<T>` value, as shown in Listing 19-23.
+`Wrapper` and use the `Vec<T>` value, as shown in Listing 19-31.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-23/src/main.rs}}
+use std::fmt;
+
+struct Wrapper(Vec<String>);
+
+impl fmt::Display for Wrapper {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "[{}]", self.0.join(", "))
+ }
+}
+
+fn main() {
+ let w = Wrapper(vec![String::from("hello"), String::from("world")]);
+ println!("w = {}", w);
+}
```
-<span class="caption">Listing 19-23: Creating a `Wrapper` type around
+<span class="caption">Listing 19-31: Creating a `Wrapper` type around
`Vec<String>` to implement `Display`</span>
The implementation of `Display` uses `self.0` to access the inner `Vec<T>`,
diff --git a/book-original/src/ch19-04-advanced-types.md b/book-pl-en/src/ch19-04-advanced-types.md
index f20d6b4..bb132a1 100644
--- a/book-original/src/ch19-04-advanced-types.md
+++ b/book-pl-en/src/ch19-04-advanced-types.md
@@ -15,7 +15,7 @@ discuss the `!` type and dynamically sized types.
The newtype pattern is useful for tasks beyond those we’ve discussed so far,
including statically enforcing that values are never confused and indicating
the units of a value. You saw an example of using newtypes to indicate units in
-Listing 19-15: recall that the `Millimeters` and `Meters` structs wrapped `u32`
+Listing 19-23: recall that the `Millimeters` and `Meters` structs wrapped `u32`
values in a newtype. If we wrote a function with a parameter of type
`Millimeters`, we couldn’t compile a program that accidentally tried to call
that function with a value of type `Meters` or a plain `u32`.
@@ -32,9 +32,9 @@ public API we provide, such as a method to add a name string to the `People`
collection; that code wouldn’t need to know that we assign an `i32` ID to names
internally. The newtype pattern is a lightweight way to achieve encapsulation
to hide implementation details, which we discussed in the [“Encapsulation that
-Hides Implementation
-Details”][encapsulation-that-hides-implementation-details]<!-- ignore -->
-section of Chapter 17.
+Hides Implementation Details”]
+[encapsulation-that-hides-implementation-details]<!-- ignore --> section of
+Chapter 17.
### Creating Type Synonyms with Type Aliases
@@ -43,16 +43,21 @@ alias* to give an existing type another name. For this we use the `type`
keyword. For example, we can create the alias `Kilometers` to `i32` like so:
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-04-kilometers-alias/src/main.rs:here}}
+type Kilometers = i32;
```
Now, the alias `Kilometers` is a *synonym* for `i32`; unlike the `Millimeters`
-and `Meters` types we created in Listing 19-15, `Kilometers` is not a separate,
+and `Meters` types we created in Listing 19-23, `Kilometers` is not a separate,
new type. Values that have the type `Kilometers` will be treated the same as
values of type `i32`:
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-04-kilometers-alias/src/main.rs:there}}
+type Kilometers = i32;
+
+let x: i32 = 5;
+let y: Kilometers = 5;
+
+println!("x + y = {}", x + y);
```
Because `Kilometers` and `i32` are the same type, we can add values of both
@@ -69,23 +74,43 @@ Box<dyn Fn() + Send + 'static>
Writing this lengthy type in function signatures and as type annotations all
over the code can be tiresome and error prone. Imagine having a project full of
-code like that in Listing 19-24.
+code like that in Listing 19-32.
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-24/src/main.rs:here}}
+let f: Box<dyn Fn() + Send + 'static> = Box::new(|| println!("hi"));
+
+fn takes_long_type(f: Box<dyn Fn() + Send + 'static>) {
+ // --snip--
+}
+
+fn returns_long_type() -> Box<dyn Fn() + Send + 'static> {
+ // --snip--
+# Box::new(|| ())
+}
```
-<span class="caption">Listing 19-24: Using a long type in many places</span>
+<span class="caption">Listing 19-32: Using a long type in many places</span>
A type alias makes this code more manageable by reducing the repetition. In
-Listing 19-25, we’ve introduced an alias named `Thunk` for the verbose type and
+Listing 19-33, we’ve introduced an alias named `Thunk` for the verbose type and
can replace all uses of the type with the shorter alias `Thunk`.
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-25/src/main.rs:here}}
+type Thunk = Box<dyn Fn() + Send + 'static>;
+
+let f: Thunk = Box::new(|| println!("hi"));
+
+fn takes_long_type(f: Thunk) {
+ // --snip--
+}
+
+fn returns_long_type() -> Thunk {
+ // --snip--
+# Box::new(|| ())
+}
```
-<span class="caption">Listing 19-25: Introducing a type alias `Thunk` to reduce
+<span class="caption">Listing 19-33: Introducing a type alias `Thunk` to reduce
repetition</span>
This code is much easier to read and write! Choosing a meaningful name for a
@@ -102,14 +127,23 @@ possible I/O errors. Many of the functions in `std::io` will be returning
the `Write` trait:
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-05-write-trait/src/lib.rs}}
+use std::io::Error;
+use std::fmt;
+
+pub trait Write {
+ fn write(&mut self, buf: &[u8]) -> Result<usize, Error>;
+ fn flush(&mut self) -> Result<(), Error>;
+
+ fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>;
+ fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Error>;
+}
```
The `Result<..., Error>` is repeated a lot. As such, `std::io` has this type of
alias declaration:
-```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs:here}}
+```rust,ignore
+type Result<T> = Result<T, std::io::Error>;
```
Because this declaration is in the `std::io` module, we can use the fully
@@ -117,8 +151,14 @@ qualified alias `std::io::Result<T>`—that is, a `Result<T, E>` with the `E`
filled in as `std::io::Error`. The `Write` trait function signatures end up
looking like this:
-```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs:there}}
+```rust,ignore
+pub trait Write {
+ fn write(&mut self, buf: &[u8]) -> Result<usize>;
+ fn flush(&mut self) -> Result<()>;
+
+ fn write_all(&mut self, buf: &[u8]) -> Result<()>;
+ fn write_fmt(&mut self, fmt: Arguments) -> Result<()>;
+}
```
The type alias helps in two ways: it makes code easier to write *and* it gives
@@ -133,8 +173,10 @@ Rust has a special type named `!` that’s known in type theory lingo as the
because it stands in the place of the return type when a function will never
return. Here is an example:
-```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-07-never-type/src/lib.rs:here}}
+```rust,ignore
+fn bar() -> ! {
+ // --snip--
+}
```
This code is read as “the function `bar` returns never.” Functions that return
@@ -142,13 +184,20 @@ never are called *diverging functions*. We can’t create values of the type `!`
so `bar` can never possibly return.
But what use is a type you can never create values for? Recall the code from
-Listing 2-5; we’ve reproduced part of it here in Listing 19-26.
+Listing 2-5; we’ve reproduced part of it here in Listing 19-34.
-```rust,ignore
-{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs:ch19}}
+```rust
+# let guess = "3";
+# loop {
+let guess: u32 = match guess.trim().parse() {
+ Ok(num) => num,
+ Err(_) => continue,
+};
+# break;
+# }
```
-<span class="caption">Listing 19-26: A `match` with an arm that ends in
+<span class="caption">Listing 19-34: A `match` with an arm that ends in
`continue`</span>
At the time, we skipped over some details in this code. In Chapter 6 in [“The
@@ -157,13 +206,16 @@ At the time, we skipped over some details in this code. In Chapter 6 in [“The
for example, the following code doesn’t work:
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-08-match-arms-different-types/src/main.rs:here}}
+let guess = match guess.trim().parse() {
+ Ok(_) => 5,
+ Err(_) => "hello",
+}
```
The type of `guess` in this code would have to be an integer *and* a string,
and Rust requires that `guess` have only one type. So what does `continue`
return? How were we allowed to return a `u32` from one arm and have another arm
-that ends with `continue` in Listing 19-26?
+that ends with `continue` in Listing 19-34?
As you might have guessed, `continue` has a `!` value. That is, when Rust
computes the type of `guess`, it looks at both match arms, the former with a
@@ -181,10 +233,17 @@ function that we call on `Option<T>` values to produce a value or panic? Here
is its definition:
```rust,ignore
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-09-unwrap-definition/src/lib.rs:here}}
+impl<T> Option<T> {
+ pub fn unwrap(self) -> T {
+ match self {
+ Some(val) => val,
+ None => panic!("called `Option::unwrap()` on a `None` value"),
+ }
+ }
+}
```
-In this code, the same thing happens as in the `match` in Listing 19-26: Rust
+In this code, the same thing happens as in the `match` in Listing 19-34: Rust
sees that `val` has the type `T` and `panic!` has the type `!`, so the result
of the overall `match` expression is `T`. This code works because `panic!`
doesn’t produce a value; it ends the program. In the `None` case, we won’t be
@@ -193,7 +252,11 @@ returning a value from `unwrap`, so this code is valid.
One final expression that has the type `!` is a `loop`:
```rust,ignore
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-10-loop-returns-never/src/main.rs:here}}
+print!("forever ");
+
+loop {
+ print!("and ever ");
+}
```
Here, the loop never ends, so `!` is the value of the expression. However, this
@@ -215,7 +278,8 @@ we can’t create a variable of type `str`, nor can we take an argument of type
`str`. Consider the following code, which does not work:
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-11-cant-create-str/src/main.rs:here}}
+let s1: str = "Hello there!";
+let s2: str = "How's it going?";
```
Rust needs to know how much memory to allocate for any value of a particular
@@ -244,11 +308,11 @@ We can combine `str` with all kinds of pointers: for example, `Box<str>` or
`Rc<str>`. In fact, you’ve seen this before but with a different dynamically
sized type: traits. Every trait is a dynamically sized type we can refer to by
using the name of the trait. In Chapter 17 in the [“Using Trait Objects That
-Allow for Values of Different
-Types”][using-trait-objects-that-allow-for-values-of-different-types]<!--
-ignore --> section, we mentioned that to use traits as trait objects, we must
-put them behind a pointer, such as `&dyn Trait` or `Box<dyn Trait>` (`Rc<dyn
-Trait>` would work too).
+Allow for Values of Different Types”]
+[using-trait-objects-that-allow-for-values-of-different-types]<!-- ignore -->
+section, we mentioned that to use traits as trait objects, we must put them
+behind a pointer, such as `&dyn Trait` or `Box<dyn Trait>` (`Rc<dyn Trait>`
+would work too).
To work with DSTs, Rust has a particular trait called the `Sized` trait to
determine whether or not a type’s size is known at compile time. This trait is
@@ -257,13 +321,17 @@ In addition, Rust implicitly adds a bound on `Sized` to every generic function.
That is, a generic function definition like this:
```rust,ignore
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-12-generic-fn-definition/src/lib.rs}}
+fn generic<T>(t: T) {
+ // --snip--
+}
```
is actually treated as though we had written this:
```rust,ignore
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/src/lib.rs}}
+fn generic<T: Sized>(t: T) {
+ // --snip--
+}
```
By default, generic functions will work only on types that have a known size at
@@ -271,7 +339,9 @@ compile time. However, you can use the following special syntax to relax this
restriction:
```rust,ignore
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/src/lib.rs}}
+fn generic<T: ?Sized>(t: &T) {
+ // --snip--
+}
```
A trait bound on `?Sized` is the opposite of a trait bound on `Sized`: we would
diff --git a/book-original/src/ch19-05-advanced-functions-and-closures.md b/book-pl-en/src/ch19-05-advanced-functions-and-closures.md
index ee04e86..3399f6e 100644
--- a/book-original/src/ch19-05-advanced-functions-and-closures.md
+++ b/book-pl-en/src/ch19-05-advanced-functions-and-closures.md
@@ -1,6 +1,6 @@
## Advanced Functions and Closures
-Next, we’ll explore some advanced features related to functions and
+Finally, we’ll explore some advanced features related to functions and
closures, which include function pointers and returning closures.
### Function Pointers
@@ -12,15 +12,27 @@ with function pointers will allow you to use functions as arguments to other
functions. Functions coerce to the type `fn` (with a lowercase f), not to be
confused with the `Fn` closure trait. The `fn` type is called a *function
pointer*. The syntax for specifying that a parameter is a function pointer is
-similar to that of closures, as shown in Listing 19-27.
+similar to that of closures, as shown in Listing 19-35.
<span class="filename">Filename: src/main.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-27/src/main.rs}}
+fn add_one(x: i32) -> i32 {
+ x + 1
+}
+
+fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
+ f(arg) + f(arg)
+}
+
+fn main() {
+ let answer = do_twice(add_one, 5);
+
+ println!("The answer is: {}", answer);
+}
```
-<span class="caption">Listing 19-27: Using the `fn` type to accept a function
+<span class="caption">Listing 19-35: Using the `fn` type to accept a function
pointer as an argument</span>
This code prints `The answer is: 12`. We specify that the parameter `f` in
@@ -47,14 +59,22 @@ function, let’s look at a use of `map`. To use the `map` function to turn a
vector of numbers into a vector of strings, we could use a closure, like this:
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-15-map-closure/src/main.rs:here}}
+let list_of_numbers = vec![1, 2, 3];
+let list_of_strings: Vec<String> = list_of_numbers
+ .iter()
+ .map(|i| i.to_string())
+ .collect();
```
Or we could name a function as the argument to `map` instead of the closure,
like this:
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-16-map-function/src/main.rs:here}}
+let list_of_numbers = vec![1, 2, 3];
+let list_of_strings: Vec<String> = list_of_numbers
+ .iter()
+ .map(ToString::to_string)
+ .collect();
```
Note that we must use the fully qualified syntax that we talked about earlier
@@ -63,22 +83,27 @@ there are multiple functions available named `to_string`. Here, we’re using th
`to_string` function defined in the `ToString` trait, which the standard
library has implemented for any type that implements `Display`.
-We have another useful pattern that exploits an implementation detail of tuple
-structs and tuple-struct enum variants. These types use `()` as initializer
-syntax, which looks like a function call. The initializers are actually
-implemented as functions returning an instance that’s constructed from their
-arguments. We can use these initializer functions as function pointers that
-implement the closure traits, which means we can specify the initializer
-functions as arguments for methods that take closures, like so:
+Another useful pattern exploits an implementation detail of tuple structs and
+tuple-struct enum variants. These items use `()` as initialiser syntax, which
+looks like a function call, and they’re actually implemented as functions
+returning an instance constructed from their arguments. They can also be called
+as a function pointer implementing the closure traits, and so can be used
+similarly to the above:
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-17-map-initializer/src/main.rs:here}}
+enum Status {
+ Value(u32),
+ Stop,
+}
+
+let list_of_statuses: Vec<Status> =
+ (0u32..20)
+ .map(Status::Value)
+ .collect();
```
-Here we create `Status::Value` instances using each `u32` value in the range
-that `map` is called on by using the initializer function of `Status::Value`.
-Some people prefer this style, and some people prefer to use closures. They
-compile to the same code, so use whichever style is clearer to you.
+Some people prefer this style, and some people prefer to use closures. They end
+up compiling to the same code, so use whichever style is clearer to you.
### Returning Closures
@@ -92,13 +117,25 @@ pointer `fn` as a return type, for example.
The following code tries to return a closure directly, but it won’t compile:
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-18-returns-closure/src/lib.rs}}
+fn returns_closure() -> Fn(i32) -> i32 {
+ |x| x + 1
+}
```
The compiler error is as follows:
```text
-{{#include ../listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt}}
+error[E0277]: the trait bound `std::ops::Fn(i32) -> i32 + 'static:
+std::marker::Sized` is not satisfied
+ -->
+ |
+1 | fn returns_closure() -> Fn(i32) -> i32 {
+ | ^^^^^^^^^^^^^^ `std::ops::Fn(i32) -> i32 + 'static`
+ does not have a constant size known at compile-time
+ |
+ = help: the trait `std::marker::Sized` is not implemented for
+ `std::ops::Fn(i32) -> i32 + 'static`
+ = note: the return type of a function must have a statically known size
```
The error references the `Sized` trait again! Rust doesn’t know how much space
@@ -106,13 +143,15 @@ it will need to store the closure. We saw a solution to this problem earlier.
We can use a trait object:
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs}}
+fn returns_closure() -> Box<dyn Fn(i32) -> i32> {
+ Box::new(|x| x + 1)
+}
```
This code will compile just fine. For more about trait objects, refer to the
-section [“Using Trait Objects That Allow for Values of Different
-Types”][using-trait-objects-that-allow-for-values-of-different-types]<!--
-ignore --> in Chapter 17.
+[“Using Trait Objects That Allow for Values of Different Types”]
+[using-trait-objects-that-allow-for-values-of-different-types]<!-- ignore -->
+section in Chapter 17.
Next, let’s look at macros!
diff --git a/book-original/src/ch19-06-macros.md b/book-pl-en/src/ch19-06-macros.md
index 8733ee7..90b11e5 100644
--- a/book-original/src/ch19-06-macros.md
+++ b/book-pl-en/src/ch19-06-macros.md
@@ -1,18 +1,17 @@
## Macros
We’ve used macros like `println!` throughout this book, but we haven’t fully
-explored what a macro is and how it works. The term *macro* refers to a family
-of features in Rust: *declarative* macros with `macro_rules!` and three kinds
-of *procedural* macros:
+explored what a macro is and how it works. *Macros* refers to a family of
+features in Rust:
-* Custom `#[derive]` macros that specify code added with the `derive` attribute
- used on structs and enums
-* Attribute-like macros that define custom attributes usable on any item
-* Function-like macros that look like function calls but operate on the tokens
- specified as their argument
+* *Declarative* macros with `macro_rules!`
+* *Procedural* macros, which come in three kinds:
+ * Custom `#[derive]` macros
+ * Attribute-like macros
+ * Function-like macros
-We’ll talk about each of these in turn, but first, let’s look at why we even
-need macros when we already have functions.
+We’ll talk about each of these in turn, but first, why do we even need macros
+when we already have functions?
### The Difference Between Macros and Functions
@@ -24,7 +23,7 @@ macros *expand* to produce more code than the code you’ve written manually.
Metaprogramming is useful for reducing the amount of code you have to write and
maintain, which is also one of the roles of functions. However, macros have
-some additional powers that functions don’t.
+some additional powers that functions don’t have.
A function signature must declare the number and type of parameters the
function has. Macros, on the other hand, can take a variable number of
@@ -40,30 +39,29 @@ Rust code that writes Rust code. Due to this indirection, macro definitions are
generally more difficult to read, understand, and maintain than function
definitions.
-Another important difference between macros and functions is that you must
-define macros or bring them into scope *before* you call them in a file, as
-opposed to functions you can define anywhere and call anywhere.
+There is one last important difference between macros and functions: you must
+define or bring macros into scope *before* you call them in a file, whereas you
+can define functions anywhere and call them anywhere.
### Declarative Macros with `macro_rules!` for General Metaprogramming
-The most widely used form of macros in Rust is *declarative macros*. These are
-also sometimes referred to as “macros by example,” “`macro_rules!` macros,” or
-just plain “macros.” At their core, declarative macros allow you to write
-something similar to a Rust `match` expression. As discussed in Chapter 6,
-`match` expressions are control structures that take an expression, compare the
+The most widely used form of macros in Rust are *declarative macros*. These are
+also sometimes referred to as “macros by example”, “`macro_rules!` macros”, or
+just plain “macros”. At their core, declarative macros are written in a form
+similar to a Rust `match` expression. As discussed in Chapter 6, `match`
+expressions are control structures that take an expression, compare the
resulting value of the expression to patterns, and then run the code associated
-with the matching pattern. Macros also compare a value to patterns that are
-associated with particular code: in this situation, the value is the literal
-Rust source code passed to the macro; the patterns are compared with the
-structure of that source code; and the code associated with each pattern, when
-matched, replaces the code passed to the macro. This all happens during
-compilation.
+with the matching pattern. Macros also compare a value to patterns that have
+code associated with them; in this situation, the value is the literal Rust
+source code passed to the macro, the patterns are compared with the structure
+of that source code, and the code associated with each pattern is the code that
+replaces the code passed to the macro. This all happens during compilation.
To define a macro, you use the `macro_rules!` construct. Let’s explore how to
use `macro_rules!` by looking at how the `vec!` macro is defined. Chapter 8
covered how we can use the `vec!` macro to create a new vector with particular
-values. For example, the following macro creates a new vector containing three
-integers:
+values. For example, the following macro creates a new vector with three
+integers inside:
```rust
let v: Vec<u32> = vec![1, 2, 3];
@@ -73,15 +71,27 @@ We could also use the `vec!` macro to make a vector of two integers or a vector
of five string slices. We wouldn’t be able to use a function to do the same
because we wouldn’t know the number or type of values up front.
-Listing 19-28 shows a slightly simplified definition of the `vec!` macro.
+Let’s look at a slightly simplified definition of the `vec!` macro in Listing
+19-36.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-28/src/lib.rs}}
+#[macro_export]
+macro_rules! vec {
+ ( $( $x:expr ),* ) => {
+ {
+ let mut temp_vec = Vec::new();
+ $(
+ temp_vec.push($x);
+ )*
+ temp_vec
+ }
+ };
+}
```
-<span class="caption">Listing 19-28: A simplified version of the `vec!` macro
+<span class="caption">Listing 19-36: A simplified version of the `vec!` macro
definition</span>
> Note: The actual definition of the `vec!` macro in the standard library
@@ -89,7 +99,7 @@ definition</span>
> is an optimization that we don’t include here to make the example simpler.
The `#[macro_export]` annotation indicates that this macro should be made
-available whenever the crate in which the macro is defined is brought into
+available whenever the crate in which we’re defining the macro is brought into
scope. Without this annotation, the macro can’t be brought into scope.
We then start the macro definition with `macro_rules!` and the name of the
@@ -101,75 +111,73 @@ expression. Here we have one arm with the pattern `( $( $x:expr ),* )`,
followed by `=>` and the block of code associated with this pattern. If the
pattern matches, the associated block of code will be emitted. Given that this
is the only pattern in this macro, there is only one valid way to match; any
-other pattern will result in an error. More complex macros will have more than
-one arm.
+other will be an error. More complex macros will have more than one arm.
Valid pattern syntax in macro definitions is different than the pattern syntax
covered in Chapter 18 because macro patterns are matched against Rust code
-structure rather than values. Let’s walk through what the pattern pieces in
-Listing 19-28 mean; for the full macro pattern syntax, see [the reference].
+structure rather than values. Let’s walk through what the pieces of the pattern
+in Listing D-1 mean; for the full macro pattern syntax, see [the reference].
-[the reference]: ../reference/macros-by-example.html
+[the reference]: ../reference/macros.html
-First, a set of parentheses encompasses the whole pattern. A dollar sign (`$`)
-is next, followed by a set of parentheses that captures values that match the
-pattern within the parentheses for use in the replacement code. Within `$()` is
-`$x:expr`, which matches any Rust expression and gives the expression the name
-`$x`.
+First, a set of parentheses encompasses the whole pattern. Next comes a dollar
+sign (`$`) followed by a set of parentheses, which captures values that match
+the pattern within the parentheses for use in the replacement code. Within
+`$()` is `$x:expr`, which matches any Rust expression and gives the expression
+the name `$x`.
The comma following `$()` indicates that a literal comma separator character
-could optionally appear after the code that matches the code in `$()`. The `*`
-specifies that the pattern matches zero or more of whatever precedes the `*`.
+could optionally appear after the code that matches the code captured in `$()`.
+The `*` following the comma specifies that the pattern matches zero or more of
+whatever precedes the `*`.
When we call this macro with `vec![1, 2, 3];`, the `$x` pattern matches three
times with the three expressions `1`, `2`, and `3`.
Now let’s look at the pattern in the body of the code associated with this arm:
-`temp_vec.push()` within `$()*` is generated for each part that matches `$()`
-in the pattern zero or more times depending on how many times the pattern
-matches. The `$x` is replaced with each expression matched. When we call this
-macro with `vec![1, 2, 3];`, the code generated that replaces this macro call
-will be the following:
+the `temp_vec.push()` code within the `$()*` part is generated for each part
+that matches `$()` in the pattern, zero or more times depending on how many
+times the pattern matches. The `$x` is replaced with each expression matched.
+When we call this macro with `vec![1, 2, 3];`, the code generated that replaces
+this macro call will be the following:
```rust,ignore
-{
- let mut temp_vec = Vec::new();
- temp_vec.push(1);
- temp_vec.push(2);
- temp_vec.push(3);
- temp_vec
-}
+let mut temp_vec = Vec::new();
+temp_vec.push(1);
+temp_vec.push(2);
+temp_vec.push(3);
+temp_vec
```
We’ve defined a macro that can take any number of arguments of any type and can
generate code to create a vector containing the specified elements.
-There are some strange edge cases with `macro_rules!`. In the future, Rust will
-have a second kind of declarative macro that will work in a similar fashion but
-fix some of these edge cases. After that update, `macro_rules!` will be
-effectively deprecated. With this in mind, as well as the fact that most Rust
-programmers will *use* macros more than *write* macros, we won’t discuss
-`macro_rules!` any further. To learn more about how to write macros, consult
-the online documentation or other resources, such as [“The Little Book of Rust
-Macros”][tlborm].
+There are some strange corners with `macro_rules!`. In the future, there
+will be a second kind of declarative macro with the `macro` keyword that
+will work in a similar fashion but fix some of these edge cases. After that
+is done, `macro_rules!` will be effectively deprecated. With this
+in mind, as well as the fact that most Rust programmers will *use* macros
+more than *write* macros, we won’t discuss `macro_rules!` any further. To
+learn more about how to write macros, consult the online documentation or
+other resources, such as [“The Little Book of Rust Macros”][tlborm].
[tlborm]: https://danielkeep.github.io/tlborm/book/index.html
### Procedural Macros for Generating Code from Attributes
-The second form of macros is *procedural macros*, which act more like functions
-(and are a type of procedure). Procedural macros accept some code as an input,
-operate on that code, and produce some code as an output rather than matching
-against patterns and replacing the code with other code as declarative macros
-do.
+The second form of macros is called *procedural macros* because they’re more
+like functions (which are a type of procedure). Procedural macros accept some
+Rust code as an input, operate on that code, and produce some Rust code as an
+output rather than matching against patterns and replacing the code with other
+code as declarative macros do.
-The three kinds of procedural macros (custom derive, attribute-like, and
-function-like) all work in a similar fashion.
+There are three kinds of procedural macros, but they all work in a similar
+fashion. First, the definitions must reside in their own crate with a special
+crate type. This is for complex technical reasons that we hope to eliminate in
+the future.
-When creating procedural macros, the definitions must reside in their own crate
-with a special crate type. This is for complex technical reasons that we hope
-to eliminate in the future. Using procedural macros looks like the code in
-Listing 19-29, where `some_attribute` is a placeholder for using a specific
+Second, using any of these kinds of macros takes on a form like the code shown
+in Listing 19-37, where `some_attribute` is a placeholder for using a specific
macro.
<span class="filename">Filename: src/lib.rs</span>
@@ -182,21 +190,23 @@ pub fn some_name(input: TokenStream) -> TokenStream {
}
```
-<span class="caption">Listing 19-29: An example of using a procedural
+<span class="caption">Listing 19-37: An example of using a procedural
macro</span>
-The function that defines a procedural macro takes a `TokenStream` as an input
-and produces a `TokenStream` as an output. The `TokenStream` type is defined by
-the `proc_macro` crate that is included with Rust and represents a sequence of
-tokens. This is the core of the macro: the source code that the macro is
-operating on makes up the input `TokenStream`, and the code the macro produces
-is the output `TokenStream`. The function also has an attribute attached to it
-that specifies which kind of procedural macro we’re creating. We can have
-multiple kinds of procedural macros in the same crate.
-
-Let’s look at the different kinds of procedural macros. We’ll start with a
-custom derive macro and then explain the small dissimilarities that make the
-other forms different.
+Procedural macros consist of a function, which is how they get their name:
+“procedure” is a synonym for “function.” Why not call them “functional macros”?
+Well, one of the types is “function-like,” and that would get confusing.
+Anyway, the function defining a procedural macro takes a `TokenStream` as an
+input and produces a `TokenStream` as an output. This is the core of the macro:
+the source code that the macro is operating on makes up the input
+`TokenStream`, and the code the macro produces is the output `TokenStream`.
+Finally, the function has an attribute on it; this attribute says which kind of
+procedural macro we’re creating. We can have multiple kinds of procedural
+macros in the same crate.
+
+Given that the kinds of macros are so similar, we’ll start with a custom derive
+macro. Then we’ll explain the small differences that make the other forms
+different.
### How to Write a Custom `derive` Macro
@@ -208,15 +218,23 @@ types, we’ll provide a procedural macro so users can annotate their type with
function. The default implementation will print `Hello, Macro! My name is
TypeName!` where `TypeName` is the name of the type on which this trait has
been defined. In other words, we’ll write a crate that enables another
-programmer to write code like Listing 19-30 using our crate.
+programmer to write code like Listing 19-38 using our crate.
<span class="filename">Filename: src/main.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-30/src/main.rs}}
+```rust,ignore
+use hello_macro::HelloMacro;
+use hello_macro_derive::HelloMacro;
+
+#[derive(HelloMacro)]
+struct Pancakes;
+
+fn main() {
+ Pancakes::hello_macro();
+}
```
-<span class="caption">Listing 19-30: The code a user of our crate will be able
+<span class="caption">Listing 19-38: The code a user of our crate will be able
to write when using our procedural macro</span>
This code will print `Hello, Macro! My name is Pancakes!` when we’re done. The
@@ -231,24 +249,38 @@ Next, we’ll define the `HelloMacro` trait and its associated function:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/src/lib.rs}}
+pub trait HelloMacro {
+ fn hello_macro();
+}
```
We have a trait and its function. At this point, our crate user could implement
the trait to achieve the desired functionality, like so:
```rust,ignore
-{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/src/main.rs}}
+use hello_macro::HelloMacro;
+
+struct Pancakes;
+
+impl HelloMacro for Pancakes {
+ fn hello_macro() {
+ println!("Hello, Macro! My name is Pancakes!");
+ }
+}
+
+fn main() {
+ Pancakes::hello_macro();
+}
```
However, they would need to write the implementation block for each type they
wanted to use with `hello_macro`; we want to spare them from having to do this
work.
-Additionally, we can’t yet provide the `hello_macro` function with default
-implementation that will print the name of the type the trait is implemented
-on: Rust doesn’t have reflection capabilities, so it can’t look up the type’s
-name at runtime. We need a macro to generate code at compile time.
+Additionally, we can’t yet provide a default implementation for the
+`hello_macro` function that will print the name of the type the trait is
+implemented on: Rust doesn’t have reflection capabilities, so it can’t look up
+the type’s name at runtime. We need a macro to generate code at compile time.
The next step is to define the procedural macro. At the time of this writing,
procedural macros need to be in their own crate. Eventually, this restriction
@@ -267,8 +299,8 @@ definition in `hello_macro`, we’ll have to change the implementation of the
procedural macro in `hello_macro_derive` as well. The two crates will need to
be published separately, and programmers using these crates will need to add
both as dependencies and bring them both into scope. We could instead have the
-`hello_macro` crate use `hello_macro_derive` as a dependency and re-export the
-procedural macro code. However, the way we’ve structured the project makes it
+`hello_macro` crate use `hello_macro_derive` as a dependency and reexport the
+procedural macro code. But the way we’ve structured the project makes it
possible for programmers to use `hello_macro` even if they don’t want the
`derive` functionality.
@@ -280,57 +312,79 @@ in a moment, so we need to add them as dependencies. Add the following to the
<span class="filename">Filename: hello_macro_derive/Cargo.toml</span>
```toml
-{{#include ../listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml:7:12}}
+[lib]
+proc-macro = true
+
+[dependencies]
+syn = "0.14.4"
+quote = "0.6.3"
```
-To start defining the procedural macro, place the code in Listing 19-31 into
+To start defining the procedural macro, place the code in Listing 19-39 into
your *src/lib.rs* file for the `hello_macro_derive` crate. Note that this code
won’t compile until we add a definition for the `impl_hello_macro` function.
<span class="filename">Filename: hello_macro_derive/src/lib.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs}}
+<!--
+This usage of `extern crate` is required for the moment with 1.31.0, see:
+https://github.com/rust-lang/rust/issues/54418
+https://github.com/rust-lang/rust/pull/54658
+https://github.com/rust-lang/rust/issues/55599
+-->
+
+```rust,ignore
+extern crate proc_macro;
+
+use crate::proc_macro::TokenStream;
+use quote::quote;
+use syn;
+
+#[proc_macro_derive(HelloMacro)]
+pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
+ // Construct a representation of Rust code as a syntax tree
+ // that we can manipulate
+ let ast = syn::parse(input).unwrap();
+
+ // Build the trait implementation
+ impl_hello_macro(&ast)
+}
```
-<span class="caption">Listing 19-31: Code that most procedural macro crates
-will require in order to process Rust code</span>
+<span class="caption">Listing 19-39: Code that most procedural macro crates
+will need to have for processing Rust code</span>
-Notice that we’ve split the code into the `hello_macro_derive` function, which
-is responsible for parsing the `TokenStream`, and the `impl_hello_macro`
-function, which is responsible for transforming the syntax tree: this makes
-writing a procedural macro more convenient. The code in the outer function
-(`hello_macro_derive` in this case) will be the same for almost every
-procedural macro crate you see or create. The code you specify in the body of
-the inner function (`impl_hello_macro` in this case) will be different
+Notice the way we’ve split the functions in Listing 19-39; this will be the
+same for almost every procedural macro crate you see or create, because it
+makes writing a procedural macro more convenient. What you choose to do in the
+place where the `impl_hello_macro` function is called will be different
depending on your procedural macro’s purpose.
We’ve introduced three new crates: `proc_macro`, [`syn`], and [`quote`]. The
`proc_macro` crate comes with Rust, so we didn’t need to add that to the
-dependencies in *Cargo.toml*. The `proc_macro` crate is the compiler’s API that
-allows us to read and manipulate Rust code from our code.
+dependencies in *Cargo.toml*. The `proc_macro` crate is the compiler’s API to
+be able to read and manipulate Rust code from our code. The `syn` crate
+parses Rust code from a string into a data structure that we can perform
+operations on. The `quote` crate takes `syn` data structures and turns them
+back into Rust code. These crates make it much simpler to parse any sort of
+Rust code we might want to handle: writing a full parser for Rust code is no
+simple task.
[`syn`]: https://crates.io/crates/syn
[`quote`]: https://crates.io/crates/quote
-The `syn` crate parses Rust code from a string into a data structure that we
-can perform operations on. The `quote` crate turns `syn` data structures back
-into Rust code. These crates make it much simpler to parse any sort of Rust
-code we might want to handle: writing a full parser for Rust code is no simple
-task.
-
-The `hello_macro_derive` function will be called when a user of our library
-specifies `#[derive(HelloMacro)]` on a type. This is possible because we’ve
-annotated the `hello_macro_derive` function here with `proc_macro_derive` and
-specified the name, `HelloMacro`, which matches our trait name; this is the
-convention most procedural macros follow.
-
-The `hello_macro_derive` function first converts the `input` from a
-`TokenStream` to a data structure that we can then interpret and perform
-operations on. This is where `syn` comes into play. The `parse` function in
-`syn` takes a `TokenStream` and returns a `DeriveInput` struct representing the
-parsed Rust code. Listing 19-32 shows the relevant parts of the `DeriveInput`
-struct we get from parsing the `struct Pancakes;` string:
+The `hello_macro_derive` function will get called when a user of our library
+specifies `#[derive(HelloMacro)]` on a type. The reason is that we’ve annotated
+the `hello_macro_derive` function here with `proc_macro_derive` and specified
+the name, `HelloMacro`, which matches our trait name; that’s the convention
+most procedural macros follow.
+
+This function first converts the `input` from a `TokenStream` to a data
+structure that we can then interpret and perform operations on. This is where
+`syn` comes into play. The `parse` function in `syn` takes a `TokenStream` and
+returns a `DeriveInput` struct representing the parsed Rust code. Listing 19-40
+shows the relevant parts of the `DeriveInput` struct we get from parsing the
+string `struct Pancakes;`:
```rust,ignore
DeriveInput {
@@ -352,62 +406,72 @@ DeriveInput {
}
```
-<span class="caption">Listing 19-32: The `DeriveInput` instance we get when
-parsing the code that has the macro’s attribute in Listing 19-30</span>
+<span class="caption">Listing 19-40: The `DeriveInput` instance we get when
+parsing the code that has the macro’s attribute in Listing 19-38</span>
The fields of this struct show that the Rust code we’ve parsed is a unit struct
with the `ident` (identifier, meaning the name) of `Pancakes`. There are more
fields on this struct for describing all sorts of Rust code; check the [`syn`
documentation for `DeriveInput`][syn-docs] for more information.
-[syn-docs]: https://docs.rs/syn/1.0/syn/struct.DeriveInput.html
+[syn-docs]: https://docs.rs/syn/0.14.4/syn/struct.DeriveInput.html
-Soon we’ll define the `impl_hello_macro` function, which is where we’ll build
-the new Rust code we want to include. But before we do, note that the output
-for our derive macro is also a `TokenStream`. The returned `TokenStream` is
-added to the code that our crate users write, so when they compile their crate,
-they’ll get the extra functionality that we provide in the modified
-`TokenStream`.
+At this point, we haven’t defined the `impl_hello_macro` function, which is
+where we’ll build the new Rust code we want to include. But before we do, note
+that its output is also a `TokenStream`. The returned `TokenStream` is added to
+the code that our crate users write, so when they compile their crate, they’ll
+get extra functionality that we provide.
-You might have noticed that we’re calling `unwrap` to cause the
-`hello_macro_derive` function to panic if the call to the `syn::parse` function
-fails here. It’s necessary for our procedural macro to panic on errors because
-`proc_macro_derive` functions must return `TokenStream` rather than `Result` to
-conform to the procedural macro API. We’ve simplified this example by using
-`unwrap`; in production code, you should provide more specific error messages
-about what went wrong by using `panic!` or `expect`.
+You might have noticed that we’re calling `unwrap` to panic if the call to the
+`syn::parse` function fails here. Panicking on errors is necessary in
+procedural macro code because `proc_macro_derive` functions must return
+`TokenStream` rather than `Result` to conform to the procedural macro API.
+We’ve chosen to simplify this example by using `unwrap`; in production code,
+you should provide more specific error messages about what went wrong by using
+`panic!` or `expect`.
Now that we have the code to turn the annotated Rust code from a `TokenStream`
into a `DeriveInput` instance, let’s generate the code that implements the
-`HelloMacro` trait on the annotated type, as shown in Listing 19-33.
+`HelloMacro` trait on the annotated type as shown in Listing 19-41.
<span class="filename">Filename: hello_macro_derive/src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/src/lib.rs:here}}
+fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
+ let name = &ast.ident;
+ let gen = quote! {
+ impl HelloMacro for #name {
+ fn hello_macro() {
+ println!("Hello, Macro! My name is {}", stringify!(#name));
+ }
+ }
+ };
+ gen.into()
+}
```
-<span class="caption">Listing 19-33: Implementing the `HelloMacro` trait using
+<span class="caption">Listing 19-41: Implementing the `HelloMacro` trait using
the parsed Rust code</span>
We get an `Ident` struct instance containing the name (identifier) of the
-annotated type using `ast.ident`. The struct in Listing 19-32 shows that when
-we run the `impl_hello_macro` function on the code in Listing 19-30, the
-`ident` we get will have the `ident` field with a value of `"Pancakes"`. Thus,
-the `name` variable in Listing 19-33 will contain an `Ident` struct instance
+annotated type using `ast.ident`. The struct in Listing 19-40 shows that the
+`ident` we get when the `impl_hello_macro` function is run on the code in
+Listing 19-38 will have the `ident` field with a value of `"Pancakes"`. Thus,
+the `name` variable in Listing 19-41 will contain an `Ident` struct instance
that, when printed, will be the string `"Pancakes"`, the name of the struct in
-Listing 19-30.
+Listing 19-38.
-The `quote!` macro lets us define the Rust code that we want to return. The
-compiler expects something different to the direct result of the `quote!`
-macro’s execution, so we need to convert it to a `TokenStream`. We do this by
-calling the `into` method, which consumes this intermediate representation and
-returns a value of the required `TokenStream` type.
+The `quote!` macro lets us write the Rust code that we want to return. The
+direct result of the `quote!` macro’s execution isn’t what’s expected by the
+compiler and needs to be converted to a `TokenStream`. We do this by calling
+the `into` method, which consumes this intermediate representation and returns
+a value of the required `TokenStream` type.
-The `quote!` macro also provides some very cool templating mechanics: we can
-enter `#name`, and `quote!` will replace it with the value in the variable
-`name`. You can even do some repetition similar to the way regular macros work.
-Check out [the `quote` crate’s docs][quote-docs] for a thorough introduction.
+The `quote!` macro also provides some very cool templating mechanics; we can
+write `#name`, and `quote!` will replace it with the value in the variable
+named `name`. You can even do some repetition similar to the way regular macros
+work. Check out [the `quote` crate’s docs][quote-docs] for a thorough
+introduction.
[quote-docs]: https://docs.rs/quote
@@ -420,25 +484,27 @@ the name of the annotated type.
The `stringify!` macro used here is built into Rust. It takes a Rust
expression, such as `1 + 2`, and at compile time turns the expression into a
string literal, such as `"1 + 2"`. This is different than `format!` or
-`println!`, macros which evaluate the expression and then turn the result into
-a `String`. There is a possibility that the `#name` input might be an
-expression to print literally, so we use `stringify!`. Using `stringify!` also
-saves an allocation by converting `#name` to a string literal at compile time.
+`println!`, which evaluate the expression and then turn the result into a
+`String`. There is a possibility that the `#name` input might be an expression
+to print literally, so we use `stringify!`. Using `stringify!` also saves an
+allocation by converting `#name` to a string literal at compile time.
At this point, `cargo build` should complete successfully in both `hello_macro`
and `hello_macro_derive`. Let’s hook up these crates to the code in Listing
-19-30 to see the procedural macro in action! Create a new binary project in
+19-38 to see the procedural macro in action! Create a new binary project in
your *projects* directory using `cargo new pancakes`. We need to add
`hello_macro` and `hello_macro_derive` as dependencies in the `pancakes`
crate’s *Cargo.toml*. If you’re publishing your versions of `hello_macro` and
-`hello_macro_derive` to [crates.io](https://crates.io/), they would be regular
+`hello_macro_derive` to *https://crates.io/*, they would be regular
dependencies; if not, you can specify them as `path` dependencies as follows:
```toml
-{{#include ../listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml:7:9}}
+[dependencies]
+hello_macro = { path = "../hello_macro" }
+hello_macro_derive = { path = "../hello_macro/hello_macro_derive" }
```
-Put the code in Listing 19-30 into *src/main.rs*, and run `cargo run`: it
+Put the code from Listing 19-38 into *src/main.rs*, and run `cargo run`: it
should print `Hello, Macro! My name is Pancakes!` The implementation of the
`HelloMacro` trait from the procedural macro was included without the
`pancakes` crate needing to implement it; the `#[derive(HelloMacro)]` added the
@@ -451,72 +517,62 @@ derive macros.
Attribute-like macros are similar to custom derive macros, but instead of
generating code for the `derive` attribute, they allow you to create new
-attributes. They’re also more flexible: `derive` only works for structs and
-enums; attributes can be applied to other items as well, such as functions.
-Here’s an example of using an attribute-like macro: say you have an attribute
-named `route` that annotates functions when using a web application framework:
+attributes. They’re also more flexible; `derive` only works for structs and
+enums; attributes can go on other items as well, like functions. As an example
+of using an attribute-like macro, you might have an attribute named `route`
+that annotates functions when using a web application framework:
```rust,ignore
#[route(GET, "/")]
fn index() {
```
-This `#[route]` attribute would be defined by the framework as a procedural
-macro. The signature of the macro definition function would look like this:
+This `#[route]` attribute would be defined by the framework itself as a
+procedural macro. The macro definition function’s signature would look like
+this:
```rust,ignore
#[proc_macro_attribute]
pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
```
-Here, we have two parameters of type `TokenStream`. The first is for the
-contents of the attribute: the `GET, "/"` part. The second is the body of the
-item the attribute is attached to: in this case, `fn index() {}` and the rest
-of the function’s body.
+Here, we have two parameters of type `TokenStream`; the first is for the
+contents of the attribute itself, that is, the `GET, "/"` part. The second is
+the body of the item the attribute is attached to, in this case, `fn index()
+{}` and the rest of the function’s body.
Other than that, attribute-like macros work the same way as custom derive
-macros: you create a crate with the `proc-macro` crate type and implement a
+macros: create a crate with the `proc-macro` crate type and implement a
function that generates the code you want!
### Function-like macros
-Function-like macros define macros that look like function calls. Similarly to
-`macro_rules!` macros, they’re more flexible than functions; for example, they
-can take an unknown number of arguments. However, `macro_rules!` macros can be
-defined only using the match-like syntax we discussed in the section
-[“Declarative Macros with `macro_rules!` for General Metaprogramming”][decl]
-earlier. Function-like macros take a `TokenStream` parameter and their
-definition manipulates that `TokenStream` using Rust code as the other two
-types of procedural macros do. An example of a function-like macro is an `sql!`
-macro that might be called like so:
-
-[decl]: #declarative-macros-with-macro_rules-for-general-metaprogramming
+Finally, function-like macros define macros that look like function calls. For
+example, an `sql!` macro that might be called like so:
```rust,ignore
let sql = sql!(SELECT * FROM posts WHERE id=1);
```
-This macro would parse the SQL statement inside it and check that it’s
-syntactically correct, which is much more complex processing than a
-`macro_rules!` macro can do. The `sql!` macro would be defined like this:
+This macro would parse the SQL statement inside of it and check that it’s
+syntactically correct. This macro would be defined like this:
```rust,ignore
#[proc_macro]
pub fn sql(input: TokenStream) -> TokenStream {
```
-This definition is similar to the custom derive macro’s signature: we receive
-the tokens that are inside the parentheses and return the code we wanted to
-generate.
+This is similar to the custom derive macro’s signature: we get in the tokens
+that are inside of the parentheses, and return the code we wanted to generate.
## Summary
-Whew! Now you have some Rust features in your toolbox that you won’t use often,
-but you’ll know they’re available in very particular circumstances. We’ve
-introduced several complex topics so that when you encounter them in error
-message suggestions or in other peoples’ code, you’ll be able to recognize
-these concepts and syntax. Use this chapter as a reference to guide you to
-solutions.
+Whew! Now you have some features of Rust in your toolbox that you won’t use
+often, but you’ll know they’re available in very particular circumstances.
+We’ve introduced several complex topics so that when you encounter them in
+error message suggestions or in other peoples’ code, you’ll be able to
+recognize these concepts and syntax. Use this chapter as a reference to guide
+you to solutions.
Next, we’ll put everything we’ve discussed throughout the book into practice
and do one more project!
diff --git a/book-original/src/ch20-00-final-project-a-web-server.md b/book-pl-en/src/ch20-00-final-project-a-web-server.md
index d260041..990337e 100644
--- a/book-original/src/ch20-00-final-project-a-web-server.md
+++ b/book-pl-en/src/ch20-00-final-project-a-web-server.md
@@ -22,9 +22,8 @@ Here is the plan to build the web server:
But before we get started, we should mention one detail: the method we’ll use
won’t be the best way to build a web server with Rust. A number of
-production-ready crates are available on [crates.io](https://crates.io/) that
-provide more complete web server and thread pool implementations than we’ll
-build.
+production-ready crates are available on *https://crates.io/* that provide more
+complete web server and thread pool implementations than we’ll build.
However, our intention in this chapter is to help you learn, not to take the
easy route. Because Rust is a systems programming language, we can choose the
diff --git a/book-original/src/ch20-01-single-threaded.md b/book-pl-en/src/ch20-01-single-threaded.md
index b46d39f..5867b47 100644
--- a/book-original/src/ch20-01-single-threaded.md
+++ b/book-pl-en/src/ch20-01-single-threaded.md
@@ -38,7 +38,17 @@ an incoming stream, it will print `Connection established!`.
<span class="filename">Filename: src/main.rs</span>
```rust,no_run
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-01/src/main.rs}}
+use std::net::TcpListener;
+
+fn main() {
+ let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
+
+ for stream in listener.incoming() {
+ let stream = stream.unwrap();
+
+ println!("Connection established!");
+ }
+}
```
<span class="caption">Listing 20-1: Listening for incoming streams and printing
@@ -130,7 +140,27 @@ look like Listing 20-2.
<span class="filename">Filename: src/main.rs</span>
```rust,no_run
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-02/src/main.rs}}
+use std::io::prelude::*;
+use std::net::TcpStream;
+use std::net::TcpListener;
+
+fn main() {
+ let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
+
+ for stream in listener.incoming() {
+ let stream = stream.unwrap();
+
+ handle_connection(stream);
+ }
+}
+
+fn handle_connection(mut stream: TcpStream) {
+ let mut buffer = [0; 512];
+
+ stream.read(&mut buffer).unwrap();
+
+ println!("Request: {}", String::from_utf8_lossy(&buffer[..]));
+}
```
<span class="caption">Listing 20-2: Reading from the `TcpStream` and printing
@@ -170,7 +200,7 @@ program’s output in the terminal will now look similar to this:
```text
$ cargo run
Compiling hello v0.1.0 (file:///projects/hello)
- Finished dev [unoptimized + debuginfo] target(s) in 0.42s
+ Finished dev [unoptimized + debuginfo] target(s) in 0.42 secs
Running `target/debug/hello`
Request: GET / HTTP/1.1
Host: 127.0.0.1:7878
@@ -265,8 +295,19 @@ Listing 20-3.
<span class="filename">Filename: src/main.rs</span>
-```rust,no_run
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-03/src/main.rs:here}}
+```rust
+# use std::io::prelude::*;
+# use std::net::TcpStream;
+fn handle_connection(mut stream: TcpStream) {
+ let mut buffer = [0; 512];
+
+ stream.read(&mut buffer).unwrap();
+
+ let response = "HTTP/1.1 200 OK\r\n\r\n";
+
+ stream.write(response.as_bytes()).unwrap();
+ stream.flush().unwrap();
+}
```
<span class="caption">Listing 20-3: Writing a tiny successful HTTP response to
@@ -299,7 +340,17 @@ possibility.
<span class="filename">Filename: hello.html</span>
```html
-{{#include ../listings/ch20-web-server/listing-20-04/hello.html}}
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Hello!</title>
+ </head>
+ <body>
+ <h1>Hello!</h1>
+ <p>Hi from Rust</p>
+ </body>
+</html>
```
<span class="caption">Listing 20-4: A sample HTML file to return in a
@@ -312,15 +363,30 @@ and send it.
<span class="filename">Filename: src/main.rs</span>
-```rust,no_run
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-05/src/main.rs:here}}
+```rust
+# use std::io::prelude::*;
+# use std::net::TcpStream;
+use std::fs;
+// --snip--
+
+fn handle_connection(mut stream: TcpStream) {
+ let mut buffer = [0; 512];
+ stream.read(&mut buffer).unwrap();
+
+ let contents = fs::read_to_string("hello.html").unwrap();
+
+ let response = format!("HTTP/1.1 200 OK\r\n\r\n{}", contents);
+
+ stream.write(response.as_bytes()).unwrap();
+ stream.flush().unwrap();
+}
```
<span class="caption">Listing 20-5: Sending the contents of *hello.html* as the
body of the response</span>
-We’ve added a line at the top to bring the standard library’s filesystem module
-into scope. The code for reading the contents of a file to a string should look
+We’ve added a line at the top to bring the standard library’s `File` into
+scope. The code for opening a file and reading the contents should look
familiar; we used it in Chapter 12 when we read the contents of a file for our
I/O project in Listing 12-4.
@@ -349,12 +415,33 @@ received against what we know a request for */* looks like and adds `if` and
<span class="filename">Filename: src/main.rs</span>
-```rust,no_run
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-06/src/main.rs:here}}
+```rust
+# use std::io::prelude::*;
+# use std::net::TcpStream;
+# use std::fs;
+// --snip--
+
+fn handle_connection(mut stream: TcpStream) {
+ let mut buffer = [0; 512];
+ stream.read(&mut buffer).unwrap();
+
+ let get = b"GET / HTTP/1.1\r\n";
+
+ if buffer.starts_with(get) {
+ let contents = fs::read_to_string("hello.html").unwrap();
+
+ let response = format!("HTTP/1.1 200 OK\r\n\r\n{}", contents);
+
+ stream.write(response.as_bytes()).unwrap();
+ stream.flush().unwrap();
+ } else {
+ // some other request
+ }
+}
```
<span class="caption">Listing 20-6: Matching the request and handling requests
-to */* differently from other requests</span>
+to */* differently than other requests</span>
First, we hardcode the data corresponding to the */* request into the `get`
variable. Because we’re reading raw bytes into the buffer, we transform `get`
@@ -380,8 +467,24 @@ indicating the response to the end user.
<span class="filename">Filename: src/main.rs</span>
-```rust,no_run
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-07/src/main.rs:here}}
+```rust
+# use std::io::prelude::*;
+# use std::net::TcpStream;
+# use std::fs;
+# fn handle_connection(mut stream: TcpStream) {
+# if true {
+// --snip--
+
+} else {
+ let status_line = "HTTP/1.1 404 NOT FOUND\r\n\r\n";
+ let contents = fs::read_to_string("404.html").unwrap();
+
+ let response = format!("{}{}", status_line, contents);
+
+ stream.write(response.as_bytes()).unwrap();
+ stream.flush().unwrap();
+}
+# }
```
<span class="caption">Listing 20-7: Responding with status code 404 and an
@@ -396,7 +499,17 @@ any HTML you want or use the example HTML in Listing 20-8.
<span class="filename">Filename: 404.html</span>
```html
-{{#include ../listings/ch20-web-server/listing-20-08/404.html}}
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Hello!</title>
+ </head>
+ <body>
+ <h1>Oops!</h1>
+ <p>Sorry, I don't know what you're asking for.</p>
+ </body>
+</html>
```
<span class="caption">Listing 20-8: Sample content for the page to send back
@@ -419,8 +532,32 @@ the large `if` and `else` blocks.
<span class="filename">Filename: src/main.rs</span>
-```rust,no_run
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-09/src/main.rs:here}}
+```rust
+# use std::io::prelude::*;
+# use std::net::TcpStream;
+# use std::fs;
+// --snip--
+
+fn handle_connection(mut stream: TcpStream) {
+# let mut buffer = [0; 512];
+# stream.read(&mut buffer).unwrap();
+#
+# let get = b"GET / HTTP/1.1\r\n";
+ // --snip--
+
+ let (status_line, filename) = if buffer.starts_with(get) {
+ ("HTTP/1.1 200 OK\r\n\r\n", "hello.html")
+ } else {
+ ("HTTP/1.1 404 NOT FOUND\r\n\r\n", "404.html")
+ };
+
+ let contents = fs::read_to_string(filename).unwrap();
+
+ let response = format!("{}{}", status_line, contents);
+
+ stream.write(response.as_bytes()).unwrap();
+ stream.flush().unwrap();
+}
```
<span class="caption">Listing 20-9: Refactoring the `if` and `else` blocks to
diff --git a/book-original/src/ch20-02-multithreaded.md b/book-pl-en/src/ch20-02-multithreaded.md
index c0731d2..a604af3 100644
--- a/book-original/src/ch20-02-multithreaded.md
+++ b/book-pl-en/src/ch20-02-multithreaded.md
@@ -17,8 +17,33 @@ for 5 seconds before responding.
<span class="filename">Filename: src/main.rs</span>
-```rust,no_run
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-10/src/main.rs:here}}
+```rust
+use std::thread;
+use std::time::Duration;
+# use std::io::prelude::*;
+# use std::net::TcpStream;
+# use std::fs::File;
+// --snip--
+
+fn handle_connection(mut stream: TcpStream) {
+# let mut buffer = [0; 512];
+# stream.read(&mut buffer).unwrap();
+ // --snip--
+
+ let get = b"GET / HTTP/1.1\r\n";
+ let sleep = b"GET /sleep HTTP/1.1\r\n";
+
+ let (status_line, filename) = if buffer.starts_with(get) {
+ ("HTTP/1.1 200 OK\r\n\r\n", "hello.html")
+ } else if buffer.starts_with(sleep) {
+ thread::sleep(Duration::from_secs(5));
+ ("HTTP/1.1 200 OK\r\n\r\n", "hello.html")
+ } else {
+ ("HTTP/1.1 404 NOT FOUND\r\n\r\n", "404.html")
+ };
+
+ // --snip--
+}
```
<span class="caption">Listing 20-10: Simulating a slow request by recognizing
@@ -99,7 +124,23 @@ new thread to handle each stream within the `for` loop.
<span class="filename">Filename: src/main.rs</span>
```rust,no_run
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-11/src/main.rs:here}}
+# use std::thread;
+# use std::io::prelude::*;
+# use std::net::TcpListener;
+# use std::net::TcpStream;
+#
+fn main() {
+ let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
+
+ for stream in listener.incoming() {
+ let stream = stream.unwrap();
+
+ thread::spawn(|| {
+ handle_connection(stream);
+ });
+ }
+}
+# fn handle_connection(mut stream: TcpStream) {}
```
<span class="caption">Listing 20-11: Spawning a new thread for each
@@ -121,8 +162,31 @@ struct we want to use instead of `thread::spawn`.
<span class="filename">Filename: src/main.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-12/src/main.rs:here}}
+```rust,no_run
+# use std::thread;
+# use std::io::prelude::*;
+# use std::net::TcpListener;
+# use std::net::TcpStream;
+# struct ThreadPool;
+# impl ThreadPool {
+# fn new(size: u32) -> ThreadPool { ThreadPool }
+# fn execute<F>(&self, f: F)
+# where F: FnOnce() + Send + 'static {}
+# }
+#
+fn main() {
+ let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
+ let pool = ThreadPool::new(4);
+
+ for stream in listener.incoming() {
+ let stream = stream.unwrap();
+
+ pool.execute(|| {
+ handle_connection(stream);
+ });
+ }
+}
+# fn handle_connection(mut stream: TcpStream) {}
```
<span class="caption">Listing 20-12: Our ideal `ThreadPool` interface</span>
@@ -141,7 +205,16 @@ compiler errors from `cargo check` to drive our development. Here is the first
error we get:
```text
-{{#include ../listings/ch20-web-server/listing-20-12/output.txt}}
+$ cargo check
+ Compiling hello v0.1.0 (file:///projects/hello)
+error[E0433]: failed to resolve. Use of undeclared type or module `ThreadPool`
+ --> src\main.rs:10:16
+ |
+10 | let pool = ThreadPool::new(4);
+ | ^^^^^^^^^^^^^^^ Use of undeclared type or module
+ `ThreadPool`
+
+error: aborting due to previous error
```
Great! This error tells us we need a `ThreadPool` type or module, so we’ll
@@ -158,7 +231,7 @@ definition of a `ThreadPool` struct that we can have for now:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/lib.rs}}
+pub struct ThreadPool;
```
Then create a new directory, *src/bin*, and move the binary crate rooted in
@@ -171,14 +244,22 @@ following code to the top of *src/bin/main.rs*:
<span class="filename">Filename: src/bin/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/bin/main.rs:here}}
+use hello::ThreadPool;
```
This code still won’t work, but let’s check it again to get the next error that
we need to address:
```text
-{{#include ../listings/ch20-web-server/no-listing-01-define-threadpool-struct/output.txt}}
+$ cargo check
+ Compiling hello v0.1.0 (file:///projects/hello)
+error[E0599]: no function or associated item named `new` found for type
+`hello::ThreadPool` in the current scope
+ --> src/bin/main.rs:13:16
+ |
+13 | let pool = ThreadPool::new(4);
+ | ^^^^^^^^^^^^^^^ function or associated item not found in
+ `hello::ThreadPool`
```
This error indicates that next we need to create an associated function named
@@ -190,7 +271,13 @@ characteristics:
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/lib.rs:here}}
+pub struct ThreadPool;
+
+impl ThreadPool {
+ pub fn new(size: usize) -> ThreadPool {
+ ThreadPool
+ }
+}
```
We chose `usize` as the type of the `size` parameter, because we know that a
@@ -202,11 +289,27 @@ ignore --> section of Chapter 3.
Let’s check the code again:
```text
-{{#include ../listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt}}
+$ cargo check
+ Compiling hello v0.1.0 (file:///projects/hello)
+warning: unused variable: `size`
+ --> src/lib.rs:4:16
+ |
+4 | pub fn new(size: usize) -> ThreadPool {
+ | ^^^^
+ |
+ = note: #[warn(unused_variables)] on by default
+ = note: to avoid this warning, consider using `_size` instead
+
+error[E0599]: no method named `execute` found for type `hello::ThreadPool` in the current scope
+ --> src/bin/main.rs:18:14
+ |
+18 | pool.execute(|| {
+ | ^^^^^^^
```
-Now the error occurs because we don’t have an `execute` method on `ThreadPool`.
-Recall from the [“Creating a Similar Interface for a Finite Number of
+Now we get a warning and an error. Ignoring the warning for a moment, the error
+occurs because we don’t have an `execute` method on `ThreadPool`. Recall from
+the [“Creating a Similar Interface for a Finite Number of
Threads”](#creating-a-similar-interface-for-a-finite-number-of-threads)<!--
ignore --> section that we decided our thread pool should have an interface
similar to `thread::spawn`. In addition, we’ll implement the `execute` function
@@ -247,11 +350,21 @@ the thread will take to execute. Let’s create an `execute` method on
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch20-web-server/no-listing-03-define-execute/src/lib.rs:here}}
+# pub struct ThreadPool;
+impl ThreadPool {
+ // --snip--
+
+ pub fn execute<F>(&self, f: F)
+ where
+ F: FnOnce() + Send + 'static
+ {
+
+ }
+}
```
We still use the `()` after `FnOnce` because this `FnOnce` represents a closure
-that takes no parameters and returns the unit type `()`. Just like function
+that takes no parameters and doesn’t return a value. Just like function
definitions, the return type can be omitted from the signature, but even if we
have no parameters, we still need the parentheses.
@@ -259,13 +372,30 @@ Again, this is the simplest implementation of the `execute` method: it does
nothing, but we’re trying only to make our code compile. Let’s check it again:
```text
-{{#include ../listings/ch20-web-server/no-listing-03-define-execute/output.txt}}
+$ cargo check
+ Compiling hello v0.1.0 (file:///projects/hello)
+warning: unused variable: `size`
+ --> src/lib.rs:4:16
+ |
+4 | pub fn new(size: usize) -> ThreadPool {
+ | ^^^^
+ |
+ = note: #[warn(unused_variables)] on by default
+ = note: to avoid this warning, consider using `_size` instead
+
+warning: unused variable: `f`
+ --> src/lib.rs:8:30
+ |
+8 | pub fn execute<F>(&self, f: F)
+ | ^
+ |
+ = note: to avoid this warning, consider using `_f` instead
```
-It compiles! But note that if you try `cargo run` and make a request in the
-browser, you’ll see the errors in the browser that we saw at the beginning of
-the chapter. Our library isn’t actually calling the closure passed to `execute`
-yet!
+We’re receiving only warnings now, which means it compiles! But note that if
+you try `cargo run` and make a request in the browser, you’ll see the errors in
+the browser that we saw at the beginning of the chapter. Our library isn’t
+actually calling the closure passed to `execute` yet!
> Note: A saying you might hear about languages with strict compilers, such as
> Haskell and Rust, is “if the code compiles, it works.” But this saying is not
@@ -276,19 +406,36 @@ yet!
#### Validating the Number of Threads in `new`
-We aren’t doing anything with the parameters to `new` and `execute`. Let’s
-implement the bodies of these functions with the behavior we want. To start,
-let’s think about `new`. Earlier we chose an unsigned type for the `size`
-parameter, because a pool with a negative number of threads makes no sense.
-However, a pool with zero threads also makes no sense, yet zero is a perfectly
-valid `usize`. We’ll add code to check that `size` is greater than zero before
-we return a `ThreadPool` instance and have the program panic if it receives a
-zero by using the `assert!` macro, as shown in Listing 20-13.
+We’ll continue to get warnings because we aren’t doing anything with the
+parameters to `new` and `execute`. Let’s implement the bodies of these
+functions with the behavior we want. To start, let’s think about `new`. Earlier
+we chose an unsigned type for the `size` parameter, because a pool with a
+negative number of threads makes no sense. However, a pool with zero threads
+also makes no sense, yet zero is a perfectly valid `usize`. We’ll add code to
+check that `size` is greater than zero before we return a `ThreadPool` instance
+and have the program panic if it receives a zero by using the `assert!` macro,
+as shown in Listing 20-13.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-13/src/lib.rs:here}}
+# pub struct ThreadPool;
+impl ThreadPool {
+ /// Create a new ThreadPool.
+ ///
+ /// The size is the number of threads in the pool.
+ ///
+ /// # Panics
+ ///
+ /// The `new` function will panic if the size is zero.
+ pub fn new(size: usize) -> ThreadPool {
+ assert!(size > 0);
+
+ ThreadPool
+ }
+
+ // --snip--
+}
```
<span class="caption">Listing 20-13: Implementing `ThreadPool::new` to panic if
@@ -339,7 +486,30 @@ returned a `ThreadPool` instance containing them.
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore,not_desired_behavior
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-14/src/lib.rs:here}}
+use std::thread;
+
+pub struct ThreadPool {
+ threads: Vec<thread::JoinHandle<()>>,
+}
+
+impl ThreadPool {
+ // --snip--
+ pub fn new(size: usize) -> ThreadPool {
+ assert!(size > 0);
+
+ let mut threads = Vec::with_capacity(size);
+
+ for _ in 0..size {
+ // create some threads and store them in the vector
+ }
+
+ ThreadPool {
+ threads
+ }
+ }
+
+ // --snip--
+}
```
<span class="caption">Listing 20-14: Creating a vector for `ThreadPool` to hold
@@ -405,7 +575,45 @@ Ready? Here is Listing 20-15 with one way to make the preceding modifications.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-15/src/lib.rs:here}}
+use std::thread;
+
+pub struct ThreadPool {
+ workers: Vec<Worker>,
+}
+
+impl ThreadPool {
+ // --snip--
+ pub fn new(size: usize) -> ThreadPool {
+ assert!(size > 0);
+
+ let mut workers = Vec::with_capacity(size);
+
+ for id in 0..size {
+ workers.push(Worker::new(id));
+ }
+
+ ThreadPool {
+ workers
+ }
+ }
+ // --snip--
+}
+
+struct Worker {
+ id: usize,
+ thread: thread::JoinHandle<()>,
+}
+
+impl Worker {
+ fn new(id: usize) -> Worker {
+ let thread = thread::spawn(|| {});
+
+ Worker {
+ id,
+ thread,
+ }
+ }
+}
```
<span class="caption">Listing 20-15: Modifying `ThreadPool` to hold `Worker`
@@ -460,7 +668,53 @@ the channel.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-16/src/lib.rs:here}}
+# use std::thread;
+// --snip--
+use std::sync::mpsc;
+
+pub struct ThreadPool {
+ workers: Vec<Worker>,
+ sender: mpsc::Sender<Job>,
+}
+
+struct Job;
+
+impl ThreadPool {
+ // --snip--
+ pub fn new(size: usize) -> ThreadPool {
+ assert!(size > 0);
+
+ let (sender, receiver) = mpsc::channel();
+
+ let mut workers = Vec::with_capacity(size);
+
+ for id in 0..size {
+ workers.push(Worker::new(id));
+ }
+
+ ThreadPool {
+ workers,
+ sender,
+ }
+ }
+ // --snip--
+}
+#
+# struct Worker {
+# id: usize,
+# thread: thread::JoinHandle<()>,
+# }
+#
+# impl Worker {
+# fn new(id: usize) -> Worker {
+# let thread = thread::spawn(|| {});
+#
+# Worker {
+# id,
+# thread,
+# }
+# }
+# }
```
<span class="caption">Listing 20-16: Modifying `ThreadPool` to store the
@@ -477,7 +731,41 @@ the closure. The code in Listing 20-17 won’t quite compile yet.
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-17/src/lib.rs:here}}
+impl ThreadPool {
+ // --snip--
+ pub fn new(size: usize) -> ThreadPool {
+ assert!(size > 0);
+
+ let (sender, receiver) = mpsc::channel();
+
+ let mut workers = Vec::with_capacity(size);
+
+ for id in 0..size {
+ workers.push(Worker::new(id, receiver));
+ }
+
+ ThreadPool {
+ workers,
+ sender,
+ }
+ }
+ // --snip--
+}
+
+// --snip--
+
+impl Worker {
+ fn new(id: usize, receiver: mpsc::Receiver<Job>) -> Worker {
+ let thread = thread::spawn(|| {
+ receiver;
+ });
+
+ Worker {
+ id,
+ thread,
+ }
+ }
+}
```
<span class="caption">Listing 20-17: Passing the receiving end of the channel
@@ -489,7 +777,17 @@ the channel into `Worker::new`, and then we use it inside the closure.
When we try to check this code, we get this error:
```text
-{{#include ../listings/ch20-web-server/listing-20-17/output.txt}}
+$ cargo check
+ Compiling hello v0.1.0 (file:///projects/hello)
+error[E0382]: use of moved value: `receiver`
+ --> src/lib.rs:27:42
+ |
+27 | workers.push(Worker::new(id, receiver));
+ | ^^^^^^^^ value moved here in
+ previous iteration of loop
+ |
+ = note: move occurs because `receiver` has type
+ `std::sync::mpsc::Receiver<Job>`, which does not implement the `Copy` trait
```
The code is trying to pass `receiver` to multiple `Worker` instances. This
@@ -512,7 +810,60 @@ receiver at a time. Listing 20-18 shows the changes we need to make.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-18/src/lib.rs:here}}
+# use std::thread;
+# use std::sync::mpsc;
+use std::sync::Arc;
+use std::sync::Mutex;
+// --snip--
+
+# pub struct ThreadPool {
+# workers: Vec<Worker>,
+# sender: mpsc::Sender<Job>,
+# }
+# struct Job;
+#
+impl ThreadPool {
+ // --snip--
+ pub fn new(size: usize) -> ThreadPool {
+ assert!(size > 0);
+
+ let (sender, receiver) = mpsc::channel();
+
+ let receiver = Arc::new(Mutex::new(receiver));
+
+ let mut workers = Vec::with_capacity(size);
+
+ for id in 0..size {
+ workers.push(Worker::new(id, Arc::clone(&receiver)));
+ }
+
+ ThreadPool {
+ workers,
+ sender,
+ }
+ }
+
+ // --snip--
+}
+
+# struct Worker {
+# id: usize,
+# thread: thread::JoinHandle<()>,
+# }
+#
+impl Worker {
+ fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
+ // --snip--
+# let thread = thread::spawn(|| {
+# receiver;
+# });
+#
+# Worker {
+# id,
+# thread,
+# }
+ }
+}
```
<span class="caption">Listing 20-18: Sharing the receiving end of the channel
@@ -536,7 +887,30 @@ at Listing 20-19.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-19/src/lib.rs:here}}
+// --snip--
+# pub struct ThreadPool {
+# workers: Vec<Worker>,
+# sender: mpsc::Sender<Job>,
+# }
+# use std::sync::mpsc;
+# struct Worker {}
+
+type Job = Box<FnOnce() + Send + 'static>;
+
+impl ThreadPool {
+ // --snip--
+
+ pub fn execute<F>(&self, f: F)
+ where
+ F: FnOnce() + Send + 'static
+ {
+ let job = Box::new(f);
+
+ self.sender.send(job).unwrap();
+ }
+}
+
+// --snip--
```
<span class="caption">Listing 20-19: Creating a `Job` type alias for a `Box`
@@ -559,8 +933,27 @@ shown in Listing 20-20 to `Worker::new`.
<span class="filename">Filename: src/lib.rs</span>
-```rust
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-20/src/lib.rs:here}}
+```rust,ignore,does_not_compile
+// --snip--
+
+impl Worker {
+ fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
+ let thread = thread::spawn(move || {
+ loop {
+ let job = receiver.lock().unwrap().recv().unwrap();
+
+ println!("Worker {} got a job; executing.", id);
+
+ (*job)();
+ }
+ });
+
+ Worker {
+ id,
+ thread,
+ }
+ }
+}
```
<span class="caption">Listing 20-20: Receiving and executing the jobs in the
@@ -583,41 +976,142 @@ The call to `recv` blocks, so if there is no job yet, the current thread will
wait until a job becomes available. The `Mutex<T>` ensures that only one
`Worker` thread at a time is trying to request a job.
+Theoretically, this code should compile. Unfortunately, the Rust compiler isn’t
+perfect yet, and we get this error:
+
+```text
+error[E0161]: cannot move a value of type std::ops::FnOnce() +
+std::marker::Send: the size of std::ops::FnOnce() + std::marker::Send cannot be
+statically determined
+ --> src/lib.rs:63:17
+ |
+63 | (*job)();
+ | ^^^^^^
+```
+
+This error is fairly cryptic because the problem is fairly cryptic. To call a
+`FnOnce` closure that is stored in a `Box<T>` (which is what our `Job` type
+alias is), the closure needs to move itself *out* of the `Box<T>` because the
+closure takes ownership of `self` when we call it. In general, Rust doesn’t
+allow us to move a value out of a `Box<T>` because Rust doesn’t know how big
+the value inside the `Box<T>` will be: recall in Chapter 15 that we used
+`Box<T>` precisely because we had something of an unknown size that we wanted
+to store in a `Box<T>` to get a value of a known size.
+
+As you saw in Listing 17-15, we can write methods that use the syntax `self:
+Box<Self>`, which allows the method to take ownership of a `Self` value stored
+in a `Box<T>`. That’s exactly what we want to do here, but unfortunately Rust
+won’t let us: the part of Rust that implements behavior when a closure is
+called isn’t implemented using `self: Box<Self>`. So Rust doesn’t yet
+understand that it could use `self: Box<Self>` in this situation to take
+ownership of the closure and move the closure out of the `Box<T>`.
+
+Rust is still a work in progress with places where the compiler could be
+improved, but in the future, the code in Listing 20-20 should work just fine.
+People just like you are working to fix this and other issues! After you’ve
+finished this book, we would love for you to join in.
+
+But for now, let’s work around this problem using a handy trick. We can tell
+Rust explicitly that in this case we can take ownership of the value inside the
+`Box<T>` using `self: Box<Self>`; then, once we have ownership of the closure,
+we can call it. This involves defining a new trait `FnBox` with the method
+`call_box` that will use `self: Box<Self>` in its signature, defining `FnBox`
+for any type that implements `FnOnce()`, changing our type alias to use the new
+trait, and changing `Worker` to use the `call_box` method. These changes are
+shown in Listing 20-21.
+
+<span class="filename">Filename: src/lib.rs</span>
+
+```rust,ignore
+trait FnBox {
+ fn call_box(self: Box<Self>);
+}
+
+impl<F: FnOnce()> FnBox for F {
+ fn call_box(self: Box<F>) {
+ (*self)()
+ }
+}
+
+type Job = Box<FnBox + Send + 'static>;
+
+// --snip--
+
+impl Worker {
+ fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
+ let thread = thread::spawn(move || {
+ loop {
+ let job = receiver.lock().unwrap().recv().unwrap();
+
+ println!("Worker {} got a job; executing.", id);
+
+ job.call_box();
+ }
+ });
+
+ Worker {
+ id,
+ thread,
+ }
+ }
+}
+```
+
+<span class="caption">Listing 20-21: Adding a new trait `FnBox` to work around
+the current limitations of `Box<FnOnce()>`</span>
+
+First, we create a new trait named `FnBox`. This trait has the one method
+`call_box`, which is similar to the `call` methods on the other `Fn*` traits
+except that it takes `self: Box<Self>` to take ownership of `self` and move the
+value out of the `Box<T>`.
+
+Next, we implement the `FnBox` trait for any type `F` that implements the
+`FnOnce()` trait. Effectively, this means that any `FnOnce()` closures can use
+our `call_box` method. The implementation of `call_box` uses `(*self)()` to
+move the closure out of the `Box<T>` and call the closure.
+
+We now need our `Job` type alias to be a `Box` of anything that implements our
+new trait `FnBox`. This will allow us to use `call_box` in `Worker` when we get
+a `Job` value instead of invoking the closure directly. Implementing the
+`FnBox` trait for any `FnOnce()` closure means we don’t have to change anything
+about the actual values we’re sending down the channel. Now Rust is able to
+recognize that what we want to do is fine.
+
+This trick is very sneaky and complicated. Don’t worry if it doesn’t make
+perfect sense; someday, it will be completely unnecessary.
+
With the implementation of this trick, our thread pool is in a working state!
Give it a `cargo run` and make some requests:
-<!-- manual-regeneration
-cd listings/ch20-web-server/listing-20-20
-cargo run
-make some requests to 127.0.0.1:7878
-Can't automate because the output depends on making requests
--->
-
```text
$ cargo run
Compiling hello v0.1.0 (file:///projects/hello)
-warning: field is never read: `workers`
+warning: field is never used: `workers`
--> src/lib.rs:7:5
|
7 | workers: Vec<Worker>,
| ^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(dead_code)]` on by default
+ = note: #[warn(dead_code)] on by default
-warning: field is never read: `id`
- --> src/lib.rs:48:5
+warning: field is never used: `id`
+ --> src/lib.rs:61:5
|
-48 | id: usize,
+61 | id: usize,
| ^^^^^^^^^
+ |
+ = note: #[warn(dead_code)] on by default
-warning: field is never read: `thread`
- --> src/lib.rs:49:5
+warning: field is never used: `thread`
+ --> src/lib.rs:62:5
|
-49 | thread: thread::JoinHandle<()>,
+62 | thread: thread::JoinHandle<()>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: #[warn(dead_code)] on by default
- Finished dev [unoptimized + debuginfo] target(s) in 1.40s
- Running `target/debug/main`
+ Finished dev [unoptimized + debuginfo] target(s) in 0.99 secs
+ Running `target/debug/hello`
Worker 0 got a job; executing.
Worker 2 got a job; executing.
Worker 1 got a job; executing.
@@ -636,21 +1130,38 @@ overloaded if the server receives a lot of requests. If we make a request to
*/sleep*, the server will be able to serve other requests by having another
thread run them.
-> Note: if you open */sleep* in multiple browser windows simultaneously, they
-> might load one at a time in 5 second intervals. Some web browsers execute
-> multiple instances of the same request sequentially for caching reasons. This
-> limitation is not caused by our web server.
+Note that if you open */sleep* in multiple browser windows simultaneously, they
+might load 5 seconds apart from each other, because some web browsers execute
+multiple instances of the same request sequentially for caching reasons. This
+limitation is not caused by our web server.
After learning about the `while let` loop in Chapter 18, you might be wondering
-why we didn’t write the worker thread code as shown in Listing 20-21.
+why we didn’t write the worker thread code as shown in Listing 20-22.
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore,not_desired_behavior
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-21/src/lib.rs:here}}
+// --snip--
+
+impl Worker {
+ fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
+ let thread = thread::spawn(move || {
+ while let Ok(job) = receiver.lock().unwrap().recv() {
+ println!("Worker {} got a job; executing.", id);
+
+ job.call_box();
+ }
+ });
+
+ Worker {
+ id,
+ thread,
+ }
+ }
+}
```
-<span class="caption">Listing 20-21: An alternative implementation of
+<span class="caption">Listing 20-22: An alternative implementation of
`Worker::new` using `while let`</span>
This code compiles and runs but doesn’t result in the desired threading
@@ -662,15 +1173,15 @@ method returns. At compile time, the borrow checker can then enforce the rule
that a resource guarded by a `Mutex` cannot be accessed unless we hold the
lock. But this implementation can also result in the lock being held longer
than intended if we don’t think carefully about the lifetime of the
-`MutexGuard<T>`. Because the values in the `while let` expression remain in
-scope for the duration of the block, the lock remains held for the duration of
-the call to `job()`, meaning other workers cannot receive jobs.
-
-By using `loop` instead and acquiring the lock without assigning to a variable,
-the temporary `MutexGuard` returned from the `lock` method is dropped as soon
-as the `let job` statement ends. This ensures that the lock is held during the
-call to `recv`, but it is released before the call to `job()`, allowing
-multiple requests to be serviced concurrently.
+`MutexGuard<T>`. Because the values in the `while` expression remain in scope
+for the duration of the block, the lock remains held for the duration of the
+call to `job.call_box()`, meaning other workers cannot receive jobs.
+
+By using `loop` instead and acquiring the lock and a job within the block
+rather than outside it, the `MutexGuard` returned from the `lock` method is
+dropped as soon as the `let job` statement ends. This ensures that the lock is
+held during the call to `recv`, but it is released before the call to
+`job.call_box()`, allowing multiple requests to be serviced concurrently.
[creating-type-synonyms-with-type-aliases]:
ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases
diff --git a/book-original/src/ch20-03-graceful-shutdown-and-cleanup.md b/book-pl-en/src/ch20-03-graceful-shutdown-and-cleanup.md
index 13df049..c083135 100644
--- a/book-original/src/ch20-03-graceful-shutdown-and-cleanup.md
+++ b/book-pl-en/src/ch20-03-graceful-shutdown-and-cleanup.md
@@ -1,6 +1,6 @@
## Graceful Shutdown and Cleanup
-The code in Listing 20-20 is responding to requests asynchronously through the
+The code in Listing 20-21 is responding to requests asynchronously through the
use of a thread pool, as we intended. We get some warnings about the `workers`,
`id`, and `thread` fields that we’re not using in a direct way that reminds us
we’re not cleaning up anything. When we use the less elegant <span
@@ -18,16 +18,24 @@ accept only two requests before gracefully shutting down its thread pool.
Let’s start with implementing `Drop` on our thread pool. When the pool is
dropped, our threads should all join to make sure they finish their work.
-Listing 20-22 shows a first attempt at a `Drop` implementation; this code won’t
+Listing 20-23 shows a first attempt at a `Drop` implementation; this code won’t
quite work yet.
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-22/src/lib.rs:here}}
+impl Drop for ThreadPool {
+ fn drop(&mut self) {
+ for worker in &mut self.workers {
+ println!("Shutting down worker {}", worker.id);
+
+ worker.thread.join().unwrap();
+ }
+ }
+}
```
-<span class="caption">Listing 20-22: Joining each thread when the thread pool
+<span class="caption">Listing 20-23: Joining each thread when the thread pool
goes out of scope</span>
First, we loop through each of the thread pool `workers`. We use `&mut` for
@@ -40,7 +48,11 @@ into an ungraceful shutdown.
Here is the error we get when we compile this code:
```text
-{{#include ../listings/ch20-web-server/listing-20-22/output.txt}}
+error[E0507]: cannot move out of borrowed content
+ --> src/lib.rs:65:13
+ |
+65 | worker.thread.join().unwrap();
+ | ^^^^^^ cannot move out of borrowed content
```
The error tells us we can’t call `join` because we only have a mutable borrow
@@ -58,15 +70,37 @@ So we know we want to update the definition of `Worker` like this:
<span class="filename">Filename: src/lib.rs</span>
-```rust,ignore,does_not_compile
-{{#rustdoc_include ../listings/ch20-web-server/no-listing-04-update-worker-definition/src/lib.rs:here}}
+```rust
+# use std::thread;
+struct Worker {
+ id: usize,
+ thread: Option<thread::JoinHandle<()>>,
+}
```
Now let’s lean on the compiler to find the other places that need to change.
Checking this code, we get two errors:
```text
-{{#include ../listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt}}
+error[E0599]: no method named `join` found for type
+`std::option::Option<std::thread::JoinHandle<()>>` in the current scope
+ --> src/lib.rs:65:27
+ |
+65 | worker.thread.join().unwrap();
+ | ^^^^
+
+error[E0308]: mismatched types
+ --> src/lib.rs:89:13
+ |
+89 | thread,
+ | ^^^^^^
+ | |
+ | expected enum `std::option::Option`, found struct
+ `std::thread::JoinHandle`
+ | help: try using a variant of the expected type: `Some(thread)`
+ |
+ = note: expected type `std::option::Option<std::thread::JoinHandle<()>>`
+ found type `std::thread::JoinHandle<_>`
```
Let’s address the second error, which points to the code at the end of
@@ -76,7 +110,16 @@ new `Worker`. Make the following changes to fix this error:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch20-web-server/no-listing-05-fix-worker-new/src/lib.rs:here}}
+impl Worker {
+ fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
+ // --snip--
+
+ Worker {
+ id,
+ thread: Some(thread),
+ }
+ }
+}
```
The first error is in our `Drop` implementation. We mentioned earlier that we
@@ -86,7 +129,17 @@ The following changes will do so:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/lib.rs:here}}
+impl Drop for ThreadPool {
+ fn drop(&mut self) {
+ for worker in &mut self.workers {
+ println!("Shutting down worker {}", worker.id);
+
+ if let Some(thread) = worker.thread.take() {
+ thread.join().unwrap();
+ }
+ }
+ }
+}
```
As discussed in Chapter 17, the `take` method on `Option` takes the `Some`
@@ -113,7 +166,11 @@ variants.
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch20-web-server/no-listing-07-define-message-enum/src/lib.rs:here}}
+# struct Job;
+enum Message {
+ NewJob(Job),
+ Terminate,
+}
```
This `Message` enum will either be a `NewJob` variant that holds the `Job` the
@@ -121,15 +178,65 @@ thread should run, or it will be a `Terminate` variant that will cause the
thread to exit its loop and stop.
We need to adjust the channel to use values of type `Message` rather than type
-`Job`, as shown in Listing 20-23.
+`Job`, as shown in Listing 20-24.
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-23/src/lib.rs:here}}
+pub struct ThreadPool {
+ workers: Vec<Worker>,
+ sender: mpsc::Sender<Message>,
+}
+
+// --snip--
+
+impl ThreadPool {
+ // --snip--
+
+ pub fn execute<F>(&self, f: F)
+ where
+ F: FnOnce() + Send + 'static
+ {
+ let job = Box::new(f);
+
+ self.sender.send(Message::NewJob(job)).unwrap();
+ }
+}
+
+// --snip--
+
+impl Worker {
+ fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Message>>>) ->
+ Worker {
+
+ let thread = thread::spawn(move ||{
+ loop {
+ let message = receiver.lock().unwrap().recv().unwrap();
+
+ match message {
+ Message::NewJob(job) => {
+ println!("Worker {} got a job; executing.", id);
+
+ job.call_box();
+ },
+ Message::Terminate => {
+ println!("Worker {} was told to terminate.", id);
+
+ break;
+ },
+ }
+ }
+ });
+
+ Worker {
+ id,
+ thread: Some(thread),
+ }
+ }
+}
```
-<span class="caption">Listing 20-23: Sending and receiving `Message` values and
+<span class="caption">Listing 20-24: Sending and receiving `Message` values and
exiting the loop if a `Worker` receives `Message::Terminate`</span>
To incorporate the `Message` enum, we need to change `Job` to `Message` in two
@@ -141,17 +248,35 @@ received, and the thread will break out of the loop if the `Terminate` variant
is received.
With these changes, the code will compile and continue to function in the same
-way as it did after Listing 20-20. But we’ll get a warning because we aren’t
+way as it did after Listing 20-21. But we’ll get a warning because we aren’t
creating any messages of the `Terminate` variety. Let’s fix this warning by
-changing our `Drop` implementation to look like Listing 20-24.
+changing our `Drop` implementation to look like Listing 20-25.
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-24/src/lib.rs:here}}
+impl Drop for ThreadPool {
+ fn drop(&mut self) {
+ println!("Sending terminate message to all workers.");
+
+ for _ in &mut self.workers {
+ self.sender.send(Message::Terminate).unwrap();
+ }
+
+ println!("Shutting down all workers.");
+
+ for worker in &mut self.workers {
+ println!("Shutting down worker {}", worker.id);
+
+ if let Some(thread) = worker.thread.take() {
+ thread.join().unwrap();
+ }
+ }
+ }
+}
```
-<span class="caption">Listing 20-24: Sending `Message::Terminate` to the
+<span class="caption">Listing 20-25: Sending `Message::Terminate` to the
workers before calling `join` on each worker thread</span>
We’re now iterating over the workers twice: once to send one `Terminate`
@@ -177,15 +302,28 @@ messages as there are workers, each worker will receive a terminate message
before `join` is called on its thread.
To see this code in action, let’s modify `main` to accept only two requests
-before gracefully shutting down the server, as shown in Listing 20-25.
+before gracefully shutting down the server, as shown in Listing 20-26.
<span class="filename">Filename: src/bin/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-25/src/bin/main.rs:here}}
+fn main() {
+ let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
+ let pool = ThreadPool::new(4);
+
+ for stream in listener.incoming().take(2) {
+ let stream = stream.unwrap();
+
+ pool.execute(|| {
+ handle_connection(stream);
+ });
+ }
+
+ println!("Shutting down.");
+}
```
-<span class="caption">Listing 20-25: Shut down the server after serving two
+<span class="caption">Listing 20-26: Shut down the server after serving two
requests by exiting the loop</span>
You wouldn’t want a real-world web server to shut down after serving only two
@@ -199,22 +337,11 @@ end of `main`, and the `drop` implementation will run.
Start the server with `cargo run`, and make three requests. The third request
should error, and in your terminal you should see output similar to this:
-<!-- manual-regeneration
-cd listings/ch20-web-server/listing-20-25
-cargo run
-curl http://127.0.0.1:7878
-curl http://127.0.0.1:7878
-curl http://127.0.0.1:7878
-third request will error because server will have shut down
-copy output below
-Can't automate because the output depends on making requests
--->
-
```text
$ cargo run
Compiling hello v0.1.0 (file:///projects/hello)
- Finished dev [unoptimized + debuginfo] target(s) in 1.0s
- Running `target/debug/main`
+ Finished dev [unoptimized + debuginfo] target(s) in 1.0 secs
+ Running `target/debug/hello`
Worker 0 got a job; executing.
Worker 3 got a job; executing.
Shutting down.
@@ -256,13 +383,176 @@ Here’s the full code for reference:
<span class="filename">Filename: src/bin/main.rs</span>
```rust,ignore
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-25/src/bin/main.rs:all}}
+use hello::ThreadPool;
+
+use std::io::prelude::*;
+use std::net::TcpListener;
+use std::net::TcpStream;
+use std::fs;
+use std::thread;
+use std::time::Duration;
+
+fn main() {
+ let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
+ let pool = ThreadPool::new(4);
+
+ for stream in listener.incoming().take(2) {
+ let stream = stream.unwrap();
+
+ pool.execute(|| {
+ handle_connection(stream);
+ });
+ }
+
+ println!("Shutting down.");
+}
+
+fn handle_connection(mut stream: TcpStream) {
+ let mut buffer = [0; 512];
+ stream.read(&mut buffer).unwrap();
+
+ let get = b"GET / HTTP/1.1\r\n";
+ let sleep = b"GET /sleep HTTP/1.1\r\n";
+
+ let (status_line, filename) = if buffer.starts_with(get) {
+ ("HTTP/1.1 200 OK\r\n\r\n", "hello.html")
+ } else if buffer.starts_with(sleep) {
+ thread::sleep(Duration::from_secs(5));
+ ("HTTP/1.1 200 OK\r\n\r\n", "hello.html")
+ } else {
+ ("HTTP/1.1 404 NOT FOUND\r\n\r\n", "404.html")
+ };
+
+ let contents = fs::read_to_string(filename).unwrap();
+
+ let response = format!("{}{}", status_line, contents);
+
+ stream.write(response.as_bytes()).unwrap();
+ stream.flush().unwrap();
+}
```
<span class="filename">Filename: src/lib.rs</span>
```rust
-{{#rustdoc_include ../listings/ch20-web-server/listing-20-25/src/lib.rs:here}}
+use std::thread;
+use std::sync::mpsc;
+use std::sync::Arc;
+use std::sync::Mutex;
+
+enum Message {
+ NewJob(Job),
+ Terminate,
+}
+
+pub struct ThreadPool {
+ workers: Vec<Worker>,
+ sender: mpsc::Sender<Message>,
+}
+
+trait FnBox {
+ fn call_box(self: Box<Self>);
+}
+
+impl<F: FnOnce()> FnBox for F {
+ fn call_box(self: Box<F>) {
+ (*self)()
+ }
+}
+
+type Job = Box<dyn FnBox + Send + 'static>;
+
+impl ThreadPool {
+ /// Create a new ThreadPool.
+ ///
+ /// The size is the number of threads in the pool.
+ ///
+ /// # Panics
+ ///
+ /// The `new` function will panic if the size is zero.
+ pub fn new(size: usize) -> ThreadPool {
+ assert!(size > 0);
+
+ let (sender, receiver) = mpsc::channel();
+
+ let receiver = Arc::new(Mutex::new(receiver));
+
+ let mut workers = Vec::with_capacity(size);
+
+ for id in 0..size {
+ workers.push(Worker::new(id, Arc::clone(&receiver)));
+ }
+
+ ThreadPool {
+ workers,
+ sender,
+ }
+ }
+
+ pub fn execute<F>(&self, f: F)
+ where
+ F: FnOnce() + Send + 'static
+ {
+ let job = Box::new(f);
+
+ self.sender.send(Message::NewJob(job)).unwrap();
+ }
+}
+
+impl Drop for ThreadPool {
+ fn drop(&mut self) {
+ println!("Sending terminate message to all workers.");
+
+ for _ in &mut self.workers {
+ self.sender.send(Message::Terminate).unwrap();
+ }
+
+ println!("Shutting down all workers.");
+
+ for worker in &mut self.workers {
+ println!("Shutting down worker {}", worker.id);
+
+ if let Some(thread) = worker.thread.take() {
+ thread.join().unwrap();
+ }
+ }
+ }
+}
+
+struct Worker {
+ id: usize,
+ thread: Option<thread::JoinHandle<()>>,
+}
+
+impl Worker {
+ fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Message>>>) ->
+ Worker {
+
+ let thread = thread::spawn(move ||{
+ loop {
+ let message = receiver.lock().unwrap().recv().unwrap();
+
+ match message {
+ Message::NewJob(job) => {
+ println!("Worker {} got a job; executing.", id);
+
+ job.call_box();
+ },
+ Message::Terminate => {
+ println!("Worker {} was told to terminate.", id);
+
+ break;
+ },
+ }
+ }
+ });
+
+ Worker {
+ id,
+ thread: Some(thread),
+ }
+ }
+}
```
We could do more here! If you want to continue enhancing this project, here are
@@ -272,9 +562,9 @@ some ideas:
* Add tests of the library’s functionality.
* Change calls to `unwrap` to more robust error handling.
* Use `ThreadPool` to perform some task other than serving web requests.
-* Find a thread pool crate on [crates.io](https://crates.io/) and implement a
- similar web server using the crate instead. Then compare its API and
- robustness to the thread pool we implemented.
+* Find a thread pool crate on *https://crates.io/* and implement a similar web
+ server using the crate instead. Then compare its API and robustness to the
+ thread pool we implemented.
## Summary
diff --git a/book-original/src/img/trpl14-01.png b/book-pl-en/src/img/trpl14-01.png
index d7deaaf..5fc5989 100644
Binary files a/book-original/src/img/trpl14-01.png and b/book-pl-en/src/img/trpl14-01.png differ
diff --git a/book-original/src/img/trpl14-02.png b/book-pl-en/src/img/trpl14-02.png
index 121801b..78e7e7b 100644
Binary files a/book-original/src/img/trpl14-02.png and b/book-pl-en/src/img/trpl14-02.png differ
diff --git a/book-original/src/img/trpl14-03.png b/book-pl-en/src/img/trpl14-03.png
index cf5a15c..ef84145 100644
Binary files a/book-original/src/img/trpl14-03.png and b/book-pl-en/src/img/trpl14-03.png differ
diff --git a/book-original/src/img/trpl14-04.png b/book-pl-en/src/img/trpl14-04.png
index dc1caab..d0ed2ca 100644
Binary files a/book-original/src/img/trpl14-04.png and b/book-pl-en/src/img/trpl14-04.png differ
diff --git a/book-original/src/title-page.md b/book-original/src/title-page.md
deleted file mode 100644
index c1cb567..0000000
--- a/book-original/src/title-page.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# The Rust Programming Language
-
-*by Steve Klabnik and Carol Nichols, with contributions from the Rust Community*
-
-This version of the text assumes you’re using Rust 1.41.0 or later with
-`edition="2018"` in *Cargo.toml* of all projects to use Rust 2018 Edition
-idioms. See the [“Installation” section of Chapter 1][install]<!-- ignore -->
-to install or update Rust, and see the new [Appendix E][editions]<!-- ignore
---> for information on editions.
-
-The 2018 Edition of the Rust language includes a number of improvements that
-make Rust more ergonomic and easier to learn. This iteration of the book
-contains a number of changes to reflect those improvements:
-
-- Chapter 7, “Managing Growing Projects with Packages, Crates, and Modules,”
- has been mostly rewritten. The module system and the way paths work in the
- 2018 Edition were made more consistent.
-- Chapter 10 has new sections titled “Traits as Parameters” and “Returning
- Types that Implement Traits” that explain the new `impl Trait` syntax.
-- Chapter 11 has a new section titled “Using `Result<T, E>` in Tests” that
- shows how to write tests that use the `?` operator.
-- The “Advanced Lifetimes” section in Chapter 19 was removed because compiler
- improvements have made the constructs in that section even rarer.
-- The previous Appendix D, “Macros,” has been expanded to include procedural
- macros and was moved to the “Macros” section in Chapter 19.
-- Appendix A, “Keywords,” also explains the new raw identifiers feature that
- enables code written in the 2015 Edition and the 2018 Edition to interoperate.
-- Appendix D is now titled “Useful Development Tools” and covers recently
- released tools that help you write Rust code.
-- We fixed a number of small errors and imprecise wording throughout the book.
- Thank you to the readers who reported them!
-
-Note that any code in earlier iterations of *The Rust Programming Language*
-that compiled will continue to compile without `edition="2018"` in the
-project’s *Cargo.toml*, even as you update the Rust compiler version you’re
-using. That’s Rust’s backward compatibility guarantees at work!
-
-The HTML format is available online at
-[https://doc.rust-lang.org/stable/book/](https://doc.rust-lang.org/stable/book/)
-and offline with installations of Rust made with `rustup`; run `rustup docs
---book` to open.
-
-This text is available in [paperback and ebook format from No Starch
-Press][nsprust].
-
-[install]: ch01-01-installation.html
-[editions]: appendix-05-editions.html
-[nsprust]: https://nostarch.com/rust
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment