Errata

Programming Rust

Errata for Programming Rust

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
i
4th paragraph (bullet list)

This statement about Systems Programming:

“Code that runs in very cheap devices, or devices that must be extremely reliable”

Should have been proofread better.

Any device should be extremely reliable, so that is not worth mentioning. As far as cost, I develop embedded software and I can assure you that our devices are the opposite of “very cheap.”

It is better to just say “Embedded Software” without mention of cost or reliability.

Nelson  Jun 19, 2021 
Mobi Page Location 14471 (Mobi)
14th chapter "Closures that borrow" in "Capturing Variables"

Below a code snippet, there is the text:

"In this case, when Rust creates the closure, it automatically borrows a reference to stat. It stands to reason: the closure refers to stat, so it must have a reference to it."

---

city.get_statistics(stat) inside the closure takes ownership of "stat", so the closure can't just borrow a reference to "stat". It is moved into the closure (even implicitly if no "move" keyword is specified) or copied if Statistic implements Copy.

Jorge Rinaldi  Aug 07, 2021 
Other Digital Version N/A

I have written 145 notes/errata (all of which aren't in the errata page) for the book and it would be impractical and quite painful (both for me and for the authors) to write them one by one here.

And since I read the Kindle edition, I took advantage of its sharing-notes feature which shows notes/errata together with the highlighted relevant text and even includes the page number.

I just sent these errata/notes to both `booktech@oreilly.com` and `bookquestions@oreilly.com` and expect (and look forward to) some going back and forth.

I've tried more than a dozen programming languages over the years and probably only borrowing/lifetimes are new concepts to me. Most notes/errata are from an outsider perspective as I didn't start using Rust when I was reading the book.

However, I have now about 10days of Rust experience and have been using it productively. Still notes/errata haven't changed much as I edited/reviewed them as most points are quite intuitive from a programming and common-sense perspective.

Looking forward to hearing from you,

Abdullah Alansari  Oct 04, 2021 
chapter 21 Macros
Table 21-1. Repetition patterns

The Table 21-1 which gives an exhaustive list of repetition patterns include mistakes.
You should remove from the list:
$( ... ),? Match 0 or 1 times, separated by commas
$( ... );? Match 0 or 1 times, separated by semicolons

The ? operator does not accept any separator token, unlike + and *;
Please see: https://github.com/rust-lang/rust/issues/48075#issuecomment-433243048

Sofiane Akermoun  Sep 06, 2022 
ePub Page n/a
text

Current Copy
slice_a.swap(&mut slice_b)
Swaps the entire contents of slice_a and slice_b.
slice_a and slice_b must be the same length.

Suggested
slice_a.swap_with_slice(&mut slice_b)
Swaps the entire contents of slice_a and slice_b.
slice_a and slice_b must be the same length.

Wilson Kuo  Oct 08, 2023 
O'Reilly learning platform Page Chapter 2 -- Section "Writing and Running Unit Tests"
Writing and Running Unit Tests

Chapter 2. Section "Writing and Running Unit Tests"
The crates recommended at the above location do not work. While trying to follow this exercise, I was repeatedly met with an error about actix-http failing to compile. More modern versions of actix-web, the crate you're asked to install, have a different API and so don't work with the rest of the instruction.

Anonymous  Dec 13, 2023 
Printed Page 6
Section "rustup and Cargo" in Chapter 2: A Tour of Rust

There was three command line examples which displays the version of the new installed rust tools cargo, rustc and rustdoc.
All commands print out the version "1.49.0" released in Dec. 2020 but this version does not support the Rust edition 2021, it only support edition 2018. All examples in this book use edition 2021.
The first Rust version which support edition 2021 is 1.56. (2021-10-04).

Thomas  Jan 22, 2022 
Printed Page 8
Bottom of the page

The implementation of GCD has an unnecessary check for swapping m and n if m < n. The Wikipedia page that is referenced in the paragraph provides a more concise pseudo-code that can be implemented in Rust as:

fn gcd(mut m: u32, mut n: u32) -> u32 {
while n != 0 {
let t = m % n;
m = n;
n = t;
}
m
}
See link in compiler explorer here: https://godbolt.org/z/fThdahK6K

Sudarshan Raghunathan  Mar 19, 2022 
Printed Page 14
Bottom paragraph

"Unlike C and C++, which require main to return zero if the program finished successfully, or a nonzero exit status if something went wrong, Rust assumes that if main returns at all, the program finished successfully."

This is in fact not required in C++, as per the C++ standard:

eel.is/c++draft/basic.start.main#5

Bart Louwers  Oct 02, 2022 
Printed Page 15 (and later)
General

1. The actix_gcd example fails to build under Windows, with a compilation error for the futures-core V0.3.21 crate.
This most annoying as Windows is my "main" working environment.
I did a build on a Ubuntu Linux VM where the build worked and then ran as expected.
In both cases, I used the default Rust setup and the example files as supplied.
2. The Mandelbrot example fails to build under both environments.
3. Since two years have elapsed since the book was published, you probably need to do a QA run of cargo build's on all the examples.

Daniel Feiglin  Nov 29, 2023 
ePub Page 18
Code doesn't compile

So the section 'Serving Pages to the Web' in Chapter 2 on page 18 gives me the following error:
cookie.set_expires(time::now() - Duration::days(365));
| ^ no implementation for `Tm - chrono::Duration`
|
= help: the trait `Sub<chrono::Duration>` is not implemented for `Tm`
= help: the following other types implement trait `Sub<Rhs>`:
<Tm as Sub<time::Duration>>
<Tm as Sub>
_____
The compiler doesn't even reach my code, so it must be an issue with dependencies.
Based on this Reddit post, other people are getting the same error:
Search for reddit and working_through_programming_rust_2nd_edition_got to see it.

Scott  Oct 30, 2023 
Printed Page 32f.
code blocks

escape_time never returns 0, thus 255 - count will never result in 255, thus the image will never contain truly white pixels.

xehpuk  Aug 02, 2021 
Printed Page 35, 36
final paragraph

At page page 35, the book makes the user write `if args.len() != 5` in order to prevent the program from running in case the wrong amount of arguments is passed to the terminal.
Afterwards, at page 36, it asks the user to run `time .\target\release\mandelbrot mandel.png 4300x3000 -1.20,0.30 -1.0,0.20` to verify that the program is running correctly (and check how long it takes to run).

The issue is that - at least on Windows - when you use commas in the terminal, they are considered separators. This means that `time .\target\release\mandelbrot mandel1.png 4000x3000 -1.20,0.35 -1.0,0.20` gets separated as `[".\target\release\mandelbrot", "mandel.png", "4000x3000", "-1.20", "0.35" , "-1.0", "0.20"]` (length 7, hence not allowed) instead of being separated as `[".\target\release\mandelbrot", "mandel.png", "4000x3000", "-1.20,0.35" , "-1.0,0.20"]` (length 5).

My solution to this was simply to `':'` as a separator of the pairs, rather than `','`

Best,

Alex

Alex Camilleri  Jul 18, 2022 
Printed Page 37
legend of Figure 2-6

It reads “parallel” but this is the result of the nonconcurrent version from page 35.

xehpuk  Aug 02, 2021 
Printed Page 38f.
2nd line of code block

rows_per_band is supposed to be rounded upward, but it isn't really.
With bounds.1 set to e.g. 64 (a multiple of threads), this would result in 9 instead of 8.
This should work: let rows_per_band = (bounds.1 as f32 / threads as f32).ceil() as usize;

xehpuk  Aug 02, 2021 
Printed Page 47
2nd half

The book instructs the user to create a file via the echo command, using `echo "Hello, world" > test.txt`

When done in Windows (via cmd or PowerShell) this will result in the file getting a UTF-16 with BOM encoding.

Consequently, when running `cargo run "world" "Rust" test.txt test-modified.txt`, the program fails, with the error

```
error: failed to read from file '.\test.txt': Error { kind: InvalidData, message: "stream did not contain valid UTF-8" }
error: process didn't exit successfully: `target\debug\quickreplace.exe world Rust .\test.txt .\test-modified.txt` (exit code: 1)
```

The workaround is to create the file from outside the terminal.

Alex Camilleri  Jul 27, 2022 
PDF Page 75
Chapter 3 - Fundamental Types. String Types, 3rd Paragraph

The 3rd paragraph says
"A string literal is a &str that refers to preallocated text, typically stored in read-only memory along with the program’s machine code. In the preceding example, poodles is a string literal, pointing to seven bytes that are created when the program begins execution and that last until it exits."

This gave me the impression that poodles would exist in the program code and behave more like constants.

So I wrote this simple code to test that understanding
fn main {
{
// that persist till the program finished/
let crymoji = "ಠ_ಠ";
}
println!("crymoji: {}", crymoji);
}

and got this compiler error, which goes ahead to says that &str obey the ownership rules, hence it is deleted from memory when the program leaves its scope.

error[E0425]: cannot find value `crymoji` in this scope
--> fundamental_types.rs:135:29
|
135 | println!("crymoji: {}", crymoji);
| ^^^^^^^ not found in this scope

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.


My opinion is that the text book should state that &str persist in memory through out the program execution when they are declared.

Rasheed Starlet  Feb 23, 2023 
PDF Page 106
Last line of the second code snippet

For the last statement `assert!(*m == 64);`, the corresponding comment is:

// and to see y's new value

But if you want to see y's new value, why not just use y like `assert!(y == 64)`? This is more direct and clear.

Yang Shuai  Jul 28, 2021 
Printed Page 199
last code block

There's this comment:

/// If either range is empty, they don't count as overlapping.
///
/// assert_eq!(ranges::overlap(0..0, 0..10), false);

While the comment is true, the test is not appropriate, as this would also pass:

/// assert_eq!(ranges::overlap(0..1, 1..10), false);

A better test would be:

/// assert_eq!(ranges::overlap(1..1, 0..10), false);

xehpuk  Aug 14, 2021 
PDF Page 257
Trait Object Layout

At the very beginning of section: "Trait Object Layout"

Should the quoted text "In memory, a trait object is a fat pointer" be "In memory, a reference to trait object is a fat pointer"? I think that would be more accurate.

Joshua Tang  Jan 27, 2023 
Printed Page 266
4th paragraph

"it's easy to bound" should be "it's easy to bind"

Tom  Jun 03, 2022 
Printed Page 306
Last paragraph.

The following is incorrect or requires more clarification since the `Box` is sized and makes it possible to invoke a method:

"...nor can you invoke a method on a `Box<dyn Write>`..."

Given the presented comparison between sized and unsized types, the correction would be:

"...nor can you invoke a method on a `dyn Write...`"

Anonymous  Feb 02, 2024 
PDF Page 310
First sentence of the second to last paragraph

The following text

> The deref and deref_mut methods take a &Self reference and return a
&Self::Target reference.

should be changed to

The deref method takes a &Self reference and returns a
&Self::Target reference, while deref_mut takes a &mut Self and returns a &mut Self::Target.

Yang Shuai  Aug 20, 2021 
Mobi Page 332
Two paragraphs before the section "Closure Performance"

"a closure is callable, but it's not a fn"

Suggested: "a closure is a callable, but it's not an fn if it captures from its environment"

Jorge Rinaldi  Aug 22, 2022 
Mobi Page 340
Entire thing

The "Serving Pages to the Web" section of Chapter 2 makes use of the gcd function, which is defined in the previous section. But the "web" section creates a new project, and nowhere is it mentioned that one should copy and paste the gcd function from the previous example. The project in its current form in the text can't be run.

Even Solberg  Jul 03, 2021 
Printed Page 452-456
Tables 17-4, 17-5, 17-6, 17-7

Some formatted strings which have minimum widths applied are displayed with fewer spaces than should actually be output.

For example (from table 17-4), format!("{:8.2} km/s", 11.186) should result in " 11.19 km/s" (prefixed with 3 spaces) but is shown with just a single space at the beginning.

This seems to be consistent across all examples that would require more than one consecutive space in the output.

D Patrick  Sep 20, 2021 
Printed Page 485
io::stdin() section

It is no longer necessary to split the `io::stdin()` call from a `lock()` call, and likewise for `io::stdout(), io::stderr()`. The following compiles fine on the Rust playground:

```
use std::io::{stdin, BufRead};

fn main() {
let lines = stdin().lock().lines();
for line in lines {
println!("{}", line.unwrap())
}
}```

Anonymous  Nov 19, 2022 
Printed Page 564
3rd paragraph

"For security, verifying a password needs to be computationally intensive so that even if attackers [...] they can't simply try trillions of possible passwords".

That's not at all how it works with cryptography and the author should probably remove this statement because it's very misleading.

The verification process always aims at saving as much CPU power as possible and the protection only relies on the key (and the algorithm) to provide strong security. Of course the general idea is to make a brute-force attack impractical, but that doesn't mean long computational time is mandatory. Then there are other techniques like a voluntary pause between attempts.

For example, the hashing operation the author is mentioning and which is used to verify passwords on Unix and similar OSes, is not intensive at all.

With public-key cryptography this is even more obvious since the public key used for verification is chosen to be as simple as possible to limit the number of operations.

Tom  Jun 30, 2022 
Printed Page 615
3rd paragraph

In the sentence: "We'd be pasting JSON data..", the apostrophe of "We'd" seems to be unspaced. That is, "We" and "d" are concatenated without a space.

Kris van Rens  Feb 04, 2022 
Printed Page 688
Second to last parag

The text in the book is "The RefWithFlag example earlier in this chapter", but the RefWithFlag example was introduced one chapter before - in Chapter 22 about unsafe code.

so
"The RefWithFlag example earlier in this chapter" -> "The RefWithFlag example earlier in the previous chapter"

Pavel Shirshov  May 29, 2022 
Printed Page 693
Index -> Symbols -> "=> operator"

The index lists the "=>" operator with page 152, but this page/section is for "Arithmethic, Bitwise, Comparison, and Logical Operators". The correct page should be 141 which talks about "if and match" (page 140 ff.).

Anonymous  Jul 24, 2022