diff --git a/.gitignore b/.gitignore index d88c0391ec..9a3cb242f1 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,7 @@ book po/messages.pot +.vscode/ + # Auto-generated files from macOS .DS_Store diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 660653908b..21c4d4567b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ abide by the [Rust code of conduct], which you can find at that link or in the ## License -RBE is dual licenced under the MIT and Apache 2.0 licenses, and so are all +RBE is dual licensed under the MIT and Apache 2.0 licenses, and so are all contributions. Please see the [`LICENSE-MIT`] and [`LICENSE-APACHE`] files in this directory for more details. @@ -55,7 +55,7 @@ $ mdbook build **The following warnings can be ignored safely.** -``` +```text [WARN] (mdbook::preprocess::cmd): The command wasn't found, is the "gettext" preprocessor installed? [WARN] (mdbook::preprocess::cmd): Command: mdbook-gettext ``` diff --git a/README.md b/README.md index 68a8714a3b..829d2277b2 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ read all content offline, however! **The following warnings can be ignored safely.** -``` +```text [WARN] (mdbook::preprocess::cmd): The command wasn't found, is the "gettext" preprocessor installed? [WARN] (mdbook::preprocess::cmd): Command: mdbook-gettext ``` diff --git a/TRANSLATING.md b/TRANSLATING.md index 6e4590cffd..16453bfdc3 100644 --- a/TRANSLATING.md +++ b/TRANSLATING.md @@ -37,7 +37,7 @@ MDBOOK_OUTPUT='{"xgettext": {"pot-file": "messages.pot"}}' \ msginit -i po/messages.pot -l xx -o po/xx.po ``` -#### Updating the exising translation resource +#### Updating the existing translation resource ```bash msgmerge --update po/xx.po po/messages.pot diff --git a/src/attribute.md b/src/attribute.md index 4d0ec63d81..195b6e1409 100644 --- a/src/attribute.md +++ b/src/attribute.md @@ -17,11 +17,12 @@ can be used to/for: Attributes look like `#[outer_attribute]` or `#![inner_attribute]`, with the difference between them being where they apply. -- `#[outer_attribute]` applies to the [item][item] immediately +* `#[outer_attribute]` applies to the [item][item] immediately following it. Some examples of items are: a function, a module declaration, a constant, a structure, an enum. Here is an example where attribute `#[derive(Debug)]` applies to the struct `Rectangle`: + ```rust #[derive(Debug)] struct Rectangle { @@ -30,11 +31,12 @@ with the difference between them being where they apply. } ``` -- `#![inner_attribute]` applies to the enclosing [item][item] (typically a +* `#![inner_attribute]` applies to the enclosing [item][item] (typically a module or a crate). In other words, this attribute is interpreted as applying to the entire scope in which it's placed. Here is an example where `#![allow(unused_variables)]` applies to the whole crate (if placed in `main.rs`): + ```rust #![allow(unused_variables)] diff --git a/src/cargo/deps.md b/src/cargo/deps.md index 85f223f98a..0a1c498d30 100644 --- a/src/cargo/deps.md +++ b/src/cargo/deps.md @@ -91,6 +91,5 @@ rebuilds what it has not already built, similar to `make`). Voila! That's all there is to it! - [manifest]: https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html diff --git a/src/cargo/test.md b/src/cargo/test.md index a86b8f831d..5f53acf2dc 100644 --- a/src/cargo/test.md +++ b/src/cargo/test.md @@ -2,8 +2,7 @@ As we know testing is integral to any piece of software! Rust has first-class support for unit and integration testing ([see this -chapter](https://doc.rust-lang.org/book/ch11-00-testing.html) in -TRPL). +chapter](https://doc.rust-lang.org/book/ch11-00-testing.html) in TRPL). From the testing chapters linked above, we see how to write unit tests and integration tests. Organizationally, we can place unit tests in the modules they @@ -20,13 +19,13 @@ foo └── my_other_test.rs ``` -Each file in `tests` is a separate +Each file in `tests` is a separate [integration test](https://doc.rust-lang.org/book/ch11-03-test-organization.html#integration-tests), i.e. a test that is meant to test your library as if it were being called from a dependent crate. -The [Testing][testing] chapter elaborates on the three different testing styles: -[Unit][unit_testing], [Doc][doc_testing], and [Integration][integration_testing]. +The [Testing][testing] chapter elaborates on the three different testing styles: +[Unit][unit_testing], [Doc][doc_testing], and [Integration][integration_testing]. `cargo` naturally provides an easy way to run all of your tests! @@ -71,7 +70,7 @@ test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out ``` One word of caution: Cargo may run multiple tests concurrently, so make sure -that they don't race with each other. +that they don't race with each other. One example of this concurrency causing issues is if two tests output to a file, such as below: @@ -120,6 +119,7 @@ mod tests { ``` Although the intent is to get the following: + ```shell $ cat ferris.txt Ferris @@ -133,7 +133,9 @@ Corro Corro Corro ``` + What actually gets put into `ferris.txt` is this: + ```shell $ cargo test test_file && cat ferris.txt Corro diff --git a/src/compatibility.md b/src/compatibility.md index 00424ceb22..a33f88efd8 100644 --- a/src/compatibility.md +++ b/src/compatibility.md @@ -1,6 +1,6 @@ # Compatibility -The Rust language is fastly evolving, and because of this certain compatibility +The Rust language is evolving rapidly, and because of this certain compatibility issues can arise, despite efforts to ensure forwards-compatibility wherever possible. diff --git a/src/conversion/from_into.md b/src/conversion/from_into.md index d65e75fba3..9ab5da9da8 100644 --- a/src/conversion/from_into.md +++ b/src/conversion/from_into.md @@ -73,8 +73,8 @@ fn main() { `From` and `Into` are designed to be complementary. We do not need to provide an implementation for both traits. -If you have implemented the `From` trait for your type, `Into` will call it -when necessary. Note, however, that the converse is not true: implementing `Into` for your type will not automatically provide it with an implementation of `From`. +If you have implemented the `From` trait for your type, `Into` will call it +when necessary. Note, however, that the converse is not true: implementing `Into` for your type will not automatically provide it with an implementation of `From`. ```rust,editable use std::convert::From; diff --git a/src/conversion/string.md b/src/conversion/string.md index d6958d47ad..7b8726ceda 100644 --- a/src/conversion/string.md +++ b/src/conversion/string.md @@ -4,7 +4,7 @@ To convert any type to a `String` is as simple as implementing the [`ToString`] trait for the type. Rather than doing so directly, you should implement the -[`fmt::Display`][Display] trait which automagically provides [`ToString`] and +[`fmt::Display`][Display] trait which automatically provides [`ToString`] and also allows printing the type as discussed in the section on [`print!`][print]. ```rust,editable diff --git a/src/crates/lib.md b/src/crates/lib.md index 729ccb8903..b85e435532 100644 --- a/src/crates/lib.md +++ b/src/crates/lib.md @@ -31,4 +31,4 @@ crate file, but this default name can be overridden by passing the `--crate-name` option to `rustc` or by using the [`crate_name` attribute][crate-name]. -[crate-name]: ../attribute/crate.md \ No newline at end of file +[crate-name]: ../attribute/crate.md diff --git a/src/crates/using_lib.md b/src/crates/using_lib.md index 8bd0feb945..3195f170c1 100644 --- a/src/crates/using_lib.md +++ b/src/crates/using_lib.md @@ -1,6 +1,6 @@ # Using a Library -To link a crate to this new library you may use `rustc`'s `--extern` flag. All +To link a crate to this new library you may use `rustc`'s `--extern` flag. All of its items will then be imported under a module named the same as the library. This module generally behaves the same way as any other module. diff --git a/src/custom_types.md b/src/custom_types.md index 20a408b2e0..2a58c4a3ad 100644 --- a/src/custom_types.md +++ b/src/custom_types.md @@ -5,4 +5,4 @@ Rust custom data types are formed mainly through the two keywords: * `struct`: define a structure * `enum`: define an enumeration -Constants can also be created via the `const` and `static` keywords. \ No newline at end of file +Constants can also be created via the `const` and `static` keywords. diff --git a/src/custom_types/enum/enum_use.md b/src/custom_types/enum/enum_use.md index 561b3f5700..80a86e1400 100644 --- a/src/custom_types/enum/enum_use.md +++ b/src/custom_types/enum/enum_use.md @@ -44,7 +44,7 @@ fn main() { ### See also: -[`match`][match] and [`use`][use] +[`match`][match] and [`use`][use] [use]: ../../mod/use.md [match]: ../../flow_control/match.md diff --git a/src/error/abort_unwind.md b/src/error/abort_unwind.md index 2afae98824..e17856677e 100644 --- a/src/error/abort_unwind.md +++ b/src/error/abort_unwind.md @@ -1,7 +1,6 @@ # `abort` and `unwind` -The previous section illustrates the error handling mechanism `panic`. Different code paths can be conditionally compiled based on the panic setting. The current values available are `unwind` and `abort`. - +The previous section illustrates the error handling mechanism `panic`. Different code paths can be conditionally compiled based on the panic setting. The current values available are `unwind` and `abort`. Building on the prior lemonade example, we explicitly use the panic strategy to exercise different lines of code. @@ -57,4 +56,3 @@ The panic strategy can be set from the command line by using `abort` or `unwind` ```console rustc lemonade.rs -C panic=abort ``` - diff --git a/src/error/multiple_error_types/define_error_type.md b/src/error/multiple_error_types/define_error_type.md index 4c374276dc..10efa82b85 100644 --- a/src/error/multiple_error_types/define_error_type.md +++ b/src/error/multiple_error_types/define_error_type.md @@ -8,11 +8,11 @@ Rust allows us to define our own error types. In general, a "good" error type: * Represents different errors with the same type * Presents nice error messages to the user * Is easy to compare with other types - - Good: `Err(EmptyVec)` - - Bad: `Err("Please use a vector with at least one element".to_owned())` + * Good: `Err(EmptyVec)` + * Bad: `Err("Please use a vector with at least one element".to_owned())` * Can hold information about the error - - Good: `Err(BadChar(c, position))` - - Bad: `Err("+ cannot be used here".to_owned())` + * Good: `Err(BadChar(c, position))` + * Bad: `Err("+ cannot be used here".to_owned())` * Composes well with other errors ```rust,editable diff --git a/src/error/multiple_error_types/wrap_error.md b/src/error/multiple_error_types/wrap_error.md index a72a9370e5..71f62626ff 100644 --- a/src/error/multiple_error_types/wrap_error.md +++ b/src/error/multiple_error_types/wrap_error.md @@ -92,7 +92,6 @@ for you. [`From::from`][from] and [`Enums`][enums] - [`Crates for handling errors`][crates-errors] [from]: https://doc.rust-lang.org/std/convert/trait.From.html diff --git a/src/error/option_unwrap.md b/src/error/option_unwrap.md index 5192767fcc..26df9b8841 100644 --- a/src/error/option_unwrap.md +++ b/src/error/option_unwrap.md @@ -5,7 +5,7 @@ We told our program to `panic` if we drink a sugary lemonade. But what if we expect _some_ drink but don't receive one? That case would be just as bad, so it needs to be handled! -We *could* test this against the null string (`""`) as we do with a lemonade. +We _could_ test this against the null string (`""`) as we do with a lemonade. Since we're using Rust, let's instead have the compiler point out cases where there's no drink. diff --git a/src/error/option_unwrap/and_then.md b/src/error/option_unwrap/and_then.md index 78c0940150..7dee272425 100644 --- a/src/error/option_unwrap/and_then.md +++ b/src/error/option_unwrap/and_then.md @@ -1,14 +1,14 @@ # Combinators: `and_then` -`map()` was described as a chainable way to simplify `match` statements. -However, using `map()` on a function that returns an `Option` results -in the nested `Option>`. Chaining multiple calls together can -then become confusing. That's where another combinator called `and_then()`, +`map()` was described as a chainable way to simplify `match` statements. +However, using `map()` on a function that returns an `Option` results +in the nested `Option>`. Chaining multiple calls together can +then become confusing. That's where another combinator called `and_then()`, known in some languages as flatmap, comes in. `and_then()` calls its function input with the wrapped value and returns the result. If the `Option` is `None`, then it returns `None` instead. -In the following example, `cookable_v3()` results in an `Option`. +In the following example, `cookable_v3()` results in an `Option`. Using `map()` instead of `and_then()` would have given an `Option>`, which is an invalid type for `eat()`. diff --git a/src/error/option_unwrap/defaults.md b/src/error/option_unwrap/defaults.md index e439f5cd41..e749c1492a 100644 --- a/src/error/option_unwrap/defaults.md +++ b/src/error/option_unwrap/defaults.md @@ -1,10 +1,11 @@ # Unpacking options and defaults There is more than one way to unpack an `Option` and fall back on a default if it is `None`. To choose the one that meets our needs, we need to consider the following: + * do we need eager or lazy evaluation? * do we need to keep the original empty value intact, or modify it in place? -## `or()` is chainable, evaluates eagerly, keeps empty value intact +## `or()` is chainable, evaluates eagerly, keeps empty value intact `or()`is chainable and eagerly evaluates its argument, as is shown in the following example. Note that because `or`'s arguments are evaluated eagerly, the variable passed to `or` is moved. @@ -29,7 +30,7 @@ fn main() { } ``` -## `or_else()` is chainable, evaluates lazily, keeps empty value intact +## `or_else()` is chainable, evaluates lazily, keeps empty value intact Another alternative is to use `or_else`, which is also chainable, and evaluates lazily, as is shown in the following example: @@ -57,7 +58,7 @@ fn main() { } ``` -## `get_or_insert()` evaluates eagerly, modifies empty value in place +## `get_or_insert()` evaluates eagerly, modifies empty value in place To make sure that an `Option` contains a value, we can use `get_or_insert` to modify it in place with a fallback value, as is shown in the following example. Note that `get_or_insert` eagerly evaluates its parameter, so variable `apple` is moved: @@ -78,9 +79,10 @@ fn main() { } ``` -## `get_or_insert_with()` evaluates lazily, modifies empty value in place +## `get_or_insert_with()` evaluates lazily, modifies empty value in place Instead of explicitly providing a value to fall back on, we can pass a closure to `get_or_insert_with`, as follows: + ```rust,editable #[derive(Debug)] enum Fruit { Apple, Orange, Banana, Kiwi, Lemon } diff --git a/src/error/option_unwrap/map.md b/src/error/option_unwrap/map.md index 6682e317a9..c063115d52 100644 --- a/src/error/option_unwrap/map.md +++ b/src/error/option_unwrap/map.md @@ -1,12 +1,12 @@ # Combinators: `map` -`match` is a valid method for handling `Option`s. However, you may -eventually find heavy usage tedious, especially with operations only valid -with an input. In these cases, [combinators][combinators] can be used to +`match` is a valid method for handling `Option`s. However, you may +eventually find heavy usage tedious, especially with operations only valid +with an input. In these cases, [combinators][combinators] can be used to manage control flow in a modular fashion. -`Option` has a built in method called `map()`, a combinator for the simple -mapping of `Some -> Some` and `None -> None`. Multiple `map()` calls can be +`Option` has a built in method called `map()`, a combinator for the simple +mapping of `Some -> Some` and `None -> None`. Multiple `map()` calls can be chained together for even more flexibility. In the following example, `process()` replaces all functions previous diff --git a/src/error/option_unwrap/question_mark.md b/src/error/option_unwrap/question_mark.md index 04de93cc76..a8483567d3 100644 --- a/src/error/option_unwrap/question_mark.md +++ b/src/error/option_unwrap/question_mark.md @@ -7,8 +7,8 @@ function is being executed and return `None`. ```rust,editable fn next_birthday(current_age: Option) -> Option { - // If `current_age` is `None`, this returns `None`. - // If `current_age` is `Some`, the inner `u8` value + 1 + // If `current_age` is `None`, this returns `None`. + // If `current_age` is `Some`, the inner `u8` value + 1 // gets assigned to `next_age` let next_age: u8 = current_age? + 1; Some(format!("Next year I will be {}", next_age)) diff --git a/src/error/result.md b/src/error/result.md index d779bfdad1..4eab431290 100644 --- a/src/error/result.md +++ b/src/error/result.md @@ -75,7 +75,6 @@ fn main() -> Result<(), ParseIntError> { } ``` - [option]: https://doc.rust-lang.org/std/option/enum.Option.html [result]: https://doc.rust-lang.org/std/result/enum.Result.html [parse]: https://doc.rust-lang.org/std/primitive.str.html#method.parse diff --git a/src/error/result/enter_question_mark.md b/src/error/result/enter_question_mark.md index ca954b1ac2..2b86862b15 100644 --- a/src/error/result/enter_question_mark.md +++ b/src/error/result/enter_question_mark.md @@ -69,7 +69,6 @@ fn main() { } ``` - [^†]: See [re-enter ?][re_enter_?] for more details. [re_enter_?]: ../multiple_error_types/reenter_question_mark.md diff --git a/src/flow_control/let_else.md b/src/flow_control/let_else.md index bf1a53bde0..2d07de740a 100644 --- a/src/flow_control/let_else.md +++ b/src/flow_control/let_else.md @@ -1,12 +1,10 @@ # let-else - > 🛈 stable since: rust 1.65 > > 🛈 you can target specific edition by compiling like this > `rustc --edition=2021 main.rs` - With `let`-`else`, a refutable pattern can match and bind variables in the surrounding scope like a normal `let`, or else diverge (e.g. `break`, `return`, `panic!`) when the pattern doesn't match. @@ -58,8 +56,7 @@ patterns with an unfortunate bit of repetition and an outer `let`: [option][option], [match][match], [if let][if_let] and the [let-else RFC][let_else_rfc]. - [match]: ./match.md [if_let]: ./if_let.md [let_else_rfc]: https://rust-lang.github.io/rfcs/3137-let-else.html -[option]: ../std/option.md \ No newline at end of file +[option]: ../std/option.md diff --git a/src/flow_control/loop.md b/src/flow_control/loop.md index 4a2405b7bf..93350c8412 100644 --- a/src/flow_control/loop.md +++ b/src/flow_control/loop.md @@ -33,4 +33,4 @@ fn main() { } } } -``` \ No newline at end of file +``` diff --git a/src/flow_control/match/binding.md b/src/flow_control/match/binding.md index ccbb7c2add..7c8ecfe016 100644 --- a/src/flow_control/match/binding.md +++ b/src/flow_control/match/binding.md @@ -47,6 +47,7 @@ fn main() { ``` ### See also: + [`functions`][functions], [`enums`][enums] and [`Option`][option] [functions]: ../../fn.md diff --git a/src/flow_control/match/destructuring.md b/src/flow_control/match/destructuring.md index 74df9fe6c2..763d1f85a0 100644 --- a/src/flow_control/match/destructuring.md +++ b/src/flow_control/match/destructuring.md @@ -8,7 +8,6 @@ A `match` block can destructure items in a variety of ways. * [Destructuring Pointers][refs] * [Destructuring Structures][struct] - [enum]: destructuring/destructure_enum.md [refs]: destructuring/destructure_pointers.md [struct]: destructuring/destructure_structures.md diff --git a/src/flow_control/match/destructuring/destructure_pointers.md b/src/flow_control/match/destructuring/destructure_pointers.md index a48aeaa6e5..4d22bba37c 100644 --- a/src/flow_control/match/destructuring/destructure_pointers.md +++ b/src/flow_control/match/destructuring/destructure_pointers.md @@ -4,8 +4,8 @@ For pointers, a distinction needs to be made between destructuring and dereferencing as they are different concepts which are used differently from languages like C/C++. - * Dereferencing uses `*` - * Destructuring uses `&`, `ref`, and `ref mut` +* Dereferencing uses `*` +* Destructuring uses `&`, `ref`, and `ref mut` ```rust,editable fn main() { diff --git a/src/fn/closures.md b/src/fn/closures.md index 379a52e43e..16669fb3b9 100644 --- a/src/fn/closures.md +++ b/src/fn/closures.md @@ -13,6 +13,7 @@ However, both input and return types *can* be inferred and input variable names *must* be specified. Other characteristics of closures include: + * using `||` instead of `()` around input variables. * optional body delimitation (`{}`) for a single line expression (mandatory otherwise). * the ability to capture the outer environment variables. diff --git a/src/fn/closures/closure_examples.md b/src/fn/closures/closure_examples.md index 2455523ad9..627783e4e9 100644 --- a/src/fn/closures/closure_examples.md +++ b/src/fn/closures/closure_examples.md @@ -1,3 +1,3 @@ # Examples in `std` -This section contains a few examples of using closures from the `std` library. \ No newline at end of file +This section contains a few examples of using closures from the `std` library. diff --git a/src/fn/closures/closure_examples/iter_find.md b/src/fn/closures/closure_examples/iter_find.md index c3605d784b..62fc57ea9e 100644 --- a/src/fn/closures/closure_examples/iter_find.md +++ b/src/fn/closures/closure_examples/iter_find.md @@ -1,7 +1,7 @@ # Searching through iterators -`Iterator::find` is a function which iterates over an iterator and searches for the -first value which satisfies some condition. If none of the values satisfy the +`Iterator::find` is a function which iterates over an iterator and searches for the +first value which satisfies some condition. If none of the values satisfy the condition, it returns `None`. Its signature: ```rust,ignore diff --git a/src/fn/diverging.md b/src/fn/diverging.md index 99e3a235a1..caef7af8fb 100644 --- a/src/fn/diverging.md +++ b/src/fn/diverging.md @@ -38,8 +38,8 @@ fn main() { ``` Although this might seem like an abstract concept, it is actually very useful and -often handy. The main advantage of this type is that it can be cast to any other -type, making it versatile in situations where an exact type is required, such as +often handy. The main advantage of this type is that it can be cast to any other +type, making it versatile in situations where an exact type is required, such as in match branches. This flexibility allows us to write code like this: ```rust diff --git a/src/generics.md b/src/generics.md index 2cfd54ffb3..f0ddee859e 100644 --- a/src/generics.md +++ b/src/generics.md @@ -2,15 +2,15 @@ *Generics* is the topic of generalizing types and functionalities to broader cases. This is extremely useful for reducing code duplication in many ways, -but can call for rather involved syntax. Namely, being generic requires -taking great care to specify over which types a generic type -is actually considered valid. The simplest and most common use of generics +but can call for rather involved syntax. Namely, being generic requires +taking great care to specify over which types a generic type +is actually considered valid. The simplest and most common use of generics is for type parameters. A type parameter is specified as generic by the use of angle brackets and upper [camel case][camelcase]: ``. "Generic type parameters" are typically represented as ``. In Rust, "generic" also describes anything that -accepts one or more generic type parameters ``. Any type specified as a +accepts one or more generic type parameters ``. Any type specified as a generic type parameter is generic, and everything else is concrete (non-generic). For example, defining a *generic function* named `foo` that takes an argument @@ -20,8 +20,8 @@ For example, defining a *generic function* named `foo` that takes an argument fn foo(arg: T) { ... } ``` -Because `T` has been specified as a generic type parameter using ``, it -is considered generic when used here as `(arg: T)`. This is the case even if `T` +Because `T` has been specified as a generic type parameter using ``, it +is considered generic when used here as `(arg: T)`. This is the case even if `T` has previously been defined as a `struct`. This example shows some of the syntax in action: diff --git a/src/generics/assoc_items.md b/src/generics/assoc_items.md index 7a3871bb76..92ab9c3593 100644 --- a/src/generics/assoc_items.md +++ b/src/generics/assoc_items.md @@ -1,10 +1,10 @@ # Associated items "Associated Items" refers to a set of rules pertaining to [`item`][items]s -of various types. It is an extension to `trait` generics, and allows +of various types. It is an extension to `trait` generics, and allows `trait`s to internally define new items. -One such item is called an *associated type*, providing simpler usage +One such item is called an *associated type*, providing simpler usage patterns when the `trait` is generic over its container type. ### See also: diff --git a/src/generics/assoc_items/the_problem.md b/src/generics/assoc_items/the_problem.md index bc6f7636b1..1b58dfd5cd 100644 --- a/src/generics/assoc_items/the_problem.md +++ b/src/generics/assoc_items/the_problem.md @@ -3,13 +3,13 @@ A `trait` that is generic over its container type has type specification requirements - users of the `trait` *must* specify all of its generic types. -In the example below, the `Contains` `trait` allows the use of the generic -types `A` and `B`. The trait is then implemented for the `Container` type, +In the example below, the `Contains` `trait` allows the use of the generic +types `A` and `B`. The trait is then implemented for the `Container` type, specifying `i32` for `A` and `B` so that it can be used with `fn difference()`. -Because `Contains` is generic, we are forced to explicitly state *all* of the -generic types for `fn difference()`. In practice, we want a way to express that -`A` and `B` are determined by the *input* `C`. As you will see in the next +Because `Contains` is generic, we are forced to explicitly state *all* of the +generic types for `fn difference()`. In practice, we want a way to express that +`A` and `B` are determined by the *input* `C`. As you will see in the next section, associated types provide exactly that capability. ```rust,editable diff --git a/src/generics/assoc_items/types.md b/src/generics/assoc_items/types.md index 3173704686..dbf6d789b4 100644 --- a/src/generics/assoc_items/types.md +++ b/src/generics/assoc_items/types.md @@ -1,6 +1,6 @@ # Associated types -The use of "Associated types" improves the overall readability of code +The use of "Associated types" improves the overall readability of code by moving inner types locally into a trait as *output* types. Syntax for the `trait` definition is as follows: diff --git a/src/generics/bounds.md b/src/generics/bounds.md index 86e54e670c..a3913f6b02 100644 --- a/src/generics/bounds.md +++ b/src/generics/bounds.md @@ -23,7 +23,7 @@ struct S(T); let s = S(vec![1]); ``` -Another effect of bounding is that generic instances are allowed to access the +Another effect of bounding is that generic instances are allowed to access the [methods] of traits specified in the bounds. For example: ```rust,editable diff --git a/src/generics/gen_fn.md b/src/generics/gen_fn.md index 264057687d..f1985fff8f 100644 --- a/src/generics/gen_fn.md +++ b/src/generics/gen_fn.md @@ -3,9 +3,9 @@ The same set of rules can be applied to functions: a type `T` becomes generic when preceded by ``. -Using generic functions sometimes requires explicitly specifying type -parameters. This may be the case if the function is called where the return type -is generic, or if the compiler doesn't have enough information to infer +Using generic functions sometimes requires explicitly specifying type +parameters. This may be the case if the function is called where the return type +is generic, or if the compiler doesn't have enough information to infer the necessary type parameters. A function call with explicitly specified type parameters looks like: diff --git a/src/generics/impl.md b/src/generics/impl.md index 69554316e0..e39ed9360c 100644 --- a/src/generics/impl.md +++ b/src/generics/impl.md @@ -49,7 +49,6 @@ fn main() { [functions returning references][fn], [`impl`][methods], and [`struct`][structs] - [fn]: ../scope/lifetime/fn.md [methods]: ../fn/methods.md [specialization_plans]: https://blog.rust-lang.org/2015/05/11/traits.html#the-future diff --git a/src/generics/new_types.md b/src/generics/new_types.md index a879ddb64c..010c1ff416 100644 --- a/src/generics/new_types.md +++ b/src/generics/new_types.md @@ -41,6 +41,7 @@ fn main() { Uncomment the last print statement to observe that the type supplied must be `Years`. To obtain the `newtype`'s value as the base type, you may use the tuple or destructuring syntax like so: + ```rust, editable struct Years(i64); @@ -56,4 +57,3 @@ fn main() { [`structs`][struct] [struct]: ../custom_types/structs.md - diff --git a/src/generics/where.md b/src/generics/where.md index f35f03f928..08e073497a 100644 --- a/src/generics/where.md +++ b/src/generics/where.md @@ -1,8 +1,8 @@ # Where clauses A bound can also be expressed using a `where` clause immediately -before the opening `{`, rather than at the type's first mention. -Additionally, `where` clauses can apply bounds to arbitrary types, +before the opening `{`, rather than at the type's first mention. +Additionally, `where` clauses can apply bounds to arbitrary types, rather than just to type parameters. Some cases that a `where` clause is useful: @@ -18,7 +18,7 @@ impl MyTrait for YourType where D: TraitE + TraitF {} ``` -* When using a `where` clause is more expressive than using normal syntax. +* When using a `where` clause is more expressive than using normal syntax. The `impl` in this example cannot be directly expressed without a `where` clause: ```rust,editable diff --git a/src/hello/print/print_debug.md b/src/hello/print/print_debug.md index 03b1975ee3..715366adf4 100644 --- a/src/hello/print/print_debug.md +++ b/src/hello/print/print_debug.md @@ -81,4 +81,3 @@ and [`struct`][structs] [derive]: ../../trait/derive.md [fmt]: https://doc.rust-lang.org/std/fmt/ [structs]: ../../custom_types/structs.md - diff --git a/src/index.md b/src/index.md index e42c196d1f..51216fc36a 100644 --- a/src/index.md +++ b/src/index.md @@ -1,12 +1,12 @@ # Rust by Example [Rust][rust] is a modern systems programming language focusing on safety, speed, -and concurrency. It accomplishes these goals by being memory safe without using +and concurrency. It accomplishes these goals by being memory safe without using garbage collection. Rust by Example (RBE) is a collection of runnable examples that illustrate various Rust concepts and standard libraries. To get even more out of these examples, don't forget -to [install Rust locally][install] and check out the [official docs][std]. +to [install Rust locally][install] and check out the [official docs][std]. Additionally for the curious, you can also [check out the source code for this site][home]. Now let's begin! @@ -59,7 +59,6 @@ Now let's begin! - [Meta](meta.md) - Documentation, Benchmarking. - [rust]: https://www.rust-lang.org/ [install]: https://www.rust-lang.org/tools/install [std]: https://doc.rust-lang.org/std/ diff --git a/src/macros.md b/src/macros.md index 14ea15e9bd..169d2e4cd2 100644 --- a/src/macros.md +++ b/src/macros.md @@ -1,4 +1,4 @@ -# macro_rules! +# `macro_rules!` Rust provides a powerful macro system that allows metaprogramming. As you've seen in previous chapters, macros look like functions, except that their name diff --git a/src/macros/overload.md b/src/macros/overload.md index 84d341a56a..090af6fe4b 100644 --- a/src/macros/overload.md +++ b/src/macros/overload.md @@ -1,6 +1,6 @@ # Overload -Macros can be overloaded to accept different combinations of arguments. +Macros can be overloaded to accept different combinations of arguments. In that regard, `macro_rules!` can work similarly to a match block: ```rust,editable @@ -28,4 +28,4 @@ fn main() { test!(1i32 + 1 == 2i32; and 2i32 * 2 == 4i32); test!(true; or false); } -``` \ No newline at end of file +``` diff --git a/src/meta/playground.md b/src/meta/playground.md index 30b87e896b..8bcbc4d1b4 100644 --- a/src/meta/playground.md +++ b/src/meta/playground.md @@ -39,7 +39,7 @@ button that says "Run", which opens the code sample up in a new tab in Rust Playground. This feature is enabled if you use the `#[doc]` attribute called [`html_playground_url`][html-playground-url]. -``` +```text #![doc(html_playground_url = "https://play.rust-lang.org/")] //! ``` //! println!("Hello World"); diff --git a/src/mod.md b/src/mod.md index f9a1183486..5066007d82 100644 --- a/src/mod.md +++ b/src/mod.md @@ -5,4 +5,4 @@ code in logical units (modules), and manage visibility (public/private) between them. A module is a collection of items: functions, structs, traits, `impl` blocks, -and even other modules. \ No newline at end of file +and even other modules. diff --git a/src/mod/struct_visibility.md b/src/mod/struct_visibility.md index 8641a72645..118ce1e641 100644 --- a/src/mod/struct_visibility.md +++ b/src/mod/struct_visibility.md @@ -1,8 +1,8 @@ # Struct visibility -Structs have an extra level of visibility with their fields. The visibility -defaults to private, and can be overridden with the `pub` modifier. This -visibility only matters when a struct is accessed from outside the module +Structs have an extra level of visibility with their fields. The visibility +defaults to private, and can be overridden with the `pub` modifier. This +visibility only matters when a struct is accessed from outside the module where it is defined, and has the goal of hiding information (encapsulation). ```rust,editable diff --git a/src/scope.md b/src/scope.md index ac70132781..47bf5a146e 100644 --- a/src/scope.md +++ b/src/scope.md @@ -1,5 +1,5 @@ # Scoping rules Scopes play an important part in ownership, borrowing, and lifetimes. -That is, they indicate to the compiler when borrows are valid, when -resources can be freed, and when variables are created or destroyed. \ No newline at end of file +That is, they indicate to the compiler when borrows are valid, when +resources can be freed, and when variables are created or destroyed. diff --git a/src/scope/borrow.md b/src/scope/borrow.md index ba1c93fcae..c80a4dded8 100644 --- a/src/scope/borrow.md +++ b/src/scope/borrow.md @@ -4,7 +4,7 @@ Most of the time, we'd like to access data without taking ownership over it. To accomplish this, Rust uses a *borrowing* mechanism. Instead of passing objects by value (`T`), objects can be passed by reference (`&T`). -The compiler statically guarantees (via its borrow checker) that references +The compiler statically guarantees (via its borrow checker) that references *always* point to valid objects. That is, while references to an object exist, the object cannot be destroyed. diff --git a/src/scope/borrow/mut.md b/src/scope/borrow/mut.md index 62119bb483..f0bd108cf4 100644 --- a/src/scope/borrow/mut.md +++ b/src/scope/borrow/mut.md @@ -1,8 +1,8 @@ # Mutability -Mutable data can be mutably borrowed using `&mut T`. This is called +Mutable data can be mutably borrowed using `&mut T`. This is called a *mutable reference* and gives read/write access to the borrower. -In contrast, `&T` borrows the data via an immutable reference, and +In contrast, `&T` borrows the data via an immutable reference, and the borrower can read the data but not modify it: ```rust,editable,ignore,mdbook-runnable @@ -54,6 +54,7 @@ fn main() { ``` ### See also: + [`static`][static] [static]: ../lifetime/static_lifetime.md diff --git a/src/scope/borrow/ref.md b/src/scope/borrow/ref.md index 3c035f64c0..e17d679e1a 100644 --- a/src/scope/borrow/ref.md +++ b/src/scope/borrow/ref.md @@ -1,7 +1,7 @@ # The ref pattern When doing pattern matching or destructuring via the `let` binding, the `ref` -keyword can be used to take references to the fields of a struct/tuple. The +keyword can be used to take references to the fields of a struct/tuple. The example below shows a few instances where this can be useful: ```rust,editable @@ -54,4 +54,4 @@ fn main() { println!("tuple is {:?}", mutable_tuple); } -``` \ No newline at end of file +``` diff --git a/src/scope/lifetime/explicit.md b/src/scope/lifetime/explicit.md index 68d144a82c..61ef3876f4 100644 --- a/src/scope/lifetime/explicit.md +++ b/src/scope/lifetime/explicit.md @@ -2,18 +2,18 @@ The borrow checker uses explicit lifetime annotations to determine how long references should be valid. In cases where lifetimes are not -elided[^1], Rust requires explicit annotations to determine what the -lifetime of a reference should be. The syntax for explicitly annotating -a lifetime uses an apostrophe character as follows: +elided[^1], Rust requires explicit annotations to determine what the +lifetime of a reference should be. The syntax for explicitly annotating +a lifetime uses an apostrophe character as follows: ```rust,ignore foo<'a> // `foo` has a lifetime parameter `'a` ``` -Similar to [closures][anonymity], using lifetimes requires generics. -Additionally, this lifetime syntax indicates that the lifetime of `foo` -may not exceed that of `'a`. Explicit annotation of a type has the form +Similar to [closures][anonymity], using lifetimes requires generics. +Additionally, this lifetime syntax indicates that the lifetime of `foo` +may not exceed that of `'a`. Explicit annotation of a type has the form `&'a T` where `'a` has already been introduced. In cases with multiple lifetimes, the syntax is similar: diff --git a/src/scope/lifetime/fn.md b/src/scope/lifetime/fn.md index 095f84b6ec..c863f09c0b 100644 --- a/src/scope/lifetime/fn.md +++ b/src/scope/lifetime/fn.md @@ -1,6 +1,6 @@ # Functions -Ignoring [elision], function signatures with lifetimes have a few constraints: +Ignoring [elision], function signatures with lifetimes have a few constraints: * any reference *must* have an annotated lifetime. * any reference being returned *must* have the same lifetime as an input or diff --git a/src/scope/lifetime/lifetime_bounds.md b/src/scope/lifetime/lifetime_bounds.md index dbc1165363..a5114e15e8 100644 --- a/src/scope/lifetime/lifetime_bounds.md +++ b/src/scope/lifetime/lifetime_bounds.md @@ -1,7 +1,7 @@ # Bounds Just like generic types can be bounded, lifetimes (themselves generic) -use bounds as well. The `:` character has a slightly different meaning here, +use bounds as well. The `:` character has a slightly different meaning here, but `+` is the same. Note how the following read: 1. `T: 'a`: *All* references in `T` must outlive lifetime `'a`. @@ -45,7 +45,7 @@ fn main() { ### See also: -[generics][generics], [bounds in generics][bounds], and +[generics][generics], [bounds in generics][bounds], and [multiple bounds in generics][multibounds] [generics]: ../../generics.md diff --git a/src/scope/lifetime/lifetime_coercion.md b/src/scope/lifetime/lifetime_coercion.md index 96090f4803..6ebff8f064 100644 --- a/src/scope/lifetime/lifetime_coercion.md +++ b/src/scope/lifetime/lifetime_coercion.md @@ -1,6 +1,6 @@ # Coercion -A longer lifetime can be coerced into a shorter one +A longer lifetime can be coerced into a shorter one so that it works inside a scope it normally wouldn't work in. This comes in the form of inferred coercion by the Rust compiler, and also in the form of declaring a lifetime difference: @@ -28,4 +28,4 @@ fn main() { println!("{} is the first", choose_first(&first, &second)); }; } -``` \ No newline at end of file +``` diff --git a/src/scope/lifetime/static_lifetime.md b/src/scope/lifetime/static_lifetime.md index 3c0b8b0b75..26f9fab783 100644 --- a/src/scope/lifetime/static_lifetime.md +++ b/src/scope/lifetime/static_lifetime.md @@ -114,7 +114,9 @@ fn main() { print_it(&i); } ``` + The compiler will tell you: + ```ignore error[E0597]: `i` does not live long enough --> src/lib.rs:15:15 diff --git a/src/scope/lifetime/struct.md b/src/scope/lifetime/struct.md index aca0bfe622..f793a0d732 100644 --- a/src/scope/lifetime/struct.md +++ b/src/scope/lifetime/struct.md @@ -42,5 +42,4 @@ fn main() { [`struct`s][structs] - [structs]: ../../custom_types/structs.md diff --git a/src/scope/lifetime/trait.md b/src/scope/lifetime/trait.md index 3c26df1194..6527df070f 100644 --- a/src/scope/lifetime/trait.md +++ b/src/scope/lifetime/trait.md @@ -29,5 +29,4 @@ fn main() { [`trait`s][trait] - [trait]: ../../trait.md diff --git a/src/scope/move.md b/src/scope/move.md index df631ee080..b20bc406e1 100644 --- a/src/scope/move.md +++ b/src/scope/move.md @@ -1,12 +1,12 @@ # Ownership and moves -Because variables are in charge of freeing their own resources, -**resources can only have one owner**. This prevents resources -from being freed more than once. Note that not all variables own +Because variables are in charge of freeing their own resources, +**resources can only have one owner**. This prevents resources +from being freed more than once. Note that not all variables own resources (e.g. [references]). When doing assignments (`let x = y`) or passing function arguments by value -(`foo(x)`), the *ownership* of the resources is transferred. In Rust-speak, +(`foo(x)`), the *ownership* of the resources is transferred. In Rust-speak, this is known as a *move*. After moving resources, the previous owner can no longer be used. This avoids diff --git a/src/scope/move/mut.md b/src/scope/move/mut.md index 3dddc4a17e..3ad32a9ade 100644 --- a/src/scope/move/mut.md +++ b/src/scope/move/mut.md @@ -21,4 +21,4 @@ fn main() { println!("mutable_box now contains {}", mutable_box); } -``` \ No newline at end of file +``` diff --git a/src/scope/move/partial_move.md b/src/scope/move/partial_move.md index 21d85a8b32..e5eb059c5e 100644 --- a/src/scope/move/partial_move.md +++ b/src/scope/move/partial_move.md @@ -1,11 +1,11 @@ # Partial moves -Within the [destructuring] of a single variable, both `by-move` and -`by-reference` pattern bindings can be used at the same time. Doing -this will result in a _partial move_ of the variable, which means -that parts of the variable will be moved while other parts stay. In -such a case, the parent variable cannot be used afterwards as a -whole, however the parts that are only referenced (and not moved) +Within the [destructuring] of a single variable, both `by-move` and +`by-reference` pattern bindings can be used at the same time. Doing +this will result in a _partial move_ of the variable, which means +that parts of the variable will be moved while other parts stay. In +such a case, the parent variable cannot be used afterwards as a +whole, however the parts that are only referenced (and not moved) can still be used. ```rust,editable @@ -35,14 +35,16 @@ fn main() { println!("The person's age from person struct is {}", person.age); } ``` -(In this example, we store the `age` variable on the heap to -illustrate the partial move: deleting `ref` in the above code would -give an error as the ownership of `person.age` would be moved to the -variable `age`. If `Person.age` were stored on the stack, `ref` would -not be required as the definition of `age` would copy the data from + +(In this example, we store the `age` variable on the heap to +illustrate the partial move: deleting `ref` in the above code would +give an error as the ownership of `person.age` would be moved to the +variable `age`. If `Person.age` were stored on the stack, `ref` would +not be required as the definition of `age` would copy the data from `person.age` without moving it.) ### See also: + [destructuring][destructuring] [destructuring]: ../../flow_control/match/destructuring.md diff --git a/src/std/box.md b/src/std/box.md index ebc8ff430a..bcb5dfde59 100644 --- a/src/std/box.md +++ b/src/std/box.md @@ -6,7 +6,7 @@ heap allocated value of type `T`. When a box goes out of scope, its destructor is called, the inner object is destroyed, and the memory on the heap is freed. Boxed values can be dereferenced using the `*` operator; this removes one layer -of indirection. +of indirection. ```rust,editable use std::mem; @@ -74,4 +74,4 @@ fn main() { println!("Unboxed point occupies {} bytes on the stack", mem::size_of_val(&unboxed_point)); } -``` \ No newline at end of file +``` diff --git a/src/std/hash.md b/src/std/hash.md index 94faacbf25..6ed0f8ca1c 100644 --- a/src/std/hash.md +++ b/src/std/hash.md @@ -1,14 +1,14 @@ # HashMap -Where vectors store values by an integer index, `HashMap`s store values by key. -`HashMap` keys can be booleans, integers, strings, -or any other type that implements the `Eq` and `Hash` traits. +Where vectors store values by an integer index, `HashMap`s store values by key. +`HashMap` keys can be booleans, integers, strings, +or any other type that implements the `Eq` and `Hash` traits. More on this in the next section. -Like vectors, `HashMap`s are growable, but HashMaps can also shrink themselves -when they have excess space. -You can create a HashMap with a certain starting capacity using -`HashMap::with_capacity(uint)`, or use `HashMap::new()` to get a HashMap +Like vectors, `HashMap`s are growable, but HashMaps can also shrink themselves +when they have excess space. +You can create a HashMap with a certain starting capacity using +`HashMap::with_capacity(uint)`, or use `HashMap::new()` to get a HashMap with a default initial capacity (recommended). ```rust,editable @@ -57,8 +57,8 @@ fn main() { } ``` -For more information on how hashing and hash maps -(sometimes called hash tables) work, have a look at +For more information on how hashing and hash maps +(sometimes called hash tables) work, have a look at [Hash Table Wikipedia][wiki-hash] [wiki-hash]: https://en.wikipedia.org/wiki/Hash_table diff --git a/src/std/hash/alt_key_types.md b/src/std/hash/alt_key_types.md index 7e68e8c67f..8c2333592c 100644 --- a/src/std/hash/alt_key_types.md +++ b/src/std/hash/alt_key_types.md @@ -1,6 +1,6 @@ # Alternate/custom key types -Any type that implements the `Eq` and `Hash` traits can be a key in `HashMap`. +Any type that implements the `Eq` and `Hash` traits can be a key in `HashMap`. This includes: * `bool` (though not very useful since there are only two possible keys) @@ -12,18 +12,18 @@ Note that `f32` and `f64` do *not* implement `Hash`, likely because [floating-point precision errors][floating] would make using them as hashmap keys horribly error-prone. -All collection classes implement `Eq` and `Hash` -if their contained type also respectively implements `Eq` and `Hash`. +All collection classes implement `Eq` and `Hash` +if their contained type also respectively implements `Eq` and `Hash`. For example, `Vec` will implement `Hash` if `T` implements `Hash`. -You can easily implement `Eq` and `Hash` for a custom type with just one line: +You can easily implement `Eq` and `Hash` for a custom type with just one line: `#[derive(PartialEq, Eq, Hash)]` -The compiler will do the rest. If you want more control over the details, -you can implement `Eq` and/or `Hash` yourself. -This guide will not cover the specifics of implementing `Hash`. +The compiler will do the rest. If you want more control over the details, +you can implement `Eq` and/or `Hash` yourself. +This guide will not cover the specifics of implementing `Hash`. -To play around with using a `struct` in `HashMap`, +To play around with using a `struct` in `HashMap`, let's try making a very simple user logon system: ```rust,editable diff --git a/src/std/hash/hashset.md b/src/std/hash/hashset.md index 63d5af8782..23ac67d15b 100644 --- a/src/std/hash/hashset.md +++ b/src/std/hash/hashset.md @@ -5,19 +5,19 @@ Consider a `HashSet` as a `HashMap` where we just care about the keys ( "What's the point of that?" you ask. "I could just store the keys in a `Vec`." -A `HashSet`'s unique feature is that -it is guaranteed to not have duplicate elements. -That's the contract that any set collection fulfills. +A `HashSet`'s unique feature is that +it is guaranteed to not have duplicate elements. +That's the contract that any set collection fulfills. `HashSet` is just one implementation. (see also: [`BTreeSet`][treeset]) -If you insert a value that is already present in the `HashSet`, -(i.e. the new value is equal to the existing and they both have the same hash), +If you insert a value that is already present in the `HashSet`, +(i.e. the new value is equal to the existing and they both have the same hash), then the new value will replace the old. -This is great for when you never want more than one of something, +This is great for when you never want more than one of something, or when you want to know if you've already got something. -But sets can do more than that. +But sets can do more than that. Sets have 4 primary operations (all of the following calls return an iterator): @@ -27,7 +27,7 @@ Sets have 4 primary operations (all of the following calls return an iterator): * `intersection`: get all the elements that are only in *both* sets. -* `symmetric_difference`: +* `symmetric_difference`: get all the elements that are in one set or the other, but *not* both. Try all of these in the following example: diff --git a/src/std/rc.md b/src/std/rc.md index 36b10907d9..658145b5ac 100644 --- a/src/std/rc.md +++ b/src/std/rc.md @@ -1,10 +1,16 @@ # `Rc` -When multiple ownership is needed, `Rc`(Reference Counting) can be used. `Rc` keeps track of the number of the references which means the number of owners of the value wrapped inside an `Rc`. +When multiple ownership is needed, `Rc`(Reference Counting) can be used. `Rc` +keeps track of the number of the references which means the number of owners of +the value wrapped inside an `Rc`. -Reference count of an `Rc` increases by 1 whenever an `Rc` is cloned, and decreases by 1 whenever one cloned `Rc` is dropped out of the scope. When an `Rc`'s reference count becomes zero (which means there are no remaining owners), both the `Rc` and the value are all dropped. +Reference count of an `Rc` increases by 1 whenever an `Rc` is cloned, and +decreases by 1 whenever one cloned `Rc` is dropped out of the scope. When an +`Rc`'s reference count becomes zero (which means there are no remaining owners), +both the `Rc` and the value are all dropped. -Cloning an `Rc` never performs a deep copy. Cloning creates just another pointer to the wrapped value, and increments the count. +Cloning an `Rc` never performs a deep copy. Cloning creates just another pointer +to the wrapped value, and increments the count. ```rust,editable use std::rc::Rc; diff --git a/src/std/result.md b/src/std/result.md index b812b9de99..50898de198 100644 --- a/src/std/result.md +++ b/src/std/result.md @@ -2,7 +2,7 @@ We've seen that the `Option` enum can be used as a return value from functions that may fail, where `None` can be returned to indicate failure. However, -sometimes it is important to express *why* an operation failed. To do this we +sometimes it is important to express *why* an operation failed. To do this we have the `Result` enum. The `Result` enum has two variants: diff --git a/src/std/result/question_mark.md b/src/std/result/question_mark.md index 66dbd2d1e4..61d938aaec 100644 --- a/src/std/result/question_mark.md +++ b/src/std/result/question_mark.md @@ -2,7 +2,7 @@ Chaining results using match can get pretty untidy; luckily, the `?` operator can be used to make things pretty again. `?` is used at the end of an expression -returning a `Result`, and is equivalent to a match expression, where the +returning a `Result`, and is equivalent to a match expression, where the `Err(err)` branch expands to an early `return Err(From::from(err))`, and the `Ok(ok)` branch expands to an `ok` expression. diff --git a/src/std/vec.md b/src/std/vec.md index f5cb1cae0c..e8cf2447e8 100644 --- a/src/std/vec.md +++ b/src/std/vec.md @@ -2,13 +2,14 @@ Vectors are re-sizable arrays. Like slices, their size is not known at compile time, but they can grow or shrink at any time. A vector is represented using -3 parameters: +3 parameters: + - pointer to the data - length -- capacity +- capacity -The capacity indicates how much memory is reserved for the vector. The vector -can grow as long as the length is smaller than the capacity. When this threshold +The capacity indicates how much memory is reserved for the vector. The vector +can grow as long as the length is smaller than the capacity. When this threshold needs to be surpassed, the vector is reallocated with a larger capacity. ```rust,editable,ignore,mdbook-runnable diff --git a/src/std_misc/file.md b/src/std_misc/file.md index 60e28cfb3d..f0538a70f7 100644 --- a/src/std_misc/file.md +++ b/src/std_misc/file.md @@ -8,4 +8,4 @@ return the `io::Result` type, which is an alias for `Result`. This makes the failure of all I/O operations *explicit*. Thanks to this, the programmer can see all the failure paths, and is encouraged to handle them in -a proactive manner. \ No newline at end of file +a proactive manner. diff --git a/src/std_misc/file/create.md b/src/std_misc/file/create.md index 4f113df880..4b96e022b0 100644 --- a/src/std_misc/file/create.md +++ b/src/std_misc/file/create.md @@ -41,6 +41,7 @@ Here's the expected successful output: ```shell $ rustc create.rs && ./create successfully wrote to lorem_ipsum.txt + $ cat lorem_ipsum.txt Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, diff --git a/src/std_misc/file/read_lines.md b/src/std_misc/file/read_lines.md index 1a2a64241e..7f186d4714 100644 --- a/src/std_misc/file/read_lines.md +++ b/src/std_misc/file/read_lines.md @@ -72,6 +72,7 @@ where P: AsRef, { ``` Running this program simply prints the lines individually. + ```shell $ echo -e "127.0.0.1\n192.168.0.1\n" > hosts.txt $ rustc read_lines.rs && ./read_lines @@ -84,4 +85,3 @@ generic `read_lines()` method with the same generic constraint, using the `where This process is more efficient than creating a `String` in memory with all of the file's contents. This can especially cause performance issues when working with larger files. - diff --git a/src/std_misc/path.md b/src/std_misc/path.md index af0f3d388e..378df6ed87 100644 --- a/src/std_misc/path.md +++ b/src/std_misc/path.md @@ -8,13 +8,13 @@ platform-specific `Path` variant. A `Path` can be created from an `OsStr`, and provides several methods to get information from the file/directory the path points to. -A `Path` is immutable. The owned version of `Path` is `PathBuf`. The relation -between `Path` and `PathBuf` is similar to that of `str` and `String`: +A `Path` is immutable. The owned version of `Path` is `PathBuf`. The relation +between `Path` and `PathBuf` is similar to that of `str` and `String`: a `PathBuf` can be mutated in-place, and can be dereferenced to a `Path`. Note that a `Path` is *not* internally represented as an UTF-8 string, but instead is stored as an `OsString`. Therefore, converting a `Path` to a `&str` -is *not* free and may fail (an `Option` is returned). However, a `Path` can be +is *not* free and may fail (an `Option` is returned). However, a `Path` can be freely converted to an `OsString` or `&OsStr` using `into_os_string` and `as_os_str`, respectively. diff --git a/src/std_misc/threads/testcase_mapreduce.md b/src/std_misc/threads/testcase_mapreduce.md index 9cc162f518..0de796d9da 100644 --- a/src/std_misc/threads/testcase_mapreduce.md +++ b/src/std_misc/threads/testcase_mapreduce.md @@ -1,14 +1,14 @@ # Testcase: map-reduce -Rust makes it very easy to parallelise data processing, without many of the headaches traditionally associated with such an attempt. +Rust makes it very easy to parallelize data processing, without many of the headaches traditionally associated with such an attempt. The standard library provides great threading primitives out of the box. These, combined with Rust's concept of Ownership and aliasing rules, automatically prevent data races. The aliasing rules (one writable reference XOR many readable references) automatically prevent -you from manipulating state that is visible to other threads. (Where synchronisation is needed, -there are synchronisation +you from manipulating state that is visible to other threads. (Where synchronization is needed, +there are synchronization primitives like `Mutex`es or `Channel`s.) In this example, we will calculate the sum of all digits in a block of numbers. @@ -120,12 +120,14 @@ fn main() { ``` ### Assignments + It is not wise to let our number of threads depend on user inputted data. What if the user decides to insert a lot of spaces? Do we _really_ want to spawn 2,000 threads? Modify the program so that the data is always chunked into a limited number of chunks, defined by a static constant at the beginning of the program. ### See also: + * [Threads][thread] * [vectors][vectors] and [iterators][iterators] * [closures][closures], [move][move] semantics and [`move` closures][move_closure] diff --git a/src/testing/dev_dependencies.md b/src/testing/dev_dependencies.md index 0899845eec..9d4c3c63c0 100644 --- a/src/testing/dev_dependencies.md +++ b/src/testing/dev_dependencies.md @@ -34,6 +34,7 @@ mod tests { ``` ## See Also + [Cargo][cargo] docs on specifying dependencies. [cargo]: http://doc.crates.io/specifying-dependencies.html diff --git a/src/testing/doc_testing.md b/src/testing/doc_testing.md index 1d6cd46ad9..4015ddcdce 100644 --- a/src/testing/doc_testing.md +++ b/src/testing/doc_testing.md @@ -1,9 +1,9 @@ # Documentation testing The primary way of documenting a Rust project is through annotating the source -code. Documentation comments are written in +code. Documentation comments are written in [CommonMark Markdown specification][commonmark] and support code blocks in them. -Rust takes care about correctness, so these code blocks are compiled and used +Rust takes care about correctness, so these code blocks are compiled and used as documentation tests. ```rust,ignore diff --git a/src/testing/unit_testing.md b/src/testing/unit_testing.md index bdce963343..f476e5e906 100644 --- a/src/testing/unit_testing.md +++ b/src/testing/unit_testing.md @@ -71,6 +71,7 @@ test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out ``` ## Tests and `?` + None of the previous unit test examples had a return type. But in Rust 2018, your unit tests can return `Result<()>`, which lets you use `?` in them! This can make them much more concise. diff --git a/src/trait.md b/src/trait.md index d4d4094683..3c297f5942 100644 --- a/src/trait.md +++ b/src/trait.md @@ -4,8 +4,8 @@ A `trait` is a collection of methods defined for an unknown type: `Self`. They can access other methods declared in the same trait. Traits can be implemented for any data type. In the example below, -we define `Animal`, a group of methods. The `Animal` `trait` is -then implemented for the `Sheep` data type, allowing the use of +we define `Animal`, a group of methods. The `Animal` `trait` is +then implemented for the `Sheep` data type, allowing the use of methods from `Animal` with a `Sheep`. ```rust,editable diff --git a/src/trait/derive.md b/src/trait/derive.md index 4769efe627..39c958f549 100644 --- a/src/trait/derive.md +++ b/src/trait/derive.md @@ -5,6 +5,7 @@ the `#[derive]` [attribute][attribute]. These traits can still be manually implemented if a more complex behavior is required. The following is a list of derivable traits: + * Comparison traits: [`Eq`][eq], [`PartialEq`][partial-eq], [`Ord`][ord], [`PartialOrd`][partial-ord]. * [`Clone`][clone], to create `T` from `&T` via a copy. @@ -12,7 +13,7 @@ The following is a list of derivable traits: * [`Hash`][hash], to compute a hash from `&T`. * [`Default`][default], to create an empty instance of a data type. * [`Debug`][debug], to format a value using the `{:?}` formatter. - + ```rust,editable // `Centimeters`, a tuple struct that can be compared #[derive(PartialEq, PartialOrd)] @@ -62,6 +63,7 @@ fn main() { ``` ### See also: + [`derive`][derive] [attribute]: ../attribute.md diff --git a/src/trait/disambiguating.md b/src/trait/disambiguating.md index 6fca4b032f..b0560950fb 100644 --- a/src/trait/disambiguating.md +++ b/src/trait/disambiguating.md @@ -1,7 +1,7 @@ # Disambiguating overlapping traits A type can implement many different traits. What if two traits both require -the same name for a function? For example, many traits might have a method +the same name for a function? For example, many traits might have a method named `get()`. They might even have different return types! Good news: because each trait implementation gets its own `impl` block, it's diff --git a/src/trait/drop.md b/src/trait/drop.md index 7aeaca7173..3e743703cd 100644 --- a/src/trait/drop.md +++ b/src/trait/drop.md @@ -1,6 +1,6 @@ # Drop -The [`Drop`][Drop] trait only has one method: `drop`, which is called automatically +The [`Drop`][Drop] trait only has one method: `drop`, which is called automatically when an object goes out of scope. The main use of the `Drop` trait is to free the resources that the implementor instance owns. @@ -54,4 +54,4 @@ fn main() { } ``` -[Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html \ No newline at end of file +[Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html diff --git a/src/trait/dyn.md b/src/trait/dyn.md index 5b2f8c2f3e..e5cd22413e 100644 --- a/src/trait/dyn.md +++ b/src/trait/dyn.md @@ -1,10 +1,18 @@ # Returning Traits with `dyn` -The Rust compiler needs to know how much space every function's return type requires. This means all your functions have to return a concrete type. Unlike other languages, if you have a trait like `Animal`, you can't write a function that returns `Animal`, because its different implementations will need different amounts of memory. +The Rust compiler needs to know how much space every function's return type requires. This means all +your functions have to return a concrete type. Unlike other languages, if you have a trait like +`Animal`, you can't write a function that returns `Animal`, because its different implementations +will need different amounts of memory. -However, there's an easy workaround. Instead of returning a trait object directly, our functions return a `Box` which _contains_ some `Animal`. A `box` is just a reference to some memory in the heap. Because a reference has a statically-known size, and the compiler can guarantee it points to a heap-allocated `Animal`, we can return a trait from our function! +However, there's an easy workaround. Instead of returning a trait object directly, our functions +return a `Box` which _contains_ some `Animal`. A `box` is just a reference to some memory in the +heap. Because a reference has a statically-known size, and the compiler can guarantee it points to a +heap-allocated `Animal`, we can return a trait from our function! -Rust tries to be as explicit as possible whenever it allocates memory on the heap. So if your function returns a pointer-to-trait-on-heap in this way, you need to write the return type with the `dyn` keyword, e.g. `Box`. +Rust tries to be as explicit as possible whenever it allocates memory on the heap. So if your +function returns a pointer-to-trait-on-heap in this way, you need to write the return type with the +`dyn` keyword, e.g. `Box`. ```rust,editable struct Sheep {} @@ -44,4 +52,4 @@ fn main() { println!("You've randomly chosen an animal, and it says {}", animal.noise()); } -``` \ No newline at end of file +``` diff --git a/src/trait/impl_trait.md b/src/trait/impl_trait.md index 34bc06bfd0..9b6618e1fc 100644 --- a/src/trait/impl_trait.md +++ b/src/trait/impl_trait.md @@ -48,7 +48,6 @@ fn parse_csv_document(src: impl std::io::BufRead) -> std::io::Result(std::io::empty())` will not work with the second example. - ## As a return type If your function returns a type that implements `MyTrait`, you can write its diff --git a/src/types.md b/src/types.md index 1d3b50aaba..24bad81af4 100644 --- a/src/types.md +++ b/src/types.md @@ -2,6 +2,7 @@ Rust provides several mechanisms to change or define the type of primitive and user defined types. The following sections cover: + * [Casting] between primitive types * Specifying the desired type of [literals] * Using [type inference] diff --git a/src/types/inference.md b/src/types/inference.md index 5d10301f42..88226503c4 100644 --- a/src/types/inference.md +++ b/src/types/inference.md @@ -2,7 +2,7 @@ The type inference engine is pretty smart. It does more than looking at the type of the value expression -during an initialization. It also looks at how the variable is used afterwards +during an initialization. It also looks at how the variable is used afterwards to infer its type. Here's an advanced example of type inference: ```rust,editable diff --git a/src/types/literals.md b/src/types/literals.md index fd26b9dcaf..275b2f57d2 100644 --- a/src/types/literals.md +++ b/src/types/literals.md @@ -1,6 +1,6 @@ # Literals -Numeric literals can be type annotated by adding the type as a suffix. As an example, +Numeric literals can be type annotated by adding the type as a suffix. As an example, to specify that the literal `42` should have the type `i32`, write `42i32`. The type of unsuffixed numeric literals will depend on how they are used. If no diff --git a/src/unsafe.md b/src/unsafe.md index 1eeec6ba35..fe83672ad0 100644 --- a/src/unsafe.md +++ b/src/unsafe.md @@ -8,11 +8,12 @@ things that unsafe is used for: * dereferencing raw pointers * calling functions or methods which are `unsafe` (including calling a function - over FFI, see [a previous chapter](std_misc/ffi.md) of the book) + over FFI, see [a previous chapter](std_misc/ffi.md) of the book) * accessing or modifying static mutable variables * implementing unsafe traits ### Raw Pointers + Raw pointers `*` and references `&T` function similarly, but references are always safe because they are guaranteed to point to valid data due to the borrow checker. Dereferencing a raw pointer can only be done through an unsafe @@ -29,6 +30,7 @@ fn main() { ``` ### Calling Unsafe Functions + Some functions can be declared as `unsafe`, meaning it is the programmer's responsibility to ensure correctness instead of the compiler's. One example of this is [`std::slice::from_raw_parts`] which will create a slice given a @@ -51,11 +53,10 @@ fn main() { } ``` -For `slice::from_raw_parts`, one of the assumptions which *must* be upheld is +For `slice::from_raw_parts`, one of the assumptions which *must* be upheld is that the pointer passed in points to valid memory and that the memory pointed to -is of the correct type. If these invariants aren't upheld then the program's +is of the correct type. If these invariants aren't upheld then the program's behaviour is undefined and there is no knowing what will happen. - [unsafe]: https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html [`std::slice::from_raw_parts`]: https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html diff --git a/src/unsafe/asm.md b/src/unsafe/asm.md index 5a6309947f..3c78436e91 100644 --- a/src/unsafe/asm.md +++ b/src/unsafe/asm.md @@ -8,6 +8,7 @@ cannot be otherwise achieved. Accessing low level hardware primitives, e.g. in k > **Note**: the examples here are given in x86/x86-64 assembly, but other architectures are also supported. Inline assembly is currently supported on the following architectures: + - x86 and x86-64 - ARM - AArch64 @@ -139,7 +140,7 @@ can be written at any time, and can therefore not share its location with any ot However, to guarantee optimal performance it is important to use as few registers as possible, so they won't have to be saved and reloaded around the inline assembly block. To achieve this Rust provides a `lateout` specifier. This can be used on any output that is -written only after all inputs have been consumed. There is also an `inlateout` variant of this +written only after all inputs have been consumed. There is also an `inlateout` variant of this specifier. Here is an example where `inlateout` *cannot* be used in `release` mode or other optimized cases: @@ -164,11 +165,19 @@ assert_eq!(a, 12); # } ``` -In unoptimized cases (e.g. `Debug` mode), replacing `inout(reg) a` with `inlateout(reg) a` in the above example can continue to give the expected result. However, with `release` mode or other optimized cases, using `inlateout(reg) a` can instead lead to the final value `a = 16`, causing the assertion to fail. +In unoptimized cases (e.g. `Debug` mode), replacing `inout(reg) a` with `inlateout(reg) a` in the +above example can continue to give the expected result. However, with `release` mode or other +optimized cases, using `inlateout(reg) a` can instead lead to the final value `a = 16`, causing the +assertion to fail. -This is because in optimized cases, the compiler is free to allocate the same register for inputs `b` and `c` since it knows that they have the same value. Furthermore, when `inlateout` is used, `a` and `c` could be allocated to the same register, in which case the first `add` instruction would overwrite the initial load from variable `c`. This is in contrast to how using `inout(reg) a` ensures a separate register is allocated for `a`. +This is because in optimized cases, the compiler is free to allocate the same register for inputs +`b` and `c` since it knows that they have the same value. Furthermore, when `inlateout` is used, `a` +and `c` could be allocated to the same register, in which case the first `add` instruction would +overwrite the initial load from variable `c`. This is in contrast to how using `inout(reg) a` +ensures a separate register is allocated for `a`. -However, the following example can use `inlateout` since the output is only modified after all input registers have been read: +However, the following example can use `inlateout` since the output is only modified after all input +registers have been read: ```rust # #[cfg(target_arch = "x86_64")] { @@ -406,13 +415,13 @@ fn load_fpu_control_word(control: u16) { Any reuse of a named label, local or otherwise, can result in an assembler or linker error or may cause other strange behavior. Reuse of a named label can happen in a variety of ways including: -- explicitly: using a label more than once in one `asm!` block, or multiple times across blocks. -- implicitly via inlining: the compiler is allowed to instantiate multiple copies of an `asm!` block, for example when the function containing it is inlined in multiple places. -- implicitly via LTO: LTO can cause code from *other crates* to be placed in the same codegen unit, and so could bring in arbitrary labels. +- explicitly: using a label more than once in one `asm!` block, or multiple times across blocks. +- implicitly via inlining: the compiler is allowed to instantiate multiple copies of an `asm!` block, for example when the function containing it is inlined in multiple places. +- implicitly via LTO: LTO can cause code from *other crates* to be placed in the same codegen unit, and so could bring in arbitrary labels. As a consequence, you should only use GNU assembler **numeric** [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions. -Moreover, on x86 when using the default Intel syntax, due to [an LLVM bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `options(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_ `asm!` block. (See [Options](#options), below, for more on `options`.) +Moreover, on x86 when using the default Intel syntax, due to [an LLVM bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `options(att_syntax)` will avoid any ambiguity, but that affects the syntax of the *entire* `asm!` block. (See [Options](#options), below, for more on `options`.) ```rust # #[cfg(target_arch = "x86_64")] { @@ -470,6 +479,7 @@ assert_eq!(a, 8); ``` Options can be provided as an optional final argument to the `asm!` macro. We specified three options here: + - `pure` means that the asm code has no observable side effects and that its output depends only on its inputs. This allows the compiler optimizer to call the inline asm fewer times or even eliminate it entirely. - `nomem` means that the asm code does not read or write to memory. By default the compiler will assume that inline assembly can read or write any memory address that is accessible to it (e.g. through a pointer passed as an operand, or a global). - `nostack` means that the asm code does not push any data onto the stack. This allows the compiler to use optimizations such as the stack red zone on x86-64 to avoid stack pointer adjustments. diff --git a/src/variable_bindings/freeze.md b/src/variable_bindings/freeze.md index b399570ff8..d99b1bd482 100644 --- a/src/variable_bindings/freeze.md +++ b/src/variable_bindings/freeze.md @@ -1,6 +1,6 @@ # Freezing -When data is bound by the same name immutably, it also *freezes*. *Frozen* data can't be +When data is bound by the same name immutably, it also *freezes*. *Frozen* data can't be modified until the immutable binding goes out of scope: ```rust,editable,ignore,mdbook-runnable diff --git a/src/variable_bindings/scope.md b/src/variable_bindings/scope.md index 9e3c79e3ee..0ac66912dd 100644 --- a/src/variable_bindings/scope.md +++ b/src/variable_bindings/scope.md @@ -1,7 +1,8 @@ # Scope and Shadowing Variable bindings have a scope, and are constrained to live in a *block*. A -block is a collection of statements enclosed by braces `{}`. +block is a collection of statements enclosed by braces `{}`. + ```rust,editable,ignore,mdbook-runnable fn main() { // This binding lives in the main function @@ -23,7 +24,9 @@ fn main() { println!("outer long: {}", long_lived_binding); } ``` + Also, [variable shadowing][variable-shadow] is allowed. + ```rust,editable,ignore,mdbook-runnable fn main() { let shadowed_binding = 1; @@ -43,4 +46,5 @@ fn main() { println!("shadowed in outer block: {}", shadowed_binding); } ``` + [variable-shadow]: https://en.wikipedia.org/wiki/Variable_shadowing