Formatter (#51)

Enforce consistent formatting use `dprint`
This commit is contained in:
Luca Palmieri
2024-05-24 17:00:03 +02:00
committed by GitHub
parent 537118574b
commit 99591a715e
157 changed files with 1057 additions and 1044 deletions

View File

@@ -10,13 +10,13 @@ impl<T> Sender<T> {
}
```
`send` takes `&self` as its argument.
`send` takes `&self` as its argument.\
But it's clearly causing a mutation: it's adding a new message to the channel.
What's even more interesting is that `Sender` is cloneable: we can have multiple instances of `Sender`
trying to modify the channel state **at the same time**, from different threads.
That's the key property we are using to build this client-server architecture. But why does it work?
Doesn't it violate Rust's rules about borrowing? How are we performing mutations via an _immutable_ reference?
Doesn't it violate Rust's rules about borrowing? How are we performing mutations via an _immutable_ reference?
## Shared rather than immutable references
@@ -31,31 +31,31 @@ It would have been more accurate to name them:
- exclusive references (`&mut T`)
Immutable/mutable is a mental model that works for the vast majority of cases, and it's a great one to get started
with Rust. But it's not the whole story, as you've just seen: `&T` doesn't actually guarantee that the data it
points to is immutable.
Don't worry, though: Rust is still keeping its promises.
with Rust. But it's not the whole story, as you've just seen: `&T` doesn't actually guarantee that the data it
points to is immutable.\
Don't worry, though: Rust is still keeping its promises.
It's just that the terms are a bit more nuanced than they might seem at first.
## `UnsafeCell`
Whenever a type allows you to mutate data through a shared reference, you're dealing with **interior mutability**.
Whenever a type allows you to mutate data through a shared reference, you're dealing with **interior mutability**.
By default, the Rust compiler assumes that shared references are immutable. It **optimises your code** based on that assumption.
By default, the Rust compiler assumes that shared references are immutable. It **optimises your code** based on that assumption.\
The compiler can reorder operations, cache values, and do all sorts of magic to make your code faster.
You can tell the compiler "No, this shared reference is actually mutable" by wrapping the data in an `UnsafeCell`.
You can tell the compiler "No, this shared reference is actually mutable" by wrapping the data in an `UnsafeCell`.\
Every time you see a type that allows interior mutability, you can be certain that `UnsafeCell` is involved,
either directly or indirectly.
either directly or indirectly.\
Using `UnsafeCell`, raw pointers and `unsafe` code, you can mutate data through shared references.
Let's be clear, though: `UnsafeCell` isn't a magic wand that allows you to ignore the borrow-checker!
`unsafe` code is still subject to Rust's rules about borrowing and aliasing.
It's an (advanced) tool that you can leverage to build **safe abstractions** whose safety can't be directly expressed
in Rust's type system. Whenever you use the `unsafe` keyword you're telling the compiler:
Let's be clear, though: `UnsafeCell` isn't a magic wand that allows you to ignore the borrow-checker!\
`unsafe` code is still subject to Rust's rules about borrowing and aliasing.
It's an (advanced) tool that you can leverage to build **safe abstractions** whose safety can't be directly expressed
in Rust's type system. Whenever you use the `unsafe` keyword you're telling the compiler:
"I know what I'm doing, I won't violate your invariants, trust me."
Every time you call an `unsafe` function, there will be documentation explaining its **safety preconditions**:
under what circumstances it's safe to execute its `unsafe` block. You can find the ones for `UnsafeCell`
Every time you call an `unsafe` function, there will be documentation explaining its **safety preconditions**:
under what circumstances it's safe to execute its `unsafe` block. You can find the ones for `UnsafeCell`
[in `std`'s documentation](https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html).
We won't be using `UnsafeCell` directly in this course, nor will we be writing `unsafe` code.
@@ -64,15 +64,15 @@ every day in Rust.
## Key examples
Let's go through a couple of important `std` types that leverage interior mutability.
These are types that you'll encounter somewhat often in Rust code, especially if you peek under the hood of
Let's go through a couple of important `std` types that leverage interior mutability.\
These are types that you'll encounter somewhat often in Rust code, especially if you peek under the hood of
some the libraries you use.
### Reference counting
`Rc` is a reference-counted pointer.
It wraps around a value and keeps track of how many references to the value exist.
When the last reference is dropped, the value is deallocated.
`Rc` is a reference-counted pointer.\
It wraps around a value and keeps track of how many references to the value exist.
When the last reference is dropped, the value is deallocated.\
The value wrapped in an `Rc` is immutable: you can only get shared references to it.
```rust
@@ -91,7 +91,7 @@ assert_eq!(Rc::strong_count(&b), 2);
// and share the same reference counter.
```
`Rc` uses `UnsafeCell` internally to allow shared references to increment and decrement the reference count.
`Rc` uses `UnsafeCell` internally to allow shared references to increment and decrement the reference count.
### `RefCell`
@@ -99,7 +99,7 @@ assert_eq!(Rc::strong_count(&b), 2);
It allows you to mutate the value wrapped in a `RefCell` even if you only have an
immutable reference to the `RefCell` itself.
This is done via **runtime borrow checking**.
This is done via **runtime borrow checking**.
The `RefCell` keeps track of the number (and type) of references to the value it contains at runtime.
If you try to borrow the value mutably while it's already borrowed immutably,
the program will panic, ensuring that Rust's borrowing rules are always enforced.
@@ -111,4 +111,4 @@ let x = RefCell::new(42);
let y = x.borrow(); // Immutable borrow
let z = x.borrow_mut(); // Panics! There is an active immutable borrow.
```
```