Skip to content

Commit

Permalink
Various small fixes
Browse files Browse the repository at this point in the history
Plus one more substantial comment on casting.
  • Loading branch information
marshallpierce committed Dec 5, 2023
1 parent 8f9902c commit ae10c46
Show file tree
Hide file tree
Showing 16 changed files with 23 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/borrowing/borrowck.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn main() {
* The above code does not compile because `a` is borrowed as mutable (through `c`) and as immutable (through `b`) at the same time.
* Move the `println!` statement for `b` before the scope that introduces `c` to make the code compile.
* After that change, the compiler realizes that `b` is only ever used before the new mutable borrow of `a` through `c`. This is a feature of the borrow checker called "non-lexical lifetimes".
* The exclusive reference constraint is quite strong. Rust uses it to ensure that data races do not occur. Rust also _relies_ on this constraint to optimize codes. For example, a value behind a shared reference can be safely cached in a register for the lifetime of that reference.
* The exclusive reference constraint is quite strong. Rust uses it to ensure that data races do not occur. Rust also _relies_ on this constraint to optimize code. For example, a value behind a shared reference can be safely cached in a register for the lifetime of that reference.
* The borrow checker is designed to accommodate many common patterns, such as taking exclusive references to different fields in a struct at the same time. But, there are some situations where it doesn't quite "get it" and this often results in "fighting with the borrow checker."

</details>
2 changes: 1 addition & 1 deletion src/borrowing/shared.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ Notes on stack returns:

</details>

[Playground]: https://play.rust-lang.org/
[Playground]: https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=0cb13be1c05d7e3446686ad9947c4671
2 changes: 1 addition & 1 deletion src/control-flow-basics/blocks-and-scopes.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn main() {
<details>

* You can show how the value of the block changes by changing the last line in the block. For instance, adding/removing a semicolon or using a `return`.
* Show that a variable's scope is limited by adding a b` in the inner block in the last example, and then trying to access it outside that block.
* Show that a variable's scope is limited by adding a `b` in the inner block in the last example, and then trying to access it outside that block.
* Shadowing is different from mutation, because after shadowing both variable's memory locations exist at the same time. Both are available under the same name, depending where you use it in the code.
* A shadowing variable can have a different type.
* Shadowing looks obscure at first, but is convenient for holding on to values after `.unwrap()`.
Expand Down
4 changes: 2 additions & 2 deletions src/memory-management/exercise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,12 @@ impl PackageBuilder {
fn main() {
let base64 = PackageBuilder::new("base64").version("0.13").build();
println!("base64: {base64:?}");
let log = PackageBuilder::new("base64")
let log = PackageBuilder::new("log")
.version("0.4")
.language(Language::Rust)
.build();
println!("log: {log:?}");
let serde = PackageBuilder::new("hawk")
let serde = PackageBuilder::new("serde")
.authors(vec!["djmitche".into()])
.version(String::from("4.0"))
.dependency(base64.as_dependency())
Expand Down
1 change: 0 additions & 1 deletion src/methods-and-traits/methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,5 @@ Key Points:
* Note how `self` is used like other structs and dot notation can be used to refer to individual fields.
* This might be a good time to demonstrate how the `&self` differs from `self` by trying to run `finish` twice.
* Beyond variants on `self`, there are also [special wrapper types](https://doc.rust-lang.org/reference/special-types-and-traits.html) allowed to be receiver types, such as `Box<Self>`.
* Note that references have not been covered yet. References in method receivers are a particularly "natural" form of reference, so there is no need to go into a great level of detail.

</details>
2 changes: 1 addition & 1 deletion src/pattern-matching/let-control-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ fn main() {
For the common case of matching a pattern and returning from the function, use
[`let
else`](https://doc.rust-lang.org/rust-by-example/flow_control/let_else.html).
The "else" case must diverge (`return`, `break`, or panic - anything but
The "else" case must evaluate to the same type as the `if` block, or diverge (`return`, `break`, or panic - anything but
falling off the end of the block).

```rust,editable
Expand Down
2 changes: 1 addition & 1 deletion src/running-the-course.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Before you run the course, you will want to:
popup (click the link with a little arrow next to "Speaker Notes"). This way
you have a clean screen to present to the class.

1. Decide on the dates. Since the course takes at least three full days, we recommend that you
1. Decide on the dates. Since the course takes four days, we recommend that you
schedule the days over two weeks. Course participants have said that
they find it helpful to have a gap in the course since it helps them process
all the information we give them.
Expand Down
4 changes: 2 additions & 2 deletions src/running-the-course/course-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
## Rust Fundamentals

The first three days make up [Rust Fundaments](../welcome-day-1.md).
The first four days make up [Rust Fundaments](../welcome-day-1.md).
The days are fast paced and we cover a lot of ground!

{{%course outline Fundamentals}}

## Deep Dives

In addition to the 3-day class on Rust Fundamentals, we cover some more
In addition to the 4-day class on Rust Fundamentals, we cover some more
specialized topics:

### Rust in Android
Expand Down
2 changes: 1 addition & 1 deletion src/slices-and-lifetimes/lifetime-elision.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ The `nearest` function provides another example of a function with multiple refe
Try adjusting the signature to "lie" about the lifetimes returned:

```rust,ignore
fn nearest<'a>(points: &'a [Point], query: &'q Point) -> Option<&'q Point> {
fn nearest<'a, 'q'>(points: &'a [Point], query: &'q Point) -> Option<&'q Point> {
```

This won't compile, demonstrating that the annotations are checked for validity
Expand Down
2 changes: 1 addition & 1 deletion src/slices-and-lifetimes/slices.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ fn main() {

* The question about modifying `a[3]` can spark an interesting discussion, but the answer is that for memory safety reasons
you cannot do it through `a` at this point in the execution, but you can read the data from both `a` and `s` safely.
It works before you created the slice, and again after the `println`, when the slice is no longer used. More details will be explained in the borrow checker section.
It works before you created the slice, and again after the `println`, when the slice is no longer used.

</details>
2 changes: 1 addition & 1 deletion src/smart-pointers/rc.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ fn main() {
* Use `Rc::strong_count` to check the reference count.
* `Rc::downgrade` gives you a *weakly reference-counted* object to
create cycles that will be dropped properly (likely in combination with
`RefCell`, on the next slide).
`RefCell`).

</details>
5 changes: 5 additions & 0 deletions src/std-traits/casting.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ The results of `as` are _always_ defined in Rust and consistent across
platforms. This might not match your intuition for changing sign or casting to
a smaller type -- check the docs, and comment for clarity.

Casting with `as` is a relatively sharp tool that is easy to use incorrectly, and can be a source of subtle bugs as future maintenance work changes the types that are used or the ranges of values in types. Casts are best used only when the intent is to indicate unconditional truncation (e.g. selecting the bottom 32 bits of a `u64` with `as u32`, regardless of what was in the high bits).

For infallible casts (e.g. `u32` to `u64`), prefer using `From` or `Into` over `as`
to confirm that the cast is in fact infallible. For fallible casts, `TryFrom` and `TryInto` are available when you want to handle casts that fit differently from those that don't.

<details>

Consider taking a break after this slide.
Expand Down
6 changes: 3 additions & 3 deletions src/std-traits/default.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ fn main() {
* A derived implementation will produce a value where all fields are set to their default values.
* This means all types in the struct must implement `Default` too.
* Standard Rust types often implement `Default` with reasonable values (e.g. `0`, `""`, etc).
* The partial struct copy works nicely with default.
* Rust standard library is aware that types can implement `Default` and provides convenience methods that use it.
* the `..` syntax is called [struct update syntax][2]
* The partial struct initialization works nicely with default.
* The Rust standard library is aware that types can implement `Default` and provides convenience methods that use it.
* The `..` syntax is called [struct update syntax][2].

</details>

Expand Down
4 changes: 2 additions & 2 deletions src/std-traits/from-and-into.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn main() {
let s = String::from("hello");
let addr = std::net::Ipv4Addr::from([127, 0, 0, 1]);
let one = i16::from(true);
let bigger = i32::from(123i16);
let bigger = i32::from(123_i16);
println!("{s}, {addr}, {one}, {bigger}");
}
```
Expand All @@ -23,7 +23,7 @@ fn main() {
let s: String = "hello".into();
let addr: std::net::Ipv4Addr = [127, 0, 0, 1].into();
let one: i16 = true.into();
let bigger: i32 = 123i16.into();
let bigger: i32 = 123_i16.into();
println!("{s}, {addr}, {one}, {bigger}");
}
```
Expand Down
3 changes: 0 additions & 3 deletions src/user-defined-types/enums.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ Key Points:
Rust has several optimizations it can employ to make enums take up less space.
* Niche optimization: Rust will merge unused bit patterns for the enum
discriminant.
* Null pointer optimization: For [some
types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees
that `size_of::<T>()` equals `size_of::<Option<T>>()`.
Expand Down
2 changes: 1 addition & 1 deletion src/user-defined-types/named-structs.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ Key Points:
* The next slide will introduce Tuple structs, used when the field names are not important.
* If you already have variables with the right names, then you can create the
struct using a shorthand.
* The syntax `..peter` allows us to copy the majority of the fields from the old struct without having to explicitly type it all out. It must always be the last element.
* The syntax `..avery` allows us to copy the majority of the fields from the old struct without having to explicitly type it all out. It must always be the last element.

</details>

0 comments on commit ae10c46

Please sign in to comment.