Skip to content

Commit dda5b4e

Browse files
committed
.
1 parent 3488d55 commit dda5b4e

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
[Website](https://qouteall.fun/qouteall-blog/)
3+
4+
If you have any suggestion, please submit in [GitHub discussion](https://github.com/qouteall/qouteall-blog/discussions).

blog/2025/How to Avoid Fighting Rust Borrow Checker.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ One benefit of interior pointer is to allow tight memory layout, without having
536536

537537
### Interior mutability summary
538538

539-
Mutable borrow exclusiveness is overly restrictive. It is not necessary for memory safety in single-threaded code. It's also . there is **interior mutability** that allows getting rid of that constraint.
539+
Mutable borrow exclusiveness is overly restrictive. It is not necessary for memory safety in single-threaded code when not using interior pointer. There is **interior mutability** that allows getting rid of that constraint.
540540

541541
Interior mutability allows you to mutate something from an immutable reference to it. (Because of that, immutable borrow doesn't necessarily mean the pointed data is actually immutable. This can cause some confusion.)
542542

@@ -582,7 +582,7 @@ In Rust, just having a mutable borrow `&mut T`, **Rust assumes that you can use
582582

583583
Another problem: It's hard to return a reference borrowed from `RefCell`.
584584

585-
As the previous example can be fixed by `Cell`, without `RefCell`, here is another contagious borrow exampleL
585+
As the previous example can be fixed by `Cell`, without `RefCell`, here is another contagious borrow example:
586586

587587
```rust
588588
use std::collections::HashMap;
@@ -720,11 +720,11 @@ Similarily, `Arc` is the multi-threaded version of `Rc`. `Mutex` `RwLock` are th
720720

721721
[`QCell<T>`](https://docs.rs/qcell/latest/qcell/) has an internal ID. `QCellOwner` is also an ID. You can only use `QCell` via an `QCellOwner` that has matched ID.
722722

723-
The borrowing to `QCellOwner` "centralizes" the borrowing of many `QCell`s associated with it, ensureing mutable borrow exclusiveness. Using it require passing borrow of `QCellOwner` in argument everywhere it's used.
723+
The borrowing to `QCellOwner` "centralizes" the borrowing of many `QCell`s associated with it, ensuring mutable borrow exclusiveness. Using it require passing borrow of `QCellOwner` in argument everywhere it's used.
724724

725-
QCell will fail to borrow if the owner ID doesn't mismatch. Different to `RefCell`, if owner ID matches, it won't panic just because nested borrow.
725+
QCell will fail to borrow if the owner ID doesn't match. Different to `RefCell`, if owner ID matches, it won't panic just because nested borrow.
726726

727-
Its runtime cost is low: just check whether cell's id matches owner's id.
727+
Its runtime cost is low. When borrowing, it just checks whether cell's id matches owner's id. It has memory cost of owner ID per cell.
728728

729729
One advantage of `QCell` is that the duplicated borrow will be compile-time error instead of runtime panic, which helps catch error earlier. If I change the previous `RefCell` panic example into `QCell`:
730730

@@ -924,7 +924,15 @@ where
924924

925925
It requires the future need to be `Send` and `'static`:
926926

927-
- `'static` means that the future is standalone and doesn't borrow other things. If the future need to share data with outside, pass `Arc<T>` into (not `&Arc<T>`). (Note that the "static" here is different to "static" in C/C++/Java/C#. In Rust, borrowing global variable is `'static` but standalone values are also `'static`.)
927+
- `'static` means:
928+
- it's a standalone value that doesn't borrow other things, or
929+
- it references a global value that will always live when program is running, or
930+
- it only borrows global values
931+
932+
The future being `'static` often require the future be standalone and doesn't borrow other things. If the future need to share data with outside, pass `Arc<T>` into (not `&Arc<T>`).
933+
934+
Note that the "static" in C/C++/Java/C# often mean global value. But in Rust, `'static` can also mean mean standalone (owned) value that's not global.
935+
928936
- `Send` means that the future can be sent across threads. Tokio use work-stealing, which means that one thread's task can be stolen by other threads that currently have no work.
929937

930938
Another important trap is that, the normal sleep `std::thread::sleep` and normal locking `std::sync::Mutex` should not be used when using async runtime, because they block using OS functionality without telling async runtime, so they will block the async runtime's scheduling thread. In Tokio, use `tokio::sync::Mutex` and `tokio::time::sleep`.

0 commit comments

Comments
 (0)