1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-03-27 16:25:43 +02:00

Reorganize borrowck notes and add note about re-borrowing (#2635)

The speaker notes on the borrowck slide are a bit hard to read since
it's a big block of bulleted points. I've reorganized the notes to be a
bit easier to read by making some of the bullet points nested and by
moving some of the points to the "More to Explore" section. I've also
added a note on re-borrowing since students sometimes ask about it, and
I've added some playground links to demonstrate some of the points.
This commit is contained in:
Nicole L 2025-02-07 14:05:27 -08:00 committed by GitHub
parent 386757e697
commit f9aca3738a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -47,26 +47,40 @@ fn main() {
- The "outlives" rule was demonstrated previously when we first looked at
references. We review it here to show students that the borrow checking is
following a few different rules to validate borrowing.
- Note that the requirement is that conflicting references not _exist_ at the
same point. It does not matter where the reference is dereferenced.
- The above code does not compile because `a` is borrowed as mutable (through
`c`) and as immutable (through `b`) at the same time.
- Note that the intermediate reference `c` isn't necessary to trigger a borrow
conflict. Replace `c` with a direct mutation of `a` and demonstrate that this
produces a similar error. This is because direct mutation of a value
effectively creates a temporary mutable reference.
- Note that the requirement is that conflicting references not _exist_ at the
same point. It does not matter where the reference is dereferenced. Try
commenting out `*c = 20` and show that the compiler error still occurs even
if we never use `c`.
- Note that the intermediate reference `c` isn't necessary to trigger a borrow
conflict. Replace `c` with a direct mutation of `a` and demonstrate that
this produces a similar error. This is because direct mutation of a value
effectively creates a temporary mutable reference.
- 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 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."
- 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".
## More to Explore
- Technically multiple mutable references to a piece of data can exist at the
same time via re-borrowing. This is what allows you to pass a mutable
reference into a function without invaliding the original reference.
[This playground example][1] demonstrates that behavior.
- Rust uses the exclusive reference constraint to ensure that data races do not
occur in multi-threaded code, since only one thread can have mutable access to
a piece of data at a time.
- Rust also uses 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.
- Fields of a struct can be borrowed independently of each other, but calling a
method on a struct will borrow the whole struct, potentially invalidating
references to individual fields. See [this playground snippet][2] for an
example of this.
</details>
[1]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8f5896878611566845fe3b0f4dc5af68
[2]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f293a31f2d4d0d31770486247c2e8437