Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More edits #1838

Merged
merged 4 commits into from
Mar 2, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 89 additions & 98 deletions nostarch/appendices-d-and-e.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,37 @@
# Appendix D - Useful Development Tools

In this appendix, we’ll talk about tools provided by the Rust project that are
useful when developing Rust code.
In this appendix, we talk about some useful development tools that the Rust
project provides. We’ll look at automatic formatting, quick ways to apply
warning fixes, a linter, and integrating with IDEs.

## Automatic Formatting with `rustfmt`

The tool `rustfmt` reformats your code according to the community code style.
Many projects use `rustfmt` to prevent arguments about which style to use when
writing Rust: everyone formats their code with the tool!
The `rustfmt` tool reformats your code according to the community code style.
Many collaborative projects use `rustfmt` to prevent arguments about which
style to use when writing Rust: everyone formats their code using the tool.

The `rustfmt` tool is not yet at the quality of a version 1.0 release, but
a preview is available for you to use in the meantime. Please give it a try and
let us know how it goes!

To install `rustfmt`:
To install `rustfmt`, enter the following:

```
$ rustup component add rustfmt-preview
$ rustup component add rustfmt
```

This will give you both `rustfmt` and `cargo-fmt`, similar to how Rust gives
you both `rustc` and `cargo`. To take any Cargo project and format it:
This command gives you `rustfmt` and `cargo-fmt`, similar to how Rust gives you
both `rustc` and `cargo`. To format any Cargo project, enter the following:

```
$ cargo fmt
```

Running this command will reformat all of the Rust code in the current crate.
This should only change the code style, not the code semantics. For more
information on `rustfmt`, see its documentation at
*https://github.com/rust-lang-nursery/rustfmt*.
Running this command reformats all the Rust code in the current crate. This
should only change the code style, not the code semantics. For more information
on `rustfmt`, see its documentation at *https://github.com/rust-lang/rustfmt/*.

## Fix Up Your Code with `rustfix`
## Fix Your Code with `rustfix`

If you’ve written code in Rust, you’ve probably seen compiler warnings. For
example, consider this code:
The rustfix tool is included with Rust installations and can automatically fix
some compiler warnings. If you’ve written code in Rust, you’ve probably seen
compiler warnings. For example, consider this code:

Filename: src/main.rs

Expand Down Expand Up @@ -77,7 +74,7 @@ $ cargo fix
Finished dev [unoptimized + debuginfo] target(s) in 0.59s
```

If 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
Expand All @@ -92,35 +89,30 @@ fn main() {
}
```

The `for` loop variable is now named `_i`, and the warning will no longer
appear.

The `cargo fix` command can also be used to transition your code between
different editions of Rust. Editions are covered in Appendix E.
The `for` loop variable is now named `_i`, and the warning no longer appears.

## More Lints with `clippy`
You can also use the `cargo fix` command to transition your code between
different Rust editions. Editions are covered in Appendix E.

The `clippy` tool is a collection of lints to catch common mistakes and improve
your Rust code.
## More Lints with Clippy

The `clippy` tool is not yet at the quality of a version 1.0 release, but a
preview is available for you to use in the meantime. Please give it a try and
let us know how it goes!
The Clippy tool is a collection of lints to analyze your code to catch common
mistakes and improve your Rust code.

To install `clippy`:
To install Clippy, enter the following:

```
$ rustup component add clippy-preview
$ rustup component add clippy
```

To take any Cargo project and run clippy’s lints on it:
To run Clippy’s lints on any Cargo project, enter the following:

```
$ cargo clippy
```

For example, if you write a program that uses an approximation of a
mathematical constant such as pi, as this program does:
For example, say you write a program that uses an approximation of a
mathematical constant, such as pi, as this program does:

Filename: src/main.rs

Expand All @@ -132,22 +124,24 @@ fn main() {
}
```

Running `cargo clippy` on this project will result in this error:
Running `cargo clippy` on this project results in this error:

```
error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::PI` found. Consider using it
directly
--> src/main.rs:2:13
|
2 | let x = 3.1415;
| ^^^^^^
|
= note: #[deny(clippy::approx_constant)] on by default
= help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.212/index.html#approx_constant
= help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/master/index.html#approx_constant
```

This lets you know that Rust has this constant defined more precisely, and that
your program would be more correct if you used the constant instead. This code
doesn’t result in any errors or warnings from `clippy`:
This error lets you know that Rust has this constant defined more precisely,
and that your program would be more correct if you used the constant instead.
You would then change your code to use the `PI` constant. The following code
doesn’t result in any errors or warnings from Clippy:

Filename: src/main.rs

