From 1b3bab9879721b915d5b4dca8554ade1d268062d Mon Sep 17 00:00:00 2001 From: funkill2 Date: Wed, 4 Dec 2024 04:00:14 +0300 Subject: [PATCH] update original --- rustbook-en/.git-blame-ignore-revs | 2 + rustbook-en/.gitignore | 2 + rustbook-en/ADMIN_TASKS.md | 47 ++-- rustbook-en/CONTRIBUTING.md | 3 +- rustbook-en/README.md | 7 +- rustbook-en/dprint.jsonc | 33 +++ rustbook-en/ferris.js | 68 ++--- .../packages/mdbook-trpl-note/README.md | 4 +- rustbook-en/packages/trpl/CHANGELOG.md | 2 +- rustbook-en/packages/trpl/README.md | 2 +- rustbook-en/src/SUMMARY.md | 172 ++++++------ rustbook-en/src/appendix-01-keywords.md | 106 +++---- rustbook-en/src/appendix-02-operators.md | 260 +++++++++--------- .../src/appendix-03-derivable-traits.md | 21 +- .../appendix-04-useful-development-tools.md | 2 +- rustbook-en/src/appendix-05-editions.md | 15 +- rustbook-en/src/appendix-07-nightly-rust.md | 25 +- rustbook-en/src/ch00-00-introduction.md | 16 +- rustbook-en/src/ch01-00-getting-started.md | 6 +- rustbook-en/src/ch01-01-installation.md | 4 +- rustbook-en/src/ch01-02-hello-world.md | 34 +-- rustbook-en/src/ch01-03-hello-cargo.md | 72 ++--- .../src/ch02-00-guessing-game-tutorial.md | 81 +++--- .../ch03-00-common-programming-concepts.md | 2 +- .../src/ch03-01-variables-and-mutability.md | 24 +- rustbook-en/src/ch03-02-data-types.md | 55 ++-- rustbook-en/src/ch03-03-how-functions-work.md | 26 +- rustbook-en/src/ch03-04-comments.md | 2 +- rustbook-en/src/ch03-05-control-flow.md | 30 +- rustbook-en/src/ch04-01-what-is-ownership.md | 70 ++--- .../src/ch04-02-references-and-borrowing.md | 32 +-- rustbook-en/src/ch04-03-slices.md | 11 +- rustbook-en/src/ch05-00-structs.md | 6 +- rustbook-en/src/ch05-01-defining-structs.md | 19 +- rustbook-en/src/ch05-02-example-structs.md | 12 +- rustbook-en/src/ch05-03-method-syntax.md | 11 +- rustbook-en/src/ch06-00-enums.md | 4 +- rustbook-en/src/ch06-01-defining-an-enum.md | 18 +- rustbook-en/src/ch06-02-match.md | 7 +- rustbook-en/src/ch06-03-if-let.md | 1 - ...ojects-with-packages-crates-and-modules.md | 12 +- .../src/ch07-01-packages-and-crates.md | 32 +-- ...ng-modules-to-control-scope-and-privacy.md | 44 +-- ...referring-to-an-item-in-the-module-tree.md | 12 +- ...g-paths-into-scope-with-the-use-keyword.md | 17 +- ...separating-modules-into-different-files.md | 38 +-- rustbook-en/src/ch08-00-common-collections.md | 10 +- rustbook-en/src/ch08-01-vectors.md | 2 +- rustbook-en/src/ch08-02-strings.md | 18 +- rustbook-en/src/ch08-03-hash-maps.md | 28 +- rustbook-en/src/ch09-00-error-handling.md | 4 +- ...ch09-01-unrecoverable-errors-with-panic.md | 22 +- .../ch09-02-recoverable-errors-with-result.md | 8 +- .../src/ch09-03-to-panic-or-not-to-panic.md | 20 +- rustbook-en/src/ch10-00-generics.md | 6 +- rustbook-en/src/ch10-01-syntax.md | 8 +- rustbook-en/src/ch10-02-traits.md | 15 +- rustbook-en/src/ch10-03-lifetime-syntax.md | 26 +- rustbook-en/src/ch11-00-testing.md | 2 +- rustbook-en/src/ch11-01-writing-tests.md | 29 +- rustbook-en/src/ch11-02-running-tests.md | 3 +- rustbook-en/src/ch11-03-test-organization.md | 71 +++-- rustbook-en/src/ch12-00-an-io-project.md | 10 +- rustbook-en/src/ch12-02-reading-a-file.md | 6 +- ...improving-error-handling-and-modularity.md | 68 ++--- ...2-04-testing-the-librarys-functionality.md | 19 +- ...2-05-working-with-environment-variables.md | 20 +- ...-06-writing-to-stderr-instead-of-stdout.md | 15 +- .../src/ch13-00-functional-features.md | 10 +- rustbook-en/src/ch13-01-closures.md | 7 +- rustbook-en/src/ch13-02-iterators.md | 10 +- .../src/ch13-03-improving-our-io-project.md | 4 +- rustbook-en/src/ch13-04-performance.md | 12 +- rustbook-en/src/ch14-00-more-about-cargo.md | 13 +- rustbook-en/src/ch14-01-release-profiles.md | 8 +- .../src/ch14-02-publishing-to-crates-io.md | 47 ++-- rustbook-en/src/ch14-03-cargo-workspaces.md | 66 ++--- .../src/ch14-04-installing-binaries.md | 12 +- rustbook-en/src/ch15-00-smart-pointers.md | 18 +- rustbook-en/src/ch15-01-box.md | 18 +- rustbook-en/src/ch15-02-deref.md | 17 +- rustbook-en/src/ch15-03-drop.md | 10 +- rustbook-en/src/ch15-04-rc.md | 2 +- .../src/ch15-05-interior-mutability.md | 22 +- rustbook-en/src/ch15-06-reference-cycles.md | 6 +- rustbook-en/src/ch16-00-concurrency.md | 26 +- rustbook-en/src/ch16-01-threads.md | 19 +- rustbook-en/src/ch16-02-message-passing.md | 27 +- rustbook-en/src/ch16-03-shared-state.md | 24 +- ...04-extensible-concurrency-sync-and-send.md | 5 +- rustbook-en/src/ch17-00-async-await.md | 24 +- rustbook-en/src/ch17-01-futures-and-syntax.md | 48 ++-- .../src/ch17-02-concurrency-with-async.md | 54 ++-- rustbook-en/src/ch17-03-more-futures.md | 68 +++-- rustbook-en/src/ch17-04-streams.md | 16 +- rustbook-en/src/ch17-05-traits-for-async.md | 36 +-- .../src/ch17-06-futures-tasks-threads.md | 21 +- rustbook-en/src/ch18-00-oop.md | 2 +- rustbook-en/src/ch18-01-what-is-oo.md | 18 +- rustbook-en/src/ch18-02-trait-objects.md | 26 +- rustbook-en/src/ch18-03-oo-design-patterns.md | 15 +- rustbook-en/src/ch19-00-patterns.md | 12 +- .../ch19-01-all-the-places-for-patterns.md | 5 +- rustbook-en/src/ch19-02-refutability.md | 4 +- rustbook-en/src/ch19-03-pattern-syntax.md | 16 +- rustbook-en/src/ch20-00-advanced-features.md | 10 +- rustbook-en/src/ch20-01-unsafe-rust.md | 67 +++-- rustbook-en/src/ch20-03-advanced-traits.md | 36 ++- rustbook-en/src/ch20-04-advanced-types.md | 29 +- ...ch20-05-advanced-functions-and-closures.md | 8 +- rustbook-en/src/ch20-06-macros.md | 36 +-- rustbook-en/src/ch21-01-single-threaded.md | 80 +++--- rustbook-en/src/ch21-02-multithreaded.md | 59 ++-- .../ch21-03-graceful-shutdown-and-cleanup.md | 10 +- rustbook-en/src/foreword.md | 2 +- rustbook-en/src/title-page.md | 4 +- rustbook-en/style-guide.md | 26 +- rustbook-en/theme/2018-edition.css | 8 +- rustbook-en/theme/listing.css | 6 +- rustbook-en/theme/semantic-notes.css | 12 +- 120 files changed, 1520 insertions(+), 1500 deletions(-) create mode 100644 rustbook-en/.git-blame-ignore-revs create mode 100644 rustbook-en/dprint.jsonc diff --git a/rustbook-en/.git-blame-ignore-revs b/rustbook-en/.git-blame-ignore-revs new file mode 100644 index 000000000..2bcb16231 --- /dev/null +++ b/rustbook-en/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Ran dprint fmt on the repo +3a30e4c1 diff --git a/rustbook-en/.gitignore b/rustbook-en/.gitignore index 17127d114..6bd6995e0 100644 --- a/rustbook-en/.gitignore +++ b/rustbook-en/.gitignore @@ -6,3 +6,5 @@ target tmp .nova +.vscode +.zed diff --git a/rustbook-en/ADMIN_TASKS.md b/rustbook-en/ADMIN_TASKS.md index c493a335c..b91b2ef96 100644 --- a/rustbook-en/ADMIN_TASKS.md +++ b/rustbook-en/ADMIN_TASKS.md @@ -14,7 +14,7 @@ occasional maintenance tasks. does) - Inspect the changes (by looking at the files changed according to git) and their effects (by looking at the files in `tmp/book-before` and - `tmp/book-after`) and commit them if they look good + `tmp/book-after`) and commit them if they look good - Grep for `manual-regeneration` and follow the instructions in those places to update output that cannot be generated by a script @@ -36,9 +36,8 @@ create a new release artifact, for example if there have been code changes due to edits or due to updating Rust and `rustfmt`, do the following: - Create a git tag for the release and push it to GitHub, or create a new tag - by going to the GitHub UI, [drafting a new - release](https://github.com/rust-lang/book/releases/new), and entering a new - tag instead of selecting an existing tag + by going to the GitHub UI, [drafting a new release](https://github.com/rust-lang/book/releases/new), and entering a new + tag instead of selecting an existing tag - Run `cargo run --bin release_listings`, which will generate `tmp/listings.tar.gz` - Upload `tmp/listings.tar.gz` in the GitHub UI for the draft release @@ -54,50 +53,50 @@ extracted into a file. To do that: - Find where the new listing should go in the `listings` directory. - There is one subdirectory for each chapter - Numbered listings should use `listing-[chapter num]-[listing num]` for - their directory names. + their directory names. - Listings without a number should start with `no-listing-` followed by a - number that indicates its position in the chapter relative to the other - listings without numbers in the chapter, then a short description that - someone could read to find the code they're looking for. + number that indicates its position in the chapter relative to the other + listings without numbers in the chapter, then a short description that + someone could read to find the code they're looking for. - Listings used only for displaying the output of the code (for example, when - we say "if we had written x instead of y, we would get this compiler - error:" but we don't actually show code x) should be named with - `output-only-` followed by a number that indicates its position in the - chapter relative to the other listings used only for output, then a short - description that authors or contributors could read to find the code - they're looking for. + we say "if we had written x instead of y, we would get this compiler + error:" but we don't actually show code x) should be named with + `output-only-` followed by a number that indicates its position in the + chapter relative to the other listings used only for output, then a short + description that authors or contributors could read to find the code + they're looking for. - **Remember to adjust surrounding listing numbers as appropriate!** - Create a full Cargo project in that directory, either by using `cargo new` or copying another listing as a starting point. - Add the code and any surrounding code needed to create a full working example. - If you only want to show part of the code in the file, use anchor comments (`// ANCHOR: some_tag` and `// ANCHOR_END: some_tag`) to mark the parts of - the file you want to show. + the file you want to show. - For Rust code, use the `{{#rustdoc_include [filename:some_tag]}}` directive within the code blocks in the text. The `rustdoc_include` directive gives the - code that doesn't get displayed to `rustdoc` for `mdbook test` purposes. + code that doesn't get displayed to `rustdoc` for `mdbook test` purposes. - For anything else, use the `{{#include [filename:some_tag]}}` directive. - If you want to display the output of a command in the text as well, create an `output.txt` file in the listing's directory as follows: - Run the command, like `cargo run` or `cargo test`, and copy all of the - output. + output. - Create a new `output.txt` file with the first line `$ [the command you ran]`. - Paste the output you just copied. - Run `./tools/update-rustc.sh`, which should perform some normalization on - the compiler output. + the compiler output. - Include the output in the text with the `{{#include [filename]}}` directive. - Add and commit output.txt. - If you want to display output but for some reason it can't be generated by a script (say, because of user input or external events like making a web - request), keep the output inline but make a comment that contains - `manual-regeneration` and instructions for manually updating the inline - output. + request), keep the output inline but make a comment that contains + `manual-regeneration` and instructions for manually updating the inline + output. - If you don't want this example to even be attempted to be formatted by `rustfmt` (for example because the example doesn't parse on purpose), add a - `rustfmt-ignore` file in the listing's directory and the reason it's not - being formatted as the contents of that file (in case it's a rustfmt bug that - might get fixed someday). + `rustfmt-ignore` file in the listing's directory and the reason it's not + being formatted as the contents of that file (in case it's a rustfmt bug that + might get fixed someday). ## See the effect of some change on the rendered book diff --git a/rustbook-en/CONTRIBUTING.md b/rustbook-en/CONTRIBUTING.md index a20cb5850..bba1a19a2 100644 --- a/rustbook-en/CONTRIBUTING.md +++ b/rustbook-en/CONTRIBUTING.md @@ -45,8 +45,7 @@ or pull request. [nostarch]: https://nostarch.com/rust-programming-language-2nd-edition -So far, we've been doing a larger revision to coincide with [Rust -Editions](https://doc.rust-lang.org/edition-guide/). Between those larger +So far, we've been doing a larger revision to coincide with [Rust Editions](https://doc.rust-lang.org/edition-guide/). Between those larger revisions, we will only be correcting errors. If your issue or pull request isn't strictly fixing an error, it might sit until the next time that we're working on a large revision: expect on the order of months or years. Thank you diff --git a/rustbook-en/README.md b/rustbook-en/README.md index b4426bd49..9935bd46f 100644 --- a/rustbook-en/README.md +++ b/rustbook-en/README.md @@ -35,7 +35,7 @@ $ cargo install mdbook --locked --version The book also uses two mdbook plugins which are part of this repository. If you do not install them, you will see warnings when building and the output will not -look right, but you *will* still be able to build the book. To use the plugins, +look right, but you _will_ still be able to build the book. To use the plugins, you should run: ```bash @@ -55,6 +55,7 @@ The output will be in the `book` subdirectory. To check it out, open it in your web browser. _Firefox:_ + ```bash $ firefox book/index.html # Linux $ open -a "Firefox" book/index.html # OS X @@ -63,6 +64,7 @@ $ start firefox.exe .\book\index.html # Windows (Cmd) ``` _Chrome:_ + ```bash $ google-chrome book/index.html # Linux $ open -a "Google Chrome" book/index.html # OS X @@ -89,8 +91,7 @@ to keep the online version of the book close to the print version when possible, it may take longer than you're used to for us to address your issue or pull request. -So far, we've been doing a larger revision to coincide with [Rust -Editions](https://doc.rust-lang.org/edition-guide/). Between those larger +So far, we've been doing a larger revision to coincide with [Rust Editions](https://doc.rust-lang.org/edition-guide/). Between those larger revisions, we will only be correcting errors. If your issue or pull request isn't strictly fixing an error, it might sit until the next time that we're working on a large revision: expect on the order of months or years. Thank you diff --git a/rustbook-en/dprint.jsonc b/rustbook-en/dprint.jsonc new file mode 100644 index 000000000..3d48ade51 --- /dev/null +++ b/rustbook-en/dprint.jsonc @@ -0,0 +1,33 @@ +{ + "typescript": { + }, + "json": { + }, + "markdown": { + }, + "malva": { + }, + "excludes": [ + "**/node_modules", + "**/*-lock.json", + "**/target", + // We don’t to apply auto-formatting to this *yet*, at a minimum. It may be + // helpful as a way of replacing some of the manual formatting we do in both + // the nostarch script and the script for pulling data back over from docx, + // though, so we may *start* doing so in the future. + "nostarch", + // These should never change at this point + "2018-edition", + "first-edition", + "second-edition", + "redirects", + // has empty list items which look like headings to a formatter + ".github/ISSUE_TEMPLATE/bug_report.md" + ], + "plugins": [ + "https://plugins.dprint.dev/typescript-0.93.3.wasm", + "https://plugins.dprint.dev/json-0.19.4.wasm", + "https://plugins.dprint.dev/markdown-0.17.8.wasm", + "https://plugins.dprint.dev/g-plane/malva-v0.11.0.wasm" + ] +} diff --git a/rustbook-en/ferris.js b/rustbook-en/ferris.js index 51e5b12a9..08f329281 100644 --- a/rustbook-en/ferris.js +++ b/rustbook-en/ferris.js @@ -7,50 +7,50 @@ /** @type {Array} */ const FERRIS_TYPES = [ { - attr: 'does_not_compile', - title: 'This code does not compile!' + attr: "does_not_compile", + title: "This code does not compile!", }, { - attr: 'panics', - title: 'This code panics!' + attr: "panics", + title: "This code panics!", }, { - attr: 'not_desired_behavior', - title: 'This code does not produce the desired behavior.' - } -] + attr: "not_desired_behavior", + title: "This code does not produce the desired behavior.", + }, +]; -document.addEventListener('DOMContentLoaded', () => { +document.addEventListener("DOMContentLoaded", () => { for (let ferrisType of FERRIS_TYPES) { - attachFerrises(ferrisType) + attachFerrises(ferrisType); } -}) +}); /** * @param {FerrisType} type */ function attachFerrises(type) { - let elements = document.getElementsByClassName(type.attr) + let elements = document.getElementsByClassName(type.attr); for (let codeBlock of elements) { // Skip SVG etc.: in principle, these should never be attached to those, but // this means if someone happens to have a browser extension which *is* // attaching them, it will not break the code. if (!(codeBlock instanceof HTMLElement)) { - continue + continue; } - let lines = codeBlock.innerText.replace(/\n$/, '').split(/\n/).length + let lines = codeBlock.innerText.replace(/\n$/, "").split(/\n/).length; /** @type {'small' | 'large'} */ - let size = lines < 4 ? 'small' : 'large' + let size = lines < 4 ? "small" : "large"; - let container = prepareFerrisContainer(codeBlock, size == 'small') + let container = prepareFerrisContainer(codeBlock, size == "small"); if (!container) { - continue + continue; } - container.appendChild(createFerris(type, size)) + container.appendChild(createFerris(type, size)); } } @@ -60,22 +60,22 @@ function attachFerrises(type) { * @returns {Element | null} - The container element to use. */ function prepareFerrisContainer(element, useButtons) { - let foundButtons = element.parentElement?.querySelector('.buttons') + let foundButtons = element.parentElement?.querySelector(".buttons"); if (useButtons && foundButtons) { - return foundButtons + return foundButtons; } - let div = document.createElement('div') - div.classList.add('ferris-container') + let div = document.createElement("div"); + div.classList.add("ferris-container"); if (!element.parentElement) { console.error(`Could not install Ferris on ${element}, which is missing a parent`); return null; } - element.parentElement.insertBefore(div, element) + element.parentElement.insertBefore(div, element); - return div + return div; } /** @@ -84,17 +84,17 @@ function prepareFerrisContainer(element, useButtons) { * @returns {HTMLAnchorElement} - The generated anchor element. */ function createFerris(type, size) { - let a = document.createElement('a') - a.setAttribute('href', 'ch00-00-introduction.html#ferris') - a.setAttribute('target', '_blank') + let a = document.createElement("a"); + a.setAttribute("href", "ch00-00-introduction.html#ferris"); + a.setAttribute("target", "_blank"); - let img = document.createElement('img') - img.setAttribute('src', 'img/ferris/' + type.attr + '.svg') - img.setAttribute('title', type.title) - img.classList.add('ferris') - img.classList.add('ferris-' + size) + let img = document.createElement("img"); + img.setAttribute("src", "img/ferris/" + type.attr + ".svg"); + img.setAttribute("title", type.title); + img.classList.add("ferris"); + img.classList.add("ferris-" + size); - a.appendChild(img) + a.appendChild(img); - return a + return a; } diff --git a/rustbook-en/packages/mdbook-trpl-note/README.md b/rustbook-en/packages/mdbook-trpl-note/README.md index 1ef5e6478..3e54ae7fd 100644 --- a/rustbook-en/packages/mdbook-trpl-note/README.md +++ b/rustbook-en/packages/mdbook-trpl-note/README.md @@ -1,6 +1,6 @@ # mdbook-trpl-note -This is a *very* simple [preprocessor][pre] for [mdBook][mdbook], focused specifically on the content of _The Rust Programming Language_ book. This preprocessor takes Markdown like this— +This is a _very_ simple [preprocessor][pre] for [mdBook][mdbook], focused specifically on the content of _The Rust Programming Language_ book. This preprocessor takes Markdown like this— ```markdown > Note: This is some material we want to provide more emphasis for, because it @@ -37,7 +37,7 @@ Here is all the important things to know about that particular subject. This allows using the relatively standard Markdown convention of (incorrectly!) using blockquotes for “callouts” or “notes” like this, while still producing semantic HTML which conveys the actual intent. > [!NOTE] -> This is *not* a full “admonition” preprocessor, and it is not remotely compliant with [the GitHub “alert” syntax][alerts]. It exists almost entirely for the sake of providing better semantic HTML for _The Rust Programming Language_ book with a minimum of disruption to existing workflows! +> This is _not_ a full “admonition” preprocessor, and it is not remotely compliant with [the GitHub “alert” syntax][alerts]. It exists almost entirely for the sake of providing better semantic HTML for _The Rust Programming Language_ book with a minimum of disruption to existing workflows! > > You are probably better off using one of the other existing alert/admonition preprocessors: > diff --git a/rustbook-en/packages/trpl/CHANGELOG.md b/rustbook-en/packages/trpl/CHANGELOG.md index e579745ea..5555b3ee6 100644 --- a/rustbook-en/packages/trpl/CHANGELOG.md +++ b/rustbook-en/packages/trpl/CHANGELOG.md @@ -2,4 +2,4 @@ ## 0.1.0 -Initial release! Adds support code for the first draft of the new async chapter of the book. \ No newline at end of file +Initial release! Adds support code for the first draft of the new async chapter of the book. diff --git a/rustbook-en/packages/trpl/README.md b/rustbook-en/packages/trpl/README.md index 7d2250488..3e97ac9b3 100644 --- a/rustbook-en/packages/trpl/README.md +++ b/rustbook-en/packages/trpl/README.md @@ -5,7 +5,7 @@ This repository is the home of the `trpl` crate used in _The Rust Programming Language_ book materials. -This crate mostly just re-exports items from *other* crates. It exists for two +This crate mostly just re-exports items from _other_ crates. It exists for two main reasons: 1. So that as you read along in _The Rust Programming Language_, you can add diff --git a/rustbook-en/src/SUMMARY.md b/rustbook-en/src/SUMMARY.md index 40f5c2242..a157cd05a 100644 --- a/rustbook-en/src/SUMMARY.md +++ b/rustbook-en/src/SUMMARY.md @@ -7,137 +7,137 @@ ## Getting started - [Getting Started](ch01-00-getting-started.md) - - [Installation](ch01-01-installation.md) - - [Hello, World!](ch01-02-hello-world.md) - - [Hello, Cargo!](ch01-03-hello-cargo.md) + - [Installation](ch01-01-installation.md) + - [Hello, World!](ch01-02-hello-world.md) + - [Hello, Cargo!](ch01-03-hello-cargo.md) - [Programming a Guessing Game](ch02-00-guessing-game-tutorial.md) - [Common Programming Concepts](ch03-00-common-programming-concepts.md) - - [Variables and Mutability](ch03-01-variables-and-mutability.md) - - [Data Types](ch03-02-data-types.md) - - [Functions](ch03-03-how-functions-work.md) - - [Comments](ch03-04-comments.md) - - [Control Flow](ch03-05-control-flow.md) + - [Variables and Mutability](ch03-01-variables-and-mutability.md) + - [Data Types](ch03-02-data-types.md) + - [Functions](ch03-03-how-functions-work.md) + - [Comments](ch03-04-comments.md) + - [Control Flow](ch03-05-control-flow.md) - [Understanding Ownership](ch04-00-understanding-ownership.md) - - [What is Ownership?](ch04-01-what-is-ownership.md) - - [References and Borrowing](ch04-02-references-and-borrowing.md) - - [The Slice Type](ch04-03-slices.md) + - [What is Ownership?](ch04-01-what-is-ownership.md) + - [References and Borrowing](ch04-02-references-and-borrowing.md) + - [The Slice Type](ch04-03-slices.md) - [Using Structs to Structure Related Data](ch05-00-structs.md) - - [Defining and Instantiating Structs](ch05-01-defining-structs.md) - - [An Example Program Using Structs](ch05-02-example-structs.md) - - [Method Syntax](ch05-03-method-syntax.md) + - [Defining and Instantiating Structs](ch05-01-defining-structs.md) + - [An Example Program Using Structs](ch05-02-example-structs.md) + - [Method Syntax](ch05-03-method-syntax.md) - [Enums and Pattern Matching](ch06-00-enums.md) - - [Defining an Enum](ch06-01-defining-an-enum.md) - - [The `match` Control Flow Construct](ch06-02-match.md) - - [Concise Control Flow with `if let`](ch06-03-if-let.md) + - [Defining an Enum](ch06-01-defining-an-enum.md) + - [The `match` Control Flow Construct](ch06-02-match.md) + - [Concise Control Flow with `if let`](ch06-03-if-let.md) ## 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 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) - [Common Collections](ch08-00-common-collections.md) - - [Storing Lists of Values with Vectors](ch08-01-vectors.md) - - [Storing UTF-8 Encoded Text with Strings](ch08-02-strings.md) - - [Storing Keys with Associated Values in Hash Maps](ch08-03-hash-maps.md) + - [Storing Lists of Values with Vectors](ch08-01-vectors.md) + - [Storing UTF-8 Encoded Text with Strings](ch08-02-strings.md) + - [Storing Keys with Associated Values in Hash Maps](ch08-03-hash-maps.md) - [Error Handling](ch09-00-error-handling.md) - - [Unrecoverable Errors with `panic!`](ch09-01-unrecoverable-errors-with-panic.md) - - [Recoverable Errors with `Result`](ch09-02-recoverable-errors-with-result.md) - - [To `panic!` or Not to `panic!`](ch09-03-to-panic-or-not-to-panic.md) + - [Unrecoverable Errors with `panic!`](ch09-01-unrecoverable-errors-with-panic.md) + - [Recoverable Errors with `Result`](ch09-02-recoverable-errors-with-result.md) + - [To `panic!` or Not to `panic!`](ch09-03-to-panic-or-not-to-panic.md) - [Generic Types, Traits, and Lifetimes](ch10-00-generics.md) - - [Generic Data Types](ch10-01-syntax.md) - - [Traits: Defining Shared Behavior](ch10-02-traits.md) - - [Validating References with Lifetimes](ch10-03-lifetime-syntax.md) + - [Generic Data Types](ch10-01-syntax.md) + - [Traits: Defining Shared Behavior](ch10-02-traits.md) + - [Validating References with Lifetimes](ch10-03-lifetime-syntax.md) - [Writing Automated Tests](ch11-00-testing.md) - - [How to Write Tests](ch11-01-writing-tests.md) - - [Controlling How Tests Are Run](ch11-02-running-tests.md) - - [Test Organization](ch11-03-test-organization.md) + - [How to Write Tests](ch11-01-writing-tests.md) + - [Controlling How Tests Are Run](ch11-02-running-tests.md) + - [Test Organization](ch11-03-test-organization.md) - [An I/O Project: Building a Command Line Program](ch12-00-an-io-project.md) - - [Accepting Command Line Arguments](ch12-01-accepting-command-line-arguments.md) - - [Reading a File](ch12-02-reading-a-file.md) - - [Refactoring to Improve Modularity and Error Handling](ch12-03-improving-error-handling-and-modularity.md) - - [Developing the Library’s Functionality with Test Driven Development](ch12-04-testing-the-librarys-functionality.md) - - [Working with Environment Variables](ch12-05-working-with-environment-variables.md) - - [Writing Error Messages to Standard Error Instead of Standard Output](ch12-06-writing-to-stderr-instead-of-stdout.md) + - [Accepting Command Line Arguments](ch12-01-accepting-command-line-arguments.md) + - [Reading a File](ch12-02-reading-a-file.md) + - [Refactoring to Improve Modularity and Error Handling](ch12-03-improving-error-handling-and-modularity.md) + - [Developing the Library’s Functionality with Test Driven Development](ch12-04-testing-the-librarys-functionality.md) + - [Working with Environment Variables](ch12-05-working-with-environment-variables.md) + - [Writing Error Messages to Standard Error Instead of Standard Output](ch12-06-writing-to-stderr-instead-of-stdout.md) ## Thinking in Rust - [Functional Language Features: Iterators and Closures](ch13-00-functional-features.md) - - [Closures: Anonymous Functions that Capture Their Environment](ch13-01-closures.md) - - [Processing a Series of Items with Iterators](ch13-02-iterators.md) - - [Improving Our I/O Project](ch13-03-improving-our-io-project.md) - - [Comparing Performance: Loops vs. Iterators](ch13-04-performance.md) + - [Closures: Anonymous Functions that Capture Their Environment](ch13-01-closures.md) + - [Processing a Series of Items with Iterators](ch13-02-iterators.md) + - [Improving Our I/O Project](ch13-03-improving-our-io-project.md) + - [Comparing Performance: Loops vs. Iterators](ch13-04-performance.md) - [More about Cargo and Crates.io](ch14-00-more-about-cargo.md) - - [Customizing Builds with Release Profiles](ch14-01-release-profiles.md) - - [Publishing a Crate to Crates.io](ch14-02-publishing-to-crates-io.md) - - [Cargo Workspaces](ch14-03-cargo-workspaces.md) - - [Installing Binaries from Crates.io with `cargo install`](ch14-04-installing-binaries.md) - - [Extending Cargo with Custom Commands](ch14-05-extending-cargo.md) + - [Customizing Builds with Release Profiles](ch14-01-release-profiles.md) + - [Publishing a Crate to Crates.io](ch14-02-publishing-to-crates-io.md) + - [Cargo Workspaces](ch14-03-cargo-workspaces.md) + - [Installing Binaries from Crates.io with `cargo install`](ch14-04-installing-binaries.md) + - [Extending Cargo with Custom Commands](ch14-05-extending-cargo.md) - [Smart Pointers](ch15-00-smart-pointers.md) - - [Using `Box` to Point to Data on the Heap](ch15-01-box.md) - - [Treating Smart Pointers Like Regular References with the `Deref` Trait](ch15-02-deref.md) - - [Running Code on Cleanup with the `Drop` Trait](ch15-03-drop.md) - - [`Rc`, the Reference Counted Smart Pointer](ch15-04-rc.md) - - [`RefCell` and the Interior Mutability Pattern](ch15-05-interior-mutability.md) - - [Reference Cycles Can Leak Memory](ch15-06-reference-cycles.md) + - [Using `Box` to Point to Data on the Heap](ch15-01-box.md) + - [Treating Smart Pointers Like Regular References with the `Deref` Trait](ch15-02-deref.md) + - [Running Code on Cleanup with the `Drop` Trait](ch15-03-drop.md) + - [`Rc`, the Reference Counted Smart Pointer](ch15-04-rc.md) + - [`RefCell` and the Interior Mutability Pattern](ch15-05-interior-mutability.md) + - [Reference Cycles Can Leak Memory](ch15-06-reference-cycles.md) - [Fearless Concurrency](ch16-00-concurrency.md) - - [Using Threads to Run Code Simultaneously](ch16-01-threads.md) - - [Using Message Passing to Transfer Data Between Threads](ch16-02-message-passing.md) - - [Shared-State Concurrency](ch16-03-shared-state.md) - - [Extensible Concurrency with the `Sync` and `Send` Traits](ch16-04-extensible-concurrency-sync-and-send.md) + - [Using Threads to Run Code Simultaneously](ch16-01-threads.md) + - [Using Message Passing to Transfer Data Between Threads](ch16-02-message-passing.md) + - [Shared-State Concurrency](ch16-03-shared-state.md) + - [Extensible Concurrency with the `Sync` and `Send` Traits](ch16-04-extensible-concurrency-sync-and-send.md) - [Async and Await](ch17-00-async-await.md) - - [Futures and the Async Syntax](ch17-01-futures-and-syntax.md) - - [Concurrency With Async](ch17-02-concurrency-with-async.md) - - [Working With Any Number of Futures](ch17-03-more-futures.md) - - [Streams](ch17-04-streams.md) - - [Digging Into the Traits for Async](ch17-05-traits-for-async.md) - - [Futures, Tasks, and Threads](ch17-06-futures-tasks-threads.md) + - [Futures and the Async Syntax](ch17-01-futures-and-syntax.md) + - [Concurrency With Async](ch17-02-concurrency-with-async.md) + - [Working With Any Number of Futures](ch17-03-more-futures.md) + - [Streams](ch17-04-streams.md) + - [Digging Into the Traits for Async](ch17-05-traits-for-async.md) + - [Futures, Tasks, and Threads](ch17-06-futures-tasks-threads.md) - [Object Oriented Programming Features of Rust](ch18-00-oop.md) - - [Characteristics of Object-Oriented Languages](ch18-01-what-is-oo.md) - - [Using Trait Objects That Allow for Values of Different Types](ch18-02-trait-objects.md) - - [Implementing an Object-Oriented Design Pattern](ch18-03-oo-design-patterns.md) + - [Characteristics of Object-Oriented Languages](ch18-01-what-is-oo.md) + - [Using Trait Objects That Allow for Values of Different Types](ch18-02-trait-objects.md) + - [Implementing an Object-Oriented Design Pattern](ch18-03-oo-design-patterns.md) ## Advanced Topics - [Patterns and Matching](ch19-00-patterns.md) - - [All the Places Patterns Can Be Used](ch19-01-all-the-places-for-patterns.md) - - [Refutability: Whether a Pattern Might Fail to Match](ch19-02-refutability.md) - - [Pattern Syntax](ch19-03-pattern-syntax.md) + - [All the Places Patterns Can Be Used](ch19-01-all-the-places-for-patterns.md) + - [Refutability: Whether a Pattern Might Fail to Match](ch19-02-refutability.md) + - [Pattern Syntax](ch19-03-pattern-syntax.md) - [Advanced Features](ch20-00-advanced-features.md) - - [Unsafe Rust](ch20-01-unsafe-rust.md) - - [Advanced Traits](ch20-03-advanced-traits.md) - - [Advanced Types](ch20-04-advanced-types.md) - - [Advanced Functions and Closures](ch20-05-advanced-functions-and-closures.md) - - [Macros](ch20-06-macros.md) + - [Unsafe Rust](ch20-01-unsafe-rust.md) + - [Advanced Traits](ch20-03-advanced-traits.md) + - [Advanced Types](ch20-04-advanced-types.md) + - [Advanced Functions and Closures](ch20-05-advanced-functions-and-closures.md) + - [Macros](ch20-06-macros.md) - [Final Project: Building a Multithreaded Web Server](ch21-00-final-project-a-web-server.md) - - [Building a Single-Threaded Web Server](ch21-01-single-threaded.md) - - [Turning Our Single-Threaded Server into a Multithreaded Server](ch21-02-multithreaded.md) - - [Graceful Shutdown and Cleanup](ch21-03-graceful-shutdown-and-cleanup.md) + - [Building a Single-Threaded Web Server](ch21-01-single-threaded.md) + - [Turning Our Single-Threaded Server into a Multithreaded Server](ch21-02-multithreaded.md) + - [Graceful Shutdown and Cleanup](ch21-03-graceful-shutdown-and-cleanup.md) - [Appendix](appendix-00.md) - - [A - Keywords](appendix-01-keywords.md) - - [B - Operators and Symbols](appendix-02-operators.md) - - [C - Derivable Traits](appendix-03-derivable-traits.md) - - [D - Useful Development Tools](appendix-04-useful-development-tools.md) - - [E - Editions](appendix-05-editions.md) - - [F - Translations of the Book](appendix-06-translation.md) - - [G - How Rust is Made and “Nightly Rust”](appendix-07-nightly-rust.md) + - [A - Keywords](appendix-01-keywords.md) + - [B - Operators and Symbols](appendix-02-operators.md) + - [C - Derivable Traits](appendix-03-derivable-traits.md) + - [D - Useful Development Tools](appendix-04-useful-development-tools.md) + - [E - Editions](appendix-05-editions.md) + - [F - Translations of the Book](appendix-06-translation.md) + - [G - How Rust is Made and “Nightly Rust”](appendix-07-nightly-rust.md) diff --git a/rustbook-en/src/appendix-01-keywords.md b/rustbook-en/src/appendix-01-keywords.md index b84894591..1df169117 100644 --- a/rustbook-en/src/appendix-01-keywords.md +++ b/rustbook-en/src/appendix-01-keywords.md @@ -14,48 +14,48 @@ macros, static values, attributes, types, traits, or lifetimes. The following is a list of keywords currently in use, with their functionality described. -* `as` - perform primitive casting, disambiguate the specific trait containing +- `as` - perform primitive casting, disambiguate the specific trait containing an item, or rename items in `use` 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 -* `crate` - in a module path, refers to the crate root -* `dyn` - dynamic dispatch to a trait object -* `else` - fallback for `if` and `if let` control flow constructs -* `enum` - define an enumeration -* `extern` - link an external function or variable -* `false` - Boolean false literal -* `fn` - define a function or the function pointer type -* `for` - loop over items from an iterator, implement a trait, or specify a +- `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 +- `crate` - in a module path, refers to the crate root +- `dyn` - dynamic dispatch to a trait object +- `else` - fallback for `if` and `if let` control flow constructs +- `enum` - define an enumeration +- `extern` - link an external function or variable +- `false` - Boolean false literal +- `fn` - define a function or the function pointer type +- `for` - loop over items from an iterator, implement a trait, or specify a higher-ranked lifetime -* `if` - branch based on the result of a conditional expression -* `impl` - implement inherent or trait functionality -* `in` - part of `for` loop syntax -* `let` - bind a variable -* `loop` - loop unconditionally -* `match` - match a value to patterns -* `mod` - define a module -* `move` - make a closure take ownership of all its captures -* `mut` - denote mutability in references, raw pointers, or pattern bindings -* `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` - method subject or current module -* `static` - global variable or lifetime lasting the entire program execution -* `struct` - define a structure -* `super` - parent module of the current module -* `trait` - define a trait -* `true` - Boolean true literal -* `type` - define a type alias or associated type -* `union` - define a [union][union]; is only a keyword when used +- `if` - branch based on the result of a conditional expression +- `impl` - implement inherent or trait functionality +- `in` - part of `for` loop syntax +- `let` - bind a variable +- `loop` - loop unconditionally +- `match` - match a value to patterns +- `mod` - define a module +- `move` - make a closure take ownership of all its captures +- `mut` - denote mutability in references, raw pointers, or pattern bindings +- `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` - method subject or current module +- `static` - global variable or lifetime lasting the entire program execution +- `struct` - define a structure +- `super` - parent module of the current module +- `trait` - define a trait +- `true` - Boolean true literal +- `type` - define a type alias or associated type +- `union` - define a [union][union]; is only a keyword when used in a union declaration -* `unsafe` - denote unsafe code, functions, traits, or implementations -* `use` - bring symbols into scope -* `where` - denote clauses that constrain a type -* `while` - loop conditionally based on the result of an expression +- `unsafe` - denote unsafe code, functions, traits, or implementations +- `use` - bring symbols into scope +- `where` - denote clauses that constrain a type +- `while` - loop conditionally based on the result of an expression [union]: ../reference/items/unions.html @@ -64,23 +64,23 @@ described. The following keywords do not yet have any functionality but are reserved by Rust for potential future use. -* `abstract` -* `become` -* `box` -* `do` -* `final` -* `macro` -* `override` -* `priv` -* `try` -* `typeof` -* `unsized` -* `virtual` -* `yield` +- `abstract` +- `become` +- `box` +- `do` +- `final` +- `macro` +- `override` +- `priv` +- `try` +- `typeof` +- `unsized` +- `virtual` +- `yield` ### Raw Identifiers -*Raw identifiers* are the syntax that lets you use keywords where they wouldn’t +_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#`. For example, `match` is a keyword. If you try to compile the following function diff --git a/rustbook-en/src/appendix-02-operators.md b/rustbook-en/src/appendix-02-operators.md index 45de3e56a..6c8b8d89d 100644 --- a/rustbook-en/src/appendix-02-operators.md +++ b/rustbook-en/src/appendix-02-operators.md @@ -13,62 +13,62 @@ overload that operator is listed. Table B-1: Operators -| Operator | Example | Explanation | Overloadable? | -|----------|---------|-------------|---------------| -| `!` | `ident!(...)`, `ident!{...}`, `ident![...]` | Macro expansion | | -| `!` | `!expr` | Bitwise or logical complement | `Not` | -| `!=` | `expr != expr` | Nonequality comparison | `PartialEq` | -| `%` | `expr % expr` | Arithmetic remainder | `Rem` | -| `%=` | `var %= expr` | Arithmetic remainder and assignment | `RemAssign` | -| `&` | `&expr`, `&mut expr` | Borrow | | -| `&` | `&type`, `&mut type`, `&'a type`, `&'a mut type` | Borrowed pointer type | | -| `&` | `expr & expr` | Bitwise AND | `BitAnd` | -| `&=` | `var &= expr` | Bitwise AND and assignment | `BitAndAssign` | -| `&&` | `expr && expr` | Short-circuiting logical AND | | -| `*` | `expr * expr` | Arithmetic multiplication | `Mul` | -| `*=` | `var *= expr` | Arithmetic multiplication and assignment | `MulAssign` | -| `*` | `*expr` | Dereference | `Deref` | -| `*` | `*const type`, `*mut type` | Raw pointer | | -| `+` | `trait + trait`, `'a + trait` | Compound type constraint | | -| `+` | `expr + expr` | Arithmetic addition | `Add` | -| `+=` | `var += expr` | Arithmetic addition and assignment | `AddAssign` | -| `,` | `expr, expr` | Argument and element separator | | -| `-` | `- expr` | Arithmetic negation | `Neg` | -| `-` | `expr - expr` | Arithmetic subtraction | `Sub` | -| `-=` | `var -= expr` | Arithmetic subtraction and assignment | `SubAssign` | -| `->` | `fn(...) -> type`, |...| -> type | Function and closure return type | | -| `.` | `expr.ident` | Member access | | -| `..` | `..`, `expr..`, `..expr`, `expr..expr` | Right-exclusive range literal | `PartialOrd` | -| `..=` | `..=expr`, `expr..=expr` | Right-inclusive range literal | `PartialOrd` | -| `..` | `..expr` | Struct literal update syntax | | -| `..` | `variant(x, ..)`, `struct_type { x, .. }` | “And the rest” pattern binding | | -| `...` | `expr...expr` | (Deprecated, use `..=` instead) In a pattern: inclusive range pattern | | -| `/` | `expr / expr` | Arithmetic division | `Div` | -| `/=` | `var /= expr` | Arithmetic division and assignment | `DivAssign` | -| `:` | `pat: type`, `ident: type` | Constraints | | -| `:` | `ident: expr` | Struct field initializer | | -| `:` | `'a: loop {...}` | Loop label | | -| `;` | `expr;` | Statement and item terminator | | -| `;` | `[...; len]` | Part of fixed-size array syntax | | -| `<<` | `expr << expr` | Left-shift | `Shl` | -| `<<=` | `var <<= expr` | Left-shift and assignment | `ShlAssign` | -| `<` | `expr < expr` | Less than comparison | `PartialOrd` | -| `<=` | `expr <= expr` | Less than or equal to comparison | `PartialOrd` | -| `=` | `var = expr`, `ident = type` | Assignment/equivalence | | -| `==` | `expr == expr` | Equality comparison | `PartialEq` | -| `=>` | `pat => expr` | Part of match arm syntax | | -| `>` | `expr > expr` | Greater than comparison | `PartialOrd` | -| `>=` | `expr >= expr` | Greater than or equal to comparison | `PartialOrd` | -| `>>` | `expr >> expr` | Right-shift | `Shr` | -| `>>=` | `var >>= expr` | Right-shift and assignment | `ShrAssign` | -| `@` | `ident @ pat` | Pattern binding | | -| `^` | `expr ^ expr` | Bitwise exclusive OR | `BitXor` | -| `^=` | `var ^= expr` | Bitwise exclusive OR and assignment | `BitXorAssign` | -| | | pat | pat | Pattern alternatives | | -| | | expr | expr | Bitwise OR | `BitOr` | -| |= | var |= expr | Bitwise OR and assignment | `BitOrAssign` | -| || | expr || expr | Short-circuiting logical OR | | -| `?` | `expr?` | Error propagation | | +| Operator | Example | Explanation | Overloadable? | +| ------------------------- | ------------------------------------------------------- | --------------------------------------------------------------------- | -------------- | +| `!` | `ident!(...)`, `ident!{...}`, `ident![...]` | Macro expansion | | +| `!` | `!expr` | Bitwise or logical complement | `Not` | +| `!=` | `expr != expr` | Nonequality comparison | `PartialEq` | +| `%` | `expr % expr` | Arithmetic remainder | `Rem` | +| `%=` | `var %= expr` | Arithmetic remainder and assignment | `RemAssign` | +| `&` | `&expr`, `&mut expr` | Borrow | | +| `&` | `&type`, `&mut type`, `&'a type`, `&'a mut type` | Borrowed pointer type | | +| `&` | `expr & expr` | Bitwise AND | `BitAnd` | +| `&=` | `var &= expr` | Bitwise AND and assignment | `BitAndAssign` | +| `&&` | `expr && expr` | Short-circuiting logical AND | | +| `*` | `expr * expr` | Arithmetic multiplication | `Mul` | +| `*=` | `var *= expr` | Arithmetic multiplication and assignment | `MulAssign` | +| `*` | `*expr` | Dereference | `Deref` | +| `*` | `*const type`, `*mut type` | Raw pointer | | +| `+` | `trait + trait`, `'a + trait` | Compound type constraint | | +| `+` | `expr + expr` | Arithmetic addition | `Add` | +| `+=` | `var += expr` | Arithmetic addition and assignment | `AddAssign` | +| `,` | `expr, expr` | Argument and element separator | | +| `-` | `- expr` | Arithmetic negation | `Neg` | +| `-` | `expr - expr` | Arithmetic subtraction | `Sub` | +| `-=` | `var -= expr` | Arithmetic subtraction and assignment | `SubAssign` | +| `->` | `fn(...) -> type`, |...| -> type | Function and closure return type | | +| `.` | `expr.ident` | Member access | | +| `..` | `..`, `expr..`, `..expr`, `expr..expr` | Right-exclusive range literal | `PartialOrd` | +| `..=` | `..=expr`, `expr..=expr` | Right-inclusive range literal | `PartialOrd` | +| `..` | `..expr` | Struct literal update syntax | | +| `..` | `variant(x, ..)`, `struct_type { x, .. }` | “And the rest” pattern binding | | +| `...` | `expr...expr` | (Deprecated, use `..=` instead) In a pattern: inclusive range pattern | | +| `/` | `expr / expr` | Arithmetic division | `Div` | +| `/=` | `var /= expr` | Arithmetic division and assignment | `DivAssign` | +| `:` | `pat: type`, `ident: type` | Constraints | | +| `:` | `ident: expr` | Struct field initializer | | +| `:` | `'a: loop {...}` | Loop label | | +| `;` | `expr;` | Statement and item terminator | | +| `;` | `[...; len]` | Part of fixed-size array syntax | | +| `<<` | `expr << expr` | Left-shift | `Shl` | +| `<<=` | `var <<= expr` | Left-shift and assignment | `ShlAssign` | +| `<` | `expr < expr` | Less than comparison | `PartialOrd` | +| `<=` | `expr <= expr` | Less than or equal to comparison | `PartialOrd` | +| `=` | `var = expr`, `ident = type` | Assignment/equivalence | | +| `==` | `expr == expr` | Equality comparison | `PartialEq` | +| `=>` | `pat => expr` | Part of match arm syntax | | +| `>` | `expr > expr` | Greater than comparison | `PartialOrd` | +| `>=` | `expr >= expr` | Greater than or equal to comparison | `PartialOrd` | +| `>>` | `expr >> expr` | Right-shift | `Shr` | +| `>>=` | `var >>= expr` | Right-shift and assignment | `ShrAssign` | +| `@` | `ident @ pat` | Pattern binding | | +| `^` | `expr ^ expr` | Bitwise exclusive OR | `BitXor` | +| `^=` | `var ^= expr` | Bitwise exclusive OR and assignment | `BitXorAssign` | +| | | pat | pat | Pattern alternatives | | +| | | expr | expr | Bitwise OR | `BitOr` | +| |= | var |= expr | Bitwise OR and assignment | `BitOrAssign` | +| || | expr || expr | Short-circuiting logical OR | | +| `?` | `expr?` | Error propagation | | ### Non-operator Symbols @@ -80,91 +80,91 @@ locations. Table B-2: Stand-Alone Syntax -| Symbol | Explanation | -|--------|-------------| -| `'ident` | Named lifetime or loop label | -| `...u8`, `...i32`, `...f64`, `...usize`, etc. | Numeric literal of specific type | -| `"..."` | String literal | -| `r"..."`, `r#"..."#`, `r##"..."##`, etc. | Raw string literal, escape characters not processed | -| `b"..."` | Byte string literal; constructs an array of bytes instead of a string | -| `br"..."`, `br#"..."#`, `br##"..."##`, etc. | Raw byte string literal, combination of raw and byte string literal | -| `'...'` | Character literal | -| `b'...'` | ASCII byte literal | -| |...| expr | Closure | -| `!` | Always empty bottom type for diverging functions | -| `_` | “Ignored” pattern binding; also used to make integer literals readable | +| Symbol | Explanation | +| --------------------------------------------- | ---------------------------------------------------------------------- | +| `'ident` | Named lifetime or loop label | +| `...u8`, `...i32`, `...f64`, `...usize`, etc. | Numeric literal of specific type | +| `"..."` | String literal | +| `r"..."`, `r#"..."#`, `r##"..."##`, etc. | Raw string literal, escape characters not processed | +| `b"..."` | Byte string literal; constructs an array of bytes instead of a string | +| `br"..."`, `br#"..."#`, `br##"..."##`, etc. | Raw byte string literal, combination of raw and byte string literal | +| `'...'` | Character literal | +| `b'...'` | ASCII byte literal | +| |...| expr | Closure | +| `!` | Always empty bottom type for diverging functions | +| `_` | “Ignored” pattern binding; also used to make integer literals readable | Table B-3 shows symbols that appear in the context of a path through the module hierarchy to an item. Table B-3: Path-Related Syntax -| Symbol | Explanation | -|--------|-------------| -| `ident::ident` | Namespace path | -| `::path` | Path relative to the extern prelude, where all other crates are rooted (i.e., an explicitly absolute path including crate name) | -| `self::path` | Path relative to the current module (i.e., an explicitly relative path). | -| `super::path` | Path relative to the parent of the current module | -| `type::ident`, `::ident` | Associated constants, functions, and types | -| `::...` | Associated item for a type that cannot be directly named (e.g., `<&T>::...`, `<[T]>::...`, etc.) | -| `trait::method(...)` | Disambiguating a method call by naming the trait that defines it | -| `type::method(...)` | Disambiguating a method call by naming the type for which it’s defined | -| `::method(...)` | Disambiguating a method call by naming the trait and type | +| Symbol | Explanation | +| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| `ident::ident` | Namespace path | +| `::path` | Path relative to the extern prelude, where all other crates are rooted (i.e., an explicitly absolute path including crate name) | +| `self::path` | Path relative to the current module (i.e., an explicitly relative path). | +| `super::path` | Path relative to the parent of the current module | +| `type::ident`, `::ident` | Associated constants, functions, and types | +| `::...` | Associated item for a type that cannot be directly named (e.g., `<&T>::...`, `<[T]>::...`, etc.) | +| `trait::method(...)` | Disambiguating a method call by naming the trait that defines it | +| `type::method(...)` | Disambiguating a method call by naming the type for which it’s defined | +| `::method(...)` | Disambiguating a method call by naming the trait and type | Table B-4 shows symbols that appear in the context of using generic type parameters. Table B-4: Generics -| Symbol | Explanation | -|--------|-------------| -| `path<...>` | Specifies parameters to generic type in a type (e.g., `Vec`) | +| Symbol | Explanation | +| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | +| `path<...>` | Specifies parameters to generic type in a type (e.g., `Vec`) | | `path::<...>`, `method::<...>` | Specifies parameters to generic type, function, or method in an expression; often referred to as turbofish (e.g., `"42".parse::()`) | -| `fn ident<...> ...` | Define generic function | -| `struct ident<...> ...` | Define generic structure | -| `enum ident<...> ...` | Define generic enumeration | -| `impl<...> ...` | Define generic implementation | -| `for<...> type` | Higher-ranked lifetime bounds | -| `type` | A generic type where one or more associated types have specific assignments (e.g., `Iterator`) | +| `fn ident<...> ...` | Define generic function | +| `struct ident<...> ...` | Define generic structure | +| `enum ident<...> ...` | Define generic enumeration | +| `impl<...> ...` | Define generic implementation | +| `for<...> type` | Higher-ranked lifetime bounds | +| `type` | A generic type where one or more associated types have specific assignments (e.g., `Iterator`) | Table B-5 shows symbols that appear in the context of constraining generic type parameters with trait bounds. Table B-5: Trait Bound Constraints -| Symbol | Explanation | -|--------|-------------| -| `T: U` | Generic parameter `T` constrained to types that implement `U` | -| `T: 'a` | Generic type `T` must outlive lifetime `'a` (meaning the type cannot transitively contain any references with lifetimes shorter than `'a`) | -| `T: 'static` | Generic type `T` contains no borrowed references other than `'static` ones | -| `'b: 'a` | Generic lifetime `'b` must outlive lifetime `'a` | -| `T: ?Sized` | Allow generic type parameter to be a dynamically sized type | -| `'a + trait`, `trait + trait` | Compound type constraint | +| Symbol | Explanation | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | +| `T: U` | Generic parameter `T` constrained to types that implement `U` | +| `T: 'a` | Generic type `T` must outlive lifetime `'a` (meaning the type cannot transitively contain any references with lifetimes shorter than `'a`) | +| `T: 'static` | Generic type `T` contains no borrowed references other than `'static` ones | +| `'b: 'a` | Generic lifetime `'b` must outlive lifetime `'a` | +| `T: ?Sized` | Allow generic type parameter to be a dynamically sized type | +| `'a + trait`, `trait + trait` | Compound type constraint | Table B-6 shows symbols that appear in the context of calling or defining macros and specifying attributes on an item. Table B-6: Macros and Attributes -| Symbol | Explanation | -|--------|-------------| -| `#[meta]` | Outer attribute | -| `#![meta]` | Inner attribute | -| `$ident` | Macro substitution | -| `$ident:kind` | Macro capture | -| `$(…)…` | Macro repetition | -| `ident!(...)`, `ident!{...}`, `ident![...]` | Macro invocation | +| Symbol | Explanation | +| ------------------------------------------- | ------------------ | +| `#[meta]` | Outer attribute | +| `#![meta]` | Inner attribute | +| `$ident` | Macro substitution | +| `$ident:kind` | Macro capture | +| `$(…)…` | Macro repetition | +| `ident!(...)`, `ident!{...}`, `ident![...]` | Macro invocation | Table B-7 shows symbols that create comments. Table B-7: Comments -| Symbol | Explanation | -|--------|-------------| -| `//` | Line comment | -| `//!` | Inner line doc comment | -| `///` | Outer line doc comment | -| `/*...*/` | Block comment | +| Symbol | Explanation | +| ---------- | ----------------------- | +| `//` | Line comment | +| `//!` | Inner line doc comment | +| `///` | Outer line doc comment | +| `/*...*/` | Block comment | | `/*!...*/` | Inner block doc comment | | `/**...*/` | Outer block doc comment | @@ -172,34 +172,34 @@ Table B-8 shows symbols that appear in the context of using tuples. Table B-8: Tuples -| Symbol | Explanation | -|--------|-------------| -| `()` | Empty tuple (aka unit), both literal and type | -| `(expr)` | Parenthesized expression | -| `(expr,)` | Single-element tuple expression | -| `(type,)` | Single-element tuple type | -| `(expr, ...)` | Tuple expression | -| `(type, ...)` | Tuple type | -| `expr(expr, ...)` | Function call expression; also used to initialize tuple `struct`s and tuple `enum` variants | -| `expr.0`, `expr.1`, etc. | Tuple indexing | +| Symbol | Explanation | +| ------------------------ | ------------------------------------------------------------------------------------------- | +| `()` | Empty tuple (aka unit), both literal and type | +| `(expr)` | Parenthesized expression | +| `(expr,)` | Single-element tuple expression | +| `(type,)` | Single-element tuple type | +| `(expr, ...)` | Tuple expression | +| `(type, ...)` | Tuple type | +| `expr(expr, ...)` | Function call expression; also used to initialize tuple `struct`s and tuple `enum` variants | +| `expr.0`, `expr.1`, etc. | Tuple indexing | Table B-9 shows the contexts in which curly braces are used. Table B-9: Curly Brackets -| Context | Explanation | -|---------|-------------| -| `{...}` | Block expression | +| Context | Explanation | +| ------------ | ---------------- | +| `{...}` | Block expression | | `Type {...}` | `struct` literal | Table B-10 shows the contexts in which square brackets are used. Table B-10: Square Brackets -| Context | Explanation | -|---------|-------------| -| `[...]` | Array literal | -| `[expr; len]` | Array literal containing `len` copies of `expr` | -| `[type; len]` | Array type containing `len` instances of `type` | -| `expr[expr]` | Collection indexing. Overloadable (`Index`, `IndexMut`) | +| Context | Explanation | +| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| `[...]` | Array literal | +| `[expr; len]` | Array literal containing `len` copies of `expr` | +| `[type; len]` | Array type containing `len` instances of `type` | +| `expr[expr]` | Collection indexing. Overloadable (`Index`, `IndexMut`) | | `expr[..]`, `expr[a..]`, `expr[..b]`, `expr[a..b]` | Collection indexing pretending to be collection slicing, using `Range`, `RangeFrom`, `RangeTo`, or `RangeFull` as the “index” | diff --git a/rustbook-en/src/appendix-03-derivable-traits.md b/rustbook-en/src/appendix-03-derivable-traits.md index 4214f091b..2365ade13 100644 --- a/rustbook-en/src/appendix-03-derivable-traits.md +++ b/rustbook-en/src/appendix-03-derivable-traits.md @@ -8,11 +8,11 @@ type you’ve annotated with the `derive` syntax. In this appendix, we provide a reference of all the traits in the standard library that you can use with `derive`. Each section covers: -* What operators and methods deriving this trait will enable -* What the implementation of the trait provided by `derive` does -* What implementing the trait signifies about the type -* The conditions in which you’re allowed or not allowed to implement the trait -* Examples of operations that require the trait +- What operators and methods deriving this trait will enable +- What the implementation of the trait provided by `derive` does +- What implementing the trait signifies about the type +- 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, consult the [standard library documentation](../std/index.html) @@ -55,7 +55,7 @@ The `PartialEq` trait allows you to compare instances of a type to check for equality and enables use of the `==` and `!=` operators. Deriving `PartialEq` implements the `eq` method. When `PartialEq` is derived on -structs, two instances are equal only if *all* fields are equal, and the +structs, two instances are equal only if _all_ fields are equal, and the instances are not equal if any fields are not equal. When derived on enums, each variant is equal to itself and not equal to the other variants. @@ -178,10 +178,7 @@ The `Default` trait is required when you use the method `unwrap_or_default` on `unwrap_or_default` will return the result of `Default::default` for the type `T` stored in the `Option`. -[creating-instances-from-other-instances-with-struct-update-syntax]: -ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax -[stack-only-data-copy]: -ch04-01-what-is-ownership.html#stack-only-data-copy -[ways-variables-and-data-interact-clone]: -ch04-01-what-is-ownership.html#ways-variables-and-data-interact-clone +[creating-instances-from-other-instances-with-struct-update-syntax]: ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax +[stack-only-data-copy]: ch04-01-what-is-ownership.html#stack-only-data-copy +[ways-variables-and-data-interact-clone]: ch04-01-what-is-ownership.html#ways-variables-and-data-interact-clone [macros]: ch20-06-macros.html#macros diff --git a/rustbook-en/src/appendix-04-useful-development-tools.md b/rustbook-en/src/appendix-04-useful-development-tools.md index 30249ed57..75e0c871b 100644 --- a/rustbook-en/src/appendix-04-useful-development-tools.md +++ b/rustbook-en/src/appendix-04-useful-development-tools.md @@ -77,7 +77,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 +When we look at _src/main.rs_ again, we’ll see that `cargo fix` has changed the code: Filename: src/main.rs diff --git a/rustbook-en/src/appendix-05-editions.md b/rustbook-en/src/appendix-05-editions.md index 90828ebba..ea9758ffa 100644 --- a/rustbook-en/src/appendix-05-editions.md +++ b/rustbook-en/src/appendix-05-editions.md @@ -1,7 +1,7 @@ ## 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! +_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 @@ -10,24 +10,24 @@ 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 +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 +- 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 +- 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 +- For those developing Rust, a new edition provides a rallying point for the project as a whole. At the time of this writing, three Rust editions are available: Rust 2015, Rust 2018, and Rust 2021. This book is written using Rust 2021 edition idioms. -The `edition` key in *Cargo.toml* indicates which edition the compiler should +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. @@ -51,7 +51,6 @@ 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 +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`. diff --git a/rustbook-en/src/appendix-07-nightly-rust.md b/rustbook-en/src/appendix-07-nightly-rust.md index ac3fbb9df..5246d7282 100644 --- a/rustbook-en/src/appendix-07-nightly-rust.md +++ b/rustbook-en/src/appendix-07-nightly-rust.md @@ -5,7 +5,7 @@ developer. ### Stability Without Stagnation -As a language, Rust cares a *lot* about the stability of your code. We want +As a language, Rust cares a _lot_ about the stability of your code. We want Rust to be a rock-solid foundation you can build on, and if things were constantly changing, that would be impossible. At the same time, if we can’t experiment with new features, we may not find out important flaws until after @@ -18,14 +18,14 @@ bring you new features, fewer bugs, and faster compile times. ### Choo, Choo! Release Channels and Riding the Trains -Rust development operates on a *train schedule*. That is, all development is +Rust development operates on a _train schedule_. That is, all development is done on the `master` branch of the Rust repository. Releases follow a software release train model, which has been used by Cisco IOS and other software -projects. There are three *release channels* for Rust: +projects. There are three _release channels_ for Rust: -* Nightly -* Beta -* Stable +- Nightly +- Beta +- Stable Most Rust developers primarily use the stable channel, but those who want to try out experimental new features may use nightly or beta. @@ -85,7 +85,7 @@ stable: * ``` Hooray! Rust 1.5 is done! However, we’ve forgotten one thing: because the six -weeks have gone by, we also need a new beta of the *next* version of Rust, 1.6. +weeks have gone by, we also need a new beta of the _next_ version of Rust, 1.6. So after `stable` branches off of `beta`, the next version of `beta` branches off of `nightly` again: @@ -125,7 +125,7 @@ each version is supported for six weeks. There’s one more catch with this release model: unstable features. Rust uses a technique called “feature flags” to determine what features are enabled in a given release. If a new feature is under active development, it lands on -`master`, and therefore, in nightly, but behind a *feature flag*. If you, as a +`master`, and therefore, in nightly, but behind a _feature flag_. If you, as a user, wish to try out the work-in-progress feature, you can, but you must be using a nightly release of Rust and annotate your source code with the appropriate flag to opt in. @@ -151,7 +151,7 @@ install nightly, for example: $ rustup toolchain install nightly ``` -You can see all of the *toolchains* (releases of Rust and associated +You can see all of the _toolchains_ (releases of Rust and associated components) you have installed with `rustup` as well. Here’s an example on one of your authors’ Windows computer: @@ -174,20 +174,19 @@ $ rustup override set nightly ``` Now, every time you call `rustc` or `cargo` inside of -*~/projects/needs-nightly*, `rustup` will make sure that you are using nightly +_~/projects/needs-nightly_, `rustup` will make sure that you are using nightly Rust, rather than your default of stable Rust. This comes in handy when you have a lot of Rust projects! ### The RFC Process and Teams So how do you learn about these new features? Rust’s development model follows -a *Request For Comments (RFC) process*. If you’d like an improvement in Rust, +a _Request For Comments (RFC) process_. If you’d like an improvement in Rust, you can write up a proposal, called an RFC. Anyone can write RFCs to improve Rust, and the proposals are reviewed and discussed by the Rust team, which is comprised of many topic subteams. There’s -a full list of the teams [on Rust’s -website](https://www.rust-lang.org/governance), which includes teams for +a full list of the teams [on Rust’s website](https://www.rust-lang.org/governance), which includes teams for each area of the project: language design, compiler implementation, infrastructure, documentation, and more. The appropriate team reads the proposal and the comments, writes some comments of their own, and eventually, diff --git a/rustbook-en/src/ch00-00-introduction.md b/rustbook-en/src/ch00-00-introduction.md index 050a62781..c2c5fa6ec 100644 --- a/rustbook-en/src/ch00-00-introduction.md +++ b/rustbook-en/src/ch00-00-introduction.md @@ -7,7 +7,7 @@ [nsprust]: https://nostarch.com/rust-programming-language-2nd-edition [nsp]: https://nostarch.com/ -Welcome to *The Rust Programming Language*, an introductory book about Rust. +Welcome to _The Rust Programming Language_, an introductory book about Rust. The Rust programming language helps you write faster, more reliable software. High-level ergonomics and low-level control are often at odds in programming language design; Rust challenges that conflict. Through balancing powerful @@ -33,12 +33,12 @@ logic rather than chasing down bugs. Rust also brings contemporary developer tools to the systems programming world: -* Cargo, the included dependency manager and build tool, makes adding, +- Cargo, the included dependency manager and build tool, makes adding, compiling, and managing dependencies painless and consistent across the Rust ecosystem. -* The Rustfmt formatting tool ensures a consistent coding style across +- The Rustfmt formatting tool ensures a consistent coding style across developers. -* The rust-analyzer powers Integrated Development Environment (IDE) +- The rust-analyzer powers Integrated Development Environment (IDE) integration for code completion and inline error messages. By using these and other tools in the Rust ecosystem, developers can be @@ -81,7 +81,7 @@ code be fast code as well. The Rust language hopes to support many other users as well; those mentioned here are merely some of the biggest stakeholders. Overall, Rust’s greatest ambition is to eliminate the trade-offs that programmers have accepted for -decades by providing safety *and* productivity, speed *and* ergonomics. Give +decades by providing safety _and_ productivity, speed _and_ ergonomics. Give Rust a try and see if its choices work for you. ## Who This Book Is For @@ -89,7 +89,7 @@ Rust a try and see if its choices work for you. This book assumes that you’ve written code in another programming language but doesn’t make any assumptions about which one. We’ve tried to make the material broadly accessible to those from a wide variety of programming backgrounds. We -don’t spend a lot of time talking about what programming *is* or how to think +don’t spend a lot of time talking about what programming _is_ or how to think about it. If you’re entirely new to programming, you would be better served by reading a book that specifically provides an introduction to programming. @@ -103,7 +103,7 @@ the topic in a later chapter. You’ll find two kinds of chapters in this book: concept chapters and project chapters. In concept chapters, you’ll learn about an aspect of Rust. In project 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. +far. Chapters 2, 12, and 21 are project chapters; the rest are concept chapters. 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 @@ -180,7 +180,7 @@ surrounding text to see whether the example you’re trying to run is meant to error. Ferris will also help you distinguish code that isn’t meant to work: | Ferris | Meaning | -|------------------------------------------------------------------------------------------------------------------|--------------------------------------------------| +| ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | | Ferris with a question mark | This code does not compile! | | Ferris throwing up their hands | This code panics! | | Ferris with one claw up, shrugging | This code does not produce the desired behavior. | diff --git a/rustbook-en/src/ch01-00-getting-started.md b/rustbook-en/src/ch01-00-getting-started.md index ff5e324f7..ccb10e884 100644 --- a/rustbook-en/src/ch01-00-getting-started.md +++ b/rustbook-en/src/ch01-00-getting-started.md @@ -3,6 +3,6 @@ Let’s start your Rust journey! There’s a lot to learn, but every journey starts somewhere. In this chapter, we’ll discuss: -* Installing Rust on Linux, macOS, and Windows -* Writing a program that prints `Hello, world!` -* Using `cargo`, Rust’s package manager and build system +- Installing Rust on Linux, macOS, and Windows +- Writing a program that prints `Hello, world!` +- Using `cargo`, Rust’s package manager and build system diff --git a/rustbook-en/src/ch01-01-installation.md b/rustbook-en/src/ch01-01-installation.md index f554c94b7..55636c09b 100644 --- a/rustbook-en/src/ch01-01-installation.md +++ b/rustbook-en/src/ch01-01-installation.md @@ -39,7 +39,7 @@ for your password. If the install is successful, the following line will appear: Rust is installed now. Great! ``` -You will also need a *linker*, which is a program that Rust uses to join its +You will also need a _linker_, which is a program that Rust uses to join its compiled outputs into one file. It is likely you already have one. If you get linker errors, you should install a C compiler, which will typically include a linker. A C compiler is also useful because some common Rust packages depend on @@ -63,7 +63,7 @@ be prompted to install Visual Studio. This provides a linker and the native libraries needed to compile programs. If you need more help with this step, see [https://rust-lang.github.io/rustup/installation/windows-msvc.html][msvc] -The rest of this book uses commands that work in both *cmd.exe* and PowerShell. +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. ### Troubleshooting diff --git a/rustbook-en/src/ch01-02-hello-world.md b/rustbook-en/src/ch01-02-hello-world.md index 7efd5726e..600401d4d 100644 --- a/rustbook-en/src/ch01-02-hello-world.md +++ b/rustbook-en/src/ch01-02-hello-world.md @@ -16,11 +16,11 @@ prints the text `Hello, world!` to the screen, so we’ll do the same here! You’ll start by making a directory to store your Rust code. It doesn’t matter to Rust where your code lives, but for the exercises and projects in this book, -we suggest making a *projects* directory in your home directory and keeping all +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. +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. For Linux, macOS, and PowerShell on Windows, enter this: @@ -42,12 +42,12 @@ For Windows CMD, enter this: ### Writing and Running a Rust Program -Next, make a new source file and call it *main.rs*. Rust files always end with -the *.rs* extension. If you’re using more than one word in your filename, the +Next, make a new source file and call it _main.rs_. Rust files always end with +the _.rs_ extension. If you’re using more than one word in your filename, the convention is to use an underscore to separate them. For example, use -*hello_world.rs* rather than *helloworld.rs*. +_hello_world.rs_ rather than _helloworld.rs_. -Now open the *main.rs* file you just created and enter the code in Listing 1-1. +Now open the _main.rs_ file you just created and enter the code in Listing 1-1. @@ -60,7 +60,7 @@ fn main() { Save the file and go back to your terminal window in the -*~/projects/hello_world* directory. On Linux or macOS, enter the following +_~/projects/hello_world_ directory. On Linux or macOS, enter the following commands to compile and run the file: ```console @@ -115,7 +115,7 @@ line as the function declaration, adding one space in between. The body of the `main` function holds the following code: ```rust - println!("Hello, world!"); +println!("Hello, world!"); ``` This line does all the work in this little program: it prints text to the @@ -171,24 +171,24 @@ main.pdb 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: +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: ```console $ ./main # or .\main.exe on Windows ``` -If your *main.rs* is your “Hello, world!” program, this line prints `Hello, +If your _main.rs_ is your “Hello, world!” program, this line prints `Hello, world!` to your terminal. If you’re more familiar with a dynamic language, such as Ruby, Python, or JavaScript, you might not be used to compiling and running a program as -separate steps. Rust is an *ahead-of-time compiled* language, meaning you can +separate steps. Rust is an _ahead-of-time compiled_ language, meaning you can compile a program and give the executable to someone else, and they can run it -even without having Rust installed. If you give someone a *.rb*, *.py*, or -*.js* file, they need to have a Ruby, Python, or JavaScript implementation +even without having Rust installed. If you give someone a _.rb_, _.py_, or +_.js_ file, they need to have a Ruby, Python, or JavaScript implementation installed (respectively). But in those languages, you only need one command to compile and run your program. Everything is a trade-off in language design. diff --git a/rustbook-en/src/ch01-03-hello-cargo.md b/rustbook-en/src/ch01-03-hello-cargo.md index dea721d38..048ee864c 100644 --- a/rustbook-en/src/ch01-03-hello-cargo.md +++ b/rustbook-en/src/ch01-03-hello-cargo.md @@ -4,7 +4,7 @@ Cargo is Rust’s build system and package manager. Most Rustaceans use this too to manage their Rust projects because Cargo handles a lot of tasks for you, such as building your code, downloading the libraries your code depends on, and building those libraries. (We call the libraries that your code needs -*dependencies*.) +_dependencies_.) The simplest Rust programs, like the one we’ve written so far, don’t have any dependencies. If we had built the “Hello, world!” project with Cargo, it would @@ -30,7 +30,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 +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: @@ -39,15 +39,15 @@ $ cargo new hello_cargo $ cd hello_cargo ``` -The first command creates a new directory and project called *hello_cargo*. -We’ve named our project *hello_cargo*, and Cargo creates its files in a +The first command creates a new directory and project called _hello_cargo_. +We’ve named our project _hello_cargo_, and Cargo creates its files in a directory of the 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. +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. +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`. @@ -55,7 +55,7 @@ repository; you can override this behavior by using `cargo new --vcs=git`. > use a different version control system or no version control system by using > the `--vcs` flag. Run `cargo new --help` to see the available options. -Open *Cargo.toml* in your text editor of choice. It should look similar to the +Open _Cargo.toml_ in your text editor of choice. It should look similar to the code in Listing 1-2. @@ -73,8 +73,8 @@ edition = "2021" -This file is in the [*TOML*][toml] (*Tom’s Obvious, Minimal -Language*) format, which is Cargo’s configuration format. +This file is in the [_TOML_][toml] (_Tom’s Obvious, Minimal +Language_) format, which is Cargo’s configuration format. The first line, `[package]`, is a section heading that indicates that the following statements are configuring a package. As we add more information to @@ -86,10 +86,10 @@ about the `edition` key in [Appendix E][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 -*crates*. We won’t need any other crates for this project, but we will in the +_crates_. We won’t need any other crates for this project, but we will in the first project in Chapter 2, so we’ll use this dependencies section then. -Now open *src/main.rs* and take a look: +Now open _src/main.rs_ and take a look: Filename: src/main.rs @@ -101,10 +101,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 project and the -project Cargo generated are that Cargo placed the code in the *src* directory -and we have a *Cargo.toml* configuration file in the top directory. +project Cargo generated 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 +Cargo expects your source files to live inside the _src_ directory. The top-level project directory is just for README files, license information, configuration files, and anything else not related to your code. Using Cargo helps you organize your projects. There’s a place for everything, and @@ -112,14 +112,14 @@ 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 -project code into the *src* directory and create an appropriate *Cargo.toml* -file. One easy way to get that *Cargo.toml* file is to run `cargo init`, which +project code into the _src_ directory and create an appropriate _Cargo.toml_ +file. One easy way to get that _Cargo.toml_ file is to run `cargo init`, which will create it for you automatically. ### Building and Running a Cargo Project 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 +program with Cargo! From your _hello_cargo_ directory, build your project by entering the following command: ```console @@ -128,10 +128,10 @@ $ cargo build Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs ``` -This command creates an executable file in *target/debug/hello_cargo* (or -*target\debug\hello_cargo.exe* on Windows) rather than in your current +This command creates an executable file in _target/debug/hello_cargo_ (or +_target\debug\hello_cargo.exe_ on Windows) rather than in your current directory. Because the default build is a debug build, Cargo puts the binary in -a directory named *debug*. You can run the executable with this command: +a directory named _debug_. You can run the executable with this command: ```console $ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows @@ -140,7 +140,7 @@ Hello, world! If all goes well, `Hello, world!` should print to the terminal. Running `cargo build` for the first time also causes Cargo to create a new file at the top -level: *Cargo.lock*. This file keeps track of the exact versions of +level: _Cargo.lock_. This file keeps track of the exact versions of dependencies in your project. This project doesn’t have dependencies, so the file is a bit sparse. You won’t ever need to change this file manually; Cargo manages its contents for you. @@ -193,13 +193,13 @@ ready to use the executable. Let’s recap what we’ve learned so far about Cargo: -* We can create a project using `cargo new`. -* We can build a project using `cargo build`. -* We can build and run a project in one step using `cargo run`. -* We can build a project without producing a binary to check for errors using +- We can create a project using `cargo new`. +- We can build a project using `cargo build`. +- We can build and run a project in one step using `cargo run`. +- We can build a project without producing a binary to check for errors using `cargo check`. -* Instead of saving the result of the build in the same directory as our code, - Cargo stores it in the *target/debug* directory. +- Instead of saving the result of the build in the same directory as our code, + Cargo stores it in the _target/debug_ directory. An additional advantage of using Cargo is that the commands are the same no matter which operating system you’re working on. So, at this point, we’ll no @@ -209,14 +209,14 @@ longer provide specific instructions for Linux and macOS versus Windows. When your project is finally ready for release, you can use `cargo build --release` to compile it with optimizations. This command will create an -executable in *target/release* instead of *target/debug*. The optimizations +executable in _target/release_ instead of _target/debug_. The optimizations make your Rust code run faster, but turning them on lengthens the time it takes for your program to compile. This is why there are two different profiles: one for development, when you want to rebuild quickly and often, and another for building the final program you’ll give to a user that won’t be rebuilt repeatedly and that will run as fast as possible. If you’re benchmarking your code’s running time, be sure to run `cargo build --release` and benchmark with -the executable in *target/release*. +the executable in _target/release_. ### Cargo as Convention @@ -243,11 +243,11 @@ For more information about Cargo, check out [its documentation][cargo]. You’re already off to a great start on your Rust journey! In this chapter, 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 -* Create and run a new project using the conventions of Cargo +- 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 +- 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 and writing Rust code. So, in Chapter 2, we’ll build a guessing game program. diff --git a/rustbook-en/src/ch02-00-guessing-game-tutorial.md b/rustbook-en/src/ch02-00-guessing-game-tutorial.md index b66a5c281..e2e7054d8 100644 --- a/rustbook-en/src/ch02-00-guessing-game-tutorial.md +++ b/rustbook-en/src/ch02-00-guessing-game-tutorial.md @@ -15,7 +15,7 @@ correct, the game will print a congratulatory message and exit. ## Setting Up a New Project -To set up a new project, go to the *projects* directory that you created in +To set up a new project, go to the _projects_ directory that you created in Chapter 1 and make a new project using Cargo, like so: ```console @@ -27,7 +27,7 @@ The first command, `cargo new`, takes the name of the project (`guessing_game`) as the first argument. The second command changes to the new project’s directory. -Look at the generated *Cargo.toml* file: +Look at the generated _Cargo.toml_ file: + ### Handling Potential Failure with `Result` @@ -229,9 +230,9 @@ discuss what this line does. As mentioned earlier, `read_line` puts whatever the user enters into the string we pass to it, but it also returns a `Result` value. [`Result`][result] is an [*enumeration*][enums], often called an *enum*, +ignore --> is an [_enumeration_][enums], often called an _enum_, which is a type that can be in one of multiple possible states. We call each -possible state a *variant*. +possible state a _variant_. [Chapter 6][enums] will cover enums in more detail. The purpose of these `Result` types is to encode error-handling information. @@ -328,12 +329,12 @@ said functionality. ### Using a Crate to Get More Functionality Remember that a crate is a collection of Rust source code files. The project -we’ve been building is a *binary crate*, which is an executable. The `rand` -crate is a *library crate*, which contains code that is intended to be used in +we’ve been building is a _binary crate_, which is an executable. The `rand` +crate is a _library crate_, which contains code that is intended to be used in other programs and can’t be executed on its own. Cargo’s coordination of external crates is where Cargo really shines. Before we -can write code that uses `rand`, we need to modify the *Cargo.toml* file to +can write code that uses `rand`, we need to modify the _Cargo.toml_ file to include the `rand` crate as a dependency. Open that file now and add the following line to the bottom, beneath the `[dependencies]` section header that Cargo created for you. Be sure to specify `rand` exactly as we have here, with @@ -351,12 +352,12 @@ this version number, or the code examples in this tutorial may not work: {{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:8:}} ``` -In the *Cargo.toml* file, everything that follows a header is part of that +In the _Cargo.toml_ file, everything that follows a header is part of that section that continues until another section starts. In `[dependencies]` you tell Cargo which external crates your project depends on and which versions of those crates you require. In this case, we specify the `rand` crate with the semantic version specifier `0.8.5`. Cargo understands [Semantic -Versioning][semver] (sometimes called *SemVer*), which is a +Versioning][semver] (sometimes called _SemVer_), which is a standard for writing version numbers. The specifier `0.8.5` is actually shorthand for `^0.8.5`, which means any version that is at least 0.8.5 but below 0.9.0. @@ -411,7 +412,7 @@ code, thanks to SemVer!) and different lines (depending on the operating system), and the lines may be in a different order. When we include an external dependency, Cargo fetches the latest versions of -everything that dependency needs from the *registry*, which is a copy of data +everything that dependency needs 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. @@ -424,11 +425,11 @@ 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 downloaded and compiled the dependencies, and you haven’t changed anything -about them in your *Cargo.toml* file. Cargo also knows that you haven’t changed +about them in your _Cargo.toml_ file. Cargo also knows that you haven’t changed anything about your code, so it doesn’t recompile that either. With nothing to do, it simply exits. -If you open the *src/main.rs* file, make a trivial change, and then save it and +If you open the _src/main.rs_ file, make a trivial change, and then save it and build again, you’ll only see two lines of output: , but for now, know that this feature is @@ -852,7 +853,7 @@ match the first arm’s pattern, and the `match` expression will just return the `num` value that `parse` produced and put inside the `Ok` value. That number will end up right where we want it in the new `guess` variable we’re creating. -If `parse` is *not* able to turn the string into a number, it will return an +If `parse` is _not_ able to turn the string into a number, it will return an `Err` value that contains more information about the error. The `Err` value does not match the `Ok(num)` pattern in the first `match` arm, but it does match the `Err(_)` pattern in the second arm. The underscore, `_`, is a diff --git a/rustbook-en/src/ch03-00-common-programming-concepts.md b/rustbook-en/src/ch03-00-common-programming-concepts.md index 2e37fad02..21ca8c58d 100644 --- a/rustbook-en/src/ch03-00-common-programming-concepts.md +++ b/rustbook-en/src/ch03-00-common-programming-concepts.md @@ -12,7 +12,7 @@ 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 +> 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 diff --git a/rustbook-en/src/ch03-01-variables-and-mutability.md b/rustbook-en/src/ch03-01-variables-and-mutability.md index 058f7bb5c..e5d599c03 100644 --- a/rustbook-en/src/ch03-01-variables-and-mutability.md +++ b/rustbook-en/src/ch03-01-variables-and-mutability.md @@ -9,10 +9,10 @@ Let’s explore how and why Rust encourages you to favor immutability and why sometimes you might want to opt out. When a variable is immutable, once a value is bound to a name, you can’t change -that value. To illustrate this, generate a new project called *variables* in -your *projects* directory by using `cargo new variables`. +that value. To illustrate this, generate a new project called _variables_ in +your _projects_ directory by using `cargo new variables`. -Then, in your new *variables* directory, open *src/main.rs* and replace its +Then, in your new _variables_ directory, open _src/main.rs_ and replace its code with the following code, which won’t compile just yet: Filename: src/main.rs @@ -30,11 +30,10 @@ regarding an immutability error, as shown in this output: This example shows how the compiler helps you find errors in your programs. Compiler errors can be frustrating, but really they only mean your program -isn’t safely doing what you want it to do yet; they do *not* mean that you’re +isn’t safely doing what you want it to do yet; they do _not_ mean that you’re not a good programmer! Experienced Rustaceans still get compiler errors. -You received the error message `` cannot assign twice to immutable variable `x` -`` because you tried to assign a second value to the immutable `x` variable. +You received the error message `` cannot assign twice to immutable variable `x` `` because you tried to assign a second value to the immutable `x` variable. It’s important that we get compile-time errors when we attempt to change a value that’s designated as immutable because this very situation can lead to @@ -42,7 +41,7 @@ bugs. If one part of our code operates on the assumption that a value will never change and another part of our code changes that value, it’s possible that the first part of the code won’t do what it was designed to do. The cause of this kind of bug can be difficult to track down after the fact, especially -when the second piece of code changes the value only *sometimes*. The Rust +when the second piece of code changes the value only _sometimes_. The Rust compiler guarantees that when you state that a value won’t change, it really won’t change, so you don’t have to keep track of it yourself. Your code is thus easier to reason through. @@ -54,7 +53,7 @@ adding `mut` in front of the variable name as you did in [Chapter intent to future readers of the code by indicating that other parts of the code will be changing this variable’s value. -For example, let’s change *src/main.rs* to the following: +For example, let’s change _src/main.rs_ to the following: Filename: src/main.rs @@ -74,13 +73,13 @@ depends on what you think is clearest in that particular situation. ### Constants -Like immutable variables, *constants* are values that are bound to a name and +Like immutable variables, _constants_ are values that are bound to a name and are not allowed to change, but there are a few differences between constants and variables. First, you aren’t allowed to use `mut` with constants. Constants aren’t just immutable by default—they’re always immutable. You declare constants using the -`const` keyword instead of the `let` keyword, and the type of the value *must* +`const` keyword instead of the `let` keyword, and the type of the value _must_ be annotated. We’ll cover types and type annotations in the next section, [“Data Types”][data-types], so don’t worry about the details right now. Just know that you must always annotate the type. @@ -124,7 +123,7 @@ hardcoded value needed to be updated in the future. As you saw in the guessing game tutorial in [Chapter 2][comparing-the-guess-to-the-secret-number], you can declare a new variable with the same name as a previous variable. Rustaceans say that the -first variable is *shadowed* by the second, which means that the second +first variable is _shadowed_ by the second, which means that the second variable is what the compiler will see when you use the name of the variable. In effect, the second variable overshadows the first, taking any uses of the variable name to itself until either it itself is shadowed or the scope ends. @@ -184,8 +183,7 @@ The error says we’re not allowed to mutate a variable’s type: Now that we’ve explored how variables work, let’s look at more data types they can have. -[comparing-the-guess-to-the-secret-number]: -ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number +[comparing-the-guess-to-the-secret-number]: ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number [data-types]: ch03-02-data-types.html#data-types [storing-values-with-variables]: ch02-00-guessing-game-tutorial.html#storing-values-with-variables [const-eval]: ../reference/const_eval.html diff --git a/rustbook-en/src/ch03-02-data-types.md b/rustbook-en/src/ch03-02-data-types.md index 881319dbc..e6d88fbb1 100644 --- a/rustbook-en/src/ch03-02-data-types.md +++ b/rustbook-en/src/ch03-02-data-types.md @@ -1,10 +1,10 @@ ## Data Types -Every value in Rust is of a certain *data type*, which tells Rust what kind of +Every value in Rust is of a certain _data type_, which tells Rust what kind of data is being specified so it knows how to work with that data. We’ll look at two data type subsets: scalar and compound. -Keep in mind that Rust is a *statically typed* language, which means that it +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 @@ -28,13 +28,13 @@ You’ll see different type annotations for other data types. ### Scalar Types -A *scalar* type represents a single value. Rust has four primary scalar types: +A _scalar_ type represents a single value. Rust has four primary scalar types: integers, floating-point numbers, Booleans, and characters. You may recognize these from other programming languages. Let’s jump into how they work in Rust. #### Integer Types -An *integer* is a number without a fractional component. We used one integer +An _integer_ is a number without a fractional component. We used one integer type in Chapter 2, the `u32` type. This type declaration indicates that the value it’s associated with should be an unsigned integer (signed integer types start with `i` instead of `u`) that takes up 32 bits of space. Table 3-1 shows @@ -44,7 +44,7 @@ the type of an integer value. Table 3-1: Integer Types in Rust | Length | Signed | Unsigned | -|---------|---------|----------| +| ------- | ------- | -------- | | 8-bit | `i8` | `u8` | | 16-bit | `i16` | `u16` | | 32-bit | `i32` | `u32` | @@ -53,7 +53,7 @@ the type of an integer value. | arch | `isize` | `usize` | Each variant can be either signed or unsigned and has an explicit size. -*Signed* and *unsigned* refer to whether it’s possible for the number to be +_Signed_ and _unsigned_ refer to whether it’s possible for the number to be negative—in other words, whether the number needs to have a sign 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 @@ -63,7 +63,7 @@ Signed numbers are stored using [two’s complement][twos-complement] representation. Each signed variant can store numbers from -(2n - 1) to 2n - -1 - 1 inclusive, where *n* is the number of bits that variant uses. So an +1 - 1 inclusive, where _n_ is the number of bits that variant uses. So an `i8` can store numbers from -(27) to 27 - 1, which equals -128 to 127. Unsigned variants can store numbers from 0 to 2n - 1, so a `u8` can store numbers from 0 to 28 - 1, which equals 0 to 255. @@ -82,7 +82,7 @@ have the same value as if you had specified `1000`. Table 3-2: Integer Literals in Rust | Number literals | Example | -|------------------|---------------| +| ---------------- | ------------- | | Decimal | `98_222` | | Hex | `0xff` | | Octal | `0o77` | @@ -98,17 +98,17 @@ some sort of collection. > > 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 that range, such as -> 256, *integer overflow* will occur, which can result in one of two behaviors. +> 256, _integer overflow_ will occur, which can result in one of two behaviors. > 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 +> 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] 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 +> _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`, the value 256 becomes > 0, the value 257 becomes 1, and so on. The program won’t panic, but the @@ -118,16 +118,16 @@ some sort of collection. > To explicitly handle the possibility of overflow, you can use these families > of methods provided by the standard library for primitive numeric types: > -> * Wrap in all modes with the `wrapping_*` methods, such as `wrapping_add`. -> * Return the `None` value if there is overflow with the `checked_*` methods. -> * Return the value and a boolean indicating whether there was overflow with +> - Wrap in all modes with the `wrapping_*` methods, such as `wrapping_add`. +> - Return the `None` value if there is overflow with the `checked_*` methods. +> - Return the value and a boolean indicating whether there was overflow with > the `overflowing_*` methods. -> * Saturate at the value’s minimum or maximum values with the `saturating_*` +> - Saturate at the value’s minimum or maximum values with the `saturating_*` > methods. #### Floating-Point Types -Rust also has two primitive types for *floating-point numbers*, which are +Rust also has two primitive types for _floating-point numbers_, which are numbers with decimal points. Rust’s floating-point types are `f32` and `f64`, which are 32 bits and 64 bits in size, respectively. The default type is `f64` because on modern CPUs, it’s roughly the same speed as `f32` but is capable of @@ -201,12 +201,12 @@ Strings”][strings] in Chapter 8. ### Compound Types -*Compound types* can group multiple values into one type. Rust has two +_Compound types_ can group multiple values into one type. Rust has two primitive compound types: tuples and arrays. #### The Tuple Type -A *tuple* is a general way of grouping together a number of values with a +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. @@ -233,7 +233,7 @@ use pattern matching to destructure a tuple value, like this: This program first creates a tuple and binds it to the variable `tup`. It then uses a pattern with `let` to take `tup` and turn it into three separate -variables, `x`, `y`, and `z`. This is called *destructuring* because it breaks +variables, `x`, `y`, and `z`. This is called _destructuring_ because it breaks the single tuple into three parts. Finally, the program prints the value of `y`, which is `6.4`. @@ -250,14 +250,14 @@ This program creates the tuple `x` and then accesses each element of the tuple using their respective indices. As with most programming languages, the first index in a tuple is 0. -The tuple without any values has a special name, *unit*. This value and its +The tuple without any values has a special name, _unit_. This value and its corresponding type are both written `()` and represent an empty value or an empty return type. Expressions implicitly return the unit value if they don’t return any other value. #### The Array Type -Another way to have a collection of multiple values is with an *array*. Unlike +Another way to have a collection of multiple values is with an _array_. Unlike a tuple, every element of an array must have the same type. Unlike arrays in some other languages, arrays in Rust have a fixed length. @@ -274,8 +274,8 @@ Arrays are useful when you want your data allocated on the stack, the same as the other types we have seen so far, rather than the heap (we will discuss the stack and the heap more in [Chapter 4][stack-and-heap]) or when you want to ensure you always have a fixed number of elements. An array isn’t as -flexible as the vector type, though. A *vector* is a similar collection type -provided by the standard library that *is* allowed to grow or shrink in size. If +flexible as the vector type, though. A _vector_ is a similar collection type +provided by the standard library that _is_ allowed to grow or shrink in size. If you’re unsure whether to use an array or a vector, chances are you should use a vector. [Chapter 8][vectors] discusses vectors in more detail. @@ -356,7 +356,7 @@ index out of bounds: the len is 5 but the index is 10 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` -The program resulted in a *runtime* error at the point of using an invalid +The program resulted in a _runtime_ error at the point of using an invalid value in the indexing operation. The program exited with an error message and didn’t execute the final `println!` statement. When you attempt to access an element using indexing, Rust will check that the index you’ve specified is less @@ -372,8 +372,7 @@ kind of error by immediately exiting instead of allowing the memory access and continuing. Chapter 9 discusses more of Rust’s error handling and how you can write readable, safe code that neither panics nor allows invalid memory access. -[comparing-the-guess-to-the-secret-number]: -ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number +[comparing-the-guess-to-the-secret-number]: ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number [twos-complement]: https://en.wikipedia.org/wiki/Two%27s_complement [control-flow]: ch03-05-control-flow.html#control-flow [strings]: ch08-02-strings.html#storing-utf-8-encoded-text-with-strings diff --git a/rustbook-en/src/ch03-03-how-functions-work.md b/rustbook-en/src/ch03-03-how-functions-work.md index bb8c73a62..8442825ab 100644 --- a/rustbook-en/src/ch03-03-how-functions-work.md +++ b/rustbook-en/src/ch03-03-how-functions-work.md @@ -5,7 +5,7 @@ important functions in the language: the `main` function, which is the entry point of many programs. You’ve also seen the `fn` keyword, which allows you to declare new functions. -Rust code uses *snake case* as the conventional style for function and variable +Rust code uses _snake case_ as the conventional style for function and variable names, in which all letters are lowercase and underscores separate words. Here’s a program that contains an example function definition: @@ -22,12 +22,12 @@ body begins and ends. We can call any function we’ve defined by entering its name followed by a set of parentheses. Because `another_function` is defined in the program, it can be called from inside the `main` function. Note that we defined `another_function` -*after* the `main` function in the source code; we could have defined it before +_after_ the `main` function in the source code; we could have defined it before as well. Rust doesn’t care where you define your functions, only that they’re defined somewhere in a scope that can be seen by the caller. -Let’s start a new binary project named *functions* to explore functions -further. Place the `another_function` example in *src/main.rs* and run it. You +Let’s start a new binary project named _functions_ to explore functions +further. Place the `another_function` example in _src/main.rs_ and run it. You should see the following output: ```console @@ -40,11 +40,11 @@ and its message is printed. ### Parameters -We can define functions to have *parameters*, which are special variables that +We can define functions to have _parameters_, which are special variables that are part of a function’s signature. When a function has parameters, you can provide it with concrete values for those parameters. Technically, the concrete -values are called *arguments*, but in casual conversation, people tend to use -the words *parameter* and *argument* interchangeably for either the variables +values are called _arguments_, but in casual conversation, people tend to use +the words _parameter_ and _argument_ interchangeably for either the variables in a function’s definition or the concrete values passed in when you call a function. @@ -67,7 +67,7 @@ The declaration of `another_function` has one parameter named `x`. The type of `println!` macro puts `5` where the pair of curly brackets containing `x` was in the format string. -In function signatures, you *must* declare the type of each parameter. This is +In function signatures, you _must_ declare the type of each parameter. This is a deliberate decision in Rust’s design: requiring type annotations in function definitions means the compiler almost never needs you to use them elsewhere in the code to figure out what type you mean. The compiler is also able to give @@ -87,8 +87,8 @@ parameters. The first parameter is named `value` and is an `i32`. The second is named `unit_label` and is type `char`. The function then prints text containing both the `value` and the `unit_label`. -Let’s try running this code. Replace the program currently in your *functions* -project’s *src/main.rs* file with the preceding example and run it using `cargo +Let’s try running this code. Replace the program currently in your _functions_ +project’s _src/main.rs_ file with the preceding example and run it using `cargo run`: ```console @@ -108,9 +108,9 @@ understand. Other languages don’t have the same distinctions, so let’s look what statements and expressions are and how their differences affect the bodies of functions. -* **Statements** are instructions that perform some action and do not return +- **Statements** are instructions that perform some action and do not return a value. -* **Expressions** evaluate to a resultant value. Let’s look at some examples. +- **Expressions** evaluate to a resultant value. Let’s look at some examples. We’ve actually already used statements and expressions. Creating a variable and assigning a value to it with the `let` keyword is a statement. In Listing 3-1, @@ -125,7 +125,7 @@ assigning a value to it with the `let` keyword is a statement. In Listing 3-1, Function definitions are also statements; the entire preceding example is a -statement in itself. (As we will see below, *calling* a function is not a +statement in itself. (As we will see below, _calling_ a function is not a statement.) Statements do not return values. Therefore, you can’t assign a `let` statement diff --git a/rustbook-en/src/ch03-04-comments.md b/rustbook-en/src/ch03-04-comments.md index bfb0cfe17..01978d605 100644 --- a/rustbook-en/src/ch03-04-comments.md +++ b/rustbook-en/src/ch03-04-comments.md @@ -1,7 +1,7 @@ ## Comments All programmers strive to make their code easy to understand, but sometimes -extra explanation is warranted. In these cases, programmers leave *comments* in +extra explanation is warranted. In these cases, programmers leave _comments_ in their source code that the compiler will ignore but people reading the source code may find useful. diff --git a/rustbook-en/src/ch03-05-control-flow.md b/rustbook-en/src/ch03-05-control-flow.md index be93b275e..ac89726fd 100644 --- a/rustbook-en/src/ch03-05-control-flow.md +++ b/rustbook-en/src/ch03-05-control-flow.md @@ -11,8 +11,8 @@ An `if` expression allows you to branch your code depending on conditions. You provide a condition and then state, “If this condition is met, run this block of code. If the condition is not met, do not run this block of code.” -Create a new project called *branches* in your *projects* directory to explore -the `if` expression. In the *src/main.rs* file, input the following: +Create a new project called _branches_ in your _projects_ directory to explore +the `if` expression. In the _src/main.rs_ file, input the following: Filename: src/main.rs @@ -24,7 +24,7 @@ All `if` expressions start with the keyword `if`, followed by a condition. In this case, the condition checks whether or not the variable `number` has a value less than 5. We place the block of code to execute if the condition is `true` immediately after the condition inside curly brackets. Blocks of code -associated with the conditions in `if` expressions are sometimes called *arms*, +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] section of Chapter 2. @@ -54,7 +54,7 @@ Run the program again, and look at the output: {{#include ../listings/ch03-common-programming-concepts/no-listing-27-if-false/output.txt}} ``` -It’s also worth noting that the condition in this code *must* be a `bool`. If +It’s also worth noting that the condition in this code _must_ be a `bool`. If the condition isn’t a `bool`, we’ll get an error. For example, try running the following code: @@ -169,9 +169,9 @@ if it had to keep track of multiple hypothetical types for any variable. ### Repetition with Loops It’s often useful to execute a block of code more than once. For this task, -Rust provides several *loops*, which will run through the code inside the loop +Rust provides several _loops_, which will run through the code inside the loop body to the end and then start immediately back at the beginning. To experiment -with loops, let’s make a new project called *loops*. +with loops, let’s make a new project called _loops_. Rust has three kinds of loops: `loop`, `while`, and `for`. Let’s try each one. @@ -180,7 +180,7 @@ Rust has three kinds of loops: `loop`, `while`, and `for`. Let’s try each one. The `loop` keyword tells Rust to execute a block of code over and over again forever or until you explicitly tell it to stop. -As an example, change the *src/main.rs* file in your *loops* directory to look +As an example, change the _src/main.rs_ file in your _loops_ directory to look like this: Filename: src/main.rs @@ -254,7 +254,7 @@ loop, `return` always exits the current function. #### Loop Labels to Disambiguate Between Multiple Loops If you have loops within loops, `break` and `continue` apply to the innermost -loop at that point. You can optionally specify a *loop label* on a loop that +loop at that point. You can optionally specify a _loop label_ on a loop that you can then use with `break` or `continue` to specify that those keywords apply to the labeled loop instead of the innermost loop. Loop labels must begin with a single quote. Here’s an example with two nested loops: @@ -375,15 +375,13 @@ and compound data types, functions, comments, `if` expressions, and loops! To practice with the concepts discussed in this chapter, try building programs to do the following: -* Convert temperatures between Fahrenheit and Celsius. -* Generate the *n*th Fibonacci number. -* Print the lyrics to the Christmas carol “The Twelve Days of Christmas,” +- Convert temperatures between Fahrenheit and Celsius. +- Generate the *n*th Fibonacci number. +- Print the lyrics to the Christmas carol “The Twelve Days of Christmas,” taking advantage of the repetition in the song. -When you’re ready to move on, we’ll talk about a concept in Rust that *doesn’t* +When you’re ready to move on, we’ll talk about a concept in Rust that _doesn’t_ commonly exist in other programming languages: ownership. -[comparing-the-guess-to-the-secret-number]: -ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number -[quitting-after-a-correct-guess]: -ch02-00-guessing-game-tutorial.html#quitting-after-a-correct-guess +[comparing-the-guess-to-the-secret-number]: ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number +[quitting-after-a-correct-guess]: ch02-00-guessing-game-tutorial.html#quitting-after-a-correct-guess diff --git a/rustbook-en/src/ch04-01-what-is-ownership.md b/rustbook-en/src/ch04-01-what-is-ownership.md index 5ef7b5f97..60d4cb4ea 100644 --- a/rustbook-en/src/ch04-01-what-is-ownership.md +++ b/rustbook-en/src/ch04-01-what-is-ownership.md @@ -1,6 +1,6 @@ ## What Is Ownership? -*Ownership* is a set of rules that govern how a Rust program manages memory. +_Ownership_ is a set of rules that govern how a Rust program manages memory. All programs have to manage the way they use a computer’s memory while running. Some languages have garbage collection that regularly looks for no-longer-used memory as the program runs; in other languages, the programmer must explicitly @@ -31,20 +31,20 @@ strings. > Both the stack and the heap are parts of memory 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 +> 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 +> 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 the heap > instead. > > The heap is less organized: when you put data on the heap, you request a > certain amount of space. The memory allocator 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* (pushing values onto +> 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_ (pushing values onto > the stack is not considered allocating). Because the pointer to the heap 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. Think of being seated at a @@ -88,9 +88,9 @@ strings. First, let’s take a look at the ownership rules. Keep these rules in mind as we work through the examples that illustrate them: -* Each value in Rust has an *owner*. -* There can only be one owner at a time. -* When the owner goes out of scope, the value will be dropped. +- Each value in Rust has an _owner_. +- There can only be one owner at a time. +- When the owner goes out of scope, the value will be dropped. ### Variable Scope @@ -100,7 +100,7 @@ examples inside a `main` function manually. As a result, our examples will be a bit more concise, letting us focus on the actual details rather than boilerplate code. -As a first example of ownership, we’ll look at the *scope* of some variables. A +As a first example of ownership, we’ll look at the _scope_ of some variables. A scope is the range within a program for which an item is valid. Take the following variable: @@ -110,7 +110,7 @@ let s = "hello"; The variable `s` refers to a string literal, where the value of the string is hardcoded into the text of our program. The variable is valid from the point at -which it’s declared until the end of the current *scope*. Listing 4-1 shows a +which it’s declared until the end of the current _scope_. Listing 4-1 shows a program with comments annotating where the variable `s` would be valid. @@ -123,8 +123,8 @@ program with comments annotating where the variable `s` would be valid. In other words, there are two important points in time here: -* When `s` comes *into* scope, it is valid. -* It remains valid until it goes *out of* scope. +- When `s` comes _into_ scope, it is valid. +- It remains valid until it goes _out of_ scope. At this point, the relationship between scopes and when variables are valid is similar to that in other programming languages. Now we’ll build on top of this @@ -167,7 +167,7 @@ Syntax”][method-syntax] section of Chapter 5, and when we talk about namespacing with modules in [“Paths for Referring to an Item in the Module Tree”][paths-module-tree] in Chapter 7. -This kind of string *can* be mutated: +This kind of string _can_ be mutated: ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/src/main.rs:here}} @@ -189,16 +189,16 @@ With the `String` type, in order to support a mutable, growable piece of text, we need to allocate an amount of memory on the heap, unknown at compile time, to hold the contents. This means: -* The memory must be requested from the memory allocator at runtime. -* We need a way of returning this memory to the allocator when we’re done with +- The memory must be requested from the memory allocator at runtime. +- We need a way of returning this memory to the allocator when we’re done with our `String`. That first part is done by us: when we call `String::from`, its implementation requests the memory it needs. This is pretty much universal in programming languages. -However, the second part is different. In languages with a *garbage collector -(GC)*, the GC keeps track of and cleans up memory that isn’t being used +However, the second part is different. In languages with a _garbage collector +(GC)_, the GC keeps track of and cleans up memory that isn’t being used anymore, and we don’t need to think about it. In most languages without a GC, it’s our responsibility to identify when memory is no longer being used and to call code to explicitly free it, just as we did to request it. Doing this @@ -223,7 +223,7 @@ the code to return the memory. Rust calls `drop` automatically at the closing curly bracket. > Note: In C++, this pattern of deallocating resources at the end of an item’s -> lifetime is sometimes called *Resource Acquisition Is Initialization (RAII)*. +> lifetime is sometimes called _Resource Acquisition Is Initialization (RAII)_. > The `drop` function in Rust will be familiar to you if you’ve used RAII > patterns. @@ -233,6 +233,7 @@ complicated situations when we want to have multiple variables use the data we’ve allocated on the heap. Let’s explore some of those situations now. + #### Variables and Data Interacting with Move @@ -297,7 +298,7 @@ src="img/trpl04-02.svg" class="center" style="width: 50%;" /> Figure 4-2: Representation in memory of the variable `s2` that has a copy of the pointer, length, and capacity of `s1` -The representation does *not* look like Figure 4-3, which is what memory would +The representation does _not_ look like Figure 4-3, which is what memory would look like if Rust instead copied the heap data as well. If Rust did this, the operation `s2 = s1` could be very expensive in terms of runtime performance if the data on the heap were large. @@ -313,7 +314,7 @@ Earlier, we said that when a variable goes out of scope, Rust automatically calls the `drop` function and cleans up the heap memory for that variable. But Figure 4-2 shows both data pointers pointing to the same location. This is a problem: when `s2` and `s1` go out of scope, they will both try to free the -same memory. This is known as a *double free* error and is one of the memory +same memory. This is known as a _double free_ error and is one of the memory safety bugs we mentioned previously. Freeing memory twice can lead to memory corruption, which can potentially lead to security vulnerabilities. @@ -333,12 +334,12 @@ invalidated reference: {{#include ../listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt}} ``` -If you’ve heard the terms *shallow copy* and *deep copy* while working with +If you’ve heard the terms _shallow copy_ and _deep copy_ while working with other languages, the concept of copying the pointer, length, and capacity without copying the data probably sounds like making a shallow copy. But because Rust also invalidates the first variable, instead of being called a -shallow copy, it’s known as a *move*. In this example, we would say that `s1` -was *moved* into `s2`. So, what actually happens is shown in Figure 4-4. +shallow copy, it’s known as a _move_. In this example, we would say that `s1` +was _moved_ into `s2`. So, what actually happens is shown in Figure 4-4. Three tables: tables s1 and s2 representing those strings on the
 stack, respectively, and both pointing to the same string data on the heap.
@@ -353,7 +354,7 @@ That solves our problem! With only `s2` valid, when it goes out of scope it
 alone will free the memory, and we’re done.
 
 In addition, there’s a design choice that’s implied by this: Rust will never
-automatically create “deep” copies of your data. Therefore, any *automatic*
+automatically create “deep” copies of your data. Therefore, any _automatic_
 copying can be assumed to be inexpensive in terms of runtime performance.
 
 #### Scope and Assignment
@@ -388,11 +389,12 @@ function on it and its memory will be freed right away. When we print the value
 at the end, it will be ` + #### Variables and Data Interacting with Clone -If we *do* want to deeply copy the heap data of the `String`, not just the +If we _do_ want to deeply copy the heap data of the `String`, not just the stack data, we can use a common method called `clone`. We’ll discuss method syntax in Chapter 5, but because methods are a common feature in many programming languages, you’ve probably seen them before. @@ -404,7 +406,7 @@ Here’s an example of the `clone` method in action: ``` This works just fine and explicitly produces the behavior shown in Figure 4-3, -where the heap data *does* get copied. +where the heap data _does_ get copied. When you see a call to `clone`, you know that some arbitrary code is being executed and that code may be expensive. It’s a visual indicator that something @@ -448,11 +450,11 @@ values can implement `Copy`, and nothing that requires allocation or is some form of resource can implement `Copy`. Here are some of the types that implement `Copy`: -* All the integer types, such as `u32`. -* The Boolean type, `bool`, with values `true` and `false`. -* All the floating-point types, such as `f64`. -* The character type, `char`. -* Tuples, if they only contain types that also implement `Copy`. For example, +- All the integer types, such as `u32`. +- The Boolean type, `bool`, with values `true` and `false`. +- All the floating-point types, such as `f64`. +- The character type, `char`. +- Tuples, if they only contain types that also implement `Copy`. For example, `(i32, i32)` implements `Copy`, but `(i32, String)` does not. ### Ownership and Functions @@ -512,7 +514,7 @@ Rust does let us return multiple values using a tuple, as shown in Listing 4-5. But this is too much ceremony and a lot of work for a concept that should be common. Luckily for us, Rust has a feature for using a value without -transferring ownership, called *references*. +transferring ownership, called _references_. [data-types]: ch03-02-data-types.html#data-types [ch8]: ch08-02-strings.html diff --git a/rustbook-en/src/ch04-02-references-and-borrowing.md b/rustbook-en/src/ch04-02-references-and-borrowing.md index 055001571..cb4d172e8 100644 --- a/rustbook-en/src/ch04-02-references-and-borrowing.md +++ b/rustbook-en/src/ch04-02-references-and-borrowing.md @@ -4,7 +4,7 @@ The issue with the tuple code in Listing 4-5 is that we have to return the `String` to the calling function so we can still use the `String` after the call to `calculate_length`, because the `String` was moved into `calculate_length`. Instead, we can provide a reference to the `String` value. -A *reference* is like a pointer in that it’s an address we can follow to access +A _reference_ is like a pointer in that it’s an address we can follow to access the data stored at that address; that data is owned by some other variable. Unlike a pointer, a reference is guaranteed to point to a valid value of a particular type for the life of that reference. @@ -23,7 +23,7 @@ reference to an object as a parameter instead of taking ownership of the value: First, notice that all the tuple code in the variable declaration and the function return value is gone. Second, note that we pass `&s1` into `calculate_length` and, in its definition, we take `&String` rather than -`String`. These ampersands represent *references*, and they allow you to refer +`String`. These ampersands represent _references_, and they allow you to refer to some value without taking ownership of it. Figure 4-6 depicts this concept. Three tables: the table for s contains only a pointer to the table
@@ -33,7 +33,7 @@ string data on the heap. Figure 4-6: A diagram of `&String s` pointing at `String s1` -> Note: The opposite of referencing by using `&` is *dereferencing*, which is +> Note: The opposite of referencing by using `&` is _dereferencing_, which is > accomplished with the dereference operator, `*`. We’ll see some uses of the > dereference operator in Chapter 8 and discuss details of dereferencing in > Chapter 15. @@ -44,7 +44,7 @@ Let’s take a closer look at the function call here: {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs:here}} ``` -The `&s1` syntax lets us create a reference that *refers* to the value of `s1` +The `&s1` syntax lets us create a reference that _refers_ to the value of `s1` but does not own it. Because it does not own it, the value it points to will not be dropped when the reference stops being used. @@ -62,7 +62,7 @@ have references as parameters instead of the actual values, we won’t need to return the values in order to give back ownership, because we never had ownership. -We call the action of creating a reference *borrowing*. As in real life, if a +We call the action of creating a reference _borrowing_. As in real life, if a person owns something, you can borrow it from them. When you’re done, you have to give it back. You don’t own it. @@ -89,7 +89,7 @@ allowed to modify something we have a reference to. ### Mutable References We can fix the code from Listing 4-6 to allow us to modify a borrowed value -with just a few small tweaks that use, instead, a *mutable reference*: +with just a few small tweaks that use, instead, a _mutable reference_: @@ -132,19 +132,19 @@ The restriction preventing multiple mutable references to the same data at the same time allows for mutation but in a very controlled fashion. It’s something that new Rustaceans struggle with because most languages let you mutate whenever you’d like. The benefit of having this restriction is that Rust can -prevent data races at compile time. A *data race* is similar to a race +prevent data races at compile time. A _data race_ is similar to a race condition and happens when these three behaviors occur: -* Two or more pointers access the same data at the same time. -* At least one of the pointers is being used to write to the data. -* There’s no mechanism being used to synchronize access to the data. +- Two or more pointers access the same data at the same time. +- At least one of the pointers is being used to write to the data. +- There’s no mechanism being used to synchronize access to the data. Data races cause undefined behavior and can be difficult to diagnose and fix when you’re trying to track them down at runtime; Rust prevents this problem by refusing to compile code with data races! As always, we can use curly brackets to create a new scope, allowing for -multiple mutable references, just not *simultaneous* ones: +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}} @@ -163,7 +163,7 @@ Here’s the error: {{#include ../listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt}} ``` -Whew! We *also* cannot have a mutable reference while we have an immutable one +Whew! We _also_ cannot have a mutable reference while we have an immutable one to the same value. Users of an immutable reference don’t expect the value to suddenly change out @@ -193,8 +193,8 @@ have to track down why your data isn’t what you thought it was. ### Dangling References -In languages with pointers, it’s easy to erroneously create a *dangling -pointer*—a pointer that references a location in memory that may have been +In languages with pointers, it’s easy to erroneously create a _dangling +pointer_—a pointer that references a location in memory that may have been given to someone else—by freeing some memory while preserving a pointer to that memory. In Rust, by contrast, the compiler guarantees that references will never be dangling references: if you have a reference to some data, the @@ -256,8 +256,8 @@ deallocated. Let’s recap what we’ve discussed about references: -* At any given time, you can have *either* one mutable reference *or* any +- At any given time, you can have _either_ one mutable reference _or_ any number of immutable references. -* References must always be valid. +- References must always be valid. Next, we’ll look at a different kind of reference: slices. diff --git a/rustbook-en/src/ch04-03-slices.md b/rustbook-en/src/ch04-03-slices.md index d01d90502..6a0bb0815 100644 --- a/rustbook-en/src/ch04-03-slices.md +++ b/rustbook-en/src/ch04-03-slices.md @@ -1,6 +1,6 @@ ## The Slice Type -*Slices* let you reference a contiguous sequence of elements in a +_Slices_ let you reference a contiguous sequence of elements in a [collection](ch08-00-common-collections.md) rather than the whole collection. A slice is a kind of reference, so it does not have ownership. @@ -18,7 +18,7 @@ fn first_word(s: &String) -> ? The `first_word` function has a `&String` as a parameter. We don’t want ownership, so this is fine. But what should we return? We don’t really have a -way to talk about *part* of a string. However, we could return the index of the +way to talk about _part_ of a string. However, we could return the index of the end of the word, indicated by a space. Let’s try that, as shown in Listing 4-7. @@ -94,7 +94,7 @@ we write a `second_word` function. Its signature would have to look like this: fn second_word(s: &String) -> (usize, usize) { ``` -Now we’re tracking a starting *and* an ending index, and we have even more +Now we’re tracking a starting _and_ an ending index, and we have even more values that were calculated from data in a particular state but aren’t tied to that state at all. We have three unrelated variables floating around that need to be kept in sync. @@ -103,7 +103,7 @@ Luckily, Rust has a solution to this problem: string slices. ### String Slices -A *string slice* is a reference to part of a `String`, and it looks like this: +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}} @@ -231,6 +231,7 @@ same time, 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! + #### String Literals as Slices @@ -269,7 +270,7 @@ and `&str` values. If we have a string slice, we can pass that directly. If we have a `String`, we can pass a slice of the `String` or a reference to the `String`. This -flexibility takes advantage of *deref coercions*, a feature we will cover in the +flexibility takes advantage of _deref coercions_, a feature we will cover in the [“Implicit Deref Coercions with Functions and Methods”][deref-coercions] section of Chapter 15. diff --git a/rustbook-en/src/ch05-00-structs.md b/rustbook-en/src/ch05-00-structs.md index d41482579..ee064224d 100644 --- a/rustbook-en/src/ch05-00-structs.md +++ b/rustbook-en/src/ch05-00-structs.md @@ -1,14 +1,14 @@ # Using Structs to Structure Related Data -A *struct*, or *structure*, is a custom data type that lets you package +A _struct_, or _structure_, is a custom data type that lets you package together and name multiple related values that make up a meaningful group. If -you’re familiar with an object-oriented language, a *struct* is like an +you’re familiar with an object-oriented language, a _struct_ is like an object’s data attributes. In this chapter, we’ll compare and contrast tuples with structs to build on what you already know and demonstrate when structs are a better way to group data. We’ll demonstrate how to define and instantiate structs. We’ll discuss how to define associated functions, especially the kind of associated functions called -*methods*, to specify behavior associated with a struct type. Structs and enums +_methods_, to specify behavior associated with a struct type. Structs and enums (discussed in Chapter 6) are the building blocks for creating new types in your program’s domain to take full advantage of Rust’s compile-time type checking. diff --git a/rustbook-en/src/ch05-01-defining-structs.md b/rustbook-en/src/ch05-01-defining-structs.md index e1325c63e..91a939243 100644 --- a/rustbook-en/src/ch05-01-defining-structs.md +++ b/rustbook-en/src/ch05-01-defining-structs.md @@ -10,7 +10,7 @@ on the order of the data to specify or access the values of an instance. To define a struct, we enter the keyword `struct` and name the entire struct. A struct’s name should describe the significance of the pieces of data being grouped together. Then, inside curly brackets, we define the names and types of -the pieces of data, which we call *fields*. For example, Listing 5-1 shows a +the pieces of data, which we call _fields_. For example, Listing 5-1 shows a struct that stores information about a user account. @@ -21,10 +21,10 @@ struct that stores information about a user account. -To use a struct after we’ve defined it, we create an *instance* of that struct +To use a struct after we’ve defined it, we create an _instance_ of that struct by specifying concrete values for each of the fields. We create an instance by -stating the name of the struct and then add curly brackets containing *key: -value* pairs, where the keys are the names of the fields and the values are the +stating the name of the struct and then add curly brackets containing _key: +value_ pairs, where the keys are the names of the fields and the values are the data we want to store in those fields. We don’t have to specify the fields in the same order in which we declared them in the struct. In other words, the struct definition is like a general template for the type, and instances fill @@ -76,12 +76,13 @@ variables is a bit tedious. If the struct had more fields, repeating each name would get even more annoying. Luckily, there’s a convenient shorthand! + ### Using the Field Init Shorthand Because the parameter names and the struct field names are exactly the same in -Listing 5-4, we can use the *field init shorthand* syntax to rewrite +Listing 5-4, we can use the _field init shorthand_ syntax to rewrite `build_user` so it behaves exactly the same but doesn’t have the repetition of `username` and `email`, as shown in Listing 5-5. @@ -103,7 +104,7 @@ than `email: email`. It’s often useful to create a new instance of a struct that includes most of the values from another instance, but changes some. You can do this using -*struct update syntax*. +_struct update syntax_. First, in Listing 5-6 we show how to create a new `User` instance in `user2` regularly, without the update syntax. We set a new value for `email` but @@ -151,7 +152,7 @@ Data: Copy”][copy] section would apply. We can still use ### Using Tuple Structs Without Named Fields to Create Different Types -Rust also supports structs that look similar to tuples, called *tuple structs*. +Rust also supports 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 @@ -184,7 +185,7 @@ example, we would write `let Point(x, y, z) = point`. ### Unit-Like Structs Without Any Fields You can also define structs that don’t have any fields! These are called -*unit-like structs* because they behave similarly to `()`, the unit type that +_unit-like structs_ because they behave similarly to `()`, the unit type that we mentioned in [“The Tuple Type”][tuples] section. Unit-like structs can be useful when you need to implement a trait on some type but don’t have any data that you want to store in the type itself. We’ll discuss traits @@ -217,7 +218,7 @@ implement them on any type, including unit-like structs. > that data to be valid for as long as the entire struct is valid. > > It’s also possible for structs to store references to data owned by something -> else, but to do so requires the use of *lifetimes*, a Rust feature that we’ll +> else, but to do so requires the use of _lifetimes_, a Rust feature that we’ll > discuss in Chapter 10. Lifetimes ensure that the data referenced by a struct > is valid for as long as the struct is. Let’s say you try to store a reference > in a struct without specifying lifetimes, like the following; this won’t work: diff --git a/rustbook-en/src/ch05-02-example-structs.md b/rustbook-en/src/ch05-02-example-structs.md index 392f1bd3b..49a109c6c 100644 --- a/rustbook-en/src/ch05-02-example-structs.md +++ b/rustbook-en/src/ch05-02-example-structs.md @@ -4,10 +4,10 @@ To understand when we might want to use structs, let’s write a program that calculates the area of a rectangle. We’ll start by using single variables, and then refactor the program until we’re using structs instead. -Let’s make a new binary project with Cargo called *rectangles* that will take +Let’s make a new binary project with Cargo called _rectangles_ that will take the width and height of a rectangle specified in pixels and calculate the area of the rectangle. Listing 5-8 shows a short program with one way of doing -exactly that in our project’s *src/main.rs*. +exactly that in our project’s _src/main.rs_. @@ -155,7 +155,7 @@ But again, the compiler gives us a helpful note: {{#include ../listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt:9:10}} ``` -Rust *does* include functionality to print out debugging information, but we +Rust _does_ include functionality to print out debugging information, but we have to explicitly opt in to make that functionality available for our struct. To do that, we add the outer attribute `#[derive(Debug)]` just before the struct definition, as shown in Listing 5-12. @@ -214,10 +214,10 @@ Here’s what the output of this example looks like: {{#include ../listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/output.txt}} ``` -We can see the first bit of output came from *src/main.rs* line 10 where we’re +We can see the first bit of output came from _src/main.rs_ line 10 where we’re debugging the expression `30 * scale`, and its resultant value is `60` (the `Debug` formatting implemented for integers is to print only their value). The -`dbg!` call on line 14 of *src/main.rs* outputs the value of `&rect1`, which is +`dbg!` call on line 14 of _src/main.rs_ outputs the value of `&rect1`, which is the `Rectangle` struct. This output uses the pretty `Debug` formatting of the `Rectangle` type. The `dbg!` macro can be really helpful when you’re trying to figure out what your code is doing! @@ -233,7 +233,7 @@ section of the Rust Reference][attributes]. Our `area` function is very specific: it only computes the area of rectangles. It would be helpful to tie this behavior more closely to our `Rectangle` struct because it won’t work with any other type. Let’s look at how we can continue to -refactor this code by turning the `area` function into an `area` *method* +refactor this code by turning the `area` function into an `area` _method_ defined on our `Rectangle` type. [the-tuple-type]: ch03-02-data-types.html#the-tuple-type diff --git a/rustbook-en/src/ch05-03-method-syntax.md b/rustbook-en/src/ch05-03-method-syntax.md index 1ea896b38..542f07d51 100644 --- a/rustbook-en/src/ch05-03-method-syntax.md +++ b/rustbook-en/src/ch05-03-method-syntax.md @@ -1,6 +1,6 @@ ## Method Syntax -*Methods* are similar to functions: we declare them with the `fn` keyword and a +_Methods_ are similar to functions: we declare them with the `fn` keyword and a name, they can have parameters and a return value, and they contain some code that’s run when the method is called from somewhere else. Unlike functions, methods are defined within the context of a struct (or an enum or a trait @@ -29,7 +29,7 @@ will be associated with the `Rectangle` type. Then we move the `area` function within the `impl` curly brackets and change the first (and in this case, only) parameter to be `self` in the signature and everywhere within the body. In `main`, where we called the `area` function and passed `rect1` as an argument, -we can instead use *method syntax* to call the `area` method on our `Rectangle` +we can instead use _method syntax_ to call the `area` method on our `Rectangle` instance. The method syntax goes after an instance: we add a dot followed by the method name, parentheses, and any arguments. @@ -81,7 +81,7 @@ method `width`. When we don’t use parentheses, Rust knows we mean the field Often, but not always, when we give a method the same name as a field we want it to only return the value in the field and do nothing else. Methods like this -are called *getters*, and Rust does not implement them automatically for struct +are called _getters_, and Rust does not implement them automatically for struct fields as some other languages do. Getters are useful because you can make the field private but the method public, and thus enable read-only access to that field as part of the type’s public API. We will discuss what public and private @@ -97,7 +97,7 @@ are and how to designate a field or method as public or private in [Chapter > `object->something()` is similar to `(*object).something()`. > > Rust doesn’t have an equivalent to the `->` operator; instead, Rust has a -> feature called *automatic referencing and dereferencing*. Calling methods is +> feature called _automatic referencing and dereferencing_. Calling methods is > one of the few places in Rust that has this behavior. > > Here’s how it works: when you call a method with `object.something()`, Rust @@ -105,6 +105,7 @@ are and how to designate a field or method as public or private in [Chapter > the method. In other words, the following are the same: > > +> > ```rust > # #[derive(Debug,Copy,Clone)] > # struct Point { @@ -188,7 +189,7 @@ parameters in functions. ### Associated Functions -All functions defined within an `impl` block are called *associated functions* +All functions defined within an `impl` block are called _associated functions_ because they’re associated with the type named after the `impl`. We can define associated functions that don’t have `self` as their first parameter (and thus are not methods) because they don’t need an instance of the type to work with. diff --git a/rustbook-en/src/ch06-00-enums.md b/rustbook-en/src/ch06-00-enums.md index 8a7faa9f3..0b9fc7806 100644 --- a/rustbook-en/src/ch06-00-enums.md +++ b/rustbook-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 +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 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/rustbook-en/src/ch06-01-defining-an-enum.md b/rustbook-en/src/ch06-01-defining-an-enum.md index 3462f3891..d61578777 100644 --- a/rustbook-en/src/ch06-01-defining-an-enum.md +++ b/rustbook-en/src/ch06-01-defining-an-enum.md @@ -10,7 +10,7 @@ Let’s look at a situation we might want to express in code and see why enums 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. Because these are the only possibilities for an -IP address that our program will come across, we can *enumerate* all possible +IP address that our program will come across, we can _enumerate_ all possible variants, which is where enumeration gets its name. Any IP address can be either a version four or a version six address, but not @@ -54,8 +54,8 @@ And we can call this function with either variant: ``` Using enums has even more advantages. Thinking more about our IP address type, -at the moment we don’t have a way to store the actual IP address *data*; we -only know what *kind* it is. Given that you just learned about structs in +at the moment we don’t have a way to store the actual IP address _data_; we +only know what _kind_ it is. Given that you just learned about structs in Chapter 5, you might be tempted to tackle this problem with structs as shown in Listing 6-1. @@ -151,10 +151,10 @@ variety of types embedded in its variants. This enum has four variants with different types: -* `Quit` has no data associated with it at all. -* `Move` has named fields, like a struct does. -* `Write` includes a single `String`. -* `ChangeColor` includes three `i32` values. +- `Quit` has no data associated with it at all. +- `Move` has named fields, like a struct does. +- `Write` includes a single `String`. +- `ChangeColor` includes three `i32` values. Defining an enum with variants such as the ones in Listing 6-2 is similar to defining different kinds of struct definitions, except the enum doesn’t use the @@ -201,7 +201,7 @@ languages. Programming language design is often thought of in terms of which features you include, but the features you exclude are important too. Rust doesn’t have the -null feature that many other languages have. *Null* is a value that means there +null feature that many other languages have. _Null_ is a value that means there is no value there. In languages with null, variables can always be in one of two states: null or not-null. @@ -301,7 +301,7 @@ more confident in your code. In order to have a value that can possibly be null, you must explicitly opt in by making the type of that value `Option`. Then, when you use that value, you are required to explicitly handle the case when the value is null. Everywhere that a value has a type that isn’t an -`Option`, you *can* safely assume that the value isn’t null. This was a +`Option`, you _can_ safely assume that the value isn’t null. This was a deliberate design decision for Rust to limit null’s pervasiveness and increase the safety of Rust code. diff --git a/rustbook-en/src/ch06-02-match.md b/rustbook-en/src/ch06-02-match.md index f81907c9e..7cbae3edf 100644 --- a/rustbook-en/src/ch06-02-match.md +++ b/rustbook-en/src/ch06-02-match.md @@ -1,5 +1,7 @@ + + ## The `match` Control Flow Construct Rust has an extremely powerful control flow construct called `match` that @@ -185,7 +187,7 @@ error: ``` Rust knows that we didn’t cover every possible case, and even knows which -pattern we forgot! Matches in Rust are *exhaustive*: we must exhaust every last +pattern we forgot! Matches in Rust are _exhaustive_: we must exhaust every last possibility in order for the code to be valid. Especially in the case of `Option`, when Rust prevents us from forgetting to explicitly handle the `None` case, it protects us from assuming that we have a value when we might @@ -220,7 +222,7 @@ patterns are evaluated in order. If we put the catch-all arm earlier, the other arms would never run, so Rust will warn us if we add arms after a catch-all! Rust also has a pattern we can use when we want a catch-all but don’t want to -*use* the value in the catch-all pattern: `_` is a special pattern that matches +_use_ the value in the catch-all pattern: `_` is a special pattern that matches any value and does not bind to that value. This tells Rust we aren’t going to use the value, so Rust won’t warn us about an unused variable. @@ -254,5 +256,4 @@ There’s more about patterns and matching that we’ll cover in [Chapter is a bit wordy. [tuples]: ch03-02-data-types.html#the-tuple-type - [ch19-00-patterns]: ch19-00-patterns.html diff --git a/rustbook-en/src/ch06-03-if-let.md b/rustbook-en/src/ch06-03-if-let.md index 829d01169..50ad9321f 100644 --- a/rustbook-en/src/ch06-03-if-let.md +++ b/rustbook-en/src/ch06-03-if-let.md @@ -81,4 +81,3 @@ function expects. In order to provide a well-organized API to your users that is straightforward to use and only exposes exactly what your users will need, let’s now turn to Rust’s modules. - diff --git a/rustbook-en/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md b/rustbook-en/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md index 0f7abf51e..1786711d8 100644 --- a/rustbook-en/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md +++ b/rustbook-en/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md @@ -11,7 +11,7 @@ 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 comprising a set of interrelated -packages that evolve together, Cargo provides *workspaces*, which we’ll cover +packages that evolve together, Cargo provides _workspaces_, which we’ll cover in the [“Cargo Workspaces”][workspaces] section in Chapter 14. We’ll also discuss encapsulating implementation details, which lets you reuse @@ -33,13 +33,13 @@ 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: +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 +- **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 +- **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 diff --git a/rustbook-en/src/ch07-01-packages-and-crates.md b/rustbook-en/src/ch07-01-packages-and-crates.md index e9bf645f3..281f27b7b 100644 --- a/rustbook-en/src/ch07-01-packages-and-crates.md +++ b/rustbook-en/src/ch07-01-packages-and-crates.md @@ -2,7 +2,7 @@ The first parts of the module system we’ll cover are packages and crates. -A *crate* is the smallest amount of code that the Rust compiler considers at a +A _crate_ is the smallest amount of code that the Rust compiler considers at a time. Even if you run `rustc` rather than `cargo` and pass a single source code file (as we did all the way back in the “Writing and Running a Rust Program” section of Chapter 1), the compiler considers that file to be a crate. Crates @@ -10,25 +10,25 @@ can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. A crate can come in one of two forms: a binary crate or a library crate. -*Binary crates* are programs you can compile to an executable that you can run, +_Binary crates_ are programs you can compile to an executable that you can run, such as a command-line program or a server. Each must have a function called `main` that defines what happens when the executable runs. All the crates we’ve created so far have been binary crates. -*Library crates* don’t have a `main` function, and they don’t compile to an +_Library crates_ don’t have a `main` function, and they don’t compile to an executable. Instead, they define functionality intended to be shared with multiple projects. For example, the `rand` crate we used in [Chapter 2][rand] provides functionality that generates random numbers. Most of the time when Rustaceans say “crate”, they mean library crate, and they use “crate” interchangeably with the general programming concept of a “library”. -The *crate root* is a source file that the Rust compiler starts from and makes +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] section). -A *package* is a bundle of one or more crates that provides a set of -functionality. A package contains a *Cargo.toml* file that describes how to +A _package_ is a bundle of one or more crates that provides a set of +functionality. A package contains a _Cargo.toml_ file that describes how to build those crates. Cargo is actually a package that contains the binary crate for the command-line tool you’ve been using to build your code. The Cargo package also contains a library crate that the binary crate depends on. Other @@ -51,20 +51,20 @@ main.rs ``` After we run `cargo new my-project`, we use `ls` to see what Cargo creates. In -the project directory, there’s a *Cargo.toml* file, giving us a package. -There’s also a *src* directory that contains *main.rs*. Open *Cargo.toml* in -your text editor, and note there’s no mention of *src/main.rs*. Cargo follows a -convention that *src/main.rs* is the crate root of a binary crate with the same +the project directory, there’s a _Cargo.toml_ file, giving us a package. +There’s also a _src_ directory that contains _main.rs_. Open _Cargo.toml_ in +your text editor, and note there’s no mention of _src/main.rs_. 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 +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 binary and a library, both with the same +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 binary and a library, 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. +in the _src/bin_ directory: each file will be a separate binary crate. [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/rustbook-en/src/ch07-02-defining-modules-to-control-scope-and-privacy.md b/rustbook-en/src/ch07-02-defining-modules-to-control-scope-and-privacy.md index c1afe4c15..29924e6fe 100644 --- a/rustbook-en/src/ch07-02-defining-modules-to-control-scope-and-privacy.md +++ b/rustbook-en/src/ch07-02-defining-modules-to-control-scope-and-privacy.md @@ -1,7 +1,7 @@ ## Defining Modules to Control Scope and Privacy In this section, we’ll talk about modules and other parts of the module system, -namely *paths*, which allow you to name items; the `use` keyword that brings a +namely _paths_, which 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. @@ -14,23 +14,23 @@ through examples of each of these rules throughout this chapter, but this is a great place to refer to as a reminder of how modules work. - **Start from the crate root**: When compiling a crate, the compiler first - looks in the crate root file (usually *src/lib.rs* for a library crate or - *src/main.rs* for a binary crate) for code to compile. + looks in the crate root file (usually _src/lib.rs_ for a library crate or + _src/main.rs_ for a binary crate) for code to compile. - **Declaring modules**: In the crate root file, you can declare new modules; -say you declare a “garden” module with `mod garden;`. The compiler will look -for the module’s code in these places: + say you declare a “garden” module with `mod garden;`. The compiler will look + for the module’s code in these places: - Inline, within curly brackets that replace the semicolon following `mod garden` - - In the file *src/garden.rs* - - In the file *src/garden/mod.rs* + - In the file _src/garden.rs_ + - In the file _src/garden/mod.rs_ - **Declaring submodules**: In any file other than the crate root, you can declare submodules. For example, you might declare `mod vegetables;` in - *src/garden.rs*. The compiler will look for the submodule’s code within the + _src/garden.rs_. The compiler will look for the submodule’s code within the directory named for the parent module in these places: - Inline, directly following `mod vegetables`, within curly brackets instead of the semicolon - - In the file *src/garden/vegetables.rs* - - In the file *src/garden/vegetables/mod.rs* + - In the file _src/garden/vegetables.rs_ + - In the file _src/garden/vegetables/mod.rs_ - **Paths to code in modules**: Once a module is part of your crate, you can refer to code in that module from anywhere else in that same crate, as long as the privacy rules allow, using the path to the code. For example, an @@ -61,7 +61,7 @@ backyard └── main.rs ``` -The crate root file in this case is *src/main.rs*, and it contains: +The crate root file in this case is _src/main.rs_, and it contains: @@ -72,7 +72,7 @@ The crate root file in this case is *src/main.rs*, and it contains: The `pub mod garden;` line tells the compiler to include the code it finds in -*src/garden.rs*, which is: +_src/garden.rs_, which is: @@ -82,7 +82,7 @@ The `pub mod garden;` line tells the compiler to include the code it finds in -Here, `pub mod vegetables;` means the code in *src/garden/vegetables.rs* is +Here, `pub mod vegetables;` means the code in _src/garden/vegetables.rs_ is included too. That code is: ```rust,noplayground,ignore @@ -93,8 +93,8 @@ Now let’s get into the details of these rules and demonstrate them in action! ### Grouping Related Code in Modules -*Modules* let us organize code within a crate for readability and easy reuse. -Modules also allow us to control the *privacy* of items because code within a +_Modules_ let us organize code within a crate for readability and easy reuse. +Modules also allow us to control the _privacy_ of items because code within a module is private by default. Private items are internal implementation details not available for outside use. We can choose to make modules and the items within them public, which exposes them to allow external code to use and depend @@ -106,7 +106,7 @@ empty to concentrate on the organization of the code rather than the implementation of a restaurant. 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 +_front of house_ and others as _back of house_. Front of house is where customers are; this encompasses where the 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 @@ -114,7 +114,7 @@ administrative work. To structure our crate in this way, we can organize its functions into nested modules. Create a new library named `restaurant` by running `cargo new -restaurant --lib`. Then enter the code in Listing 7-1 into *src/lib.rs* to +restaurant --lib`. Then enter the code in Listing 7-1 into _src/lib.rs_ to define some modules and function signatures; this code is the front of house section. @@ -139,10 +139,10 @@ groups rather than having to read through all the definitions, making it easier to find the definitions relevant to them. 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 +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*. +known as the _module tree_. Listing 7-2 shows the module tree for the structure in Listing 7-1. @@ -164,10 +164,10 @@ crate This tree shows how some of the modules nest inside other modules; for example, `hosting` nests inside `front_of_house`. The tree also shows that some modules -are *siblings*, meaning they’re defined in the same module; `hosting` and +are _siblings_, meaning they’re defined in the same module; `hosting` and `serving` are siblings defined within `front_of_house`. 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 +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 diff --git a/rustbook-en/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md b/rustbook-en/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md index da07d9fd8..a336f94a6 100644 --- a/rustbook-en/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md +++ b/rustbook-en/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md @@ -6,10 +6,10 @@ know its path. A path can take two forms: -* An *absolute path* is the full path starting from a crate root; for code +- An _absolute path_ is the full path starting from a crate root; for code from an external crate, the absolute path begins with the crate name, and for code from the current crate, it starts with the literal `crate`. -* A *relative path* starts from the current module and uses `self`, `super`, or +- 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 @@ -126,7 +126,7 @@ shown in Listing 7-6. 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 +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, not access its inner code. Because modules are containers, there’s not much we can do by only making the @@ -179,15 +179,15 @@ interested in this topic, see [The Rust API Guidelines][api-guidelines]. > #### Best Practices for Packages with a Binary and a Library > -> We mentioned that a package can contain both a *src/main.rs* binary crate -> root as well as a *src/lib.rs* library crate root, and both crates will have +> We mentioned that a package can contain both a _src/main.rs_ binary crate +> root as well as a _src/lib.rs_ library crate root, and both crates will have > the package name by default. Typically, packages with this pattern of > containing both a library and a binary crate will have just enough code in the > binary crate to start an executable that calls code within the library crate. > This lets other projects benefit from most of the functionality that the > package provides because the library crate’s code can be shared. > -> The module tree should be defined in *src/lib.rs*. Then, any public items can +> The module tree should be defined in _src/lib.rs_. Then, any public items can > be used in the binary crate by starting paths with the name of the package. > The binary crate becomes a user of the library crate just like a completely > external crate would use the library crate: it can only use the public API. diff --git a/rustbook-en/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md b/rustbook-en/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md index aaf7713e9..97b2b656a 100644 --- a/rustbook-en/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md +++ b/rustbook-en/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md @@ -112,7 +112,7 @@ meant when we used `Result`. 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 +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`. @@ -133,7 +133,7 @@ considered idiomatic, so the choice is up to you! 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 +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. @@ -171,7 +171,7 @@ Chapter 14. 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*: +added this line to _Cargo.toml_: 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) +is also sometimes used as part of the prelude pattern: see [the standard library documentation](../std/prelude/index.html#other-preludes) for more information on that pattern. [ch14-pub-use]: ch14-02-publishing-to-crates-io.html#exporting-a-convenient-public-api-with-pub-use diff --git a/rustbook-en/src/ch07-05-separating-modules-into-different-files.md b/rustbook-en/src/ch07-05-separating-modules-into-different-files.md index 2952e4b15..4de9b6908 100644 --- a/rustbook-en/src/ch07-05-separating-modules-into-different-files.md +++ b/rustbook-en/src/ch07-05-separating-modules-into-different-files.md @@ -7,14 +7,14 @@ file to make the code easier to navigate. For example, let’s start from the code in Listing 7-17 that had multiple restaurant modules. We’ll extract modules into files instead of having all the modules defined in the crate root file. 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*. +_src/lib.rs_, but this procedure also works with binary crates whose crate root +file is _src/main.rs_. First we’ll extract the `front_of_house` module to its own file. Remove the code inside the curly brackets for the `front_of_house` module, leaving only -the `mod front_of_house;` declaration, so that *src/lib.rs* contains the code +the `mod front_of_house;` declaration, so that _src/lib.rs_ contains the code shown in Listing 7-21. Note that this won’t compile until we create the -*src/front_of_house.rs* file in Listing 7-22. +_src/front_of_house.rs_ file in Listing 7-22. @@ -25,7 +25,7 @@ shown in Listing 7-21. Note that this won’t compile until we create the Next, place the code that was in the curly brackets into a new file named -*src/front_of_house.rs*, as shown in Listing 7-22. The compiler knows to look +_src/front_of_house.rs_, as shown in Listing 7-22. The compiler knows to look in this file because it came across the module declaration in the crate root with the name `front_of_house`. @@ -37,21 +37,21 @@ with the name `front_of_house`. -Note that you only need to load a file using a `mod` declaration *once* in your +Note that you only need to load a file using a `mod` declaration _once_ in your module tree. Once the compiler knows the file is part of the project (and knows where in the module tree the code resides because of where you’ve put the `mod` statement), other files in your project should refer to the loaded file’s code using a path to where it was declared, as covered in the [“Paths for Referring to an Item in the Module Tree”][paths] section. In other words, -`mod` is *not* an “include” operation that you may have seen in other +`mod` is _not_ an “include” operation that you may have seen in other programming languages. Next, we’ll extract the `hosting` module to its own file. The process is a bit different because `hosting` is a child module of `front_of_house`, not of the root module. We’ll place the file for `hosting` in a new directory that will be -named for its ancestors in the module tree, in this case *src/front_of_house*. +named for its ancestors in the module tree, in this case _src/front_of_house_. -To start moving `hosting`, we change *src/front_of_house.rs* to contain only +To start moving `hosting`, we change _src/front_of_house.rs_ to contain only the declaration of the `hosting` module: @@ -62,7 +62,7 @@ the declaration of the `hosting` module: -Then we create a *src/front_of_house* directory and a *hosting.rs* file to +Then we create a _src/front_of_house_ directory and a _hosting.rs_ file to contain the definitions made in the `hosting` module: @@ -73,8 +73,8 @@ contain the definitions made in the `hosting` module: -If we instead put *hosting.rs* in the *src* directory, the compiler would -expect the *hosting.rs* code to be in a `hosting` module declared in the crate +If we instead put _hosting.rs_ in the _src_ directory, the compiler would +expect the _hosting.rs_ code to be in a `hosting` module declared in the crate root, and not declared as a child of the `front_of_house` module. The compiler’s rules for which files to check for which modules’ code mean the directories and files more closely match the module tree. @@ -86,21 +86,21 @@ directories and files more closely match the module tree. > `front_of_house` declared in the crate root, the compiler will look for the > module’s code in: > -> * *src/front_of_house.rs* (what we covered) -> * *src/front_of_house/mod.rs* (older style, still supported path) +> - _src/front_of_house.rs_ (what we covered) +> - _src/front_of_house/mod.rs_ (older style, still supported path) > > For a module named `hosting` that is a submodule of `front_of_house`, the > compiler will look for the module’s code in: > -> * *src/front_of_house/hosting.rs* (what we covered) -> * *src/front_of_house/hosting/mod.rs* (older style, still supported path) +> - _src/front_of_house/hosting.rs_ (what we covered) +> - _src/front_of_house/hosting/mod.rs_ (older style, still supported path) > > If you use both styles for the same module, you’ll get a compiler error. > Using a mix of both styles for different modules in the same project is > allowed, but might be confusing for people navigating your project. > -> The main downside to the style that uses files named *mod.rs* is that your -> project can end up with many files named *mod.rs*, which can get confusing +> The main downside to the style that uses files named _mod.rs_ is that your +> project can end up with many files named _mod.rs_, which can get confusing > when you have them open in your editor at the same time. We’ve moved each module’s code to a separate file, and the module tree remains @@ -109,7 +109,7 @@ 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 +_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. diff --git a/rustbook-en/src/ch08-00-common-collections.md b/rustbook-en/src/ch08-00-common-collections.md index c9de36be1..7cc5c424b 100644 --- a/rustbook-en/src/ch08-00-common-collections.md +++ b/rustbook-en/src/ch08-00-common-collections.md @@ -1,7 +1,7 @@ # Common Collections Rust’s standard library includes a number of very useful data structures called -*collections*. Most other data types represent one specific value, but +_collections_. Most other data types represent one specific value, but collections can contain multiple values. Unlike the built-in array and tuple types, the data these collections point to is stored on the heap, which means the amount of data does not need to be known at compile time and can grow or @@ -10,11 +10,11 @@ and costs, and choosing an appropriate one for your current situation is a skill you’ll develop over time. In this chapter, we’ll discuss three collections that are used very often in Rust programs: -* A *vector* allows you to store a variable number of values next to each other. -* A *string* is a collection of characters. We’ve mentioned the `String` type +- A _vector_ allows you to store a variable number of values next to each other. +- A _string_ is a collection of characters. We’ve mentioned the `String` type previously, but in this chapter we’ll talk about it in depth. -* A *hash map* allows you to associate a value with a specific key. It’s a - particular implementation of the more general data structure called a *map*. +- A _hash map_ allows you to associate a value with a specific key. It’s a + particular implementation of the more general data structure called a _map_. To learn about the other kinds of collections provided by the standard library, see [the documentation][collections]. diff --git a/rustbook-en/src/ch08-01-vectors.md b/rustbook-en/src/ch08-01-vectors.md index c29728a7a..d711c9904 100644 --- a/rustbook-en/src/ch08-01-vectors.md +++ b/rustbook-en/src/ch08-01-vectors.md @@ -1,6 +1,6 @@ ## Storing Lists of Values with Vectors -The first collection type we’ll look at is `Vec`, also known as a *vector*. +The first collection type we’ll look at is `Vec`, also known as a _vector_. Vectors allow you to store more than one value in a single data structure that puts all the values next to each other in memory. Vectors can only store values of the same type. They are useful when you have a list of items, such as the diff --git a/rustbook-en/src/ch08-02-strings.md b/rustbook-en/src/ch08-02-strings.md index 5635263b6..6df7dd83c 100644 --- a/rustbook-en/src/ch08-02-strings.md +++ b/rustbook-en/src/ch08-02-strings.md @@ -18,9 +18,9 @@ complicated by the differences between how people and computers interpret ### What Is a String? -We’ll first define what we mean by the term *string*. Rust has only one string +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*, +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. @@ -132,7 +132,7 @@ If the `push_str` method took ownership of `s2`, we wouldn’t be able to print its value on the last line. However, this code works as we’d expect! The `push` method takes a single character as a parameter and adds it to the -`String`. Listing 8-17 adds the letter *l* to a `String` using the `push` +`String`. Listing 8-17 adds the letter _l_ to a `String` using the `push` method. @@ -174,21 +174,21 @@ call this method with `String` values. We’ll discuss generics in Chapter 10. This signature gives us the clues we need in order to understand the tricky bits of the `+` operator. -First, `s2` has an `&`, meaning that we’re adding a *reference* of the second +First, `s2` has an `&`, meaning that we’re adding a _reference_ of the second string to the first string. This is because of the `s` parameter in the `add` function: we can only add a `&str` to a `String`; we can’t add two `String` values together. But wait—the type of `&s2` is `&String`, not `&str`, as specified in the second parameter to `add`. So why does Listing 8-18 compile? The reason we’re able to use `&s2` in the call to `add` is that the compiler -can *coerce* the `&String` argument into a `&str`. When we call the `add` -method, Rust uses a *deref coercion*, which here turns `&s2` into `&s2[..]`. +can _coerce_ the `&String` argument into a `&str`. When we call the `add` +method, Rust uses a _deref coercion_, which here turns `&s2` into `&s2[..]`. We’ll discuss deref coercion in more depth in Chapter 15. Because `add` does not take ownership of the `s` parameter, `s2` will still be a valid `String` after this operation. Second, we can see in the signature that `add` takes ownership of `self` -because `self` does *not* have an `&`. This means `s1` in Listing 8-18 will be +because `self` does _not_ have an `&`. This means `s1` in Listing 8-18 will be moved into the `add` call and will no longer be valid after that. So, although `let s3 = s1 + &s2;` looks like it will copy both strings and create a new one, this statement actually takes ownership of `s1`, appends a copy of the contents @@ -254,7 +254,7 @@ encoded UTF-8 example strings from Listing 8-14. First, this one: In this case, `len` will be `4`, which means the vector storing the string `"Hola"` is 4 bytes long. Each of these letters takes one byte when encoded in UTF-8. The following line, however, may surprise you (note that this string -begins with the capital Cyrillic letter *Ze*, not the number 3): +begins with the capital Cyrillic letter _Ze_, not the number 3): ```rust {{#rustdoc_include ../listings/ch08-common-collections/listing-08-14/src/main.rs:russian}} @@ -289,7 +289,7 @@ at all and prevents misunderstandings early in the development process. Another point about UTF-8 is that there are actually three relevant ways to look at strings from Rust’s perspective: as bytes, scalar values, and grapheme -clusters (the closest thing to what we would call *letters*). +clusters (the closest thing to what we would call _letters_). If we look at the Hindi word “नमस्ते” written in the Devanagari script, it is stored as a vector of `u8` values that looks like this: diff --git a/rustbook-en/src/ch08-03-hash-maps.md b/rustbook-en/src/ch08-03-hash-maps.md index 057501415..3db150419 100644 --- a/rustbook-en/src/ch08-03-hash-maps.md +++ b/rustbook-en/src/ch08-03-hash-maps.md @@ -1,11 +1,11 @@ ## Storing Keys with Associated Values in Hash Maps -The last of our common collections is the *hash map*. The type `HashMap` -stores a mapping of keys of type `K` to values of type `V` using a *hashing -function*, which determines how it places these keys and values into memory. +The last of our common collections is the _hash map_. The type `HashMap` +stores a mapping of keys of type `K` to values of type `V` using a _hashing +function_, which determines how it places these keys and values into memory. Many programming languages support this kind of data structure, but they often -use a different name, such as *hash*, *map*, *object*, *hash table*, -*dictionary*, or *associative array*, just to name a few. +use a different name, such as _hash_, _map_, _object_, _hash table_, +_dictionary_, or _associative array_, just to name a few. Hash maps are useful when you want to look up data not by using an index, as you can with vectors, but by using a key that can be of any type. For example, @@ -21,7 +21,7 @@ As always, check the standard library documentation for more information. One way to create an empty hash map is to use `new` and to add elements with `insert`. In Listing 8-20, we’re keeping track of the scores of two teams whose -names are *Blue* and *Yellow*. The Blue team starts with 10 points, and the +names are _Blue_ and _Yellow_. The Blue team starts with 10 points, and the Yellow team starts with 50. @@ -112,7 +112,7 @@ When you want to change the data in a hash map, you have to decide how to handle the case when a key already has a value assigned. You could replace the old value with the new value, completely disregarding the old value. You could keep the old value and ignore the new value, only adding the new value if the -key *doesn’t* already have a value. Or you could combine the old value and the +key _doesn’t_ already have a value. Or you could combine the old value and the new value. Let’s look at how to do each of these! #### Overwriting a Value @@ -135,6 +135,7 @@ This code will print `{"Blue": 25}`. The original value of `10` has been overwritten. + #### Adding a Key and Value Only If a Key Isn’t Present @@ -203,13 +204,13 @@ changes are safe and allowed by the borrowing rules. ### Hashing Functions -By default, `HashMap` uses a hashing function called *SipHash* that can provide +By default, `HashMap` uses a hashing function called _SipHash_ that can provide resistance to denial-of-service (DoS) attacks involving hash tables[^siphash]. This is not the fastest hashing algorithm available, but the trade-off for better security that comes with the drop in performance is worth it. If you profile your code and find that the default hash function is too slow for your purposes, you can switch to another function -by specifying a different hasher. A *hasher* is a type that implements the +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][traits]. You don’t necessarily have to implement your own hasher from scratch; [crates.io](https://crates.io/) @@ -228,9 +229,9 @@ some exercises you should now be equipped to solve: the value in the middle position) and mode (the value that occurs most often; a hash map will be helpful here) of the list. 1. Convert strings to pig latin. The first consonant of each word is moved to - the end of the word and *ay* is added, so *first* becomes *irst-fay*. Words - that start with a vowel have *hay* added to the end instead (*apple* becomes - *apple-hay*). Keep in mind the details about UTF-8 encoding! + the end of the word and _ay_ is added, so _first_ becomes _irst-fay_. Words + that start with a vowel have _hay_ added to the end instead (_apple_ becomes + _apple-hay_). Keep in mind the details about UTF-8 encoding! 1. Using a hash map and vectors, create a text interface to allow a user to add employee names to a department in a company; for example, “Add Sally to Engineering” or “Add Amir to Sales.” Then let the user retrieve a list of all @@ -243,7 +244,6 @@ 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! -[validating-references-with-lifetimes]: -ch10-03-lifetime-syntax.html#validating-references-with-lifetimes +[validating-references-with-lifetimes]: ch10-03-lifetime-syntax.html#validating-references-with-lifetimes [access]: #accessing-values-in-a-hash-map [traits]: ch10-02-traits.html diff --git a/rustbook-en/src/ch09-00-error-handling.md b/rustbook-en/src/ch09-00-error-handling.md index cf997d91b..a5240b199 100644 --- a/rustbook-en/src/ch09-00-error-handling.md +++ b/rustbook-en/src/ch09-00-error-handling.md @@ -7,8 +7,8 @@ code will compile. This requirement makes your program more robust by ensuring that you’ll discover errors and handle them appropriately before you’ve deployed your code to production! -Rust groups errors into two major categories: *recoverable* and *unrecoverable* -errors. For a recoverable error, such as a *file not found* error, we most +Rust groups errors into two major categories: _recoverable_ and _unrecoverable_ +errors. For a recoverable error, such as a _file not found_ error, we most likely just want to report the problem to the user and retry the operation. Unrecoverable errors are always symptoms of bugs, such as trying to access a location beyond the end of an array, and so we want to immediately stop the diff --git a/rustbook-en/src/ch09-01-unrecoverable-errors-with-panic.md b/rustbook-en/src/ch09-01-unrecoverable-errors-with-panic.md index bb3b8ed1f..792932f5f 100644 --- a/rustbook-en/src/ch09-01-unrecoverable-errors-with-panic.md +++ b/rustbook-en/src/ch09-01-unrecoverable-errors-with-panic.md @@ -11,17 +11,17 @@ panic occurs to make it easier to track down the source of the panic. > ### Unwinding the Stack or Aborting in Response to a Panic > -> By default, when a panic occurs the program starts *unwinding*, which means +> By default, when a panic occurs the program starts _unwinding_, which means > Rust walks back up the stack and cleans up the data from each function it > encounters. However, walking back and cleaning up is a lot of work. Rust, -> therefore, allows you to choose the alternative of immediately *aborting*, +> therefore, allows you to choose the alternative of immediately _aborting_, > which ends the program without cleaning up. > > Memory that the program was using will then need to be cleaned up by the > operating system. If in your project you need to make the resultant binary as > small as possible, you can switch from unwinding to aborting upon a panic by > adding `panic = 'abort'` to the appropriate `[profile]` sections in your -> *Cargo.toml* file. For example, if you want to abort on panic in release mode, +> _Cargo.toml_ file. For example, if you want to abort on panic in release mode, > add this: > > ```toml @@ -47,8 +47,8 @@ When you run the program, you’ll see something like this: The call to `panic!` causes the error message contained in the last two lines. The first line shows our panic message and the place in our source code where -the panic occurred: *src/main.rs:2:5* indicates that it’s the second line, -fifth character of our *src/main.rs* file. +the panic occurred: _src/main.rs:2:5_ indicates that it’s the second line, +fifth character of our _src/main.rs_ file. In this case, the line indicated is part of our code, and if we go to that line, we see the `panic!` macro call. In other cases, the `panic!` call might @@ -57,6 +57,7 @@ the error message will be someone else’s code where the `panic!` macro is called, not the line of our code that eventually led to the `panic!` call. + We can use the backtrace of the functions the `panic!` call came from to figure @@ -83,7 +84,7 @@ 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 +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. @@ -96,12 +97,12 @@ continue. Let’s try it and see: {{#include ../listings/ch09-error-handling/listing-09-01/output.txt}} ``` -This error points at line 4 of our *main.rs* where we attempt to access index +This error points at line 4 of our _main.rs_ where we attempt to access index `99` of the vector in `v`. The `note:` line tells us that we can set the `RUST_BACKTRACE` environment variable to get a backtrace of exactly what happened to cause the error. A -*backtrace* is a list of all the functions that have been called to get to this +_backtrace_ is a list of all the functions that have been called to get to this point. Backtraces in Rust work as they do in other languages: the key to reading the backtrace is to start from the top and read until you see files you wrote. That’s the spot where the problem originated. The lines above that spot @@ -153,7 +154,7 @@ default when using `cargo build` or `cargo run` without the `--release` flag, as we have here. In the output in Listing 9-2, line 6 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 +project that’s causing the problem: line 4 of _src/main.rs_. If we don’t want our program to panic, we should start our investigation at the location pointed to by the first line mentioning a file we wrote. In Listing 9-1, where we deliberately wrote code that would panic, the way to fix the panic is to not @@ -166,5 +167,4 @@ handle error conditions in the [“To `panic!` or Not to `panic!`”][to-panic-or-not-to-panic] 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 +[to-panic-or-not-to-panic]: ch09-03-to-panic-or-not-to-panic.html#to-panic-or-not-to-panic diff --git a/rustbook-en/src/ch09-02-recoverable-errors-with-result.md b/rustbook-en/src/ch09-02-recoverable-errors-with-result.md index 81f628192..13117d7df 100644 --- a/rustbook-en/src/ch09-02-recoverable-errors-with-result.md +++ b/rustbook-en/src/ch09-02-recoverable-errors-with-result.md @@ -78,7 +78,7 @@ writing. The other arm of the `match` handles the case where we get an `Err` value from `File::open`. In this example, we’ve chosen to call the `panic!` macro. If -there’s no file named *hello.txt* in our current directory and we run this +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: ```console @@ -178,7 +178,7 @@ call the `panic!` macro for us. Here is an example of `unwrap` in action: -If we run this code without a *hello.txt* file, we’ll see an error message from +If we run this code without a _hello.txt_ file, we’ll see an error message from the `panic!` call that the `unwrap` method makes: section in Chapter 18. For now, you can read `Box` to mean “any kind of error.” Using `?` on a `Result` diff --git a/rustbook-en/src/ch09-03-to-panic-or-not-to-panic.md b/rustbook-en/src/ch09-03-to-panic-or-not-to-panic.md index 9b7850ca9..90d9eacfd 100644 --- a/rustbook-en/src/ch09-03-to-panic-or-not-to-panic.md +++ b/rustbook-en/src/ch09-03-to-panic-or-not-to-panic.md @@ -57,7 +57,7 @@ of the `parse` method: we still get a `Result` value, and the compiler will still make us handle the `Result` as if the `Err` variant is a possibility because the compiler isn’t smart enough to see that this string is always a valid IP address. If the IP address string came from a user rather than being -hardcoded into the program and therefore *did* have a possibility of failure, +hardcoded into the program and therefore _did_ have a possibility of failure, we’d definitely want to handle the `Result` in a more robust way instead. Mentioning the assumption that this IP address is hardcoded will prompt us to change `expect` to better error-handling code if, in the future, we need to get @@ -66,17 +66,17 @@ the IP address from some other source instead. ### Guidelines for Error Handling It’s advisable to have your code panic when it’s possible that your code could -end up in a bad state. In this context, a *bad state* is when some assumption, +end up in a bad state. In this context, a _bad state_ is when some assumption, guarantee, contract, or invariant has been broken, such as when invalid values, contradictory values, or missing values are passed to your code—plus one or more of the following: -* The bad state is something that is unexpected, as opposed to something that +- The bad state is something that is unexpected, as opposed to something that will likely happen occasionally, like a user entering data in the wrong format. -* Your code after this point needs to rely on not being in this bad state, +- Your code after this point needs to rely on not being in this bad state, rather than checking for the problem at every step. -* There’s not a good way to encode this information in the types you use. We’ll +- There’s not a good way to encode this information in the types you use. We’ll work through an example of what we mean in the [“Encoding States and Behavior as Types”][encoding] section of Chapter 18. @@ -102,11 +102,11 @@ attempting to operate on invalid data can expose your code to vulnerabilities. This is the main reason the standard library will call `panic!` if you attempt an out-of-bounds memory access: trying to access memory that doesn’t belong to the current data structure is a common security problem. Functions often have -*contracts*: their behavior is only guaranteed if the inputs meet particular +_contracts_: their behavior is only guaranteed if the inputs meet particular requirements. Panicking when the contract is violated makes sense because a contract violation always indicates a caller-side bug, and it’s not a kind of error you want the calling code to have to explicitly handle. In fact, there’s -no reasonable way for calling code to recover; the calling *programmers* need +no reasonable way for calling code to recover; the calling _programmers_ need to fix the code. Contracts for a function, especially when a violation will cause a panic, should be explained in the API documentation for the function. @@ -116,7 +116,7 @@ checking done by the compiler) to do many of the checks for you. If your function has a particular type as a parameter, you can proceed with your code’s logic knowing that the compiler has already ensured you have a valid value. For example, if you have a type rather than an `Option`, your program expects to -have *something* rather than *nothing*. Your code then doesn’t have to handle +have _something_ rather than _nothing_. Your code then doesn’t have to handle two cases for the `Some` and `None` variants: it will only have one case for definitely having a value. Code trying to pass nothing to your function won’t even compile, so your function doesn’t have to check for that case at runtime. @@ -193,11 +193,11 @@ 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 -a *getter* because its purpose is to get some data from its fields and return +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 using the `Guess` struct is not allowed to set `value` directly: code outside -the module *must* use the `Guess::new` function to create an instance of +the module _must_ use the `Guess::new` function to create an instance of `Guess`, thereby ensuring there’s no way for a `Guess` to have a `value` that hasn’t been checked by the conditions in the `Guess::new` function. diff --git a/rustbook-en/src/ch10-00-generics.md b/rustbook-en/src/ch10-00-generics.md index 2e68384e1..20289557f 100644 --- a/rustbook-en/src/ch10-00-generics.md +++ b/rustbook-en/src/ch10-00-generics.md @@ -1,7 +1,7 @@ # Generic Types, Traits, and Lifetimes Every programming language has tools for effectively handling the duplication -of concepts. In Rust, one such tool is *generics*: abstract stand-ins for +of concepts. In Rust, one such tool is _generics_: abstract stand-ins for concrete types or other properties. We can express the behavior of generics or how they relate to other generics without knowing what will be in their place when compiling and running the code. @@ -18,11 +18,11 @@ then use the same technique to make a generic function from two functions that differ only in the types of their parameters. We’ll also explain how to use generic types in struct and enum definitions. -Then you’ll learn how to use *traits* to define behavior in a generic way. You +Then you’ll learn how to use _traits_ to define behavior in a generic way. You can combine traits with generic types to constrain a generic type to accept only those types that have a particular behavior, as opposed to just any type. -Finally, we’ll discuss *lifetimes*: a variety of generics that give the +Finally, we’ll discuss _lifetimes_: a variety of generics that give the compiler information about how references relate to each other. Lifetimes allow us to give the compiler enough information about borrowed values so that it can ensure references will be valid in more situations than it could without our diff --git a/rustbook-en/src/ch10-01-syntax.md b/rustbook-en/src/ch10-01-syntax.md index 2a22baf58..00e813978 100644 --- a/rustbook-en/src/ch10-01-syntax.md +++ b/rustbook-en/src/ch10-01-syntax.md @@ -33,7 +33,7 @@ To parameterize the types in a new single function, we need to name the type parameter, just as we do for the value parameters to a function. You can use any identifier as a type parameter name. But we’ll use `T` because, by convention, type parameter names in Rust are short, often just one letter, and -Rust’s type-naming convention is UpperCamelCase. Short for *type*, `T` is the +Rust’s type-naming convention is UpperCamelCase. Short for _type_, `T` is the default choice of most Rust programmers. When we use a parameter in the body of the function, we have to declare the @@ -71,7 +71,7 @@ If we compile this code right now, we’ll get this error: {{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt}} ``` -The help text mentions `std::cmp::PartialOrd`, which is a *trait*, and we’re +The help text mentions `std::cmp::PartialOrd`, which is a _trait_, and we’re going to talk about traits in the next section. For now, know that this error states that the body of `largest` won’t work for all possible types that `T` could be. Because we want to compare values of type `T` in the body, we can @@ -104,7 +104,7 @@ types. Note that because we’ve used only one generic type to define `Point`, this definition says that the `Point` struct is generic over some type `T`, and -the fields `x` and `y` are *both* that same type, whatever that type may be. If +the fields `x` and `y` are _both_ that same type, whatever that type may be. If we create an instance of a `Point` that has values of different types, as in Listing 10-7, our code won’t compile. @@ -270,7 +270,7 @@ parameters. The good news is that using generic types won’t make your program run any slower than it would with concrete types. Rust accomplishes this by performing monomorphization of the code using -generics at compile time. *Monomorphization* is the process of turning generic +generics at compile time. _Monomorphization_ is the process of turning generic code into specific code by filling in the concrete types that are used when compiled. In this process, the compiler does the opposite of the steps we used to create the generic function in Listing 10-5: the compiler looks at all the diff --git a/rustbook-en/src/ch10-02-traits.md b/rustbook-en/src/ch10-02-traits.md index d9c40518e..5628eef64 100644 --- a/rustbook-en/src/ch10-02-traits.md +++ b/rustbook-en/src/ch10-02-traits.md @@ -1,11 +1,11 @@ ## Traits: Defining Shared Behavior -A *trait* defines the functionality a particular type has and can share with +A _trait_ defines the functionality a particular type has and can share with other types. We can use traits to define shared behavior in an abstract way. We -can use *trait bounds* to specify that a generic type can be any type that has +can use _trait bounds_ to specify that a generic type can be any type that has certain behavior. -> Note: Traits are similar to a feature often called *interfaces* in other +> Note: Traits are similar to a feature often called _interfaces_ in other > languages, although with some differences. ### Defining a Trait @@ -105,7 +105,7 @@ But we can’t implement external traits on external types. For example, we can implement the `Display` trait on `Vec` within our `aggregator` crate because `Display` and `Vec` are both defined in the standard library and aren’t local to our `aggregator` crate. This restriction is part of a property called -*coherence*, and more specifically the *orphan rule*, so named because the +_coherence_, and more specifically the _orphan rule_, so named because the parent type is not present. This rule ensures that other people’s code can’t break your code and vice versa. Without the rule, two crates could implement the same trait for the same type, and Rust wouldn’t know which implementation @@ -206,12 +206,13 @@ function with any other type, such as a `String` or an `i32`, won’t compile because those types don’t implement `Summary`. + #### Trait Bound Syntax The `impl Trait` syntax works for straightforward cases but is actually syntax -sugar for a longer form known as a *trait bound*; it looks like this: +sugar for a longer form known as a _trait bound_; it looks like this: ```rust,ignore pub fn notify(item: &T) { @@ -334,7 +335,7 @@ traits. For example, the type `Pair` in Listing 10-15 always implements the is a type alias for the type of the `impl` block, which in this case is `Pair`). But in the next `impl` block, `Pair` only implements the `cmp_display` method if its inner type `T` implements the `PartialOrd` trait -that enables comparison *and* the `Display` trait that enables printing. +that enables comparison _and_ the `Display` trait that enables printing. @@ -346,7 +347,7 @@ that enables comparison *and* the `Display` trait that enables printing. We can also conditionally implement a trait for any type that implements another trait. Implementations of a trait on any type that satisfies the trait -bounds are called *blanket implementations* and are used extensively in the +bounds are called _blanket implementations_ and are used extensively in the Rust standard library. For example, the standard library implements the `ToString` trait on any type that implements the `Display` trait. The `impl` block in the standard library looks similar to this code: diff --git a/rustbook-en/src/ch10-03-lifetime-syntax.md b/rustbook-en/src/ch10-03-lifetime-syntax.md index d9922d38a..0a356ec64 100644 --- a/rustbook-en/src/ch10-03-lifetime-syntax.md +++ b/rustbook-en/src/ch10-03-lifetime-syntax.md @@ -6,7 +6,7 @@ references are valid as long as we need them to be. One detail we didn’t discuss in the [“References and Borrowing”][references-and-borrowing] section in Chapter 4 is -that every reference in Rust has a *lifetime*, which is the scope for which +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 only when multiple types are possible. In a similar way, we must annotate lifetimes @@ -21,7 +21,7 @@ lifetime syntax so you can get comfortable with the concept. ### Preventing Dangling References with Lifetimes -The main aim of lifetimes is to prevent *dangling references*, which cause a +The main aim of lifetimes is to prevent _dangling references_, which cause a program to reference data other than the data it’s intended to reference. Consider the program in Listing 10-16, which has an outer scope and an inner scope. @@ -62,7 +62,7 @@ determine that this code is invalid? It uses a borrow checker. ### The Borrow Checker -The Rust compiler has a *borrow checker* that compares scopes to determine +The Rust compiler has a _borrow checker_ that compares scopes to determine whether all borrows are valid. Listing 10-17 shows the same code as Listing 10-16 but with annotations showing the lifetimes of the variables. @@ -188,8 +188,8 @@ relate to each other in the context of the `longest` function. ### Lifetime Annotations in Function Signatures To use lifetime annotations in function signatures, we need to declare the -generic *lifetime* parameters inside angle brackets between the function name -and the parameter list, just as we did with generic *type* parameters. +generic _lifetime_ parameters inside angle brackets between the function name +and the parameter list, just as we did with generic _type_ parameters. We want the signature to express the following constraint: the returned reference will be valid as long as both the parameters are valid. This is the @@ -324,7 +324,7 @@ any relationship with the lifetime of `x` or the return value. When returning a reference from a function, the lifetime parameter for the return type needs to match the lifetime parameter for one of the parameters. If -the reference returned does *not* refer to one of the parameters, it must refer +the reference returned does _not_ refer to one of the parameters, it must refer to a value created within this function. However, this would be a dangling reference because the value will go out of scope at the end of the function. Consider this attempted implementation of the `longest` function that won’t @@ -425,7 +425,7 @@ deterministic patterns will emerge and be added to the compiler. In the future, even fewer lifetime annotations might be required. The patterns programmed into Rust’s analysis of references are called the -*lifetime elision rules*. These aren’t rules for programmers to follow; they’re +_lifetime elision rules_. These aren’t rules for programmers to follow; they’re a set of particular cases that the compiler will consider, and if your code fits these cases, you don’t need to write the lifetimes explicitly. @@ -435,8 +435,8 @@ compiler won’t guess what the lifetime of the remaining references should be. Instead of guessing, the compiler will give you an error that you can resolve by adding the lifetime annotations. -Lifetimes on function or method parameters are called *input lifetimes*, and -lifetimes on return values are called *output lifetimes*. +Lifetimes on function or method parameters are called _input lifetimes_, and +lifetimes on return values are called _output lifetimes_. The compiler uses three rules to figure out the lifetimes of the references when there aren’t explicit annotations. The first rule applies to input @@ -557,7 +557,7 @@ and all lifetimes have been accounted for. ### The Static Lifetime One special lifetime we need to discuss is `'static`, which denotes that the -affected reference *can* live for the entire duration of the program. All +affected reference _can_ live for the entire duration of the program. All string literals have the `'static` lifetime, which we can annotate as follows: ```rust @@ -611,8 +611,6 @@ that you will only need in very advanced scenarios; for those, you should read the [Rust Reference][reference]. But next, you’ll learn how to write tests in Rust so you can make sure your code is working the way it should. -[references-and-borrowing]: -ch04-02-references-and-borrowing.html#references-and-borrowing -[string-slices-as-parameters]: -ch04-03-slices.html#string-slices-as-parameters +[references-and-borrowing]: ch04-02-references-and-borrowing.html#references-and-borrowing +[string-slices-as-parameters]: ch04-03-slices.html#string-slices-as-parameters [reference]: ../reference/index.html diff --git a/rustbook-en/src/ch11-00-testing.md b/rustbook-en/src/ch11-00-testing.md index ea85a1410..f6e799d58 100644 --- a/rustbook-en/src/ch11-00-testing.md +++ b/rustbook-en/src/ch11-00-testing.md @@ -16,7 +16,7 @@ it. This function’s signature accepts an integer as a parameter and returns an integer as a result. When we implement and compile that function, Rust does all the type checking and borrow checking that you’ve learned so far to ensure that, for instance, we aren’t passing a `String` value or an invalid reference -to this function. But Rust *can’t* check that this function will do precisely +to this function. But Rust _can’t_ check that this function will do precisely what we intend, which is return the parameter plus 2 rather than, say, the parameter plus 10 or the parameter minus 50! That’s where tests come in. diff --git a/rustbook-en/src/ch11-01-writing-tests.md b/rustbook-en/src/ch11-01-writing-tests.md index 5c6452a7b..93009f4d0 100644 --- a/rustbook-en/src/ch11-01-writing-tests.md +++ b/rustbook-en/src/ch11-01-writing-tests.md @@ -4,9 +4,9 @@ Tests are Rust functions that verify that the non-test code is functioning in the expected manner. The bodies of test functions typically perform these three actions: -* Set up any needed data or state. -* Run the code you want to test. -* Assert that the results are what you expect. +- Set up any needed data or state. +- Run the code you want to test. +- Assert that the results are what you expect. Let’s look at the features Rust provides specifically for writing tests that take these actions, which include the `test` attribute, a few macros, and the @@ -40,7 +40,7 @@ $ cargo new adder --lib $ cd adder ``` -The contents of the *src/lib.rs* file in your `adder` library should look like +The contents of the _src/lib.rs_ file in your `adder` library should look like Listing 11-1. @@ -100,7 +100,7 @@ Benchmark tests are, as of this writing, only available in nightly Rust. See [the documentation about benchmark tests][bench] to learn more. We can pass an argument to the `cargo test` command to run only tests whose -name matches a string; this is called *filtering* and we’ll cover that in the +name matches a string; this is called _filtering_ and we’ll cover that in the [“Running a Subset of Tests by Name”][subset] section. Here we haven’t filtered the tests being run, so the end of the summary shows `0 filtered out`. @@ -134,7 +134,7 @@ fail 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. In Chapter 9, we talked about how the simplest way to panic is to call the `panic!` macro. Enter the new test as a function named -`another`, so your *src/lib.rs* file looks like Listing 11-3. +`another`, so your _src/lib.rs_ file looks like Listing 11-3. @@ -164,7 +164,7 @@ Instead of `ok`, the line `test tests::another` shows `FAILED`. Two new sections appear between the individual results and the summary: the first displays the detailed reason for each test failure. In this case, we get the details that `another` failed because it `panicked at 'Make this test fail'` on -line 17 in the *src/lib.rs* file. The next section lists just the names of all +line 17 in the _src/lib.rs_ file. The next section lists just the names of all the failing tests, which is useful when there are lots of tests and lots of detailed failing test output. We can use the name of a failing test to run just that test to more easily debug it; we’ll talk more about ways to run tests in @@ -188,7 +188,7 @@ macro helps us check that our code is functioning in the way we intend. In Chapter 5, Listing 5-15, we used a `Rectangle` struct and a `can_hold` method, which are repeated here in Listing 11-5. Let’s put this code in the -*src/lib.rs* file, then write some tests for it using the `assert!` macro. +_src/lib.rs_ file, then write some tests for it using the `assert!` macro. @@ -275,7 +275,7 @@ do this by using the `assert!` macro and passing it an expression using the provides a pair of macros—`assert_eq!` and `assert_ne!`—to perform this test more conveniently. These macros compare two arguments for equality or inequality, respectively. They’ll also print the two values if the assertion -fails, which makes it easier to see *why* the test failed; conversely, the +fails, which makes it easier to see _why_ the test failed; conversely, the `assert!` macro only indicates that it got a `false` value for the `==` expression, without printing the values that led to the `false` value. @@ -331,7 +331,7 @@ that displays `` assertion failed: `(left == right)` ``. The `assert_ne!` macro will pass if the two values we give it are not equal and fail if they’re equal. This macro is most useful for cases when we’re not sure -what a value *will* be, but we know what the value definitely *shouldn’t* be. +what a value _will_ be, but we know what the value definitely _shouldn’t_ be. For example, if we’re testing a function that is guaranteed to change its input in some way, but the way in which the input is changed depends on the day of the week that we run our tests, the best thing to assert might be that the @@ -367,6 +367,7 @@ 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: Filename: src/lib.rs + ```rust,noplayground {{#rustdoc_include ../listings/ch11-writing-automated-tests/no-listing-05-greeter/src/lib.rs}} ``` @@ -525,7 +526,7 @@ 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`. To assert that an operation returns an `Err` variant, *don’t* use the +E>`. To assert that an operation returns an `Err` variant, _don’t_ use the question mark operator on the `Result` value. Instead, use `assert!(value.is_err())`. @@ -533,13 +534,11 @@ 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 test`. -[concatenation-with-the--operator-or-the-format-macro]: -ch08-02-strings.html#concatenation-with-the--operator-or-the-format-macro +[concatenation-with-the--operator-or-the-format-macro]: ch08-02-strings.html#concatenation-with-the--operator-or-the-format-macro [bench]: ../unstable-book/library-features/test.html [ignoring]: ch11-02-running-tests.html#ignoring-some-tests-unless-specifically-requested [subset]: ch11-02-running-tests.html#running-a-subset-of-tests-by-name -[controlling-how-tests-are-run]: -ch11-02-running-tests.html#controlling-how-tests-are-run +[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 diff --git a/rustbook-en/src/ch11-02-running-tests.md b/rustbook-en/src/ch11-02-running-tests.md index 1c9a1a35d..dc4afc2af 100644 --- a/rustbook-en/src/ch11-02-running-tests.md +++ b/rustbook-en/src/ch11-02-running-tests.md @@ -19,7 +19,6 @@ section][tests] of the [the rustc book][rustc]. [tests]: https://doc.rust-lang.org/rustc/tests/index.html [rustc]: https://doc.rust-lang.org/rustc/index.html - ### Running Tests in Parallel or Consecutively When you run multiple tests, by default they run in parallel using threads, @@ -29,7 +28,7 @@ on each other or on any shared state, including a shared environment, such as the current working directory or environment variables. For example, say each of your tests runs some code that creates a file on disk -named *test-output.txt* and writes some data to that file. Then each test reads +named _test-output.txt_ and writes some data to that file. Then each test reads the data in that file and asserts that the file contains a particular value, which is different in each test. Because the tests run at the same time, one test might overwrite the file in the time between another test writing and diff --git a/rustbook-en/src/ch11-03-test-organization.md b/rustbook-en/src/ch11-03-test-organization.md index 323f01a74..d0c6ef300 100644 --- a/rustbook-en/src/ch11-03-test-organization.md +++ b/rustbook-en/src/ch11-03-test-organization.md @@ -3,8 +3,8 @@ As mentioned at the start of the chapter, testing is a complex discipline, and different people use different terminology and organization. The Rust community thinks about tests in terms of two main categories: unit tests and integration -tests. *Unit tests* are small and more focused, testing one module in isolation -at a time, and can test private interfaces. *Integration tests* are entirely +tests. _Unit tests_ are small and more focused, testing one module in isolation +at a time, and can test private interfaces. _Integration tests_ are entirely external to your library and use your code in the same way any other external code would, using only the public interface and potentially exercising multiple modules per test. @@ -16,7 +16,7 @@ library are doing what you expect them to, separately and together. The purpose of unit tests is to test each unit of code in isolation from the rest of the code to quickly pinpoint where code is and isn’t working as -expected. You’ll put unit tests in the *src* directory in each file with the +expected. You’ll put unit tests in the _src_ directory in each file with the code that they’re testing. The convention is to create a module named `tests` in each file to contain the test functions and to annotate the module with `cfg(test)`. @@ -42,7 +42,7 @@ this chapter, Cargo generated this code for us: ``` On the automatically generated `tests` module, the attribute `cfg` stands for -*configuration* and tells Rust that the following item should only be included +_configuration_ and tells Rust that the following item should only be included given a certain configuration option. In this case, the configuration option is `test`, which is provided by Rust for compiling and running tests. By using the `cfg` attribute, Cargo compiles our test code only if we actively run the tests @@ -82,18 +82,18 @@ functions that are part of your library’s public API. Their purpose is to test whether many parts of your library work together correctly. Units of code that work correctly on their own could have problems when integrated, so test coverage of the integrated code is important as well. To create integration -tests, you first need a *tests* directory. +tests, you first need a _tests_ directory. -#### The *tests* Directory +#### The _tests_ Directory -We create a *tests* directory at the top level of our project directory, next -to *src*. Cargo knows to look for integration test files in this directory. We +We create a _tests_ directory at the top level of our project directory, next +to _src_. Cargo knows to look for integration test files in this directory. We can then make as many test files as we want, and Cargo 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, and create a new file named -*tests/integration_test.rs*. Your directory structure should look like this: +_src/lib.rs_ file, make a _tests_ directory, and create a new file named +_tests/integration_test.rs_. Your directory structure should look like this: ```text adder @@ -105,7 +105,7 @@ adder └── integration_test.rs ``` -Enter the code in Listing 11-13 into the *tests/integration_test.rs* file. +Enter the code in Listing 11-13 into the _tests/integration_test.rs_ file. @@ -115,12 +115,12 @@ Enter the code in Listing 11-13 into the *tests/integration_test.rs* file. -Each file in the *tests* directory is a separate crate, so we need to bring our +Each file in the _tests_ directory is a separate crate, so we need to bring our library into each test crate’s scope. For that reason we add `use adder::add_two;` at the top of the code, which we didn’t need in the unit tests. -We don’t need to annotate any code in *tests/integration_test.rs* with -`#[cfg(test)]`. Cargo treats the *tests* directory specially and compiles files +We don’t need to annotate any code in _tests/integration_test.rs_ with +`#[cfg(test)]`. Cargo treats the _tests_ directory specially and compiles files in this directory only when we run `cargo test`. Run `cargo test` now: ```console @@ -143,7 +143,7 @@ that integration test and a summary line for the results of the integration test just before the `Doc-tests adder` section starts. Each integration test file has its own section, so if we add more files in the -*tests* directory, there will be more integration test sections. +_tests_ directory, there will be more integration test sections. We can still run a particular integration test function by specifying the test function’s name as an argument to `cargo test`. To run all the tests in a @@ -154,24 +154,24 @@ followed by the name of the file: {{#include ../listings/ch11-writing-automated-tests/output-only-05-single-integration/output.txt}} ``` -This command runs only the tests in the *tests/integration_test.rs* file. +This command runs only the tests in the _tests/integration_test.rs_ file. #### Submodules in Integration Tests As you add more integration tests, you might want to make more files in the -*tests* directory to help organize them; for example, you can group the test +_tests_ directory to help organize them; for example, you can group the test functions by the functionality they’re testing. As mentioned earlier, each file -in the *tests* directory is compiled as its own separate crate, which is useful +in the _tests_ directory is compiled as its own separate crate, which is useful for creating separate scopes to more closely imitate the way end users will be -using your crate. However, this means files in the *tests* directory don’t -share the same behavior as files in *src* do, as you learned in Chapter 7 +using your crate. However, this means files in the _tests_ directory don’t +share the same behavior as files in _src_ do, as you learned in Chapter 7 regarding how to separate code into modules and files. -The different behavior of *tests* directory files is most noticeable when you +The different behavior of _tests_ directory files is most noticeable when you have a set of helper functions to use in multiple integration test files and you try to follow the steps in the [“Separating Modules into Different Files”][separating-modules-into-files] section of Chapter 7 to -extract them into a common module. For example, if we create *tests/common.rs* +extract them into a common module. For example, if we create _tests/common.rs_ and place a function named `setup` in it, we can add some code to `setup` that we want to call from multiple test functions in multiple test files: @@ -182,7 +182,7 @@ we want to call from multiple test functions in multiple test files: ``` When we run the tests again, we’ll see a new section in the test output for the -*common.rs* file, even though this file doesn’t contain any test functions nor +_common.rs_ file, even though this file doesn’t contain any test functions nor did we call the `setup` function from anywhere: ```console @@ -192,7 +192,7 @@ did we call the `setup` function from anywhere: Having `common` appear in the test results with `running 0 tests` displayed for it is not what we wanted. We just wanted to share some code with the other integration test files. To avoid having `common` appear in the test output, -instead of creating *tests/common.rs*, we’ll create *tests/common/mod.rs*. The +instead of creating _tests/common.rs_, we’ll create _tests/common/mod.rs_. The project directory now looks like this: ```text @@ -210,14 +210,14 @@ This is the older naming convention that Rust also understands that we mentioned in the [“Alternate File Paths”][alt-paths] section of Chapter 7. Naming the file this way tells Rust not to treat the `common` module as an integration test file. When we move the `setup` function code into -*tests/common/mod.rs* and delete the *tests/common.rs* file, the section in the -test output will no longer appear. Files in subdirectories of the *tests* +_tests/common/mod.rs_ and delete the _tests/common.rs_ file, the section in the +test output will no longer appear. Files in subdirectories of the _tests_ directory don’t get compiled as separate crates or have sections in the test output. -After we’ve created *tests/common/mod.rs*, we can use it from any of the +After we’ve created _tests/common/mod.rs_, we can use it from any of the integration test files as a module. Here’s an example of calling the `setup` -function from the `it_adds_two` test in *tests/integration_test.rs*: +function from the `it_adds_two` test in _tests/integration_test.rs_: Filename: tests/integration_test.rs @@ -231,17 +231,17 @@ we demonstrated in Listing 7-21. Then, in the test function, we can call the #### Integration Tests for Binary Crates -If our project is a binary crate that only contains a *src/main.rs* file and -doesn’t have a *src/lib.rs* file, we can’t create integration tests in the -*tests* directory and bring functions defined in the *src/main.rs* file into +If our project is a binary crate that only contains a _src/main.rs_ file and +doesn’t have a _src/lib.rs_ file, we can’t create integration tests in the +_tests_ directory and bring functions defined in the _src/main.rs_ file into scope with a `use` statement. Only library crates expose functions that other crates can use; binary crates are meant to be run on their own. This is one of the reasons Rust projects that provide a binary have a -straightforward *src/main.rs* file that calls logic that lives in the -*src/lib.rs* file. Using that structure, integration tests *can* test the +straightforward _src/main.rs_ file that calls logic that lives in the +_src/lib.rs_ file. Using that structure, integration tests _can_ test the library crate with `use` to make the important functionality available. If the -important functionality works, the small amount of code in the *src/main.rs* +important functionality works, the small amount of code in the _src/main.rs_ file will work as well, and that small amount of code doesn’t need to be tested. ## Summary @@ -259,6 +259,5 @@ Let’s combine the knowledge you learned in this chapter and in previous chapters to work on a project! [paths]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html -[separating-modules-into-files]: -ch07-05-separating-modules-into-different-files.html +[separating-modules-into-files]: ch07-05-separating-modules-into-different-files.html [alt-paths]: ch07-05-separating-modules-into-different-files.html#alternate-file-paths diff --git a/rustbook-en/src/ch12-00-an-io-project.md b/rustbook-en/src/ch12-00-an-io-project.md index e179e1180..e421cc12f 100644 --- a/rustbook-en/src/ch12-00-an-io-project.md +++ b/rustbook-en/src/ch12-00-an-io-project.md @@ -29,11 +29,11 @@ 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 ([Chapter 7][ch7]) -* Using vectors and strings ([Chapter 8][ch8]) -* Handling errors ([Chapter 9][ch9]) -* Using traits and lifetimes where appropriate ([Chapter 10][ch10]) -* Writing tests ([Chapter 11][ch11]) +- Organizing code ([Chapter 7][ch7]) +- Using vectors and strings ([Chapter 8][ch8]) +- Handling errors ([Chapter 9][ch9]) +- Using traits and lifetimes where appropriate ([Chapter 10][ch10]) +- Writing tests ([Chapter 11][ch11]) We’ll also briefly introduce closures, iterators, and trait objects, which [Chapter 13][ch13] and [Chapter 18][ch18] will diff --git a/rustbook-en/src/ch12-02-reading-a-file.md b/rustbook-en/src/ch12-02-reading-a-file.md index 804683d50..bc6d79139 100644 --- a/rustbook-en/src/ch12-02-reading-a-file.md +++ b/rustbook-en/src/ch12-02-reading-a-file.md @@ -4,7 +4,7 @@ Now we’ll add functionality to read the file specified in the `file_path` argument. First we need a sample file to test it with: we’ll use a file with a small amount of text over multiple lines with some repeated words. Listing 12-3 has an Emily Dickinson poem that will work well! Create a file called -*poem.txt* at the root level of your project, and enter the poem “I’m Nobody! +_poem.txt_ at the root level of your project, and enter the poem “I’m Nobody! Who are you?” @@ -15,7 +15,7 @@ Who are you?” -With the text in place, edit *src/main.rs* and add code to read the file, as +With the text in place, edit _src/main.rs_ and add code to read the file, as shown in Listing 12-4. @@ -38,7 +38,7 @@ of `contents` after the file is read, so we can check that the program is working so far. Let’s run this code with any string as the first command line argument (because -we haven’t implemented the searching part yet) and the *poem.txt* file as the +we haven’t implemented the searching part yet) and the _poem.txt_ file as the second argument: ```console diff --git a/rustbook-en/src/ch12-03-improving-error-handling-and-modularity.md b/rustbook-en/src/ch12-03-improving-error-handling-and-modularity.md index bf2b7c35b..0bf85bdd6 100644 --- a/rustbook-en/src/ch12-03-improving-error-handling-and-modularity.md +++ b/rustbook-en/src/ch12-03-improving-error-handling-and-modularity.md @@ -41,34 +41,34 @@ community has developed guidelines for splitting the separate concerns of a binary program when `main` starts getting large. This process has the following steps: -* Split your program into a *main.rs* file and a *lib.rs* file and move your - program’s logic to *lib.rs*. -* As long as your command line parsing logic is small, it can remain in - *main.rs*. -* When the command line parsing logic starts getting complicated, extract it - from *main.rs* and move it to *lib.rs*. +- Split your program into a _main.rs_ file and a _lib.rs_ file and move your + program’s logic to _lib.rs_. +- As long as your command line parsing logic is small, it can remain in + _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: -* 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 +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 can’t test the `main` function directly, this structure lets you test all of -your program’s logic by moving it into functions in *lib.rs*. The code that -remains in *main.rs* will be small enough to verify its correctness by reading +your program’s logic by moving it into functions in _lib.rs_. The code that +remains in _main.rs_ will be small enough to verify its correctness by reading it. Let’s rework our program by following this process. #### Extracting the Argument Parser We’ll extract the functionality for parsing arguments into a function that `main` will call to prepare for moving the command line parsing logic to -*src/lib.rs*. Listing 12-5 shows the new start of `main` that calls a new -function `parse_config`, which we’ll define in *src/main.rs* for the moment. +_src/lib.rs_. Listing 12-5 shows the new start of `main` that calls a new +function `parse_config`, which we’ll define in _src/main.rs_ for the moment. @@ -243,6 +243,7 @@ we’ll use the other technique you learned about in Chapter 9—[returning a `Result`][ch9-result] that indicates either success or an error. + #### Returning a `Result` Instead of Calling `panic!` @@ -283,6 +284,7 @@ handle the `Result` value returned from the `build` function and exit the process more cleanly in the error case. + #### Calling `Config::build` and Handling Errors @@ -307,7 +309,7 @@ In this listing, we’ve used a method we haven’t covered in detail yet: Using `unwrap_or_else` allows us to define some custom, non-`panic!` error handling. If the `Result` is an `Ok` value, this method’s behavior is similar to `unwrap`: it returns the inner value that `Ok` is wrapping. However, if the -value is an `Err` value, this method calls the code in the *closure*, which is +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]. For now, you just need to know that `unwrap_or_else` will pass the inner value of @@ -342,7 +344,7 @@ inspection, and we’ll be able to write tests for all the other logic. Listing 12-11 shows the extracted `run` function. For now, we’re just making the small, incremental improvement of extracting the function. We’re still -defining the function in *src/main.rs*. +defining the function in _src/main.rs_. @@ -379,14 +381,14 @@ the `run` function to `Result<(), Box>`. This function previously returned the unit type, `()`, and we keep that as the value returned in the `Ok` case. -For the error type, we used the *trait object* `Box` (and we’ve +For the error type, we used the _trait object_ `Box` (and we’ve brought `std::error::Error` into scope with a `use` statement at the top). We’ll cover trait objects in [Chapter 18][ch18]. For now, just know that `Box` 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*. +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]. Rather than @@ -435,20 +437,20 @@ both cases: we print the error and exit. ### Splitting Code into a Library Crate Our `minigrep` project is looking good so far! Now we’ll split the -*src/main.rs* file and put some code into the *src/lib.rs* file. That way, we -can test the code and have a *src/main.rs* file with fewer responsibilities. +_src/main.rs_ file and put some code into the _src/lib.rs_ file. That way, we +can test the code and have a _src/main.rs_ file with fewer responsibilities. -Let’s move all the code that isn’t in the `main` function from *src/main.rs* to -*src/lib.rs*: +Let’s move all the code that isn’t in the `main` function from _src/main.rs_ to +_src/lib.rs_: -* The `run` function definition -* The relevant `use` statements -* The definition of `Config` -* The `Config::build` function definition +- The `run` function definition +- The relevant `use` statements +- The definition of `Config` +- The `Config::build` function definition -The contents of *src/lib.rs* should have the signatures shown in Listing 12-13 +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 Listing 12-14. @@ -462,8 +464,8 @@ We’ve made liberal use of the `pub` keyword: on `Config`, on its fields and it `build` method, and on the `run` function. We now have a library crate that has a public API 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. +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. @@ -480,7 +482,7 @@ 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 -modular. Almost all of our work will be done in *src/lib.rs* from here on out. +modular. Almost all of our work will be done in _src/lib.rs_ from here on out. Let’s take advantage of this newfound modularity by doing something that would have been difficult with the old code but is easy with the new code: we’ll diff --git a/rustbook-en/src/ch12-04-testing-the-librarys-functionality.md b/rustbook-en/src/ch12-04-testing-the-librarys-functionality.md index 7034783d7..92dac84aa 100644 --- a/rustbook-en/src/ch12-04-testing-the-librarys-functionality.md +++ b/rustbook-en/src/ch12-04-testing-the-librarys-functionality.md @@ -1,7 +1,7 @@ ## Developing the Library’s Functionality with Test-Driven Development -Now that we’ve extracted the logic into *src/lib.rs* and left the argument -collecting and error handling in *src/main.rs*, it’s much easier to write tests +Now that we’ve extracted the logic into _src/lib.rs_ and left the argument +collecting and error handling in _src/main.rs_, it’s much easier to write tests for the core functionality of our code. We can call functions directly with various arguments and check return values without having to call our binary from the command line. @@ -28,8 +28,8 @@ lines that match the query. We’ll add this functionality in a function called ### Writing a Failing Test 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 +_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]. The test function specifies the behavior we want the `search` function to have: it will take a query and the text to search, and it will return only the lines from the text that @@ -75,7 +75,7 @@ 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 -`contents` argument. This is important! The data referenced *by* a slice needs +`contents` argument. This is important! The data referenced _by_ a slice needs to be valid for the reference to be valid; if the compiler assumes we’re making string slices of `query` rather than `contents`, it will do its safety checking incorrectly. @@ -205,20 +205,20 @@ will print each line returned from `search`: We’re still using a `for` loop to return each line from `search` and print it. 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*. +should return exactly one line from the Emily Dickinson poem: _frog_. ```console {{#include ../listings/ch12-an-io-project/no-listing-02-using-search-in-run/output.txt}} ``` -Cool! Now let’s try a word that will match multiple lines, like *body*: +Cool! Now let’s try a word that will match multiple lines, like _body_: ```console {{#include ../listings/ch12-an-io-project/output-only-03-multiple-matches/output.txt}} ``` 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*: +word that isn’t anywhere in the poem, such as _monomorphization_: ```console {{#include ../listings/ch12-an-io-project/output-only-04-no-matches/output.txt}} @@ -232,8 +232,7 @@ To round out this project, we’ll briefly demonstrate how to work with environment variables and how to print to standard error, both of which are useful when you’re writing command line programs. -[validating-references-with-lifetimes]: -ch10-03-lifetime-syntax.html#validating-references-with-lifetimes +[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 diff --git a/rustbook-en/src/ch12-05-working-with-environment-variables.md b/rustbook-en/src/ch12-05-working-with-environment-variables.md index 630f98cb2..b91b00ba8 100644 --- a/rustbook-en/src/ch12-05-working-with-environment-variables.md +++ b/rustbook-en/src/ch12-05-working-with-environment-variables.md @@ -25,15 +25,15 @@ tests, as shown in Listing 12-20. 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 +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 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. -The new test for the case-*insensitive* search uses `"rUsT"` as its query. In +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 +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 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 @@ -109,7 +109,7 @@ function, as shown in Listing 12-22. This still 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 bring that module into scope at the top of *src/lib.rs*. Then +library, so we bring that module into scope at the top of _src/lib.rs_. Then we’ll use the `var` function from the `env` module to check to see if any value has been set for an environment variable named `IGNORE_CASE`, as shown in Listing 12-23. @@ -133,7 +133,7 @@ We’re using the `is_ok` method on the `Result` to check whether the environmen variable is set, which means the program should do a case-insensitive search. If the `IGNORE_CASE` environment variable isn’t set to anything, `is_ok` will return `false` and the program will perform a case-sensitive search. We don’t -care about the *value* of the environment variable, just whether it’s set or +care about the _value_ of the environment variable, just whether it’s set or unset, so we’re checking `is_ok` rather than using `unwrap`, `expect`, or any of the other methods we’ve seen on `Result`. @@ -143,14 +143,14 @@ We pass the value in the `ignore_case` variable to the `Config` instance so the Let’s give it a try! First we’ll run our program without the environment variable set and with the query `to`, which should match any line that contains -the word *to* in all lowercase: +the word _to_ in all lowercase: ```console {{#include ../listings/ch12-an-io-project/listing-12-23/output.txt}} ``` Looks like that still works! Now let’s run the program with `IGNORE_CASE` set -to `1` but with the same query *to*: +to `1` but with the same query _to_: ```console $ IGNORE_CASE=1 cargo run -- to poem.txt @@ -170,7 +170,7 @@ It can be unset with the `Remove-Item` cmdlet: PS> Remove-Item Env:IGNORE_CASE ``` -We should get lines that contain *to* that might have uppercase letters: +We should get lines that contain _to_ that might have uppercase letters: + ## Closures: Anonymous Functions that Capture Their Environment @@ -11,6 +12,7 @@ We’ll demonstrate how these closure features allow for code reuse and behavior customization. + @@ -258,6 +260,7 @@ in the main thread after the closure is defined to see what compiler errors you get! + @@ -266,9 +269,9 @@ get! Once a closure has captured a reference or captured ownership of a value from the environment where the closure is defined (thus affecting what, if anything, -is moved *into* the closure), the code in the body of the closure defines what +is moved _into_ the closure), the code in the body of the closure defines what happens to the references or values when the closure is evaluated later (thus -affecting what, if anything, is moved *out of* the closure). A closure body can +affecting what, if anything, is moved _out of_ the closure). A closure body can do any of the following: move a captured value out of the closure, mutate the captured value, neither move nor mutate the value, or capture nothing from the environment to begin with. diff --git a/rustbook-en/src/ch13-02-iterators.md b/rustbook-en/src/ch13-02-iterators.md index 5942a62c5..65573f114 100644 --- a/rustbook-en/src/ch13-02-iterators.md +++ b/rustbook-en/src/ch13-02-iterators.md @@ -5,7 +5,7 @@ turn. An iterator is responsible for the logic of iterating over each item and determining when the sequence has finished. When you use iterators, you don’t have to reimplement that logic yourself. -In Rust, iterators are *lazy*, meaning they have no effect until you call +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-10 creates an iterator over the items in the vector `v1` by calling the `iter` method defined on `Vec`. This code by itself doesn’t do anything @@ -65,7 +65,7 @@ pub trait Iterator { ``` Notice this definition uses some new syntax: `type Item` and `Self::Item`, -which are defining an *associated type* with this trait. We’ll talk about +which are defining an _associated type_ with this trait. We’ll talk about associated types in depth in Chapter 20. For now, all you need to know is that this code says implementing the `Iterator` trait requires that you also define an `Item` type, and this `Item` type is used in the return type of the `next` @@ -90,7 +90,7 @@ from the vector. Note that we needed to make `v1_iter` mutable: calling the `next` method on an iterator changes internal state that the iterator uses to keep track of where -it is in the sequence. In other words, this code *consumes*, or uses up, the +it is in the sequence. In other words, this code _consumes_, or uses up, the iterator. Each call to `next` eats up an item from the iterator. We didn’t need to make `v1_iter` mutable when we used a `for` loop because the loop took ownership of `v1_iter` and made it mutable behind the scenes. @@ -111,7 +111,7 @@ trait. Some of these methods call the `next` method in their definition, which is why you’re required to implement the `next` method when implementing the `Iterator` trait. -Methods that call `next` are called *consuming adapters*, because calling them +Methods that call `next` are called _consuming adapters_, because calling them uses up the iterator. One example is the `sum` method, which takes ownership of the iterator and iterates through the items by repeatedly calling `next`, thus consuming the iterator. As it iterates through, it adds each item to a running @@ -131,7 +131,7 @@ ownership of the iterator we call it on. ### Methods that Produce Other Iterators -*Iterator adapters* are methods defined on the `Iterator` trait that don’t +_Iterator adapters_ are methods defined on the `Iterator` trait that don’t consume the iterator. Instead, they produce different iterators by changing some aspect of the original iterator. diff --git a/rustbook-en/src/ch13-03-improving-our-io-project.md b/rustbook-en/src/ch13-03-improving-our-io-project.md index c560bc112..489bdc10f 100644 --- a/rustbook-en/src/ch13-03-improving-our-io-project.md +++ b/rustbook-en/src/ch13-03-improving-our-io-project.md @@ -41,7 +41,7 @@ operations that borrow, we can move the `String` values from the iterator into #### Using the Returned Iterator Directly -Open your I/O project’s *src/main.rs* file, which should look like this: +Open your I/O project’s _src/main.rs_ file, which should look like this: Filename: src/main.rs @@ -67,7 +67,7 @@ we’re passing ownership of the iterator returned from `env::args` to `Config::build` directly. Next, we need to update the definition of `Config::build`. In your I/O -project’s *src/lib.rs* file, let’s change the signature of `Config::build` to +project’s _src/lib.rs_ file, let’s change the signature of `Config::build` to look like Listing 13-19. This still won’t compile because we need to update the function body. diff --git a/rustbook-en/src/ch13-04-performance.md b/rustbook-en/src/ch13-04-performance.md index 0dbc7420a..d9cc06f99 100644 --- a/rustbook-en/src/ch13-04-performance.md +++ b/rustbook-en/src/ch13-04-performance.md @@ -4,9 +4,9 @@ To determine whether to use loops or iterators, you need to know which implementation is faster: the version of the `search` function with an explicit `for` loop or the version with iterators. -We ran a benchmark by loading the entire contents of *The Adventures of -Sherlock Holmes* by Sir Arthur Conan Doyle into a `String` and looking for the -word *the* in the contents. Here are the results of the benchmark on the +We ran a benchmark by loading the entire contents of _The Adventures of +Sherlock Holmes_ by Sir Arthur Conan Doyle into a `String` and looking for the +word _the_ in the contents. Here are the results of the benchmark on the version of `search` using the `for` loop and the version using iterators: ```text @@ -24,10 +24,10 @@ various sizes as the `contents`, different words and words of different lengths as the `query`, and all kinds of other variations. The point is this: iterators, although a high-level abstraction, get compiled down to roughly the same code as if you’d written the lower-level code yourself. Iterators are one -of Rust’s *zero-cost abstractions*, by which we mean using the abstraction +of Rust’s _zero-cost abstractions_, by which we mean using the abstraction imposes no additional runtime overhead. This is analogous to how Bjarne Stroustrup, the original designer and implementor of C++, defines -*zero-overhead* in “Foundations of C++” (2012): +_zero-overhead_ in “Foundations of C++” (2012): > In general, C++ implementations obey the zero-overhead principle: What you > don’t use, you don’t pay for. And further: What you do use, you couldn’t hand @@ -70,7 +70,7 @@ consuming the value. What assembly code would this Rust code compile to? Well, as of this writing, it compiles down to the same assembly you’d write by hand. There’s no loop at all corresponding to the iteration over the values in `coefficients`: Rust knows that there are 12 iterations, so it “unrolls” the -loop. *Unrolling* is an optimization that removes the overhead of the loop +loop. _Unrolling_ is an optimization that removes the overhead of the loop controlling code and instead generates repetitive code for each iteration of the loop. diff --git a/rustbook-en/src/ch14-00-more-about-cargo.md b/rustbook-en/src/ch14-00-more-about-cargo.md index 8f8b8e51c..a6d0d9154 100644 --- a/rustbook-en/src/ch14-00-more-about-cargo.md +++ b/rustbook-en/src/ch14-00-more-about-cargo.md @@ -4,12 +4,11 @@ So far we’ve used only the most basic features of Cargo to build, run, and tes 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/) -* Organize large projects with workspaces -* Install binaries from [crates.io](https://crates.io/) -* Extend Cargo using custom commands +- Customize your build through release profiles +- Publish libraries on [crates.io](https://crates.io/) +- Organize large projects with workspaces +- Install binaries from [crates.io](https://crates.io/) +- Extend Cargo using custom commands Cargo can do even more than the functionality we cover in this chapter, so for -a full explanation of all its features, see [its -documentation](https://doc.rust-lang.org/cargo/). +a full explanation of all its features, see [its documentation](https://doc.rust-lang.org/cargo/). diff --git a/rustbook-en/src/ch14-01-release-profiles.md b/rustbook-en/src/ch14-01-release-profiles.md index 5038cf697..6dd52c642 100644 --- a/rustbook-en/src/ch14-01-release-profiles.md +++ b/rustbook-en/src/ch14-01-release-profiles.md @@ -1,6 +1,6 @@ ## Customizing Builds with Release Profiles -In Rust, *release profiles* are predefined and customizable profiles with +In Rust, _release profiles_ are predefined and customizable profiles with different configurations that allow a programmer to have more control over various options for compiling code. Each profile is configured independently of the others. @@ -29,7 +29,7 @@ $ cargo build --release The `dev` and `release` are these different profiles used by the compiler. Cargo has default settings for each of the profiles that apply when you haven't -explicitly added any `[profile.*]` sections in the project’s *Cargo.toml* file. +explicitly added any `[profile.*]` sections in the project’s _Cargo.toml_ file. By adding `[profile.*]` sections for any profile you want to customize, you override any subset of the default settings. For example, here are the default values for the `opt-level` setting for the `dev` and `release` profiles: @@ -55,8 +55,8 @@ so release mode trades longer compile time for code that runs faster. That is why the default `opt-level` for the `release` profile is `3`. You can override a default setting by adding a different value for it in -*Cargo.toml*. For example, if we want to use optimization level 1 in the -development profile, we can add these two lines to our project’s *Cargo.toml* +_Cargo.toml_. For example, if we want to use optimization level 1 in the +development profile, we can add these two lines to our project’s _Cargo.toml_ file: Filename: Cargo.toml diff --git a/rustbook-en/src/ch14-02-publishing-to-crates-io.md b/rustbook-en/src/ch14-02-publishing-to-crates-io.md index 0a72279cb..5b9b36d32 100644 --- a/rustbook-en/src/ch14-02-publishing-to-crates-io.md +++ b/rustbook-en/src/ch14-02-publishing-to-crates-io.md @@ -16,10 +16,10 @@ Accurately documenting your packages will help other users know how and when to use them, so it’s worth investing the time to write documentation. In Chapter 3, we discussed how to comment Rust code using two slashes, `//`. Rust also has a particular kind of comment for documentation, known conveniently as a -*documentation comment*, that will generate HTML documentation. The HTML +_documentation comment_, that will generate HTML documentation. The HTML displays the contents of documentation comments for public API items intended -for programmers interested in knowing how to *use* your crate as opposed to how -your crate is *implemented*. +for programmers interested in knowing how to _use_ your crate as opposed to how +your crate is _implemented_. Documentation comments use three slashes, `///`, instead of two and support Markdown notation for formatting the text. Place documentation comments just @@ -39,7 +39,7 @@ section with the heading `Examples`, and then provide code that demonstrates how to use the `add_one` function. We can generate the HTML documentation from this documentation comment by running `cargo doc`. This command runs the `rustdoc` tool distributed with Rust and puts the generated HTML documentation -in the *target/doc* directory. +in the _target/doc_ directory. For convenience, running `cargo doc --open` will build the HTML for your current crate’s documentation (as well as the documentation for all of your @@ -58,14 +58,14 @@ We used the `# Examples` Markdown heading in Listing 14-1 to create a section in the HTML with the title “Examples.” Here are some other sections that crate authors commonly use in their documentation: -* **Panics**: The scenarios in which the function being documented could +- **Panics**: The scenarios in which the function being documented could panic. Callers of the function who don’t want their programs to panic should make sure they don’t call the function in these situations. -* **Errors**: If the function returns a `Result`, describing the kinds of +- **Errors**: If the function returns a `Result`, describing the kinds of errors that might occur and what conditions might cause those errors to be returned can be helpful to callers so they can write code to handle the different kinds of errors in different ways. -* **Safety**: If the function is `unsafe` to call (we discuss unsafety in +- **Safety**: If the function is `unsafe` to call (we discuss unsafety in Chapter 20), there should be a section explaining why the function is unsafe and covering the invariants that the function expects callers to uphold. @@ -106,12 +106,12 @@ that the example and the code are out of sync with each other! The style of doc comment `//!` adds documentation to the item that contains the comments rather than to the items following the comments. We typically use -these doc comments inside the crate root file (*src/lib.rs* by convention) or +these doc comments inside the crate root file (_src/lib.rs_ by convention) or inside a module to document the crate or the module as a whole. For example, to add documentation that describes the purpose of the `my_crate` crate that contains the `add_one` function, we add documentation comments that -start with `//!` to the beginning of the *src/lib.rs* file, as shown in Listing +start with `//!` to the beginning of the _src/lib.rs_ file, as shown in Listing 14-2: @@ -125,7 +125,7 @@ start with `//!` to the beginning of the *src/lib.rs* file, as shown in Listing Notice there isn’t any code after the last line that begins with `//!`. Because we started the comments with `//!` instead of `///`, we’re documenting the item that contains this comment rather than an item that follows this comment. In -this case, that item is the *src/lib.rs* file, which is the crate root. These +this case, that item is the _src/lib.rs_ file, which is the crate root. These comments describe the entire crate. When we run `cargo doc --open`, these comments will display on the front @@ -158,7 +158,7 @@ They might also be annoyed at having to enter `use` `my_crate::some_module::another_module::UsefulType;` rather than `use` `my_crate::UsefulType;`. -The good news is that if the structure *isn’t* convenient for others to use +The good news is that if the structure _isn’t_ convenient for others to use from another library, you don’t have to rearrange your internal organization: instead, you can re-export items to make a public structure that’s different from your private structure by using `pub use`. Re-exporting takes a public @@ -275,7 +275,7 @@ 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 +_~/.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/). @@ -283,7 +283,7 @@ revoke it and generate a new token on [crates.io](https://crates.io/) for others to use. -Be careful, because a publish is *permanent*. The version can never be +Be careful, 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/) is to act as a permanent archive of code so that builds of all projects that depend on crates from @@ -411,12 +411,13 @@ anyone can easily add your crate as a dependency of their project. ### Publishing a New Version of an Existing Crate When you’ve made changes to your crate and are ready to release a new version, -you change the `version` value specified in your *Cargo.toml* file and +you change the `version` value specified in your _Cargo.toml_ file and republish. Use the [Semantic Versioning rules][semver] to decide what an appropriate next version number is based on the kinds of changes you’ve made. Then run `cargo publish` to upload the new version. + ### Deprecating Versions from Crates.io with `cargo yank` @@ -424,12 +425,12 @@ Then run `cargo publish` to upload the new version. Although you can’t remove previous versions of a crate, you can prevent any future projects from adding them as a new dependency. This is useful when a crate version is broken for one reason or another. In such situations, Cargo -supports *yanking* a crate version. +supports _yanking_ a crate version. Yanking a version prevents new projects from depending on that version while allowing all existing projects that depend on it to continue. Essentially, a -yank means that all projects with a *Cargo.lock* will not break, and any future -*Cargo.lock* files generated will not use the yanked version. +yank means that all projects with a _Cargo.lock_ will not break, and any future +_Cargo.lock_ files generated will not use the yanked version. To yank a version of a crate, in the directory of the crate that you’ve previously published, run `cargo yank` and specify which version you want to @@ -457,7 +458,7 @@ $ cargo yank --vers 1.0.1 --undo Unyank guessing_game@1.0.1 ``` -A yank *does not* delete any code. It cannot, for example, delete accidentally +A yank _does not_ delete any code. It cannot, for example, delete accidentally uploaded secrets. If that happens, you must reset those secrets immediately. [spdx]: http://spdx.org/licenses/ diff --git a/rustbook-en/src/ch14-03-cargo-workspaces.md b/rustbook-en/src/ch14-03-cargo-workspaces.md index 04bf2d6e7..8f257b584 100644 --- a/rustbook-en/src/ch14-03-cargo-workspaces.md +++ b/rustbook-en/src/ch14-03-cargo-workspaces.md @@ -3,12 +3,12 @@ In Chapter 12, we built a package that included a binary crate and a library crate. As your project develops, you might find that the library crate continues to get bigger and you want to split your package further into -multiple library crates. Cargo offers a feature called *workspaces* that can +multiple library crates. Cargo offers a feature called _workspaces_ that can help manage multiple related packages that are developed in tandem. ### Creating a Workspace -A *workspace* is a set of packages that share the same *Cargo.lock* and output +A _workspace_ is a set of packages that share the same _Cargo.lock_ and output directory. Let’s make a project using a workspace—we’ll use trivial code so we can concentrate on the structure of the workspace. There are multiple ways to structure a workspace, so we'll just show one common way. We’ll have a @@ -23,7 +23,7 @@ $ mkdir add $ cd add ``` -Next, in the *add* directory, we create the *Cargo.toml* file that will +Next, in the _add_ directory, we create the _Cargo.toml_ file that will configure the entire workspace. This file won’t have a `[package]` section. Instead, it will start with a `[workspace]` section that will allow us to add members to the workspace. We also make a point to use the latest and greatest @@ -31,7 +31,7 @@ version of Cargo’s resolver algorithm in our workspace by setting the `resolver` to `"2"`. by specifying the path to the package with our binary -crate; in this case, that path is *adder*: +crate; in this case, that path is _adder_: Filename: Cargo.toml @@ -40,7 +40,7 @@ crate; in this case, that path is *adder*: ``` Next, we’ll create the `adder` binary crate by running `cargo new` within the -*add* directory: +_add_ directory: + ## Installing Binaries with `cargo install` @@ -7,18 +8,17 @@ 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/). 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 +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 is suitable for including within other programs. Usually, crates have -information in the *README* file about whether a crate is a library, has a +information in the _README_ file about whether a crate is a library, has a binary target, or both. All binaries installed with `cargo install` are stored in the installation -root’s *bin* folder. If you installed Rust using *rustup.rs* and don’t have any +root’s _bin_ folder. If you installed Rust using _rustup.rs_ and don’t have any custom configurations, this directory will be *$HOME/.cargo/bin*. Ensure that -directory is in your `$PATH` to be able to run programs you’ve installed with -`cargo install`. +directory is in your `$PATH`to be able to run programs you’ve installed with`cargo install`. For example, in Chapter 12 we mentioned that there’s a Rust implementation of the `grep` tool called `ripgrep` for searching files. To install `ripgrep`, we diff --git a/rustbook-en/src/ch15-00-smart-pointers.md b/rustbook-en/src/ch15-00-smart-pointers.md index 9ecdcc835..323463bf4 100644 --- a/rustbook-en/src/ch15-00-smart-pointers.md +++ b/rustbook-en/src/ch15-00-smart-pointers.md @@ -1,25 +1,25 @@ # Smart Pointers -A *pointer* is a general concept for a variable that contains an address in +A _pointer_ is a general concept for a variable that contains an address in memory. This address refers to, or “points at,” some other data. The most common kind of pointer in Rust is a reference, which you learned about in Chapter 4. References are indicated by the `&` symbol and borrow the value they point to. They don’t have any special capabilities other than referring to data, and have no overhead. -*Smart pointers*, on the other hand, are data structures that act like a +_Smart pointers_, on the other hand, are data structures that act like a pointer but also have additional metadata and capabilities. The concept of smart pointers isn’t unique to Rust: smart pointers originated in C++ and exist in other languages as well. Rust has a variety of smart pointers defined in the standard library that provide functionality beyond that provided by references. To explore the general concept, we’ll look at a couple of different examples of -smart pointers, including a *reference counting* smart pointer type. This +smart pointers, including a _reference counting_ smart pointer type. This pointer enables you to allow data to have multiple owners by keeping track of the number of owners and, when no owners remain, cleaning up the data. Rust, with its concept of ownership and borrowing, has an additional difference between references and smart pointers: while references only borrow data, in -many cases, smart pointers *own* the data they point to. +many cases, smart pointers _own_ the data they point to. Though we didn’t call them as such at the time, we’ve already encountered a few smart pointers in this book, including `String` and `Vec` in Chapter 8. Both @@ -41,13 +41,13 @@ frequently in Rust, this chapter won’t cover every existing smart pointer. Man libraries have their own smart pointers, and you can even write your own. We’ll cover the most common smart pointers in the standard library: -* `Box` for allocating values on the heap -* `Rc`, a reference counting type that enables multiple ownership -* `Ref` and `RefMut`, accessed through `RefCell`, a type that enforces +- `Box` for allocating values on the heap +- `Rc`, a reference counting type that enables multiple ownership +- `Ref` and `RefMut`, accessed through `RefCell`, a type that enforces the borrowing rules at runtime instead of compile time -In addition, we’ll cover the *interior mutability* pattern where an immutable +In addition, we’ll cover the _interior mutability_ pattern where an immutable type exposes an API for mutating an interior value. We’ll also discuss -*reference cycles*: how they can leak memory and how to prevent them. +_reference cycles_: how they can leak memory and how to prevent them. Let’s dive in! diff --git a/rustbook-en/src/ch15-01-box.md b/rustbook-en/src/ch15-01-box.md index 548152b5c..f53ee6aaa 100644 --- a/rustbook-en/src/ch15-01-box.md +++ b/rustbook-en/src/ch15-01-box.md @@ -1,6 +1,6 @@ ## Using `Box` to Point to Data on the Heap -The most straightforward smart pointer is a *box*, whose type is written +The most straightforward smart pointer is a _box_, whose type is written `Box`. Boxes allow you to store data on the heap rather than the stack. What remains on the stack is the pointer to the heap data. Refer to Chapter 4 to review the difference between the stack and the heap. @@ -9,11 +9,11 @@ Boxes don’t have performance overhead, other than storing their data on the heap instead of on the stack. But they don’t have many extra capabilities either. You’ll use them most often in these situations: -* When you have a type whose size can’t be known at compile time and you want +- When you have a type whose size can’t be known at compile time and you want to use a value of that type in a context that requires an exact size -* When you have a large amount of data and you want to transfer ownership but +- When you have a large amount of data and you want to transfer ownership but ensure the data won’t be copied when you do so -* When you want to own a value and you care only that it’s a type that +- When you want to own a value and you care only that it’s a type that implements a particular trait rather than being of a specific type We’ll demonstrate the first situation in the [“Enabling Recursive Types with @@ -23,7 +23,7 @@ time because the data is copied around on the stack. To improve performance in this situation, we can store the large amount of data on the heap in a box. Then, only the small amount of pointer data is copied around on the stack, while the data it references stays in one place on the heap. The third case is -known as a *trait object*, and Chapter 18 devotes an entire section, [“Using +known as a _trait object_, and Chapter 18 devotes an entire section, [“Using Trait Objects That Allow for Values of Different Types,”][trait-objects] just to that topic. So what you learn here you’ll apply again in Chapter 18! @@ -59,14 +59,14 @@ wouldn’t be allowed to if we didn’t have boxes. ### Enabling Recursive Types with Boxes -A value of *recursive type* can have another value of the same type as part of +A value of _recursive type_ can have another value of the same type as part of itself. Recursive types pose an issue because at compile time Rust needs to know how much space a type takes up. However, the nesting of values of recursive types could theoretically continue infinitely, so Rust can’t know how much space the value needs. Because boxes have a known size, we can enable recursive types by inserting a box in the recursive type definition. -As an example of a recursive type, let’s explore the *cons list*. This is a data +As an example of a recursive type, let’s explore the _cons list_. This is a data type commonly found in functional programming languages. The cons list type we’ll define is straightforward except for the recursion; therefore, the concepts in the example we’ll work with will be useful any time you get into @@ -74,7 +74,7 @@ more complex situations involving recursive types. #### More Information About the Cons List -A *cons list* is a data structure that comes from the Lisp programming language +A _cons list_ is a data structure that comes from the Lisp programming language and its dialects and is made up of nested pairs, and is the Lisp version of a linked list. Its name comes from the `cons` function (short for “construct function”) in Lisp that constructs a new pair from its two arguments. By @@ -97,7 +97,7 @@ which is an invalid or absent value. The cons list isn’t a commonly used data structure in Rust. Most of the time when you have a list of items in Rust, `Vec` is a better choice to use. -Other, more complex recursive data types *are* useful in various situations, +Other, more complex recursive data types _are_ useful in various situations, but by starting with the cons list in this chapter, we can explore how boxes let us define a recursive data type without much distraction. diff --git a/rustbook-en/src/ch15-02-deref.md b/rustbook-en/src/ch15-02-deref.md index 449e472dc..a0b00e1a7 100644 --- a/rustbook-en/src/ch15-02-deref.md +++ b/rustbook-en/src/ch15-02-deref.md @@ -1,7 +1,7 @@ ## Treating Smart Pointers Like Regular References with the `Deref` Trait Implementing the `Deref` trait allows you to customize the behavior of the -*dereference operator* `*` (not to be confused with the multiplication or glob +_dereference operator_ `*` (not to be confused with the multiplication or glob operator). By implementing `Deref` in such a way that a smart pointer can be treated like a regular reference, you can write code that operates on references and use that code with smart pointers too. @@ -11,7 +11,7 @@ Then we’ll try to define a custom type that behaves like `Box`, 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 -Rust’s *deref coercion* feature and how it lets us work with either references +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` type we’re about to @@ -20,6 +20,7 @@ or smart pointers. > is less important than the pointer-like behavior. + ### Following the Pointer to the Value @@ -40,7 +41,7 @@ reference to the value: The variable `x` holds an `i32` value `5`. We set `y` equal to a reference to `x`. We can assert that `x` is equal to `5`. However, if we want to make an assertion about the value in `y`, we have to use `*y` to follow the reference -to the value it’s pointing to (hence *dereference*) so the compiler can compare +to the value it’s pointing to (hence _dereference_) so the compiler can compare the actual value. Once we dereference `y`, we have access to the integer value `y` is pointing to that we can compare with `5`. @@ -187,7 +188,7 @@ Listing 15-9. ### Implicit Deref Coercions with Functions and Methods -*Deref coercion* converts a reference to a type that implements the `Deref` +_Deref coercion_ converts a reference to a type that implements the `Deref` trait 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 is a convenience Rust performs on arguments to @@ -268,9 +269,9 @@ operator on mutable references. Rust does deref coercion when it finds types and trait implementations in three cases: -* From `&T` to `&U` when `T: Deref` -* From `&mut T` to `&mut U` when `T: DerefMut` -* From `&mut T` to `&U` when `T: Deref` +- From `&T` to `&U` when `T: Deref` +- From `&mut T` to `&mut U` when `T: DerefMut` +- From `&mut T` to `&U` when `T: Deref` The first two cases are the same as each other except that the second implements mutability. The first case states that if you have a `&T`, and `T` @@ -278,7 +279,7 @@ implements `Deref` to some type `U`, you can get a `&U` transparently. The second case states that the same deref coercion happens for mutable references. The third case is trickier: Rust will also coerce a mutable reference to an -immutable one. But the reverse is *not* possible: immutable references will +immutable one. But the reverse is _not_ possible: immutable references will 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 diff --git a/rustbook-en/src/ch15-03-drop.md b/rustbook-en/src/ch15-03-drop.md index 8c402f408..4f0b96bd9 100644 --- a/rustbook-en/src/ch15-03-drop.md +++ b/rustbook-en/src/ch15-03-drop.md @@ -93,14 +93,14 @@ When we try to compile this code, we’ll get this error: ``` This error message states that we’re not allowed to explicitly call `drop`. The -error message uses the term *destructor*, which is the general programming term -for a function that cleans up an instance. A *destructor* is analogous to a -*constructor*, which creates an instance. The `drop` function in Rust is one +error message uses the term _destructor_, which is the general programming term +for a function that cleans up an instance. A _destructor_ is analogous to a +_constructor_, which creates an instance. The `drop` function in Rust is one particular destructor. Rust doesn’t let us call `drop` explicitly because Rust would still automatically call `drop` on the value at the end of `main`. This would cause a -*double free* error because Rust would be trying to clean up the same value +_double free_ error because Rust would be trying to clean up the same value twice. We can’t disable the automatic insertion of `drop` when a value goes out of @@ -126,7 +126,7 @@ Running this code will print the following: {{#include ../listings/ch15-smart-pointers/listing-15-16/output.txt}} ``` -The text ```Dropping CustomSmartPointer with data `some data`!``` is printed +The text ``Dropping CustomSmartPointer with data `some data`!`` is printed between the `CustomSmartPointer created.` and `CustomSmartPointer dropped before the end of main.` text, showing that the `drop` method code is called to drop `c` at that point. diff --git a/rustbook-en/src/ch15-04-rc.md b/rustbook-en/src/ch15-04-rc.md index c5bf9a489..6d1b243fc 100644 --- a/rustbook-en/src/ch15-04-rc.md +++ b/rustbook-en/src/ch15-04-rc.md @@ -8,7 +8,7 @@ that point to it. A node shouldn’t be cleaned up unless it doesn’t have any edges pointing to it and so has no owners. You have to enable multiple ownership explicitly by using the Rust type -`Rc`, which is an abbreviation for *reference counting*. The `Rc` type +`Rc`, which is an abbreviation for _reference counting_. The `Rc` type keeps track of the number of references to a value to determine whether or not the value is still in use. If there are zero references to a value, the value can be cleaned up without any references becoming invalid. diff --git a/rustbook-en/src/ch15-05-interior-mutability.md b/rustbook-en/src/ch15-05-interior-mutability.md index 5b103dc0b..f1d5547c7 100644 --- a/rustbook-en/src/ch15-05-interior-mutability.md +++ b/rustbook-en/src/ch15-05-interior-mutability.md @@ -1,6 +1,6 @@ ## `RefCell` and the Interior Mutability Pattern -*Interior mutability* is a design pattern in Rust that allows you to mutate +_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 @@ -22,12 +22,12 @@ Unlike `Rc`, the `RefCell` type represents single ownership over the data it holds. So, what makes `RefCell` different from a type like `Box`? Recall the borrowing rules you learned in Chapter 4: -* At any given time, you can have *either* (but not both) one mutable reference +- At any given time, you can have _either_ (but not both) one mutable reference or any number of immutable references. -* References must always be valid. +- References must always be valid. With references and `Box`, the borrowing rules’ invariants are enforced at -compile time. With `RefCell`, these invariants are enforced *at runtime*. +compile time. With `RefCell`, these invariants are enforced _at runtime_. With references, if you break these rules, you’ll get a compiler error. With `RefCell`, if you break these rules, your program will panic and exit. @@ -60,16 +60,16 @@ multithreaded program in Chapter 16. Here is a recap of the reasons to choose `Box`, `Rc`, or `RefCell`: -* `Rc` enables multiple owners of the same data; `Box` and `RefCell` +- `Rc` enables multiple owners of the same data; `Box` and `RefCell` have single owners. -* `Box` allows immutable or mutable borrows checked at compile time; `Rc` +- `Box` allows immutable or mutable borrows checked at compile time; `Rc` allows only immutable borrows checked at compile time; `RefCell` allows immutable or mutable borrows checked at runtime. -* Because `RefCell` allows mutable borrows checked at runtime, you can +- Because `RefCell` allows mutable borrows checked at runtime, you can mutate the value inside the `RefCell` even when the `RefCell` is immutable. -Mutating the value inside an immutable value is the *interior mutability* +Mutating the value inside an immutable value is the _interior mutability_ pattern. Let’s look at a situation in which interior mutability is useful and examine how it’s possible. @@ -104,10 +104,10 @@ an immutable value and see why that is useful. Sometimes during testing a programmer will use a type in place of another type, in order to observe particular behavior and assert it’s implemented correctly. -This placeholder type is called a *test double*. Think of it in the sense of a +This placeholder type is called a _test double_. Think of it in the sense of a “stunt double” in filmmaking, where a person steps in and substitutes for an actor to do a particular tricky scene. Test doubles stand in for other types -when we’re running tests. *Mock objects* are specific types of test doubles +when we’re running tests. _Mock objects_ are specific types of test doubles that record what happens during a test so you can assert that the correct actions took place. @@ -284,7 +284,7 @@ provide. A common way to use `RefCell` is in combination with `Rc`. Recall that `Rc` lets you have multiple owners of some data, but it only gives immutable access to that data. If you have an `Rc` that holds a `RefCell`, you can -get a value that can have multiple owners *and* that you can mutate! +get a value that can have multiple owners _and_ that you can mutate! For example, recall the cons list example in Listing 15-18 where we used `Rc` to allow multiple lists to share ownership of another list. Because diff --git a/rustbook-en/src/ch15-06-reference-cycles.md b/rustbook-en/src/ch15-06-reference-cycles.md index 2ea12edb6..a28df6438 100644 --- a/rustbook-en/src/ch15-06-reference-cycles.md +++ b/rustbook-en/src/ch15-06-reference-cycles.md @@ -1,7 +1,7 @@ ## Reference Cycles Can Leak Memory Rust’s memory safety guarantees make it difficult, but not impossible, to -accidentally create memory that is never cleaned up (known as a *memory leak*). +accidentally create memory that is never cleaned up (known as a _memory leak_). Preventing memory leaks entirely is not one of Rust’s guarantees, meaning memory leaks are memory safe in Rust. We can see that Rust allows memory leaks by using `Rc` and `RefCell`: it’s possible to create references where @@ -111,7 +111,7 @@ reference cycles. So far, we’ve demonstrated that calling `Rc::clone` increases the `strong_count` of an `Rc` instance, and an `Rc` instance is only cleaned -up if its `strong_count` is 0. You can also create a *weak reference* to the +up if its `strong_count` is 0. You can also create a _weak reference_ to the value within an `Rc` instance by calling `Rc::downgrade` and passing a reference to the `Rc`. Strong references are how you can share ownership of an `Rc` instance. Weak references don’t express an ownership relationship, @@ -136,7 +136,7 @@ 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* +item, we’ll create a tree whose items know about their children items _and_ their parent items. #### Creating a Tree Data Structure: a `Node` with Child Nodes diff --git a/rustbook-en/src/ch16-00-concurrency.md b/rustbook-en/src/ch16-00-concurrency.md index 410f3e40d..27293fd23 100644 --- a/rustbook-en/src/ch16-00-concurrency.md +++ b/rustbook-en/src/ch16-00-concurrency.md @@ -1,8 +1,8 @@ # Fearless Concurrency Handling concurrent programming safely and efficiently is another of Rust’s -major goals. *Concurrent programming*, where different parts of a program -execute independently, and *parallel programming*, where different parts of a +major goals. _Concurrent programming_, where different parts of a program +execute independently, and _parallel programming_, where different parts of a program execute at the same time, are becoming increasingly important as more computers take advantage of their multiple processors. Historically, programming in these contexts has been difficult and error prone: Rust hopes to @@ -11,22 +11,22 @@ change that. Initially, the Rust team thought that ensuring memory safety and preventing concurrency problems were two separate challenges to be solved with different methods. Over time, the team discovered that the ownership and type systems are -a powerful set of tools to help manage memory safety *and* concurrency +a powerful set of tools to help manage memory safety _and_ concurrency problems! By leveraging ownership and type checking, many concurrency errors are compile-time errors in Rust rather than runtime errors. Therefore, rather than making you spend lots of time trying to reproduce the exact circumstances under which a runtime concurrency bug occurs, incorrect code will refuse to compile and present an error explaining the problem. As a result, you can fix your code while you’re working on it rather than potentially after it has been -shipped to production. We’ve nicknamed this aspect of Rust *fearless* -*concurrency*. Fearless concurrency allows you to write code that is free of +shipped to production. We’ve nicknamed this aspect of Rust _fearless_ +_concurrency_. Fearless concurrency allows you to write code that is free of subtle bugs and is easy to refactor without introducing new bugs. > Note: For simplicity’s sake, we’ll refer to many of the problems as -> *concurrent* rather than being more precise by saying *concurrent and/or -> parallel*. If this book were about concurrency and/or parallelism, we’d be -> more specific. For this chapter, please mentally substitute *concurrent -> and/or parallel* whenever we use *concurrent*. +> _concurrent_ rather than being more precise by saying _concurrent and/or +> parallel_. If this book were about concurrency and/or parallelism, we’d be +> more specific. For this chapter, please mentally substitute _concurrent +> and/or parallel_ whenever we use _concurrent_. Many languages are dogmatic about the solutions they offer for handling concurrent problems. For example, Erlang has elegant functionality for @@ -41,9 +41,9 @@ for your situation and requirements. Here are the topics we’ll cover in this chapter: -* How to create threads to run multiple pieces of code at the same time -* *Message-passing* concurrency, where channels send messages between threads -* *Shared-state* concurrency, where multiple threads have access to some piece +- How to create threads to run multiple pieces of code at the same time +- _Message-passing_ concurrency, where channels send messages between threads +- _Shared-state_ concurrency, where multiple threads have access to some piece of data -* The `Sync` and `Send` traits, which extend Rust’s concurrency guarantees to +- The `Sync` and `Send` traits, which extend Rust’s concurrency guarantees to user-defined types as well as types provided by the standard library diff --git a/rustbook-en/src/ch16-01-threads.md b/rustbook-en/src/ch16-01-threads.md index cc6466404..17d56ef7b 100644 --- a/rustbook-en/src/ch16-01-threads.md +++ b/rustbook-en/src/ch16-01-threads.md @@ -1,9 +1,9 @@ ## Using Threads to Run Code Simultaneously In most current operating systems, an executed program’s code is run in a -*process*, and the operating system will manage multiple processes at once. +_process_, and the operating system will manage multiple processes at once. Within a program, you can also have independent parts that run simultaneously. -The features that run these independent parts are called *threads*. For +The features that run these independent parts are called _threads_. For example, a web server could have multiple threads so that it could respond to more than one request at the same time. @@ -13,11 +13,11 @@ Because threads can run simultaneously, there’s no inherent guarantee about th order in which parts of your code on different threads will run. This can lead to problems, such as: -* Race conditions, where threads are accessing data or resources in an +- Race conditions, where threads are accessing data or resources in an inconsistent order -* Deadlocks, where two threads are waiting for each other, preventing both +- Deadlocks, where two threads are waiting for each other, preventing both threads from continuing -* Bugs that happen only in certain situations and are hard to reproduce and fix +- Bugs that happen only in certain situations and are hard to reproduce and fix reliably Rust attempts to mitigate the negative effects of using threads, but @@ -27,7 +27,7 @@ thread. Programming languages implement threads in a few different ways, and many operating systems provide an API the language can call for creating new threads. -The Rust standard library uses a *1:1* model of thread implementation, whereby a +The Rust standard library uses a _1:1_ model of thread implementation, whereby a program uses one operating system thread per one language thread. There are crates that implement other models of threading that make different tradeoffs to the 1:1 model. (Rust’s async system, which we will see in the next chapter, @@ -104,7 +104,7 @@ call `join` to make sure the spawned thread finishes before `main` exits: Calling `join` on the handle blocks the thread currently running until the -thread represented by the handle terminates. *Blocking* a thread means that +thread represented by the handle terminates. _Blocking_ a thread means that thread is prevented from performing work or exiting. Because we’ve put the call to `join` after the main thread’s `for` loop, running Listing 16-2 should produce output similar to this: @@ -202,7 +202,7 @@ example, we get the following error: {{#include ../listings/ch16-fearless-concurrency/listing-16-03/output.txt}} ``` -Rust *infers* how to capture `v`, and because `println!` only needs a reference +Rust _infers_ how to capture `v`, and because `println!` only needs a reference to `v`, the closure tries to borrow `v`. However, there’s a problem: Rust can’t tell how long the spawned thread will run, so it doesn’t know if the reference to `v` will always be valid. @@ -246,7 +246,6 @@ should borrow the values. The modification to Listing 16-3 shown in Listing - ```rust {{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-05/src/main.rs}} ``` @@ -275,6 +274,6 @@ Rust’s conservative default of borrowing; it doesn’t let us violate the ownership rules. With a basic understanding of threads and the thread API, let’s look at what we -can *do* with threads. +can _do_ with threads. [capture]: ch13-01-closures.html#capturing-references-or-moving-ownership diff --git a/rustbook-en/src/ch16-02-message-passing.md b/rustbook-en/src/ch16-02-message-passing.md index f2d396bfa..d5b3c91ec 100644 --- a/rustbook-en/src/ch16-02-message-passing.md +++ b/rustbook-en/src/ch16-02-message-passing.md @@ -1,13 +1,12 @@ ## Using Message Passing to Transfer Data Between Threads -One increasingly popular approach to ensuring safe concurrency is *message -passing*, where threads or actors communicate by sending each other messages -containing data. Here’s the idea in a slogan from [the Go language -documentation](https://golang.org/doc/effective_go.html#concurrency): +One increasingly popular approach to ensuring safe concurrency is _message +passing_, where threads or actors communicate by sending each other messages +containing data. Here’s the idea in a slogan from [the Go language documentation](https://golang.org/doc/effective_go.html#concurrency): “Do not communicate by sharing memory; instead, share memory by communicating.” To accomplish message-sending concurrency, Rust's standard library provides an -implementation of *channels*. A channel is a general programming concept by +implementation of _channels_. A channel is a general programming concept by which data is sent from one thread to another. You can imagine a channel in programming as being like a directional channel of @@ -19,7 +18,7 @@ the upstream location where you put rubber ducks into the river, and the receiver half is where the rubber duck ends up downstream. One part of your code calls methods on the transmitter with the data you want to send, and another part checks the receiving end for arriving messages. A channel is said -to be *closed* if either the transmitter or receiver half is dropped. +to be _closed_ if either the transmitter or receiver half is dropped. Here, we’ll work up to a program that has one thread to generate values and send them down a channel, and another thread that will receive the values and @@ -43,9 +42,9 @@ want to send over the channel. halves to `tx` and `rx` We create a new channel using the `mpsc::channel` function; `mpsc` stands for -*multiple producer, single consumer*. In short, the way Rust’s standard library -implements channels means a channel can have multiple *sending* ends that -produce values but only one *receiving* end that consumes those values. Imagine +_multiple producer, single consumer_. In short, the way Rust’s standard library +implements channels means a channel can have multiple _sending_ ends that +produce values but only one _receiving_ end that consumes those values. Imagine multiple streams flowing together into one big river: everything sent down any 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 @@ -54,7 +53,7 @@ working. The `mpsc::channel` function returns a tuple, the first element of which is the sending end—the transmitter—and the second element is the receiving end—the receiver. The abbreviations `tx` and `rx` are traditionally used in many fields -for *transmitter* and *receiver* respectively, so we name our variables as such +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 19. For now, know that using a `let` statement @@ -97,7 +96,7 @@ receiving a chat message. The receiver has two useful methods: `recv` and `try_recv`. We’re using `recv`, -short for *receive*, which will block the main thread’s execution and wait +short for _receive_, which will block the main thread’s execution and wait until a value is sent down the channel. Once a value is sent, `recv` will return it in a `Result`. When the transmitter closes, `recv` will return an error to signal that no more values will be coming. @@ -133,7 +132,7 @@ The ownership rules play a vital role in message sending because they help you write safe, concurrent code. Preventing errors in concurrent programming is the advantage of thinking about ownership throughout your Rust programs. Let’s do an experiment to show how channels and ownership work together to prevent -problems: we’ll try to use a `val` value in the spawned thread *after* we’ve +problems: we’ll try to use a `val` value in the spawned thread _after_ we’ve sent it down the channel. Try compiling the code in Listing 16-9 to see why this code isn’t allowed: @@ -206,8 +205,8 @@ the spawned thread. ### Creating Multiple Producers by Cloning the Transmitter -Earlier we mentioned that `mpsc` was an acronym for *multiple producer, -single consumer*. Let’s put `mpsc` to use and expand the code in Listing 16-10 +Earlier we mentioned that `mpsc` was an acronym for _multiple producer, +single consumer_. Let’s put `mpsc` to use and expand the code in Listing 16-10 to create multiple threads that all send values to the same receiver. We can do so by cloning the transmitter, as shown in Listing 16-11: diff --git a/rustbook-en/src/ch16-03-shared-state.md b/rustbook-en/src/ch16-03-shared-state.md index d319c6d6c..52de2fb7d 100644 --- a/rustbook-en/src/ch16-03-shared-state.md +++ b/rustbook-en/src/ch16-03-shared-state.md @@ -20,18 +20,18 @@ for shared memory. ### Using Mutexes to Allow Access to Data from One Thread at a Time -*Mutex* is an abbreviation for *mutual exclusion*, as in, a mutex allows only +_Mutex_ is an abbreviation for _mutual exclusion_, as in, a mutex allows only one thread to access some data at any given time. To access the data in a mutex, a thread must first signal that it wants access by asking to acquire the -mutex’s *lock*. The lock is a data structure that is part of the mutex that +mutex’s _lock_. The lock is a data structure that is part of the mutex that keeps track of who currently has exclusive access to the data. Therefore, the -mutex is described as *guarding* the data it holds via the locking system. +mutex is described as _guarding_ the data it holds via the locking system. Mutexes have a reputation for being difficult to use because you have to remember two rules: -* You must attempt to acquire the lock before using the data. -* When you’re done with the data that the mutex guards, you must unlock the +- You must attempt to acquire the lock before using the data. +- When you’re done with the data that the mutex guards, you must unlock the data so other threads can acquire the lock. For a real-world metaphor for a mutex, imagine a panel discussion at a @@ -72,12 +72,12 @@ that case, no one would ever be able to get the lock, so we’ve chosen to After we’ve acquired the lock, we can treat the return value, named `num` in this case, as a mutable reference to the data inside. The type system ensures that we acquire a lock before using the value in `m`. The type of `m` is -`Mutex`, not `i32`, so we *must* call `lock` to be able to use the `i32` +`Mutex`, not `i32`, so we _must_ call `lock` to be able to use the `i32` value. We can’t forget; the type system won’t let us access the inner `i32` otherwise. As you might suspect, `Mutex` is a smart pointer. More accurately, the call -to `lock` *returns* a smart pointer called `MutexGuard`, wrapped in a +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 @@ -153,7 +153,7 @@ a lot. Wow, that error message is very wordy! Here’s the important part to focus on: `` `Rc>` cannot be sent between threads safely ``. The compiler is -also telling us the reason why: ``the trait `Send` is not implemented for +also telling us the reason why: `` the trait `Send` is not implemented for `Rc>` ``. 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. @@ -169,9 +169,9 @@ to the reference count in a thread-safe way. #### Atomic Reference Counting with `Arc` -Fortunately, `Arc` *is* a type like `Rc` that is safe to use in -concurrent situations. The *a* stands for *atomic*, meaning it’s an *atomically -reference counted* type. Atomics are an additional kind of concurrency +Fortunately, `Arc` _is_ a type like `Rc` that is safe to use in +concurrent situations. The _a_ stands for _atomic_, meaning it’s an _atomically +reference counted_ type. Atomics are an additional kind of concurrency primitive that we won’t cover in detail here: see the standard library documentation for [`std::sync::atomic`][atomic] for more details. At this point, you just need to know that atomics work like primitive @@ -231,7 +231,7 @@ Another detail to note is that Rust can’t protect you from all kinds of logic errors when you use `Mutex`. Recall in Chapter 15 that using `Rc` came with the risk of creating reference cycles, where two `Rc` values refer to each other, causing memory leaks. Similarly, `Mutex` comes with the risk of -creating *deadlocks*. These occur when an operation needs to lock two resources +creating _deadlocks_. These occur when an operation needs to lock two resources and two threads have each acquired one of the locks, causing them to wait for each other forever. If you’re interested in deadlocks, try creating a Rust program that has a deadlock; then research deadlock mitigation strategies for diff --git a/rustbook-en/src/ch16-04-extensible-concurrency-sync-and-send.md b/rustbook-en/src/ch16-04-extensible-concurrency-sync-and-send.md index 148b68ab3..4bae9d68c 100644 --- a/rustbook-en/src/ch16-04-extensible-concurrency-sync-and-send.md +++ b/rustbook-en/src/ch16-04-extensible-concurrency-sync-and-send.md @@ -1,6 +1,6 @@ ## Extensible Concurrency with the `Sync` and `Send` Traits -Interestingly, the Rust language has *very* few concurrency features. Almost +Interestingly, the Rust language has _very_ few concurrency features. Almost every concurrency feature we’ve talked about so far in this chapter has been part of the standard library, not the language. Your options for handling concurrency are not limited to the language or the standard library; you can @@ -82,6 +82,5 @@ run on multiple threads without the kinds of hard-to-track-down bugs common in other languages. Concurrent programming is no longer a concept to be afraid of: go forth and make your programs concurrent, fearlessly! -[sharing-a-mutext-between-multiple-threads]: -ch16-03-shared-state.html#sharing-a-mutext-between-multiple-threads +[sharing-a-mutext-between-multiple-threads]: ch16-03-shared-state.html#sharing-a-mutext-between-multiple-threads [nomicon]: ../nomicon/index.html diff --git a/rustbook-en/src/ch17-00-async-await.md b/rustbook-en/src/ch17-00-async-await.md index 5fe702022..acd0ed376 100644 --- a/rustbook-en/src/ch17-00-async-await.md +++ b/rustbook-en/src/ch17-00-async-await.md @@ -27,10 +27,10 @@ happen while the network operation is still ongoing. > Note: The video export is the kind of operation which is often described as > “CPU-bound” or “compute-bound”. It’s limited by the speed of the computer’s -> ability to process data within the *CPU* or *GPU*, and how much of that speed +> ability to process data within the _CPU_ or _GPU_, and how much of that speed > it can use. The video download is the kind of operation which is often > described as “IO-bound,” because it’s limited by the speed of the computer’s -> *input and output*. It can only go as fast as the data can be sent across the +> _input and output_. It can only go as fast as the data can be sent across the > network. In both of these examples, the operating system’s invisible interrupts provide a @@ -44,14 +44,14 @@ For example, if we’re building a tool to manage file downloads, we should be able to write our program in such a way that starting one download does not lock up the UI, and users should be able to start multiple downloads at the same time. Many operating system APIs for interacting with the network are -*blocking*, though. That is, these APIs block the program’s progress until the +_blocking_, though. That is, these APIs block the program’s progress until the data that they are processing is completely ready. -> Note: This is how *most* function calls work, if you think about it! However, +> Note: This is how _most_ function calls work, if you think about it! However, > we normally reserve the term “blocking” for function calls which interact with > files, the network, or other resources on the computer, because those are the > places where an individual program would benefit from the operation being -> *non*-blocking. +> _non_-blocking. We could avoid blocking our main thread by spawning a dedicated thread to download each file. However, we would eventually find that the overhead of those @@ -79,7 +79,7 @@ could assign a single individual multiple tasks, or we could assign one task per team member, or we could do a mix of both approaches. When an individual works on several different tasks before any of them is -complete, this is *concurrency*. Maybe you have two different projects checked +complete, this is _concurrency_. Maybe you have two different projects checked out on your computer, and when you get bored or stuck on one project, you switch to the other. You’re just one person, so you can’t make progress on both tasks at the exact same time—but you can multi-task, making progress on multiple @@ -94,7 +94,7 @@ tasks by switching between them. When you agree to split up a group of tasks between the people on the team, with -each person taking one task and working on it alone, this is *parallelism*. Each +each person taking one task and working on it alone, this is _parallelism_. Each person on the team can make progress at the exact same time.
@@ -106,10 +106,10 @@ person on the team can make progress at the exact same time.
With both of these situations, you might have to coordinate between different -tasks. Maybe you *thought* the task that one person was working on was totally +tasks. Maybe you _thought_ the task that one person was working on was totally independent from everyone else’s work, but it actually needs something finished by another person on the team. Some of the work could be done in parallel, but -some of it was actually *serial*: it could only happen in a series, one thing +some of it was actually _serial_: it could only happen in a series, one thing after the other, as in Figure 17-3.
@@ -146,8 +146,8 @@ under the hood. Now, let’s dive into how async programming in Rust actually works! In the rest of this chapter, we will: -* see how to use Rust’s `async` and `await` syntax -* explore how to use the async model to solve some of the same challenges we +- see how to use Rust’s `async` and `await` syntax +- explore how to use the async model to solve some of the same challenges we looked at in Chapter 16 -* look at how multithreading and async provide complementary solutions, which +- look at how multithreading and async provide complementary solutions, which you can even use together in many cases diff --git a/rustbook-en/src/ch17-01-futures-and-syntax.md b/rustbook-en/src/ch17-01-futures-and-syntax.md index 86d2668fa..11089811b 100644 --- a/rustbook-en/src/ch17-01-futures-and-syntax.md +++ b/rustbook-en/src/ch17-01-futures-and-syntax.md @@ -1,9 +1,9 @@ ## Futures and the Async Syntax -The key elements of asynchronous programming in Rust are *futures* and Rust’s +The key elements of asynchronous programming in Rust are _futures_ and Rust’s `async` and `await` keywords. -A *future* is a value which may not be ready now, but will become ready at some +A _future_ is a value which may not be ready now, but will become ready at some point in the future. (This same concept shows up in many languages, sometimes under other names such as “task” or “promise”.) Rust provides a `Future` trait as a building block so different async operations can be implemented with @@ -14,10 +14,10 @@ made and what "ready" means. The `async` keyword can be applied to blocks and functions to specify that they can be interrupted and resumed. Within an async block or async function, you can -use the `await` keyword to wait for a future to become ready, called *awaiting a -future*. Each place you await a future within an async block or function is a +use the `await` keyword to wait for a future to become ready, called _awaiting a +future_. Each place you await a future within an async block or function is a place that async block or function may get paused and resumed. The process of -checking with a future to see if its value is available yet is called *polling*. +checking with a future to see if its value is available yet is called _polling_. Some other languages also use `async` and `await` keywords for async programming. If you’re familiar with those languages, you may notice some @@ -95,11 +95,11 @@ we need to wait for the server to send back the first part of its response, which will include HTTP headers, cookies, and so on. That part of the response can be delivered separately from the body of the request. Especially if the body is very large, it can take some time for it all to arrive. Thus, we have -to wait for the *entirety* of the response to arrive, so the `text` method is +to wait for the _entirety_ of the response to arrive, so the `text` method is also async. We have to explicitly await both of these futures, because futures in Rust are -*lazy*: they don’t do anything until you ask them to with `await`. (In fact, +_lazy_: they don’t do anything until you ask them to with `await`. (In fact, Rust will show a compiler warning if you don’t use a future.) This should remind you of our discussion of iterators [back in Chapter 13][iterators-lazy]. Iterators do nothing unless you call their `next` method—whether directly, or @@ -127,7 +127,7 @@ here, but `map` is more idiomatic.) In the body of the function we supply to a `String`. When all is said and done, we have an `Option`. Notice that Rust’s `await` keyword goes after the expression you’re awaiting, -not before it. That is, it’s a *postfix keyword*. This may be different from +not before it. That is, it’s a _postfix keyword_. This may be different from what you might be used to if you have used async in other languages. Rust chose this because it makes chains of methods much nicer to work with. As a result, we can change the body of `page_url_for` to chain the `trpl::get` and `text` @@ -152,7 +152,7 @@ body is an async block. An async function’s return type is the type of the anonymous data type the compiler creates for that async block. Thus, writing `async fn` is equivalent to writing a function which returns a -*future* of the return type. When the compiler sees a function definition such +_future_ of the return type. When the compiler sees a function definition such as the `async fn page_title` in Listing 17-1, it’s equivalent to a non-async function defined like this: @@ -173,26 +173,26 @@ fn page_title(url: &str) -> impl Future> + '_ { Let’s walk through each part of the transformed version: -* It uses the `impl Trait` syntax we discussed back in the [“Traits as +- It uses the `impl Trait` syntax we discussed back in the [“Traits as Parameters”][impl-trait] section in Chapter 10. -* The returned trait is a `Future`, with an associated type of `Output`. Notice +- The returned trait is a `Future`, with an associated type of `Output`. Notice that the `Output` type is `Option`, which is the same as the the original return type from the `async fn` version of `page_title`. -* All of the code called in the body of the original function is wrapped in an +- All of the code called in the body of the original function is wrapped in an `async move` block. Remember that blocks are expressions. This whole block is the expression returned from the function. -* This async block produces a value with the type `Option`, as described +- This async block produces a value with the type `Option`, as described above. That value matches the `Output` type in the return type. This is just like other blocks you have seen. -* The new function body is an `async move` block because of how it uses the +- The new function body is an `async move` block because of how it uses the `url` parameter. (We’ll talk about `async` vs. `async move` much more later in the chapter.) -* The new version of the function has a kind of lifetime we haven’t seen before +- The new version of the function has a kind of lifetime we haven’t seen before in the output type: `'_`. Because the function returns a `Future` which refers to a reference—in this case, the reference from the `url` parameter—we need to tell Rust that we mean for that reference to be included. We don’t have to name the lifetime here, because Rust is smart enough to know there is only one - reference which could be involved, but we *do* have to be explicit that the + reference which could be involved, but we _do_ have to be explicit that the resulting `Future` is bound by that lifetime. Now we can call `page_title` in `main`. To start, we’ll just get the title @@ -228,10 +228,10 @@ error[E0752]: `main` function is not allowed to be `async` | ^^^^^^^^^^^^^^^ `main` function is not allowed to be `async` ``` -The reason `main` can’t be marked `async` is that async code needs a *runtime*: +The reason `main` can’t be marked `async` is that async code needs a _runtime_: a Rust crate which manages the details of executing asynchronous code. A -program’s `main` function can *initialize* a runtime, but it’s not a runtime -*itself*. (We’ll see more about why this is a bit later.) Every Rust program +program’s `main` function can _initialize_ a runtime, but it’s not a runtime +_itself_. (We’ll see more about why this is a bit later.) Every Rust program that executes async code has at least one place where it sets up a runtime and executes the futures. @@ -288,7 +288,7 @@ Phew: we finally have some working async code! This now compiles, and we can run it. Before we add code to race two sites against each other, let’s briefly turn our attention back to how futures work. -Each *await point*—that is, every place where the code uses the `await` +Each _await point_—that is, every place where the code uses the `await` keyword—represents a place where control gets handed back to the runtime. To make that work, Rust needs to keep track of the state involved in the async block, so that the runtime can kick off some other work and then come back when @@ -309,7 +309,7 @@ the compiler also handles checking those for us, and has good error messages. We’ll work through a few of those later in the chapter! Ultimately, something has to execute that state machine. That something is a -runtime. (This is why you may sometimes come across references to *executors* +runtime. (This is why you may sometimes come across references to _executors_ when looking into runtimes: an executor is the part of a runtime responsible for executing the async code.) @@ -320,7 +320,7 @@ but `main` is the starting point for the program! Instead, we call the `trpl::run` function in `main`, which sets up a runtime and runs the future returned by the `async` block until it returns `Ready`. -> Note: some runtimes provide macros to make it so you *can* write an async main +> Note: some runtimes provide macros to make it so you _can_ write an async main > function. Those macros rewrite `async fn main() { ... }` to be a normal `fn > main` which does the same thing we did by hand in Listing 17-5: call a > function which runs a future to completion the way `trpl::run` does. @@ -367,7 +367,7 @@ enum Either { The `race` function returns `Left` if the first argument finishes first, with that future’s output, and `Right` with the second future argument’s output if -*that* one finishes first. This matches the order the arguments appear when +_that_ one finishes first. This matches the order the arguments appear when calling the function: the first argument is to the left of the second argument. We also update `page_title` to return the same URL passed in. That way, if @@ -384,7 +384,9 @@ dig into even more of the things we can do with async. [impl-trait]: ch10-02-traits.html#traits-as-parameters [iterators-lazy]: ch13-02-iterators.html + + [crate-source]: https://github.com/rust-lang/book/tree/main/packages/trpl [futures-crate]: https://crates.io/crates/futures [tokio]: https://tokio.rs diff --git a/rustbook-en/src/ch17-02-concurrency-with-async.md b/rustbook-en/src/ch17-02-concurrency-with-async.md index 22557d1b7..522b84092 100644 --- a/rustbook-en/src/ch17-02-concurrency-with-async.md +++ b/rustbook-en/src/ch17-02-concurrency-with-async.md @@ -7,7 +7,7 @@ threads and futures. In many cases, the APIs for working with concurrency using async are very similar to those for using threads. In other cases, they end up being shaped -quite differently. Even when the APIs *look* similar between threads and async, +quite differently. Even when the APIs _look_ similar between threads and async, they often have different behavior—and they nearly always have different performance characteristics. @@ -76,7 +76,7 @@ after awaiting it.
-This updated version runs till *both* loops finish. +This updated version runs till _both_ loops finish. @@ -297,25 +297,25 @@ With the updated code in Listing 17-11, the messages get printed at The program still never exits, though, because of the way `while let` loop interacts with `trpl::join`: -* The future returned from `trpl::join` only completes once *both* futures +- The future returned from `trpl::join` only completes once _both_ futures passed to it have completed. -* The `tx` future completes once it finishes sleeping after sending the last +- The `tx` future completes once it finishes sleeping after sending the last message in `vals`. -* The `rx` future won’t complete until the `while let` loop ends. -* The `while let` loop won’t end until awaiting `rx.recv` produces `None`. -* Awaiting `rx.recv` will only return `None` once the other end of the channel +- The `rx` future won’t complete until the `while let` loop ends. +- The `while let` loop won’t end until awaiting `rx.recv` produces `None`. +- Awaiting `rx.recv` will only return `None` once the other end of the channel is closed. -* The channel will only close if we call `rx.close` or when the sender side, +- The channel will only close if we call `rx.close` or when the sender side, `tx`, is dropped. -* We don’t call `rx.close` anywhere, and `tx` won’t be dropped until the +- We don’t call `rx.close` anywhere, and `tx` won’t be dropped until the outermost async block passed to `trpl::run` ends. -* The block can’t end because it is blocked on `trpl::join` completing, which +- The block can’t end because it is blocked on `trpl::join` completing, which takes us back to the top of this list! We could manually close `rx` by calling `rx.close` somewhere, but that doesn’t make much sense. Stopping after handling some arbitrary number of messages would make the program shut down, but we could miss messages. We need some other way -to make sure that `tx` gets dropped *before* the end of the function. +to make sure that `tx` gets dropped _before_ the end of the function. Right now, the async block where we send the messages only borrows `tx` because sending a message doesn’t require ownership, but if we could move `tx` into @@ -326,7 +326,7 @@ same basic dynamics apply to async blocks, so the `move` keyword works with async blocks just as it does with closures. In Listing 17-12, we change the async block for sending messages from a plain -`async` block to an `async move` block. When we run *this* version of the code, +`async` block to an `async move` block. When we run _this_ version of the code, it shuts down gracefully after the last message is sent and received. @@ -341,7 +341,7 @@ This async channel is also a multiple-producer channel, so we can call `clone` on `tx` if we want to send messages from multiple futures. In Listing 17-13, we clone `tx`, creating `tx1` outside the first async block. We move `tx1` into that block just as we did before with `tx`. Then, later, we move the original -`tx` into a *new* async block, where we send more messages on a slightly slower +`tx` into a _new_ async block, where we send more messages on a slightly slower delay. We happen to put this new async block after the async block for receiving messages, but it could go before it just as well. The key is the order of the futures are awaited in, not the order they are created in. diff --git a/rustbook-en/src/ch17-03-more-futures.md b/rustbook-en/src/ch17-03-more-futures.md index cab96d1f1..aaf8e9084 100644 --- a/rustbook-en/src/ch17-03-more-futures.md +++ b/rustbook-en/src/ch17-03-more-futures.md @@ -23,7 +23,7 @@ futures into a collection and then waiting on some or all the futures in that collection to complete is a common pattern. To check all the futures in some collection, we’ll need to iterate over and -join on *all* of them. The `trpl::join_all` function accepts any type which +join on _all_ of them. The `trpl::join_all` function accepts any type which implements the `Iterator` trait, which we learned about back in Chapter 13, so it seems like just the ticket. Let’s try putting our futures in a vector, and replace `join!` with `join_all`. @@ -44,7 +44,6 @@ cargo build copy just the compiler error --> - ```text error[E0308]: mismatched types --> src/main.rs:45:37 @@ -71,7 +70,7 @@ by the compiler for async blocks. You can’t put two different hand-written structs in a `Vec`, and the same thing applies to the different structs generated by the compiler. -To make this work, we need to use *trait objects*, just as we did in [“Returning +To make this work, we need to use _trait objects_, just as we did in [“Returning Errors from the run function”][dyn] in Chapter 12. (We’ll cover trait objects in detail in Chapter 18.) Using trait objects lets us treat each of the anonymous futures produced by these types as the same type, because all of them @@ -112,11 +111,11 @@ back to the `Unpin` errors in a moment. First, let’s fix the type errors on th The type we had to write here is a little involved, so let’s walk through it: -* The innermost type is the future itself. We note explicitly that the output of +- The innermost type is the future itself. We note explicitly that the output of the future is the unit type `()` by writing `Future`. -* Then we annotate the trait with `dyn` to mark it as dynamic. -* The entire trait reference is wrapped in a `Box`. -* Finally, we state explicitly that `futures` is a `Vec` containing these items. +- Then we annotate the trait with `dyn` to mark it as dynamic. +- The entire trait reference is wrapped in a `Box`. +- Finally, we state explicitly that `futures` is a `Vec` containing these items. That already made a big difference. Now when we run the compiler, we only have the errors mentioning `Unpin`. Although there are three of them, notice that @@ -235,7 +234,7 @@ note: required by a bound in `futures_util::future::join_all::JoinAll` | ^^^^^^ required by this bound in `JoinAll` ``` -That is a *lot* to digest, so let’s pull it apart. The first part of the message +That is a _lot_ to digest, so let’s pull it apart. The first part of the message tell us that the first async block (`src/main.rs:8:23: 20:10`) does not implement the `Unpin` trait, and suggests using `pin!` or `Box::pin` to resolve it. Later in the chapter, we’ll dig into a few more details about `Pin` and @@ -274,7 +273,7 @@ Phew! There’s a bit more we can explore here. For one thing, using `Pin>` comes with a small amount of extra overhead from putting these futures on the heap with `Box`—and we’re only doing that to get the types to line up. We don’t -actually *need* the heap allocation, after all: these futures are local to this +actually _need_ the heap allocation, after all: these futures are local to this particular function. As noted above, `Pin` is itself a wrapper type, so we can get the benefit of having a single type in the `Vec`—the original reason we reached for `Box`—without doing a heap allocation. We can use `Pin` directly @@ -308,7 +307,7 @@ types. For example, in Listing 17-20, the anonymous future for `a` implements We can use `trpl::join!` to await them, because it allows you to pass in -multiple future types and produces a tuple of those types. We *cannot* use +multiple future types and produces a tuple of those types. We _cannot_ use `trpl::join_all`, because it requires the futures passed in all to have the same type. Remember, that error is what got us started on this adventure with `Pin`! @@ -322,8 +321,8 @@ syntax for working with them, and that is a good thing. ### Racing futures When we “join” futures with the `join` family of functions and macros, we -require *all* of them to finish before we move on. Sometimes, though, we only -need *some* future from a set to finish before we move on—kind of similar to +require _all_ of them to finish before we move on. Sometimes, though, we only +need _some_ future from a set to finish before we move on—kind of similar to racing one future against another. In Listing 17-21, we once again use `trpl::race` to run two futures, `slow` and @@ -347,20 +346,20 @@ Notice that if you flip the order of the arguments to `race`, the order of the “started” messages changes, even though the `fast` future always completes first. That’s because the implementation of this particular `race` function is not fair. It always runs the futures passed as arguments in the order they’re -passed. Other implementations *are* fair, and will randomly choose which future +passed. Other implementations _are_ fair, and will randomly choose which future to poll first. Regardless of whether the implementation of race we’re using is -fair, though, *one* of the futures will run up to the first `await` in its body +fair, though, _one_ of the futures will run up to the first `await` in its body before another task can start. Recall from [Our First Async Program][async-program] that at each await point, Rust gives a runtime a chance to pause the task and switch to another one if the -future being awaited isn’t ready. The inverse is also true: Rust *only* pauses +future being awaited isn’t ready. The inverse is also true: Rust _only_ pauses async blocks and hands control back to a runtime at an await point. Everything between await points is synchronous. That means if you do a bunch of work in an async block without an await point, that future will block any other futures from making progress. You may sometimes -hear this referred to as one future *starving* other futures. In some cases, +hear this referred to as one future _starving_ other futures. In some cases, that may not be a big deal. However, if you are doing some kind of expensive setup or long-running work, or if you have a future which will keep doing some particular task indefinitely, you’ll need to think about when and where to @@ -370,7 +369,7 @@ By the same token, if you have long-running blocking operations, async can be a useful tool for providing ways for different parts of the program to relate to each other. -But *how* would you hand control back to the runtime in those cases? +But _how_ would you hand control back to the runtime in those cases? ### Yielding @@ -390,7 +389,7 @@ blocking. In Listing 17-23, we use `slow` to emulate doing this kind of CPU-bound work in a pair of futures. To begin, each future only hands control back to the runtime -*after* carrying out a bunch of slow operations. +_after_ carrying out a bunch of slow operations. @@ -431,7 +430,7 @@ means we need something we can await! We can already see this kind of handoff happening in Listing 17-23: if we removed the `trpl::sleep` at the end of the `a` future, it would complete -without the `b` future running *at all*. Maybe we could use the `sleep` function +without the `b` future running _at all_. Maybe we could use the `sleep` function as a starting point? @@ -469,7 +468,7 @@ swap back and forth each time one of them hits an await point. In this case, we have done that after every call to `slow`, but we could break up the work however makes the most sense to us. -We don’t really want to *sleep* here, though: we want to make progress as fast +We don’t really want to _sleep_ here, though: we want to make progress as fast as we can. We just need to hand back control to the runtime. We can do that directly, using the `yield_now` function. In Listing 17-25, we replace all those `sleep` calls with `yield_now`. @@ -486,7 +485,7 @@ This is both clearer about the actual intent and can be significantly faster than using `sleep`, because timers such as the one used by `sleep` often have limits to how granular they can be. The version of `sleep` we are using, for example, will always sleep for at least a millisecond, even if we pass it a -`Duration` of one nanosecond. Again, modern computers are *fast*: they can do a +`Duration` of one nanosecond. Again, modern computers are _fast_: they can do a lot in one millisecond! You can see this for yourself by setting up a little benchmark, such as the one @@ -505,23 +504,23 @@ compared to the future using `trpl::yield_now`. -The version with `yield_now` is *way* faster! +The version with `yield_now` is _way_ faster! This means that async can be useful even for compute-bound tasks, depending on what else your program is doing, because it provides a useful tool for structuring the relationships between different parts of the program. This is a -form of *cooperative multitasking*, where each future has the power to determine +form of _cooperative multitasking_, where each future has the power to determine when it hands over control via await points. Each future therefore also has the responsibility to avoid blocking for too long. In some Rust-based embedded -operating systems, this is the *only* kind of multitasking! +operating systems, this is the _only_ kind of multitasking! In real-world code, you won’t usually be alternating function calls with await points on every single line, of course. While yielding control in this way is relatively inexpensive, it’s not free! In many cases, trying to break up a compute-bound task might make it significantly slower, so sometimes it’s better -for *overall* performance to let an operation block briefly. You should always +for _overall_ performance to let an operation block briefly. You should always measure to see what your code’s actual performance bottlenecks are. The -underlying dynamic is an important one to keep in mind if you *are* seeing a +underlying dynamic is an important one to keep in mind if you _are_ seeing a lot of work happening in serial that you expected to happen concurrently, though! @@ -545,12 +544,12 @@ future. Let’s implement this! To begin, let’s think about the API for `timeout`: -* It needs to be an async function itself so we can await it. -* Its first parameter should be a future to run. We can make it generic to allow +- It needs to be an async function itself so we can await it. +- Its first parameter should be a future to run. We can make it generic to allow it to work with any future. -* Its second parameter will be the maximum time to wait. If we use a `Duration`, +- Its second parameter will be the maximum time to wait. If we use a `Duration`, that will make it easy to pass along to `trpl::sleep`. -* It should return a `Result`. If the future completes successfully, the +- It should return a `Result`. If the future completes successfully, the `Result` will be `Ok` with the value produced by the future. If the timeout elapses first, the `Result` will be `Err` with the duration that the timeout waited for. @@ -567,7 +566,7 @@ Listing 17-28 shows this declaration. -That satisfies our goals for the types. Now let’s think about the *behavior* we +That satisfies our goals for the types. Now let’s think about the _behavior_ we need: we want to race the future passed in against the duration. We can use `trpl::sleep` to make a timer future from the duration, and use `trpl::race` to run that timer with the future the caller passes in. @@ -611,19 +610,18 @@ APIs. We’ve now seen a number of ways to work with multiple futures at the same time. Up next, we’ll look at how we can work with multiple futures in a -sequence over time, with *streams*. Here are a couple more things you might want +sequence over time, with _streams_. Here are a couple more things you might want to consider first, though: -* We used a `Vec` with `join_all` to wait for all of the futures in some group +- We used a `Vec` with `join_all` to wait for all of the futures in some group to finish. How could you use a `Vec` to process a group of futures in sequence, instead? What are the tradeoffs of doing that? -* Take a look at the `futures::stream::FuturesUnordered` type from the `futures` +- Take a look at the `futures::stream::FuturesUnordered` type from the `futures` crate. How would using it be different from using a `Vec`? (Don’t worry about the fact that it is from the `stream` part of the crate; it works just fine with any collection of futures.) - [collections]: ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: ch12-03-improving-error-handling-and-modularity.html [async-program]: ch17-01-futures-and-syntax.html#our-first-async-program diff --git a/rustbook-en/src/ch17-04-streams.md b/rustbook-en/src/ch17-04-streams.md index d08e40689..11b4a04fd 100644 --- a/rustbook-en/src/ch17-04-streams.md +++ b/rustbook-en/src/ch17-04-streams.md @@ -4,7 +4,7 @@ So far in this chapter, we have mostly stuck to individual futures. The one big exception was the async channel we used. Recall how we used the receiver for our async channel in the [“Message Passing”][17-02-messages] earlier in the chapter. The async `recv` method produces a sequence of items over time. This is an -instance of a much more general pattern, often called a *stream*. +instance of a much more general pattern, often called a _stream_. A sequence of items is something we’ve seen before, when we looked at the `Iterator` trait in Chapter 13. There are two differences between iterators and @@ -206,7 +206,7 @@ need to use async. However, we can’t make `get_messages` itself into an async function, because then we’d return a `Future>` instead of a `Stream>`. The caller would have to await `get_messages` itself to get access to the stream. But remember: everything in a -given future happens linearly; concurrency happens *between* futures. Awaiting +given future happens linearly; concurrency happens _between_ futures. Awaiting `get_messages` would require it to send all the messages, including sleeping between sending each message, before returning the receiver stream. As a result, the timeout would end up useless. There would be no delays in the stream itself: @@ -216,7 +216,7 @@ Instead, we leave `get_messages` as a regular function which returns a stream, and spawn a task to handle the async `sleep` calls. > Note: calling `spawn_task` in this way works because we already set up our -> runtime. Calling this particular implementation of `spawn_task` *without* +> runtime. Calling this particular implementation of `spawn_task` _without_ > first setting up a runtime will cause a panic. Other implementations choose > different tradeoffs: they might spawn a new runtime and so avoid the panic but > end up with a bit of extra overhead, or simply not provide a standalone way to @@ -321,7 +321,7 @@ In Listing 17-38, we rework the `intervals` stream, because `messages` is already in the basic format we want and has to handle timeout errors. First, we can use the `map` helper method to transform the `intervals` into a string. Second, we need to match the `Timeout` from `messages`. Because we don’t -actually *want* a timeout for `intervals`, though, we can just create a timeout +actually _want_ a timeout for `intervals`, though, we can just create a timeout which is longer than the other durations we are using. Here, we create a 10-second timeout with `Duration::from_secs(10)`. Finally, we need to make `stream` mutable, so that the `while let` loop’s `next` calls can iterate @@ -337,7 +337,7 @@ through the stream, and pin it so that it’s safe to do so.
-That gets us *almost* to where we need to be. Everything type checks. If you run +That gets us _almost_ to where we need to be. Everything type checks. If you run this, though, there will be two problems. First, it will never stop! You’ll need to stop it with ctrl-c. Second, the messages from the English alphabet will be buried in the midst of all the @@ -367,7 +367,7 @@ hundred milliseconds should do, because that is in the same ballpark as how often our messages arrive. To limit the number of items we will accept from a stream, we can use the `take` -method. We apply it to the *merged* stream, because we want to limit the final +method. We apply it to the _merged_ stream, because we want to limit the final output, not just one stream or the other. @@ -381,7 +381,7 @@ output, not just one stream or the other. Now when we run the program, it stops after pulling twenty items from the stream, and the intervals don’t overwhelm the messages. We also don’t get `Interval: 100` or `Interval: 200` or so on, but instead get `Interval: 1`, -`Interval: 2`, and so on—even though we have a source stream which *can* +`Interval: 2`, and so on—even though we have a source stream which _can_ produce an event every millisecond. That’s because the `throttle` call produces a new stream, wrapping the original stream, so that the original stream only gets polled at the throttle rate, not its own “native” rate. We @@ -424,7 +424,7 @@ channel-based streams, the `send` calls could fail when the other side of the channel closes—and that’s just a matter of how the runtime executes the futures which make up the stream. Up until now we have ignored this by calling `unwrap`, but in a well-behaved app, we should explicitly handle the error, at minimum by -ending the loop so we don’t try to send any more messages! Listing 17-40 shows +ending the loop so we don’t try to send any more messages! Listing 17-40 shows a simple error strategy: print the issue and then `break` from the loops. As usual, the correct way to handle a message send error will vary—just make sure you have a strategy. diff --git a/rustbook-en/src/ch17-05-traits-for-async.md b/rustbook-en/src/ch17-05-traits-for-async.md index e3819d9a4..b5cc800ce 100644 --- a/rustbook-en/src/ch17-05-traits-for-async.md +++ b/rustbook-en/src/ch17-05-traits-for-async.md @@ -5,8 +5,8 @@ Throughout the chapter, we’ve used the `Future`, `Pin`, `Unpin`, `Stream`, and far into the details of how they work or how they fit together. Much of the time when writing Rust day to day, this is fine. Sometimes, though, you’ll hit situations where understanding a few more of these details matters. In this -section, we’ll dig down *enough* further to help with those situations—while -still leaving the *really* deep dive for other documentation! +section, we’ll dig down _enough_ further to help with those situations—while +still leaving the _really_ deep dive for other documentation! ### Future @@ -110,7 +110,7 @@ advances it when `poll` returns `Poll::Ready(Some(message))` or The exact details of how a runtime does that are more than we will cover in even this deep dive section. The key here is to see the basic mechanic of futures: a -runtime *polls* each future it is responsible for, putting it back to sleep when +runtime _polls_ each future it is responsible for, putting it back to sleep when it is not yet ready. ### Pinning and the Pin and Unpin Traits @@ -159,7 +159,7 @@ the collection all implement the `Future` trait, and `Box` only implements trait. That’s a lot! But we can understand it, if we dive a little further into how the -`Future` type actually works, in particular around *pinning*. +`Future` type actually works, in particular around _pinning_. Let’s look again at the definition of `Future`: @@ -194,7 +194,7 @@ to the type, which is wrapped in a `Pin`. `Pin` is a wrapper type. In some ways, it’s similar to the `Box`, `Rc`, and other smart pointer types we saw in Chapter 15, which also wrap other types. -Unlike those, however, `Pin` only works with *pointer types* such as references +Unlike those, however, `Pin` only works with _pointer types_ such as references (`&` and `&mut`) and smart pointers (`Box`, `Rc`, and so on). To be precise, `Pin` works with types which implement the `Deref` or `DerefMut` traits, which we covered in Chapter 15. You can think of this restriction as equivalent to @@ -262,13 +262,13 @@ In principle, the Rust compiler could try to update every reference to an object every time it gets moved. That would potentially be a lot of performance overhead, especially given there can be a whole web of references that need updating. On the other hand, if we could make sure the data structure in -question *doesn’t move in memory*, we don’t have to update any references. +question _doesn’t move in memory_, we don’t have to update any references. This is exactly what Rust’s borrow checker requires: you can’t move an item which has any active references to it using safe code. -`Pin` builds on that to give us the exact guarantee we need. When we *pin* a +`Pin` builds on that to give us the exact guarantee we need. When we _pin_ a value by wrapping a pointer to that value in `Pin`, it can no longer move. Thus, -if you have `Pin>`, you actually pin the `SomeType` value, *not* +if you have `Pin>`, you actually pin the `SomeType` value, _not_ the `Box` pointer. Figure 17-6 illustrates this:
@@ -313,19 +313,19 @@ around in cases such as these. For that, we have `Unpin`. Chapter 16. Recall that marker traits have no functionality of their own. They exist only to tell the compiler that it’s safe to use the type which implements a given trait in a particular context. `Unpin` informs the compiler that a given -type does *not* need to uphold any particular guarantees about whether the value +type does _not_ need to uphold any particular guarantees about whether the value in question can be moved. Just as with `Send` and `Sync`, the compiler implements `Unpin` automatically for all types where it can prove it is safe. The special case, again similar to -`Send` and `Sync`, is the case where `Unpin` is *not* implemented for a type. +`Send` and `Sync`, is the case where `Unpin` is _not_ implemented for a type. The notation for this is `impl !Unpin for SomeType`, where `SomeType` is the -name of a type which *does* need to uphold those guarantees to be safe whenever +name of a type which _does_ need to uphold those guarantees to be safe whenever a pointer to that type is used in a `Pin`. In other words, there are two things to keep in mind about the relationship between `Pin` and `Unpin`. First, `Unpin` is the “normal” case, and `!Unpin` is -the special case. Second, whether a type implements `Unpin` or `!Unpin` *only* +the special case. Second, whether a type implements `Unpin` or `!Unpin` _only_ matters when using a pinned pointer to that type like `Pin<&mut SomeType>`. To make that concrete, think about a `String`: it has a length and the Unicode @@ -360,7 +360,7 @@ from back in Listing 17-17. We originally tried to move the futures produced by async blocks into a `Vec>>`, but as we’ve seen, those futures may have internal references, so they don’t implement `Unpin`. They need to be pinned, and then we can pass the `Pin` type into the `Vec`, -confident that the underlying data in the futures will *not* be moved. +confident that the underlying data in the futures will _not_ be moved. `Pin` and `Unpin` are mostly important for building lower-level libraries, or when you’re building a runtime itself, rather than for day to day Rust code. @@ -369,7 +369,7 @@ idea of how to fix the code! > Note: This combination of `Pin` and `Unpin` allows a whole class of complex > types to be safe in Rust which are otherwise difficult to implement because -> they’re self-referential. Types which require `Pin` show up *most* commonly +> they’re self-referential. Types which require `Pin` show up _most_ commonly > in async Rust today, but you might—very rarely!—see it in other contexts, too. > > The specifics of how `Pin` and `Unpin` work, and the rules they’re required @@ -389,7 +389,7 @@ Now that we have a deeper grasp on the `Future`, `Pin`, and `Unpin` traits, we can turn our attention to the `Stream` trait. As described in the section introducing streams, streams are similar to asynchronous iterators. Unlike `Iterator` and `Future`, there is no definition of a `Stream` trait in the -standard library as of the time of writing, but there *is* a very common +standard library as of the time of writing, but there _is_ a very common definition from the `futures` crate used throughout the ecosystem. Let’s review the definitions of the `Iterator` and `Future` traits, so we can @@ -432,9 +432,9 @@ standard library. In the meantime, it’s part of the toolkit of most runtimes, so you can rely on it, and everything we cover below should generally apply! In the example we saw in the section on streaming, though, we didn’t use -`poll_next` *or* `Stream`, but instead used `next` and `StreamExt`. We *could* +`poll_next` _or_ `Stream`, but instead used `next` and `StreamExt`. We _could_ work directly in terms of the `poll_next` API by hand-writing our own `Stream` -state machines, of course, just as we *could* work with futures directly via +state machines, of course, just as we _could_ work with futures directly via their `poll` method. Using `await` is much nicer, though, so the `StreamExt` trait supplies the `next` method so we can do just that. @@ -468,7 +468,7 @@ APIs. In the version of `StreamExt` used in the `trpl` crate, the trait not only defines the `next` method, it also supplies an implementation of `next`, which correctly handles the details of calling `Stream::poll_next`. This means that -even when you need to write your own streaming data type, you *only* have to +even when you need to write your own streaming data type, you _only_ have to implement `Stream`, and then anyone who uses your data type can use `StreamExt` and its methods with it automatically. diff --git a/rustbook-en/src/ch17-06-futures-tasks-threads.md b/rustbook-en/src/ch17-06-futures-tasks-threads.md index 4569d727c..5fa662981 100644 --- a/rustbook-en/src/ch17-06-futures-tasks-threads.md +++ b/rustbook-en/src/ch17-06-futures-tasks-threads.md @@ -4,7 +4,7 @@ As we saw in the previous chapter, threads provide one approach to concurrency. We’ve seen another approach to concurrency in this chapter, using async with futures and streams. You might be wondering why you would choose one or the other. The answer is: it depends! And in many cases, the choice isn’t threads -*or* async but rather threads *and* async. +_or_ async but rather threads _and_ async. Many operating systems have supplied threading-based concurrency models for decades now, and many programming languages have support for them as a result. @@ -48,9 +48,9 @@ spawn millions of async tasks on any modern personal computer. If we tried to do that with threads, we would literally run out of memory! However, there’s a reason these APIs are so similar. Threads act as a boundary -for sets of synchronous operations; concurrency is possible *between* threads. -Tasks act as a boundary for sets of *asynchronous* operations; concurrency is -possible both *between* and *within* tasks, because a task can switch between +for sets of synchronous operations; concurrency is possible _between_ threads. +Tasks act as a boundary for sets of _asynchronous_ operations; concurrency is +possible both _between_ and _within_ tasks, because a task can switch between futures in its body. Finally, futures are Rust’s most granular unit of concurrency, and each future may represent a tree of other futures. The runtime—specifically, its executor—manages tasks, and tasks manage futures. In @@ -65,7 +65,7 @@ Concurrency with threads is in some ways a simpler programming model than concurrency with `async`. That can be a strength or a weakness. Threads are somewhat “fire and forget,” they have no native equivalent to a future, so they simply run to completion, without interruption except by the operating system -itself. That is, they have no built-in support for *intra-task concurrency* the +itself. That is, they have no built-in support for _intra-task concurrency_ the way futures do. Threads in Rust also have no mechanisms for cancellation—a subject we haven’t covered in depth in this chapter, but which is implicit in the fact that whenever we ended a future, its state got cleaned up correctly. @@ -77,22 +77,22 @@ or the `throttle` method we used with streams in [“Composing Streams”][strea The fact that futures are richer data structures means they can be composed together more naturally, as we have seen. -Tasks then give *additional* control over futures, allowing you to choose where +Tasks then give _additional_ control over futures, allowing you to choose where and how to group the futures. And it turns out that threads and tasks often work very well together, because tasks can (at least in some runtimes) be moved around between threads. We haven’t mentioned it up until now, but under the hood the `Runtime` we have been using, including the `spawn_blocking` and `spawn_task` functions, is multithreaded by default! Many runtimes use an -approach called *work stealing* to transparently move tasks around between +approach called _work stealing_ to transparently move tasks around between threads based on the current utilization of the threads, with the aim of improving the overall performance of the system. To build that actually requires -threads *and* tasks, and therefore futures. +threads _and_ tasks, and therefore futures. As a default way of thinking about which to use when: -- If the work is *very parallelizable*, such as processing a bunch of data where +- If the work is _very parallelizable_, such as processing a bunch of data where each part can be processed separately, threads are a better choice. -- If the work is *very concurrent*, such as handling messages from a bunch of +- If the work is _very concurrent_, such as handling messages from a bunch of different sources which may come in a different intervals or different rates, async is a better choice. @@ -136,6 +136,5 @@ Next, we’ll talk about idiomatic ways to model problems and structure solution as your Rust programs get bigger. In addition, we’ll discuss how Rust’s idioms relate to those you might be familiar with from object-oriented programming. - [combining-futures]: ch17-03-more-futures.html#building-our-own-async-abstractions [streams]: ch17-04-streams.html#composing-streams diff --git a/rustbook-en/src/ch18-00-oop.md b/rustbook-en/src/ch18-00-oop.md index e20f6583f..adcde4c5a 100644 --- a/rustbook-en/src/ch18-00-oop.md +++ b/rustbook-en/src/ch18-00-oop.md @@ -4,7 +4,7 @@ Object-oriented programming (OOP) is a way of modeling programs. Objects as a programmatic concept were introduced in the programming language Simula in the 1960s. Those objects influenced Alan Kay’s programming architecture in which objects pass messages to each other. To describe this architecture, he coined -the term *object-oriented programming* in 1967. Many competing definitions +the term _object-oriented programming_ in 1967. Many competing definitions describe what OOP is, and by some of these definitions Rust is object-oriented, but by others it is not. In this chapter, we’ll explore certain characteristics that are commonly considered object-oriented and how those characteristics diff --git a/rustbook-en/src/ch18-01-what-is-oo.md b/rustbook-en/src/ch18-01-what-is-oo.md index 3d977dadc..e37075746 100644 --- a/rustbook-en/src/ch18-01-what-is-oo.md +++ b/rustbook-en/src/ch18-01-what-is-oo.md @@ -10,23 +10,23 @@ Rust supports it. ### Objects Contain Data and Behavior -The book *Design Patterns: Elements of Reusable Object-Oriented Software* by +The book _Design Patterns: Elements of Reusable Object-Oriented Software_ by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison-Wesley -Professional, 1994), colloquially referred to as *The Gang of Four* book, is a +Professional, 1994), colloquially referred to as _The Gang of Four_ book, is a catalog of object-oriented design patterns. It defines OOP this way: -> Object-oriented programs are made up of objects. An *object* packages both +> Object-oriented programs are made up of objects. An _object_ packages both > data and the procedures that operate on that data. The procedures are -> typically called *methods* or *operations*. +> typically called _methods_ or _operations_. Using this definition, Rust is object-oriented: structs and enums have data, and `impl` blocks provide methods on structs and enums. Even though structs and -enums with methods aren’t *called* objects, they provide the same +enums with methods aren’t _called_ objects, they provide the same functionality, according to the Gang of Four’s definition of objects. ### Encapsulation that Hides Implementation Details -Another aspect commonly associated with OOP is the idea of *encapsulation*, +Another aspect commonly associated with OOP is the idea of _encapsulation_, which means that the implementation details of an object aren’t accessible to code using that object. Therefore, the only way to interact with an object is through its public API; code using the object shouldn’t be able to reach into @@ -94,7 +94,7 @@ not for different parts of code enables encapsulation of implementation details. ### Inheritance as a Type System and as Code Sharing -*Inheritance* is a mechanism whereby an object can inherit elements from +_Inheritance_ is a mechanism whereby an object can inherit elements from another object’s definition, thus gaining the parent object’s data and behavior without you having to define them again. @@ -121,7 +121,7 @@ implementation of a method inherited from a parent class. The other reason to use inheritance relates to the type system: to enable a child type to be used in the same places as the parent type. This is also -called *polymorphism*, which means that you can substitute multiple objects for +called _polymorphism_, which means that you can substitute multiple objects for each other at runtime if they share certain characteristics. > ### Polymorphism @@ -132,7 +132,7 @@ each other at runtime if they share certain characteristics. > > Rust instead uses generics to abstract over different possible types and > trait bounds to impose constraints on what those types must provide. This is -> sometimes called *bounded parametric polymorphism*. +> sometimes called _bounded parametric polymorphism_. Inheritance has recently fallen out of favor as a programming design solution in many programming languages because it’s often at risk of sharing more code diff --git a/rustbook-en/src/ch18-02-trait-objects.md b/rustbook-en/src/ch18-02-trait-objects.md index 6f05a4e0d..99e1e7390 100644 --- a/rustbook-en/src/ch18-02-trait-objects.md +++ b/rustbook-en/src/ch18-02-trait-objects.md @@ -40,7 +40,7 @@ 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 +takes a _trait object_. A trait object points to both an instance of a type implementing our specified trait and 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` smart pointer, then the `dyn` @@ -56,7 +56,7 @@ We’ve mentioned that, in Rust, we refrain from calling structs and enums “objects” to distinguish them from other languages’ objects. In a struct or enum, the data in the struct fields and the behavior in `impl` blocks are separated, whereas in other languages, the data and behavior combined into one -concept is often labeled an object. However, trait objects *are* more like +concept is often labeled an object. However, trait objects _are_ more like objects in other languages in the sense that they combine data and behavior. But trait objects differ from traditional objects in that we can’t add data to a trait object. Trait objects aren’t as generally useful as objects in other @@ -182,8 +182,8 @@ 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 +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 18-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` @@ -227,9 +227,9 @@ 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 +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. @@ -239,10 +239,12 @@ so it doesn’t know which method implemented on which type to call. Instead, at runtime, Rust uses the pointers inside the trait object to know which method to call. This lookup incurs a runtime cost that doesn’t occur with static dispatch. Dynamic dispatch also prevents the compiler from choosing to inline a -method’s code, which in turn prevents some optimizations. However, we did get -extra flexibility in the code that we wrote in Listing 18-5 and were able to -support in Listing 18-9, so it’s a trade-off to consider. +method’s code, which in turn prevents some optimizations, and Rust has some +rules about where you can and cannot use dynamic dispatch, called [_dyn +compatibility_][dyn-compatibility]. However, we did get extra flexibility in the code +that we wrote in Listing 18-5 and were able to support in Listing 18-9, so it’s +a trade-off to consider. -[performance-of-code-using-generics]: -ch10-01-syntax.html#performance-of-code-using-generics +[performance-of-code-using-generics]: ch10-01-syntax.html#performance-of-code-using-generics [dynamically-sized]: ch20-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait +[dyn-compatibility]: https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility diff --git a/rustbook-en/src/ch18-03-oo-design-patterns.md b/rustbook-en/src/ch18-03-oo-design-patterns.md index 29ff10901..8f50a56fd 100644 --- a/rustbook-en/src/ch18-03-oo-design-patterns.md +++ b/rustbook-en/src/ch18-03-oo-design-patterns.md @@ -1,8 +1,8 @@ ## Implementing an Object-Oriented Design Pattern -The *state pattern* is an object-oriented design pattern. The crux of the +The _state pattern_ is an object-oriented design pattern. The crux of the pattern is that we define a set of states a value can have internally. The -states are represented by a set of *state objects*, and the value’s behavior +states are represented by a set of _state objects_, and the value’s behavior changes based on its state. We’re going to work through an example of a blog post struct that has a field to hold its state, which will be a state object from the set "draft", "review", or "published". @@ -208,6 +208,7 @@ slice. We can now have a `Post` in the `PendingReview` state as well as in the Listing 18-11 now works up to line 10! + ### Adding `approve` to Change the Behavior of `content` @@ -330,10 +331,10 @@ The implementation using the state pattern is easy to extend to add more functionality. To see the simplicity of maintaining code that uses the state pattern, try a few of these suggestions: -* Add a `reject` method that changes the post’s state from `PendingReview` back +- Add a `reject` method that changes the post’s state from `PendingReview` back to `Draft`. -* Require two calls to `approve` before the state can be changed to `Published`. -* Allow users to add text content only when a post is in the `Draft` state. +- Require two calls to `approve` before the state can be changed to `Published`. +- Allow users to add text content only when a post is in the `Draft` state. Hint: have the state object responsible for what might change about the content but not responsible for modifying the `Post`. @@ -348,9 +349,9 @@ another design pattern. Another downside is that we’ve duplicated some logic. To eliminate some of the duplication, we might try to make default implementations for the `request_review` and `approve` methods on the `State` trait that return `self`; -however, this would violate object safety, because the trait doesn’t know what +however, this would not be dyn compatible, because the trait doesn’t know what the concrete `self` will be exactly. We want to be able to use `State` as a -trait object, so we need its methods to be object safe. +trait object, so we need its methods to be dyn compatible. Other duplication includes the similar implementations of the `request_review` and `approve` methods on `Post`. Both methods delegate to the implementation of diff --git a/rustbook-en/src/ch19-00-patterns.md b/rustbook-en/src/ch19-00-patterns.md index dc9290e33..4574ac0b8 100644 --- a/rustbook-en/src/ch19-00-patterns.md +++ b/rustbook-en/src/ch19-00-patterns.md @@ -1,15 +1,15 @@ # Patterns and Matching -*Patterns* are a special syntax in Rust for matching against the structure of +_Patterns_ are a special syntax in Rust for matching against the structure of types, both complex and simple. Using patterns in conjunction with `match` expressions and other constructs gives you more control over a program’s control flow. A pattern consists of some combination of the following: -* Literals -* Destructured arrays, enums, structs, or tuples -* Variables -* Wildcards -* Placeholders +- Literals +- Destructured arrays, enums, structs, or tuples +- Variables +- Wildcards +- Placeholders Some example patterns include `x`, `(a, 3)`, and `Some(Color::Red)`. In the contexts in which patterns are valid, these components describe the shape of diff --git a/rustbook-en/src/ch19-01-all-the-places-for-patterns.md b/rustbook-en/src/ch19-01-all-the-places-for-patterns.md index 11f5919a4..0db908a8a 100644 --- a/rustbook-en/src/ch19-01-all-the-places-for-patterns.md +++ b/rustbook-en/src/ch19-01-all-the-places-for-patterns.md @@ -32,7 +32,7 @@ match x { The patterns in this `match` expression are the `None` and `Some(i)` on the left of each arrow. -One requirement for `match` expressions is that they need to be *exhaustive* in +One requirement for `match` expressions is that they need to be _exhaustive_ in the sense that all possibilities for the value in the `match` expression must be accounted for. One way to ensure you’ve covered every possibility is to have a catchall pattern for the last arm: for example, a variable name matching any @@ -251,5 +251,4 @@ work the same in every place we can use them. In some places, the patterns must be irrefutable; in other circumstances, they can be refutable. We’ll discuss these two concepts next. -[ignoring-values-in-a-pattern]: -ch19-03-pattern-syntax.html#ignoring-values-in-a-pattern +[ignoring-values-in-a-pattern]: ch19-03-pattern-syntax.html#ignoring-values-in-a-pattern diff --git a/rustbook-en/src/ch19-02-refutability.md b/rustbook-en/src/ch19-02-refutability.md index 3601f5d14..515358879 100644 --- a/rustbook-en/src/ch19-02-refutability.md +++ b/rustbook-en/src/ch19-02-refutability.md @@ -1,10 +1,10 @@ ## Refutability: Whether a Pattern Might Fail to Match Patterns come in two forms: refutable and irrefutable. Patterns that will match -for any possible value passed are *irrefutable*. An example would be `x` in the +for any possible value passed are _irrefutable_. An example would be `x` in the statement `let x = 5;` because `x` matches anything and therefore cannot fail to match. Patterns that can fail to match for some possible value are -*refutable*. An example would be `Some(x)` in the expression `if let Some(x) = +_refutable_. An example would be `Some(x)` in the expression `if let Some(x) = a_value` because if the value in the `a_value` variable is `None` rather than `Some`, the `Some(x)` pattern will not match. diff --git a/rustbook-en/src/ch19-03-pattern-syntax.md b/rustbook-en/src/ch19-03-pattern-syntax.md index 4503cf77e..21c1137d9 100644 --- a/rustbook-en/src/ch19-03-pattern-syntax.md +++ b/rustbook-en/src/ch19-03-pattern-syntax.md @@ -68,8 +68,8 @@ Guards”](#extra-conditionals-with-match-guards) section. ### Multiple Patterns In `match` expressions, you can match multiple patterns using the `|` syntax, -which is the pattern *or* operator. For example, in the following code we match -the value of `x` against the match arms, the first of which has an *or* option, +which is the pattern _or_ operator. For example, in the following code we match +the value of `x` against the match arms, the first of which has an _or_ option, meaning if the value of `x` matches either of the values in that arm, that arm’s code will run: @@ -450,7 +450,7 @@ compiler error because using `..` in two places like this is ambiguous. ### Extra Conditionals with Match Guards -A *match guard* is an additional `if` condition, specified after the pattern in +A _match guard_ is an additional `if` condition, specified after the pattern in a `match` arm, that must also match for that arm to be chosen. Match guards are useful for expressing more complex ideas than a pattern alone allows. @@ -504,15 +504,15 @@ pattern as `Some(y)`, which would have shadowed the outer `y`, we specify there is no `n` variable outside the `match`. The match guard `if n == y` is not a pattern and therefore doesn’t introduce new -variables. This `y` *is* the outer `y` rather than a new `y` shadowing it, and +variables. This `y` _is_ the outer `y` rather than a new `y` shadowing it, and we can look for a value that has the same value as the outer `y` by comparing `n` to `y`. -You can also use the *or* operator `|` in a match guard to specify multiple +You can also use the _or_ operator `|` in a match guard to specify multiple patterns; the match guard condition will apply to all the patterns. Listing 19-28 shows the precedence when combining a pattern that uses `|` with a match guard. The important part of this example is that the `if y` match guard -applies to `4`, `5`, *and* `6`, even though it might look like `if y` only +applies to `4`, `5`, _and_ `6`, even though it might look like `if y` only applies to `6`. @@ -524,7 +524,7 @@ applies to `6`. The match condition states that the arm only matches if the value of `x` is -equal to `4`, `5`, or `6` *and* if `y` is `true`. When this code runs, the +equal to `4`, `5`, or `6` _and_ if `y` is `true`. When this code runs, the pattern of the first arm matches because `x` is `4`, but the match guard `if y` is false, so the first arm is not chosen. The code moves on to the second arm, which does match, and this program prints `no`. The reason is that the `if` @@ -549,7 +549,7 @@ were applied only to the final value in the list of values specified using the ### `@` Bindings -The *at* operator `@` lets us create a variable that holds a value at the same +The _at_ operator `@` lets us create a variable that holds a value at the same time as we’re testing that value for a pattern match. In Listing 19-29, we want to test that a `Message::Hello` `id` field is within the range `3..=7`. We also want to bind the value to the variable `id_variable` so we can use it in the diff --git a/rustbook-en/src/ch20-00-advanced-features.md b/rustbook-en/src/ch20-00-advanced-features.md index 3e612d2af..049681b5d 100644 --- a/rustbook-en/src/ch20-00-advanced-features.md +++ b/rustbook-en/src/ch20-00-advanced-features.md @@ -10,13 +10,13 @@ grasp of all the features Rust has to offer. In this chapter, we’ll cover: -* Unsafe Rust: how to opt out of some of Rust’s guarantees and take +- Unsafe Rust: how to opt out of some of Rust’s guarantees and take responsibility for manually upholding those guarantees -* Advanced traits: associated types, default type parameters, fully qualified +- 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, +- Advanced types: more about the newtype pattern, type aliases, the never type, and dynamically sized types -* Advanced functions and closures: function pointers and returning closures -* Macros: ways to define code that defines more code at compile time +- Advanced functions and closures: function pointers and returning closures +- Macros: ways to define code that defines more code at compile time It’s a panoply of Rust features with something for everyone! Let’s dive in! diff --git a/rustbook-en/src/ch20-01-unsafe-rust.md b/rustbook-en/src/ch20-01-unsafe-rust.md index 935b4fe43..3e6147fe9 100644 --- a/rustbook-en/src/ch20-01-unsafe-rust.md +++ b/rustbook-en/src/ch20-01-unsafe-rust.md @@ -2,13 +2,13 @@ All the code we’ve discussed so far has had Rust’s memory safety guarantees enforced at compile time. However, Rust has a second language hidden inside it -that doesn’t enforce these memory safety guarantees: it’s called *unsafe Rust* +that doesn’t enforce these memory safety guarantees: it’s called _unsafe Rust_ and works just like regular Rust, but gives us extra superpowers. Unsafe Rust exists because, by nature, static analysis is conservative. When the compiler tries to determine whether or not code upholds the guarantees, it’s better for it to reject some valid programs than to accept some invalid -programs. Although the code *might* be okay, if the Rust compiler doesn’t have +programs. Although the code _might_ be okay, if the Rust compiler doesn’t have enough information to be confident, it will reject the code. In these cases, you can use unsafe code to tell the compiler, “Trust me, I know what I’m doing.” Be warned, however, that you use unsafe Rust at your own risk: if you @@ -27,14 +27,14 @@ Rust and how to do it. 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 that you -can’t in safe Rust, which we call *unsafe superpowers*. Those superpowers +can’t in safe Rust, which we call _unsafe superpowers_. Those superpowers include the ability to: -* Dereference a raw pointer -* Call an unsafe function or method -* Access or modify a mutable static variable -* Implement an unsafe trait -* Access fields of a `union` +- Dereference a raw pointer +- Call an unsafe function or method +- Access or modify a mutable static variable +- Implement an unsafe trait +- Access fields of a `union` 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 @@ -69,20 +69,20 @@ some abstractions that provide a safe interface to unsafe code. In Chapter 4, in the [“Dangling References”][dangling-references] section, we mentioned that the compiler ensures references are always -valid. Unsafe Rust has two new types called *raw pointers* that are similar to +valid. Unsafe Rust has two new types called _raw pointers_ that are similar to references. As with references, raw pointers can be immutable or mutable and are written as `*const T` and `*mut T`, respectively. The asterisk isn’t the dereference operator; it’s part of the type name. In the context of raw -pointers, *immutable* means that the pointer can’t be directly assigned to +pointers, _immutable_ means that the pointer can’t be directly assigned to after being dereferenced. Different from references and smart pointers, raw pointers: -* Are allowed to ignore the borrowing rules by having both immutable and +- Are allowed to ignore the borrowing rules by having both immutable and mutable pointers or multiple mutable pointers to the same location -* Aren’t guaranteed to point to valid memory -* Are allowed to be null -* Don’t implement any automatic cleanup +- Aren’t guaranteed to point to valid memory +- Are allowed to be null +- Don’t implement any automatic cleanup By opting out of having Rust enforce these guarantees, you can give up guaranteed safety in exchange for greater performance or the ability to @@ -125,7 +125,7 @@ where you can use a raw borrow operator instead, but it is possible.
-Recall that we can create raw pointers in safe code, but we can’t *dereference* +Recall that we can create raw pointers in safe code, but we can’t _dereference_ raw pointers and read the data being pointed to. In Listing 20-3, we use the dereference operator `*` on a raw pointer that requires an `unsafe` block. @@ -305,7 +305,7 @@ that the slice this code creates contains valid `i32` values. Attempting to use Sometimes, your Rust code might need to interact with code written in another language. For this, Rust has the keyword `extern` that facilitates the creation -and use of a *Foreign Function Interface (FFI)*. An FFI is a way for a +and use of a _Foreign Function Interface (FFI)_. An FFI is a way for a programming language to define functions and enable a different (foreign) programming language to call those functions. @@ -326,7 +326,7 @@ safety. Within the `unsafe extern "C"` block, we list the names and signatures of external functions from another language we want to call. The `"C"` part defines -which *application binary interface (ABI)* the external function uses: the ABI +which _application binary interface (ABI)_ the external function uses: the ABI defines how to call the function at the assembly level. The `"C"` ABI is the most common and follows the C programming language’s ABI. @@ -345,7 +345,7 @@ it no longer requires an `unsafe` block, as shown in Listing 20-9.
Marking a function as `safe` does not inherently make it safe! Instead, it is -like a promise you are making to Rust that it *is* safe. It is still your +like a promise you are making to Rust that it _is_ safe. It is still your responsibility to make sure that promise is kept! > #### Calling Rust Functions from Other Languages @@ -354,7 +354,7 @@ responsibility to make sure that promise is kept! > call Rust functions. Instead of creating a whole `extern` block, we add the > `extern` keyword and specify the ABI to use just before the `fn` keyword for > the relevant function. We also need to add a `#[unsafe(no_mangle)]` annotation -> to tell the Rust compiler not to mangle the name of this function. *Mangling* +> to tell the Rust compiler not to mangle the name of this function. _Mangling_ > is when a compiler changes the name we’ve given a function to a different name > that contains more information for other parts of the compilation process to > consume but is less human readable. Every programming language compiler @@ -378,11 +378,11 @@ responsibility to make sure that promise is kept! ### Accessing or Modifying a Mutable Static Variable -In this book, we’ve not yet talked about *global variables*, which Rust does +In this book, we’ve not yet talked about _global variables_, which Rust does support but can be problematic with Rust’s ownership rules. If two threads are accessing the same mutable global variable, it can cause a data race. -In Rust, global variables are called *static* variables. Listing 20-10 shows an +In Rust, global variables are called _static_ variables. Listing 20-10 shows an example declaration and use of a static variable with a string slice as a value. @@ -408,7 +408,7 @@ values in a static variable have a fixed address in memory. Using the value will always access the same data. Constants, on the other hand, are allowed to duplicate their data whenever they’re used. Another difference is that static variables can be mutable. Accessing and modifying mutable static variables is -*unsafe*. Listing 20-11 shows how to declare, access, and modify a mutable +_unsafe_. Listing 20-11 shows how to declare, access, and modify a mutable static variable named `COUNTER`. @@ -472,7 +472,7 @@ those checks manually and indicate as such with `unsafe`. ### Accessing Fields of a Union The final action that works only with `unsafe` is accessing fields of a -*union*. A `union` is similar to a `struct`, but only one declared field is +_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 @@ -483,8 +483,8 @@ instance. You can learn more about unions in [the Rust Reference][reference]. When writing unsafe code, you might want to check that what you have written actually is safe and correct. One of the best ways to do that is to use [Miri][miri], an official Rust tool for detecting undefined behavior. Whereas -the borrow checker is a *static* tool which works at compile time, Miri is a -*dynamic* tool which works at runtime. It checks your code by running your +the borrow checker is a _static_ tool which works at compile time, Miri is a +_dynamic_ tool which works at runtime. It checks your code by running your program, or its test suite, and detecting when you violate the rules it understands about how Rust should work. @@ -507,15 +507,15 @@ It helpfully and correctly notices that we have shared references to mutable data, and warns about it. In this case, it does not tell us how to fix the problem, but it means that we know there is a possible issue and can think about how to make sure it is safe. In other cases, it can actually tell us that some -code is *sure* to be wrong and make recommendations about how to fix it. +code is _sure_ to be wrong and make recommendations about how to fix it. -Miri doesn’t catch *everything* you might get wrong when writing unsafe code. +Miri doesn’t catch _everything_ you might get wrong when writing unsafe code. For one thing, since it is a dynamic check, it only catches problems with code that actually gets run. That means you will need to use it in conjunction with good testing techniques to increase your confidence about the unsafe code you have written. For another thing, it does not cover every possible way your code -can be unsound. If Miri *does* catch a problem, you know there’s a bug, but just -because Miri *doesn’t* catch a bug doesn’t mean there isn’t a problem. Miri can +can be unsound. If Miri _does_ catch a problem, you know there’s a bug, but just +because Miri _doesn’t_ catch a bug doesn’t mean there isn’t a problem. Miri can catch a lot, though. Try running it on the other examples of unsafe code in this chapter and see what it says! @@ -529,12 +529,9 @@ annotation makes it easier to track down the source of problems when they occur. Whenever you write unsafe code, you can use Miri to help you be more confident that the code you have written upholds Rust’s rules. -[dangling-references]: -ch04-02-references-and-borrowing.html#dangling-references -[differences-between-variables-and-constants]: -ch03-01-variables-and-mutability.html#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 +[dangling-references]: ch04-02-references-and-borrowing.html#dangling-references +[differences-between-variables-and-constants]: ch03-01-variables-and-mutability.html#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 [the-slice-type]: ch04-03-slices.html#the-slice-type [reference]: ../reference/items/unions.html [miri]: https://github.com/rust-lang/miri diff --git a/rustbook-en/src/ch20-03-advanced-traits.md b/rustbook-en/src/ch20-03-advanced-traits.md index d95b1d9b9..3b5b80728 100644 --- a/rustbook-en/src/ch20-03-advanced-traits.md +++ b/rustbook-en/src/ch20-03-advanced-traits.md @@ -7,7 +7,7 @@ about Rust, we can get into the nitty-gritty. ### Specifying Placeholder Types in Trait Definitions with Associated Types -*Associated types* connect a type placeholder with a trait such that the trait +_Associated types_ connect a type placeholder with a trait such that the trait method definitions can use these placeholder types in their signatures. The implementor of a trait will specify the concrete type to be used instead of the placeholder type for the particular implementation. That way, we can define a @@ -91,8 +91,8 @@ the generic type. This eliminates the need for implementors of the trait to specify a concrete type if the default type works. You specify a default type when declaring a generic type with the `` syntax. -A great example of a situation where this technique is useful is with *operator -overloading*, in which you customize the behavior of an operator (such as `+`) +A great example of a situation where this technique is useful is with _operator +overloading_, in which you customize the behavior of an operator (such as `+`) in particular situations. Rust doesn’t allow you to create your own operators or overload arbitrary @@ -127,8 +127,8 @@ trait Add { ``` This code should look generally familiar: a trait with one method and an -associated type. The new part is `Rhs=Self`: this syntax is called *default -type parameters*. The `Rhs` generic type parameter (short for “right hand +associated type. The new part is `Rhs=Self`: this syntax is called _default +type parameters_. The `Rhs` generic type parameter (short for “right hand side”) defines the type of the `rhs` parameter in the `add` method. If we don’t specify a concrete type for `Rhs` when we implement the `Add` trait, the type of `Rhs` will default to `Self`, which will be the type we’re implementing @@ -141,7 +141,7 @@ default. We have two structs, `Millimeters` and `Meters`, holding values in different units. This thin wrapping of an existing type in another struct is known as the -*newtype pattern*, which we describe in more detail in the [“Using the Newtype +_newtype pattern_, which we describe in more detail in the [“Using the Newtype Pattern to Implement External Traits on External Types”][newtype] section. 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` @@ -160,8 +160,8 @@ value of the `Rhs` type parameter instead of using the default of `Self`. You’ll use default type parameters in two main ways: -* To extend a type without breaking existing code -* To allow customization in specific cases most users won’t need +- To extend a type without breaking existing code +- To allow customization in specific cases most users won’t need The standard library’s `Add` trait is an example of the second purpose: usually, you’ll add two like types, but the `Add` trait provides the ability to @@ -234,15 +234,15 @@ Running this code prints the following: {{#include ../listings/ch20-advanced-features/listing-20-19/output.txt}} ``` -Because the `fly` method takes a `self` parameter, if we had two *types* that -both implement one *trait*, Rust could figure out which implementation of a +Because the `fly` method takes a `self` parameter, if we had two _types_ that +both implement one _trait_, Rust could figure out which implementation of a trait to use based on the type of `self`. However, associated functions that are not methods don’t have a `self` parameter. When there are multiple types or traits that define non-method functions with the same function name, Rust doesn't always know which type you -mean unless you use *fully qualified syntax*. For example, in Listing 20-20 we -create a trait for an animal shelter that wants to name all baby dogs *Spot*. +mean unless you use _fully qualified syntax_. For example, in Listing 20-20 we +create a trait for an animal shelter that wants to name all baby dogs _Spot_. We make an `Animal` trait with an associated non-method function `baby_name`. The `Animal` trait is implemented for the struct `Dog`, on which we also provide an associated non-method function `baby_name` directly. @@ -332,7 +332,7 @@ Sometimes, you might write a trait definition that depends on another trait: for a type to implement the first trait, you want to require that type to also implement the second trait. You would do this so that your trait definition can make use of the associated items of the second trait. The trait your trait -definition is relying on is called a *supertrait* of your trait. +definition is relying on is called a _supertrait_ of your trait. For example, let’s say we want to make an `OutlinePrint` trait with an `outline_print` method that will print a given value formatted so that it's @@ -410,13 +410,13 @@ In Chapter 10 in the [“Implementing a Trait on a Type”][implementing-a-trait-on-a-type] section, we mentioned the orphan rule that states we’re only allowed to implement a trait on a type if 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 +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] 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. +_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. @@ -454,9 +454,7 @@ This newtype pattern is also useful even when traits are not involved. Let’s switch focus and look at some advanced ways to interact with Rust’s type system. [newtype]: ch20-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types -[implementing-a-trait-on-a-type]: -ch10-02-traits.html#implementing-a-trait-on-a-type -[traits-defining-shared-behavior]: -ch10-02-traits.html#traits-defining-shared-behavior +[implementing-a-trait-on-a-type]: ch10-02-traits.html#implementing-a-trait-on-a-type +[traits-defining-shared-behavior]: ch10-02-traits.html#traits-defining-shared-behavior [smart-pointer-deref]: ch15-02-deref.html#treating-smart-pointers-like-regular-references-with-the-deref-trait [tuple-structs]: ch05-01-defining-structs.html#using-tuple-structs-without-named-fields-to-create-different-types diff --git a/rustbook-en/src/ch20-04-advanced-types.md b/rustbook-en/src/ch20-04-advanced-types.md index a3f1f4320..498a3c36b 100644 --- a/rustbook-en/src/ch20-04-advanced-types.md +++ b/rustbook-en/src/ch20-04-advanced-types.md @@ -38,7 +38,7 @@ section of Chapter 18. ### Creating Type Synonyms with Type Aliases -Rust provides the ability to declare a *type alias* to give an existing type +Rust provides the ability to declare a _type 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: @@ -46,7 +46,7 @@ the alias `Kilometers` to `i32` like so: {{#rustdoc_include ../listings/ch20-advanced-features/no-listing-04-kilometers-alias/src/main.rs:here}} ``` -Now, the alias `Kilometers` is a *synonym* for `i32`; unlike the `Millimeters` +Now, the alias `Kilometers` is a _synonym_ for `i32`; unlike the `Millimeters` and `Meters` types we created in Listing 20-16, `Kilometers` is not a separate, new type. Values that have the type `Kilometers` will be treated the same as values of type `i32`: @@ -94,7 +94,7 @@ can replace all uses of the type with the shorter alias `Thunk`. This code is much easier to read and write! Choosing a meaningful name for a -type alias can help communicate your intent as well (*thunk* is a word for code +type alias can help communicate your intent as well (_thunk_ is a word for code to be evaluated at a later time, so it’s an appropriate name for a closure that gets stored). @@ -126,7 +126,7 @@ looking like this: {{#rustdoc_include ../listings/ch20-advanced-features/no-listing-06-result-alias/src/lib.rs:there}} ``` -The type alias helps in two ways: it makes code easier to write *and* it gives +The type alias helps in two ways: it makes code easier to write _and_ it gives us a consistent interface across all of `std::io`. Because it’s an alias, it’s just another `Result`, which means we can use any methods that work on `Result` with it, as well as special syntax like the `?` operator. @@ -134,7 +134,7 @@ just another `Result`, which means we can use any methods that work on ### The Never Type that Never Returns Rust has a special type named `!` that’s known in type theory lingo as the -*empty type* because it has no values. We prefer to call it the *never type* +_empty type_ because it has no values. We prefer to call it the _never type_ because it stands in the place of the return type when a function will never return. Here is an example: @@ -143,7 +143,7 @@ return. Here is an example: ``` This code is read as “the function `bar` returns never.” Functions that return -never are called *diverging functions*. We can’t create values of the type `!` +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 @@ -167,7 +167,7 @@ example, the following code doesn’t work: {{#rustdoc_include ../listings/ch20-advanced-features/no-listing-08-match-arms-different-types/src/main.rs:here}} ``` -The type of `guess` in this code would have to be an integer *and* a string, +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 20-27? @@ -211,8 +211,8 @@ when it got to the `break`. Rust needs to know certain details about its types, such as how much space to allocate for a value of a particular type. This leaves one corner of its type -system a little confusing at first: the concept of *dynamically sized types*. -Sometimes referred to as *DSTs* or *unsized types*, these types let us write +system a little confusing at first: the concept of _dynamically sized types_. +Sometimes referred to as _DSTs_ or _unsized types_, these types let us write code using values whose size we can know only at runtime. Let’s dig into the details of a dynamically sized type called `str`, which @@ -237,7 +237,7 @@ of `s1` and `s2` a `&str` rather than a `str`. Recall from the [“String Slices”][string-slices] section of Chapter 4 that the slice data structure just stores the starting position and the length of the slice. So although a `&T` is a single value that stores the memory address of where the -`T` is located, a `&str` is *two* values: the address of the `str` and its +`T` is located, a `&str` is _two_ values: the address of the `str` and its length. As such, we can know the size of a `&str` value at compile time: it’s twice the length of a `usize`. That is, we always know the size of a `&str`, no matter how long the string it refers to is. In general, this is the way in @@ -291,11 +291,8 @@ pointer. In this case, we’ve chosen a reference. Next, we’ll talk about functions and closures! -[encapsulation-that-hides-implementation-details]: -ch18-01-what-is-oo.html#encapsulation-that-hides-implementation-details +[encapsulation-that-hides-implementation-details]: ch18-01-what-is-oo.html#encapsulation-that-hides-implementation-details [string-slices]: ch04-03-slices.html#string-slices -[the-match-control-flow-operator]: -ch06-02-match.html#the-match-control-flow-operator -[using-trait-objects-that-allow-for-values-of-different-types]: -ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types +[the-match-control-flow-operator]: ch06-02-match.html#the-match-control-flow-operator +[using-trait-objects-that-allow-for-values-of-different-types]: ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types [using-the-newtype-pattern]: ch20-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types diff --git a/rustbook-en/src/ch20-05-advanced-functions-and-closures.md b/rustbook-en/src/ch20-05-advanced-functions-and-closures.md index 618568d0d..9f04892b0 100644 --- a/rustbook-en/src/ch20-05-advanced-functions-and-closures.md +++ b/rustbook-en/src/ch20-05-advanced-functions-and-closures.md @@ -9,7 +9,7 @@ We’ve talked about how to pass closures to functions; you can also pass regula functions to functions! This technique is useful when you want to pass a function you’ve already defined rather than defining a new closure. 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*. Passing functions +closure trait. The `fn` type is called a _function pointer_. Passing functions with function pointers will allow you to use functions as arguments to other functions. @@ -122,8 +122,6 @@ ignore --> in Chapter 19. Next, let’s look at macros! -[advanced-traits]: -ch20-03-advanced-traits.html#advanced-traits +[advanced-traits]: ch20-03-advanced-traits.html#advanced-traits [enum-values]: ch06-01-defining-an-enum.html#enum-values -[using-trait-objects-that-allow-for-values-of-different-types]: -ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types +[using-trait-objects-that-allow-for-values-of-different-types]: ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types diff --git a/rustbook-en/src/ch20-06-macros.md b/rustbook-en/src/ch20-06-macros.md index cd4ded07d..c687c8b61 100644 --- a/rustbook-en/src/ch20-06-macros.md +++ b/rustbook-en/src/ch20-06-macros.md @@ -1,14 +1,14 @@ ## 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. The term _macro_ refers to a family +of features in Rust: _declarative_ macros with `macro_rules!` and three kinds +of _procedural_ macros: -* Custom `#[derive]` macros that specify code added with the `derive` attribute +- 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 +- 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 We’ll talk about each of these in turn, but first, let’s look at why we even @@ -17,10 +17,10 @@ need macros when we already have functions. ### The Difference Between Macros and Functions Fundamentally, macros are a way of writing code that writes other code, which -is known as *metaprogramming*. In Appendix C, we discuss the `derive` +is known as _metaprogramming_. In Appendix C, we discuss the `derive` attribute, which generates an implementation of various traits for you. We’ve also used the `println!` and `vec!` macros throughout the book. All of these -macros *expand* to produce more code than the code you’ve written manually. +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 @@ -41,12 +41,12 @@ 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 +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. ### Declarative Macros with `macro_rules!` for General Metaprogramming -The most widely used form of macros in Rust is the *declarative macro*. These +The most widely used form of macros in Rust is the _declarative macro_. 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, @@ -92,7 +92,7 @@ available whenever the crate in which the macro is defined 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 -macro we’re defining *without* the exclamation mark. The name, in this case +macro we’re defining _without_ the exclamation mark. The name, in this case `vec`, is followed by curly brackets denoting the body of the macro definition. The structure in the `vec!` body is similar to the structure of a `match` @@ -150,7 +150,7 @@ Daniel Keep and continued by Lukas Wirth. ### Procedural Macros for Generating Code from Attributes -The second form of macros is the *procedural macro*, which acts more like a +The second form of macros is the _procedural macro_, which acts more like a function (and is 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 @@ -266,7 +266,7 @@ possible for programmers to use `hello_macro` even if they don’t want the We need to declare the `hello_macro_derive` crate as a procedural macro crate. We’ll also need functionality from the `syn` and `quote` crates, as you’ll see in a moment, so we need to add them as dependencies. Add the following to the -*Cargo.toml* file for `hello_macro_derive`: +_Cargo.toml_ file for `hello_macro_derive`: @@ -277,7 +277,7 @@ in a moment, so we need to add them as dependencies. Add the following to the To start defining the procedural macro, place the code in Listing 20-32 into -your *src/lib.rs* file for the `hello_macro_derive` crate. Note that this code +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. @@ -299,7 +299,7 @@ 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 +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. The `syn` crate parses Rust code from a string into a data structure that we @@ -413,9 +413,9 @@ 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 20-31 to see the procedural macro in action! Create a new binary project in -your *projects* directory using `cargo new pancakes`. We need to add +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 +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 dependencies; if not, you can specify them as `path` dependencies as follows: @@ -423,7 +423,7 @@ dependencies; if not, you can specify them as `path` dependencies as follows: {{#include ../listings/ch20-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml:7:9}} ``` -Put the code in Listing 20-31 into *src/main.rs*, and run `cargo run`: it +Put the code in Listing 20-31 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 diff --git a/rustbook-en/src/ch21-01-single-threaded.md b/rustbook-en/src/ch21-01-single-threaded.md index 9712b69a4..813a35247 100644 --- a/rustbook-en/src/ch21-01-single-threaded.md +++ b/rustbook-en/src/ch21-01-single-threaded.md @@ -5,10 +5,10 @@ let’s look at a quick overview of the protocols involved in building web servers. The details of these protocols are beyond the scope of this book, but a brief overview will give you the information you need. -The two main protocols involved in web servers are *Hypertext Transfer -Protocol* *(HTTP)* and *Transmission Control Protocol* *(TCP)*. Both protocols -are *request-response* protocols, meaning a *client* initiates requests and a -*server* listens to the requests and provides a response to the client. The +The two main protocols involved in web servers are _Hypertext Transfer +Protocol_ _(HTTP)_ and _Transmission Control Protocol_ _(TCP)_. Both protocols +are _request-response_ protocols, meaning a _client_ initiates requests and a +_server_ listens to the requests and provides a response to the client. The contents of those requests and responses are defined by the protocols. TCP is the lower-level protocol that describes the details of how information @@ -30,7 +30,7 @@ $ cargo new hello $ cd hello ``` -Now enter the code in Listing 21-1 in *src/main.rs* to start. This code will +Now enter the code in Listing 21-1 in _src/main.rs_ to start. This code will listen at the local address `127.0.0.1:7878` for incoming TCP streams. When it gets an incoming stream, it will print `Connection established!`. @@ -48,7 +48,7 @@ representing your computer (this is the same on every computer and doesn’t represent the authors’ computer specifically), and `7878` is the port. We’ve chosen this port for two reasons: HTTP isn’t normally accepted on this port so our server is unlikely to conflict with any other web server you might have -running on your machine, and 7878 is *rust* typed on a telephone. +running on your machine, and 7878 is _rust_ typed on a telephone. The `bind` function in this scenario works like the `new` function in that it will return a new `TcpListener` instance. The function is called `bind` @@ -67,8 +67,8 @@ stop the program if errors happen. The `incoming` method on `TcpListener` returns an iterator that gives us a sequence of streams (more specifically, streams of type `TcpStream`). A single -*stream* represents an open connection between the client and the server. A -*connection* is the name for the full request and response process in which a +_stream_ represents an open connection between the client and the server. A +_connection_ is the name for the full request and response process in which a client connects to the server, the server generates a response, and the server closes the connection. As such, we will read from the `TcpStream` to see what the client sent and then write our response to the stream to send data back to @@ -80,7 +80,7 @@ our program if the stream has any errors; if there aren’t any errors, the program prints a message. We’ll add more functionality for the success case in the next listing. The reason we might receive errors from the `incoming` method when a client connects to the server is that we’re not actually iterating over -connections. Instead, we’re iterating over *connection attempts*. The +connections. Instead, we’re iterating over _connection attempts_. The connection might not be successful for a number of reasons, many of them operating system specific. For example, many operating systems have a limit to the number of simultaneous open connections they can support; new connection @@ -88,7 +88,7 @@ attempts beyond that number will produce an error until some of the open connections are closed. Let’s try running this code! Invoke `cargo run` in the terminal and then load -*127.0.0.1:7878* in a web browser. The browser should show an error message +_127.0.0.1:7878_ in a web browser. The browser should show an error message like “Connection reset,” because the server isn’t currently sending back any data. But when you look at your terminal, you should see several messages that were printed when the browser connected to the server! @@ -102,7 +102,7 @@ Connection established! Sometimes, you’ll see multiple messages printed for one browser request; the reason might be that the browser is making a request for the page as well as a -request for other resources, like the *favicon.ico* icon that appears in the +request for other resources, like the _favicon.ico_ icon that appears in the browser tab. It could also be that the browser is trying to connect to the server multiple @@ -193,8 +193,8 @@ Request: [ Depending on your browser, you might get slightly different output. Now that we’re printing the request data, we can see why we get multiple connections from one browser request by looking at the path after `GET` in the first line -of the request. If the repeated connections are all requesting */*, we know the -browser is trying to fetch */* repeatedly because it’s not getting a response +of the request. If the repeated connections are all requesting _/_, we know the +browser is trying to fetch _/_ repeatedly because it’s not getting a response from our program. Let’s break down this request data to understand what the browser is asking of @@ -210,34 +210,34 @@ headers CRLF message-body ``` -The first line is the *request line* that holds information about what the -client is requesting. The first part of the request line indicates the *method* +The first line is the _request line_ that holds information about what the +client is requesting. The first part of the request line indicates the _method_ being used, such as `GET` or `POST`, which describes how the client is making this request. Our client used a `GET` request, which means it is asking for information. -The next part of the request line is */*, which indicates the *Uniform Resource -Identifier* *(URI)* the client is requesting: a URI is almost, but not quite, -the same as a *Uniform Resource Locator* *(URL)*. The difference between URIs +The next part of the request line is _/_, which indicates the _Uniform Resource +Identifier_ _(URI)_ the client is requesting: a URI is almost, but not quite, +the same as a _Uniform Resource Locator_ _(URL)_. The difference between URIs and URLs isn’t important for our purposes in this chapter, but the HTTP spec uses the term URI, so we can just mentally substitute URL for URI here. The last part is the HTTP version the client uses, and then the request line -ends in a *CRLF sequence*. (CRLF stands for *carriage return* and *line feed*, +ends in a _CRLF sequence_. (CRLF stands for _carriage return_ and _line feed_, which are terms from the typewriter days!) The CRLF sequence can also be written as `\r\n`, where `\r` is a carriage return and `\n` is a line feed. The CRLF sequence separates the request line from the rest of the request data. Note that when the CRLF is printed, we see a new line start rather than `\r\n`. Looking at the request line data we received from running our program so far, -we see that `GET` is the method, */* is the request URI, and `HTTP/1.1` is the +we see that `GET` is the method, _/_ is the request URI, and `HTTP/1.1` is the version. After the request line, the remaining lines starting from `Host:` onward are headers. `GET` requests have no body. Try making a request from a different browser or asking for a different -address, such as *127.0.0.1:7878/test*, to see how the request data changes. +address, such as _127.0.0.1:7878/test_, to see how the request data changes. Now that we know what the browser is asking for, let’s send back some data! @@ -252,7 +252,7 @@ headers CRLF message-body ``` -The first line is a *status line* that contains the HTTP version used in the +The first line is a _status line_ that contains the HTTP version used in the response, a numeric status code that summarizes the result of the request, and a reason phrase that provides a text description of the status code. After the CRLF sequence are any headers, another CRLF sequence, and the body of the @@ -288,15 +288,15 @@ application you would add error handling here. With these changes, let’s run our code and make a request. We’re no longer printing any data to the terminal, so we won’t see any output other than the -output from Cargo. When you load *127.0.0.1:7878* in a web browser, you should +output from Cargo. When you load _127.0.0.1:7878_ in a web browser, you should get a blank page instead of an error. You’ve just hand-coded receiving an HTTP request and sending a response! ### Returning Real HTML Let’s implement the functionality for returning more than a blank page. Create -the new file *hello.html* in the root of your project directory, not in the -*src* directory. You can input any HTML you want; Listing 21-4 shows one +the new file _hello.html_ in the root of your project directory, not in the +_src_ directory. You can input any HTML you want; Listing 21-4 shows one possibility. @@ -330,25 +330,25 @@ response. To ensure a valid HTTP response, we add the `Content-Length` header which is set to the size of our response body, in this case the size of `hello.html`. -Run this code with `cargo run` and load *127.0.0.1:7878* in your browser; you +Run this code with `cargo run` and load _127.0.0.1:7878_ in your browser; you should see your HTML rendered! Currently, we’re ignoring the request data in `http_request` and just sending back the contents of the HTML file unconditionally. That means if you try -requesting *127.0.0.1:7878/something-else* in your browser, you’ll still get +requesting _127.0.0.1:7878/something-else_ in your browser, you’ll still get back this same HTML response. At the moment, our server is very limited and does not do what most web servers do. We want to customize our responses depending on the request and only send back the HTML file for a well-formed -request to */*. +request to _/_. ### Validating the Request and Selectively Responding Right now, our web server will return the HTML in the file no matter what the client requested. Let’s add functionality to check that the browser is -requesting */* before returning the HTML file and return an error if the +requesting _/_ before returning the HTML file and return an error if the browser requests anything else. For this we need to modify `handle_connection`, as shown in Listing 21-6. This new code checks the content of the request -received against what we know a request for */* looks like and adds `if` and +received against what we know a request for _/_ looks like and adds `if` and `else` blocks to treat requests differently. @@ -367,16 +367,16 @@ stops the program if the iterator has no items. The second `unwrap` handles the Listing 21-2. Next, we check the `request_line` to see if it equals the request line of a GET -request to the */* path. If it does, the `if` block returns the contents of our +request to the _/_ path. If it does, the `if` block returns the contents of our HTML file. -If the `request_line` does *not* equal the GET request to the */* path, it +If the `request_line` does _not_ equal the GET request to the _/_ path, it means we’ve received some other request. We’ll add code to the `else` block in a moment to respond to all other requests. -Run this code now and request *127.0.0.1:7878*; you should get the HTML in -*hello.html*. If you make any other request, such as -*127.0.0.1:7878/something-else*, you’ll get a connection error like those you +Run this code now and request _127.0.0.1:7878_; you should get the HTML in +_hello.html_. If you make any other request, such as +_127.0.0.1:7878/something-else_, you’ll get a connection error like those you saw when running the code in Listing 21-1 and Listing 21-2. Now let’s add the code in Listing 21-7 to the `else` block to return a response @@ -393,8 +393,8 @@ indicating the response to the end user. Here, our response has a status line with status code 404 and the reason phrase -`NOT FOUND`. The body of the response will be the HTML in the file *404.html*. -You’ll need to create a *404.html* file next to *hello.html* for the error +`NOT FOUND`. The body of the response will be the HTML in the file _404.html_. +You’ll need to create a _404.html_ file next to _hello.html_ for the error page; again feel free to use any HTML you want or use the example HTML in Listing 21-8. @@ -406,9 +406,9 @@ Listing 21-8. -With these changes, run your server again. Requesting *127.0.0.1:7878* should -return the contents of *hello.html*, and any other request, like -*127.0.0.1:7878/foo*, should return the error HTML from *404.html*. +With these changes, run your server again. Requesting _127.0.0.1:7878_ should +return the contents of _hello.html_, and any other request, like +_127.0.0.1:7878/foo_, should return the error HTML from _404.html_. ### A Touch of Refactoring diff --git a/rustbook-en/src/ch21-02-multithreaded.md b/rustbook-en/src/ch21-02-multithreaded.md index 788ee5468..c2e7865ab 100644 --- a/rustbook-en/src/ch21-02-multithreaded.md +++ b/rustbook-en/src/ch21-02-multithreaded.md @@ -12,7 +12,7 @@ this, but first, we’ll look at the problem in action. We’ll look at how a slow-processing request can affect other requests made to our current server implementation. Listing 21-10 implements handling a request -to */sleep* with a simulated slow response that will cause the server to sleep +to _/sleep_ with a simulated slow response that will cause the server to sleep for 5 seconds before responding. @@ -29,7 +29,7 @@ string literal values; `match` doesn’t do automatic referencing and dereferencing like the equality method does. The first arm is the same as the `if` block from Listing 21-9. The second arm -matches a request to */sleep*. When that request is received, the server will +matches a request to _/sleep_. When that request is received, the server will sleep for 5 seconds before rendering the successful HTML page. The third arm is the same as the `else` block from Listing 21-9. @@ -37,9 +37,9 @@ You can see how primitive our server is: real libraries would handle the recognition of multiple requests in a much less verbose way! Start the server using `cargo run`. Then open two browser windows: one for -*http://127.0.0.1:7878/* and the other for *http://127.0.0.1:7878/sleep*. If -you enter the */* URI a few times, as before, you’ll see it respond quickly. -But if you enter */sleep* and then load */*, you’ll see that */* waits until +_http://127.0.0.1:7878/_ and the other for _http://127.0.0.1:7878/sleep_. If +you enter the _/_ URI a few times, as before, you’ll see it respond quickly. +But if you enter _/sleep_ and then load _/_, you’ll see that _/_ waits until `sleep` has slept for its full 5 seconds before loading. There are multiple techniques we could use to avoid requests backing up behind @@ -48,7 +48,7 @@ implement is a thread pool. ### Improving Throughput with a Thread Pool -A *thread pool* is a group of spawned threads that are waiting and ready to +A _thread pool_ is a group of spawned threads that are waiting and ready to handle a task. When the program receives a new task, it assigns one of the threads in the pool to the task, and that thread will process the task. The remaining threads in the pool are available to handle any other tasks that come @@ -74,8 +74,8 @@ back up in the queue, but we’ve increased the number of long-running requests we can handle before reaching that point. This technique is just one of many ways to improve the throughput of a web -server. Other options you might explore are the *fork/join model*, the -*single-threaded async I/O model*, or the *multi-threaded async I/O model*. If +server. Other options you might explore are the _fork/join model_, the +_single-threaded async I/O model_, or the _multi-threaded async I/O model_. If you’re interested in this topic, you can read more about other solutions and try to implement them; with a low-level language like Rust, all of these options are possible. @@ -94,6 +94,7 @@ what we should change next to get the code to work. Before we do that, however, we’ll explore the technique we’re not going to use as a starting point. + #### Spawning a Thread for Each Request @@ -116,8 +117,8 @@ to handle each stream within the `for` loop. As you learned in Chapter 16, `thread::spawn` will create a new thread and then run the code in the closure in the new thread. If you run this code and load -*/sleep* in your browser, then */* in two more browser tabs, you’ll indeed see -that the requests to */* don’t have to wait for */sleep* to finish. However, as +_/sleep_ in your browser, then _/_ in two more browser tabs, you’ll indeed see +that the requests to _/_ don’t have to wait for _/sleep_ to finish. However, as we mentioned, this will eventually overwhelm the system because you’d be making new threads without any limit. @@ -126,6 +127,7 @@ where async and await really shine! Keep that in mind as we build the thread pool and think about how things would look different or the same with async. + #### Creating a Finite Number of Threads @@ -151,11 +153,12 @@ closure and gives it to a thread in the pool to run. This code won’t yet compile, but we’ll try so the compiler can guide us in how to fix it. + #### Building `ThreadPool` Using Compiler Driven Development -Make the changes in Listing 21-12 to *src/main.rs*, and then let’s use the +Make the changes in Listing 21-12 to _src/main.rs_, and then let’s use the compiler errors from `cargo check` to drive our development. Here is the first error we get: @@ -171,7 +174,7 @@ we change to a library crate, we could also use the separate thread pool library for any work we want to do using a thread pool, not just for serving web requests. -Create a *src/lib.rs* that contains the following, which is the simplest +Create a _src/lib.rs_ that contains the following, which is the simplest definition of a `ThreadPool` struct that we can have for now: @@ -182,8 +185,8 @@ definition of a `ThreadPool` struct that we can have for now: -Then edit *main.rs* file to bring `ThreadPool` into scope from the library -crate by adding the following code to the top of *src/main.rs*: +Then edit _main.rs_ file to bring `ThreadPool` into scope from the library +crate by adding the following code to the top of _src/main.rs_: @@ -293,10 +296,10 @@ yet! > Haskell and Rust, is “if the code compiles, it works.” But this saying is not > universally true. Our project compiles, but it does absolutely nothing! If we > were building a real, complete project, this would be a good time to start -> writing unit tests to check that the code compiles *and* has the behavior we +> writing unit tests to check that the code compiles _and_ has the behavior we > want. -Consider: what would be different here if we were going to execute a *future* +Consider: what would be different here if we were going to execute a _future_ instead of a closure? #### Validating the Number of Threads in `new` @@ -389,13 +392,13 @@ threads. Here, we’ll look at how we actually create threads. The standard library provides `thread::spawn` as a way to create threads, and `thread::spawn` expects to get some code the thread should run as soon as the thread is created. However, in our case, we want to create the threads and have -them *wait* for code that we’ll send later. The standard library’s +them _wait_ for code that we’ll send later. The standard library’s implementation of threads doesn’t include any way to do that; we have to implement it manually. We’ll implement this behavior by introducing a new data structure between the `ThreadPool` and the threads that will manage this new behavior. We’ll call -this data structure *Worker*, which is a common term in pooling +this data structure _Worker_, which is a common term in pooling implementations. The Worker picks up code that needs to be run and runs the code in the Worker’s thread. Think of people working in the kitchen at a restaurant: the workers wait until orders come in from customers, and then @@ -438,7 +441,7 @@ because it’s now holding `Worker` instances instead of `JoinHandle<()>` instances. We use the counter in the `for` loop as an argument to `Worker::new`, and we store each new `Worker` in the vector named `workers`. -External code (like our server in *src/main.rs*) doesn’t need to know the +External code (like our server in _src/main.rs_) doesn’t need to know the implementation details regarding using a `Worker` struct within `ThreadPool`, so we make the `Worker` struct and its `new` function private. The `Worker::new` function uses the `id` we give it and stores a `JoinHandle<()>` @@ -453,7 +456,7 @@ instance that is created by spawning a new thread using an empty closure. > [`spawn`][builder-spawn] method that returns `Result` instead. This code will compile and will store the number of `Worker` instances we -specified as an argument to `ThreadPool::new`. But we’re *still* not processing +specified as an argument to `ThreadPool::new`. But we’re _still_ not processing the closure that we get in `execute`. Let’s look at how to do that next. #### Sending Requests to Threads via Channels @@ -520,7 +523,7 @@ When we try to check this code, we get this error: The code is trying to pass `receiver` to multiple `Worker` instances. This won’t work, as you’ll recall from Chapter 16: the channel implementation that -Rust provides is multiple *producer*, single *consumer*. This means we can’t +Rust provides is multiple _producer_, single _consumer_. This means we can’t just clone the consuming end of the channel to fix this code. We also don’t want to send a message multiple times to multiple consumers; we want one list of messages with multiple workers such that each message gets processed once. @@ -576,7 +579,7 @@ reason we use `unwrap` is that we know the failure case won’t happen, but the compiler doesn’t know that. But we’re not quite done yet! In the worker, our closure being passed to -`thread::spawn` still only *references* the receiving end of the channel. +`thread::spawn` still only _references_ the receiving end of the channel. Instead, we need the closure to loop forever, asking the receiving end of the channel for a job and running the job when it gets one. Let’s make the change shown in Listing 21-20 to `Worker::new`. @@ -591,7 +594,7 @@ shown in Listing 21-20 to `Worker::new`. Here, we first call `lock` on the `receiver` to acquire the mutex, and then we call `unwrap` to panic on any errors. Acquiring a lock might fail if the mutex -is in a *poisoned* state, which can happen if some other thread panicked while +is in a _poisoned_ state, which can happen if some other thread panicked while holding the lock rather than releasing the lock. In this situation, calling `unwrap` to have this thread panic is the correct action to take. Feel free to change this `unwrap` to an `expect` with an error message that is meaningful to @@ -657,10 +660,10 @@ Worker 2 got a job; executing. Success! We now have a thread pool that executes connections asynchronously. There are never more than four threads created, so our system won’t get 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 +_/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 +> 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. @@ -700,10 +703,8 @@ let` (and `if let` and `match`) does not drop temporary values until the end of the associated block. In Listing 21-21, the lock remains held for the duration of the call to `job()`, meaning other workers cannot receive jobs. -[creating-type-synonyms-with-type-aliases]: -ch20-04-advanced-types.html#creating-type-synonyms-with-type-aliases +[creating-type-synonyms-with-type-aliases]: ch20-04-advanced-types.html#creating-type-synonyms-with-type-aliases [integer-types]: ch03-02-data-types.html#integer-types -[fn-traits]: -ch13-01-closures.html#moving-captured-values-out-of-the-closure-and-the-fn-traits +[fn-traits]: ch13-01-closures.html#moving-captured-values-out-of-the-closure-and-the-fn-traits [builder]: ../std/thread/struct.Builder.html [builder-spawn]: ../std/thread/struct.Builder.html#method.spawn diff --git a/rustbook-en/src/ch21-03-graceful-shutdown-and-cleanup.md b/rustbook-en/src/ch21-03-graceful-shutdown-and-cleanup.md index b60278240..36e85f32b 100644 --- a/rustbook-en/src/ch21-03-graceful-shutdown-and-cleanup.md +++ b/rustbook-en/src/ch21-03-graceful-shutdown-and-cleanup.md @@ -238,11 +238,11 @@ Here’s the full code for reference: We could do more here! If you want to continue enhancing this project, here are some ideas: -* Add more documentation to `ThreadPool` and its public methods. -* 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 +- Add more documentation to `ThreadPool` and its public methods. +- 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. diff --git a/rustbook-en/src/foreword.md b/rustbook-en/src/foreword.md index 2265e2714..f108b65a6 100644 --- a/rustbook-en/src/foreword.md +++ b/rustbook-en/src/foreword.md @@ -1,7 +1,7 @@ # Foreword It wasn’t always so clear, but the Rust programming language is fundamentally -about *empowerment*: no matter what kind of code you are writing now, Rust +about _empowerment_: no matter what kind of code you are writing now, Rust empowers you to reach farther, to program with confidence in a wider variety of domains than you did before. diff --git a/rustbook-en/src/title-page.md b/rustbook-en/src/title-page.md index daaf01a3d..730149320 100644 --- a/rustbook-en/src/title-page.md +++ b/rustbook-en/src/title-page.md @@ -1,7 +1,7 @@ # The Rust Programming Language -*by Steve Klabnik, Carol Nichols, and Chris Krycho, with contributions from the -Rust Community* +_by Steve Klabnik, Carol Nichols, and Chris Krycho, with contributions from the +Rust Community_ This version of the text assumes you’re using Rust 1.82.0 (released 2024-10-17) or later. See the [“Installation” section of Chapter 1][install] diff --git a/rustbook-en/style-guide.md b/rustbook-en/style-guide.md index 56677811f..04dc805ca 100644 --- a/rustbook-en/style-guide.md +++ b/rustbook-en/style-guide.md @@ -2,33 +2,33 @@ ## Prose -* Prefer title case for chapter/section headings, ex: `## Generating a Secret +- Prefer title case for chapter/section headings, ex: `## Generating a Secret Number` rather than `## Generating a secret number`. -* Prefer italics over single quotes when calling out a term, ex: `is an +- Prefer italics over single quotes when calling out a term, ex: `is an *associated function* of` rather than `is an ‘associated function’ of`. -* When talking about a method in prose, DO NOT include the parentheses, ex: +- When talking about a method in prose, DO NOT include the parentheses, ex: `read_line` rather than `read_line()`. -* Hard wrap at 80 chars -* Prefer not mixing code and not-code in one word, ex: ``Remember when we wrote +- Hard wrap at 80 chars +- Prefer not mixing code and not-code in one word, ex: ``Remember when we wrote `use std::io`?`` rather than ``Remember when we `use`d `std::io`?`` ## Code -* Add the file name before markdown blocks to make it clear which file we're +- Add the file name before markdown blocks to make it clear which file we're talking about, when applicable. -* When making changes to code, make it clear which parts of the code changed +- When making changes to code, make it clear which parts of the code changed and which stayed the same... not sure how to do this yet -* Split up long lines as appropriate to keep them under 80 chars if possible -* Use `bash` syntax highlighting for command line output code blocks +- Split up long lines as appropriate to keep them under 80 chars if possible +- Use `bash` syntax highlighting for command line output code blocks ## Links Once all the scripts are done: -* If a link shouldn't be printed, mark it to be ignored - * This includes all "Chapter XX" intra-book links, which *should* be links +- If a link shouldn't be printed, mark it to be ignored + - This includes all "Chapter XX" intra-book links, which _should_ be links for the HTML version -* Make intra-book links and stdlib API doc links relative so they work whether +- Make intra-book links and stdlib API doc links relative so they work whether the book is read offline or on docs.rust-lang.org -* Use markdown links and keep in mind that they will be changed into `text at +- Use markdown links and keep in mind that they will be changed into `text at *url*` in print, so word them in a way that it reads well in that format diff --git a/rustbook-en/theme/2018-edition.css b/rustbook-en/theme/2018-edition.css index b1dcf9364..2276ccbe3 100644 --- a/rustbook-en/theme/2018-edition.css +++ b/rustbook-en/theme/2018-edition.css @@ -1,9 +1,9 @@ span.caption { - font-size: .8em; - font-weight: 600; + font-size: 0.8em; + font-weight: 600; } span.caption code { - font-size: 0.875em; - font-weight: 400; + font-size: 0.875em; + font-weight: 400; } diff --git a/rustbook-en/theme/listing.css b/rustbook-en/theme/listing.css index 5998d39f3..40ae35a5f 100644 --- a/rustbook-en/theme/listing.css +++ b/rustbook-en/theme/listing.css @@ -1,8 +1,8 @@ figure.listing { - margin: 0; + margin: 0; } .listing figcaption { - font-size: .8em; - font-weight: 600; + font-size: 0.8em; + font-weight: 600; } diff --git a/rustbook-en/theme/semantic-notes.css b/rustbook-en/theme/semantic-notes.css index 7e68eb371..b6852a099 100644 --- a/rustbook-en/theme/semantic-notes.css +++ b/rustbook-en/theme/semantic-notes.css @@ -4,10 +4,10 @@ identical while updating the presentation. */ .note { - margin: 20px 0; - padding: 0 20px; - color: var(--fg); - background-color: var(--quote-bg); - border-block-start: 0.1em solid var(--quote-border); - border-block-end: 0.1em solid var(--quote-border); + margin: 20px 0; + padding: 0 20px; + color: var(--fg); + background-color: var(--quote-bg); + border-block-start: 0.1em solid var(--quote-border); + border-block-end: 0.1em solid var(--quote-border); }