Expand All @@ -159,73 +153,70 @@ fn main() {
}
```

For more information on `clippy`, see its documentation at
*https://github.com/rust-lang-nursery/rust-clippy*.
For more information on Clippy, see its documentation at
*https://github.com/rust-lang/rust-clippy/*.

## IDE Integration Using the Rust Language Server

To help IDE integration, the Rust project distributes the `rls`, which stands
for the Rust Language Server. This tool speaks the Language Server Protocol
described at *http://langserver.org/*, which is a specification for IDEs and
programming languages to communicate with each other. The `rls` can be used by
different clients, such as the Rust plugin for Visual Studio: Code at
*https://marketplace.visualstudio.com/items?itemName=rust-lang.rust*.
To help IDE integration, the Rust project distributes the *Rust Language
Server* (`rls`). This tool speaks the Language Server Protocol described at
*http://langserver.org/*, which is a specification for IDEs and programming
languages to communicate with each other. Different clients can use the `rls`,
such as the Rust plug-in for Visual Studio Code available from
*https://marketplace.visualstudio.com/items?itemName=rust-lang.rust/*.

The `rls` is not yet at the quality of a version 1.0 release, but a preview is
available for you to use in the meantime. Please give it a try and let us know
how it goes!

To install the `rls`:
To install the `rls`, enter the following:

```
$ rustup component add rls-preview
$ rustup component add rls
```

Then install the language server support in your particular IDE, and you will
gain abilities such as autocompletion, jump to definition, and inline errors.
Then install the language server support in your particular IDE; you’ll gain
abilities such as autocompletion, jump to definition, and inline errors.

For more information on the `rls`, see its documentation at
*https://github.com/rust-lang-nursery/rls*.
*https://github.com/rust-lang/rls/*.

# Appendix E - Editions

Way back in Chapter 1, we saw that `cargo new` adds a bit of metadata to your
*Cargo.toml* about an `edition`. This appendix talks about what that means!
In Chapter 1, you saw that `cargo new` adds a bit of metadata to your
*Cargo.toml* file about an edition. This appendix talks about what that means!

The Rust language and compiler have a six-week release cycle. This means users
get a constant stream of new features. Other programming languages release
larger changes less often; Rust chooses to release smaller updates more
frequently. After a while, all of those tiny changes add up. But from release
to release, it can be hard to look back and say “Wow, between Rust 1.10 and
Rust 1.31, Rust has changed a lot!”
The Rust language and compiler have a six-week release cycle, meaning users get
a constant stream of new features. Other programming languages release larger
changes less often; Rust releases smaller updates more frequently. After a
while, all of these tiny changes add up. But from release to release, it can be
difficult to look back and say, “Wow, between Rust 1.10 and Rust 1.31, Rust has
changed a lot!”

Every two or three years, the Rust team produces a new *edition* of Rust.
Each edition brings together the features that have landed into a clear
package with fully updated documentation and tooling. New editions ship
as part of the usual six-week release process.
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.

This serves different purposes for different people:
Editions serve different purposes for different people:

* For active Rust users, it brings together incremental changes into an
easy-to-understand package.
* For non-users, it signals that some major advancements have landed, which
might make Rust worth another look.
* For those developing Rust itself, it provides a rallying point for the
* For active Rust users, a new edition brings together incremental changes into
an easy-to-understand package.
* For non-users, a new edition signals that some major advancements have
landed, which might make Rust worth another look.
* For those developing Rust, a new edition provides a rallying point for the
project as a whole.

At the time of writing, there are two editions: Rust 2015 and Rust 2018.
This book is written using Rust 2018 edition idioms.
At the time of this writing, two Rust editions are available: Rust 2015 and
Rust 2018. This book is written using Rust 2018 edition idioms.

The `edition` key in *Cargo.toml* indicates which edition the compiler should
use for your code. If the key doesn’t exist, Rust uses `2015` as the edition
value for backward compatibility reasons.

The `edition` key in *Cargo.toml* indicates which edition your code should be
compiled under. If the key does not exist, it defaults to `2015` for backwards
compatibility reasons.
Each project can opt in to an edition other than the default 2015 edition.
Editions can contain incompatible changes, such as including a new keyword that
conflicts with identifiers in code. However, unless you opt in to those
changes, your code will continue to compile even as you upgrade the Rust
compiler version you use.

Each project can choose to opt in to an edition other than the default 2015
edition. By doing so, editions can contain incompatible changes, such as adding
a new keyword that might conflict with identifiers in code or turning warnings
into errors. But unless you opt in to those changes, your code will continue to
compile even as you upgrade the version of the Rust compiler that you use. All
Rust compiler versions support any edition that existed prior to that
All Rust compiler versions support any edition that existed prior to that
compiler’s release, and they can link crates of any supported editions
together. Edition changes only affect the way the compiler initially parses
code. Therefore, if you’re using Rust 2015 and one of your dependencies uses
Expand All @@ -234,12 +225,12 @@ opposite situation, where your project uses Rust 2018 and a dependency uses
Rust 2015, works as well.

To be clear: most features will be available on all editions. Developers using
any edition of Rust will continue to see improvements as new stable releases
are made. In some cases, however, mainly when new keywords are added, there may
be new features that are only available in later editions. You only need to
switch editions if you want to take advantage of such features.

For more details, the Edition
Guide at *https://rust-lang-nursery.github.io/edition-guide/* is a complete
book about editions, including how to automatically upgrade your code to
a new edition via `cargo fix`.
any Rust edition will continue to see improvements as new stable releases are
made. However, in some cases, mainly when new keywords are added, some new
features might only be available in later editions. You will need to switch
editions if you want to take advantage of such features.

For more details, the *Edition Guide* at
*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`.
32 changes: 17 additions & 15 deletions nostarch/appendix-a-new-section.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
This is a new section to appear at the end of Appendix A, after the "Keywords Reserved for Future Use" section.
This is a new section to appear at the end of Appendix A, after the “Keywords
Reserved for Future Use” section.

### Raw Identifiers

*Raw identifiers* let you use keywords where they would not normally be allowed
by prefixing them with `r#`.
*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 this function that
uses `match` as its name:
For example, `match` is a keyword. If you try to compile the following function
that uses `match` as its name:

Filename: src/main.rs

Expand All @@ -26,8 +27,9 @@ error: expected identifier, found keyword `match`
| ^^^^^ expected identifier, found keyword
```

The error says that you can't use the keyword `match` as the function
identifier. You can use `match` as a function name by using a raw identifier:
The error shows that you can’t use the keyword `match` as the function
identifier. To use `match` as a function name, you need to use the raw
identifier syntax, like this:

Filename: src/main.rs

Expand All @@ -41,15 +43,15 @@ fn main() {
}
```

This code will compile without any errors. Note the `r#` prefix on both the
function name in its definition as well as where the function is called in
`main`.
This code will compile without any errors. Note the `r#` prefix on the function
name in its definition as well as where the function is called in `main`.

Raw identifiers allow you to use any word you choose as an identifier, even if
that word happens to be a reserved keyword. In addition, raw identifiers allow
you to use libraries written in a different Rust edition than your crate uses.
For example, `try` is not a keyword in the 2015 edition but is in the 2018
edition. If you depend on a library that is written using the 2015 edition and
has a `try` function, to call that function from your 2018 edition code, you’ll
need to use the raw identifier syntax, `r#try` in this case. See Appendix
E for more information on editions.
For example, `try` isn’t a keyword in the 2015 edition but is in the 2018
edition. If you depend on a library that’s written using the 2015 edition and
has a `try` function, you’ll need to use the raw identifier syntax, `r#try` in
this case, to call that function from your 2018 edition code. See Appendix E
for more information on editions.

21 changes: 11 additions & 10 deletions nostarch/chapter19-new-function-pointer-text.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ page 448.

---

Another useful pattern exploits an implementation detail of tuple structs and
tuple-struct enum variants. These items use `()` as initializer syntax, which
looks like a function call. The initializers are actually implemented as
functions returning an instance constructed from their arguments. These
initializer functions can also be used as a function pointer that implements
the closure traits, so they can also be specified as arguments for methods that
take closures:
We have another useful pattern that exploits an implementation detail of tuple
structs and tuple-struct enum variants. These types use `()` as initializer
syntax, which looks like a function call. The initializers are actually
implemented as functions returning an instance that’s constructed from their
arguments. We can use these initializer functions as function pointers that
implement the closure traits, which means we can specify the initializer
functions as arguments for methods that take closures, like so:

```
enum Status {
Expand All @@ -24,7 +24,8 @@ let list_of_statuses: Vec<Status> =
.collect();
```

This code creates `Status::Value` instances using each `u32` value in the range
Here we create `Status::Value` instances using each `u32` value in the range
that `map` is called on by using the initializer function of `Status::Value`.
Some people prefer this style, and some people prefer to use closures. They end
up compiling to the same code, so use whichever style is clearer to you.
Some people prefer this style, and some people prefer to use closures. They
compile to the same code, so use whichever style is clearer to you.

Binary file added nostarch/docx/appendices-d-and-e.docx
Binary file not shown.
Binary file added nostarch/docx/appendix-a-new-section.docx
Binary file not shown.
Binary file not shown.
Loading