Add: windows mvp - transparent bugs not fixed

This commit is contained in:
DaZuo0122
2026-02-12 22:58:33 +08:00
commit 61825f647d
147 changed files with 28498 additions and 0 deletions

View File

@@ -0,0 +1,177 @@
---
name: m14-mental-model
description: "Use when learning Rust concepts. Keywords: mental model, how to think about ownership, understanding borrow checker, visualizing memory layout, analogy, misconception, explaining ownership, why does Rust, help me understand, confused about, learning Rust, explain like I'm, ELI5, intuition for, coming from Java, coming from Python, 心智模型, 如何理解所有权, 学习 Rust, Rust 入门, 为什么 Rust"
user-invocable: false
---
# Mental Models
> **Layer 2: Design Choices**
## Core Question
**What's the right way to think about this Rust concept?**
When learning or explaining Rust:
- What's the correct mental model?
- What misconceptions should be avoided?
- What analogies help understanding?
---
## Key Mental Models
| Concept | Mental Model | Analogy |
|---------|--------------|---------|
| Ownership | Unique key | Only one person has the house key |
| Move | Key handover | Giving away your key |
| `&T` | Lending for reading | Lending a book |
| `&mut T` | Exclusive editing | Only you can edit the doc |
| Lifetime `'a` | Valid scope | "Ticket valid until..." |
| `Box<T>` | Heap pointer | Remote control to TV |
| `Rc<T>` | Shared ownership | Multiple remotes, last turns off |
| `Arc<T>` | Thread-safe Rc | Remotes from any room |
---
## Coming From Other Languages
| From | Key Shift |
|------|-----------|
| Java/C# | Values are owned, not references by default |
| C/C++ | Compiler enforces safety rules |
| Python/Go | No GC, deterministic destruction |
| Functional | Mutability is safe via ownership |
| JavaScript | No null, use Option instead |
---
## Thinking Prompt
When confused about Rust:
1. **What's the ownership model?**
- Who owns this data?
- How long does it live?
- Who can access it?
2. **What guarantee is Rust providing?**
- No data races
- No dangling pointers
- No use-after-free
3. **What's the compiler telling me?**
- Error = violation of safety rule
- Solution = work with the rules
---
## Trace Up ↑
To design understanding (Layer 2):
```
"Why can't I do X in Rust?"
↑ Ask: What safety guarantee would be violated?
↑ Check: m01-m07 for the rule being enforced
↑ Ask: What's the intended design pattern?
```
---
## Trace Down ↓
To implementation (Layer 1):
```
"I understand the concept, now how do I implement?"
↓ m01-ownership: Ownership patterns
↓ m02-resource: Smart pointer choice
↓ m07-concurrency: Thread safety
```
---
## Common Misconceptions
| Error | Wrong Model | Correct Model |
|-------|-------------|---------------|
| E0382 use after move | GC cleans up | Ownership = unique key transfer |
| E0502 borrow conflict | Multiple writers OK | Only one writer at a time |
| E0499 multiple mut borrows | Aliased mutation | Exclusive access for mutation |
| E0106 missing lifetime | Ignoring scope | References have validity scope |
| E0507 cannot move from `&T` | Implicit clone | References don't own data |
## Deprecated Thinking
| Deprecated | Better |
|------------|--------|
| "Rust is like C++" | Different ownership model |
| "Lifetimes are GC" | Compile-time validity scope |
| "Clone solves everything" | Restructure ownership |
| "Fight the borrow checker" | Work with the compiler |
| "`unsafe` to avoid rules" | Understand safe patterns first |
---
## Ownership Visualization
```
Stack Heap
+----------------+ +----------------+
| main() | | |
| s1 ─────────────────────> │ "hello" |
| | | |
| fn takes(s) { | | |
| s2 (moved) ─────────────> │ "hello" |
| } | | (s1 invalid) |
+----------------+ +----------------+
After move: s1 is no longer valid
```
## Reference Visualization
```
+----------------+
| data: String |────────────> "hello"
+----------------+
│ &data (immutable borrow)
+------+------+
| reader1 reader2 (multiple OK)
+------+------+
+----------------+
| data: String |────────────> "hello"
+----------------+
│ &mut data (mutable borrow)
+------+
| writer (only one)
+------+
```
---
## Learning Path
| Stage | Focus | Skills |
|-------|-------|--------|
| Beginner | Ownership basics | m01-ownership, m14-mental-model |
| Intermediate | Smart pointers, error handling | m02, m06 |
| Advanced | Concurrency, unsafe | m07, unsafe-checker |
| Expert | Design patterns | m09-m15, domain-* |
---
## Related Skills
| When | See |
|------|-----|
| Ownership errors | m01-ownership |
| Smart pointers | m02-resource |
| Concurrency | m07-concurrency |
| Anti-patterns | m15-anti-pattern |

View File

@@ -0,0 +1,286 @@
# Thinking in Rust: Mental Models
## Core Mental Models
### 1. Ownership as Resource Management
```
Traditional: "Who has a pointer to this data?"
Rust: "Who OWNS this data and is responsible for freeing it?"
```
Key insight: Every value has exactly one owner. When the owner goes out of scope, the value is dropped.
```rust
{
let s = String::from("hello"); // s owns the String
// use s...
} // s goes out of scope, String is dropped (memory freed)
```
### 2. Borrowing as Temporary Access
```
Traditional: "I'll just read from this pointer"
Rust: "I'm borrowing this value, owner still responsible for it"
```
Key insight: Borrows are like library books - you can read them, but must return them.
```rust
fn print_length(s: &String) { // borrows s
println!("{}", s.len());
} // borrow ends, caller still owns s
let my_string = String::from("hello");
print_length(&my_string); // lend to function
println!("{}", my_string); // still have it
```
### 3. Lifetimes as Validity Scopes
```
Traditional: "Hope this pointer is still valid"
Rust: "Compiler tracks exactly how long references are valid"
```
Key insight: A reference can't outlive the data it points to.
```rust
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
// 'a means: the returned reference is valid as long as BOTH inputs are valid
if x.len() > y.len() { x } else { y }
}
```
---
## Shifting Perspectives
### From "Everything is a Reference" (Java/C#)
Java mental model:
```java
// Everything is implicitly a reference
User user = new User("Alice"); // user is a reference
List<User> users = new ArrayList<>();
users.add(user); // shares the reference
user.setName("Bob"); // affects the list too!
```
Rust mental model:
```rust
// Values are owned, sharing is explicit
let user = User::new("Alice"); // user is owned
let mut users = vec![];
users.push(user); // user moved into vec, can't use user anymore
// user.set_name("Bob"); // ERROR: user was moved
// If you need sharing:
use std::rc::Rc;
let user = Rc::new(User::new("Alice"));
let user2 = Rc::clone(&user); // explicit shared ownership
```
### From "Manual Memory Management" (C/C++)
C mental model:
```c
char* s = malloc(100);
// ... must remember to free(s) ...
// ... what if we return early? ...
// ... what if an exception occurs? ...
free(s);
```
Rust mental model:
```rust
let s = String::with_capacity(100);
// ... use s ...
// No need to free - Rust drops s automatically when scope ends
// Even with early returns, panics, or any control flow
```
### From "Garbage Collection" (Go/Python)
GC mental model:
```python
# Create objects, GC will figure it out
users = []
for name in names:
users.append(User(name))
# GC runs sometime later, when it feels like it
```
Rust mental model:
```rust
let users: Vec<User> = names
.iter()
.map(|name| User::new(name))
.collect();
// Memory is freed EXACTLY when users goes out of scope
// Deterministic, no GC pauses, no unpredictable memory usage
```
---
## Key Questions to Ask
### When Designing Functions
1. **Does this function need to own the data, or just read it?**
- Need to keep it: take ownership (`fn process(data: Vec<T>)`)
- Just reading: borrow (`fn process(data: &[T])`)
- Need to modify: mutable borrow (`fn process(data: &mut Vec<T>)`)
2. **Does the return value contain references to inputs?**
- Yes: need lifetime annotations
- No: lifetime elision usually works
### When Designing Structs
1. **Should this struct own its data or reference it?**
- Long-lived, independent: own (`name: String`)
- Short-lived view: reference (`name: &'a str`)
2. **Do multiple parts need to access the same data?**
- Single-threaded: `Rc<T>` or `Rc<RefCell<T>>`
- Multi-threaded: `Arc<T>` or `Arc<Mutex<T>>`
### When Hitting Borrow Checker Errors
1. **Am I trying to use a value after moving it?**
- Clone it, borrow it, or restructure the code
2. **Am I trying to have multiple mutable references?**
- Scope the mutations, use interior mutability, or redesign
3. **Does a reference outlive its source?**
- Return owned data instead, or use `'static`
---
## Common Patterns
### The Clone Escape Hatch
When fighting the borrow checker, `.clone()` often works:
```rust
// Can't do this - double borrow
let mut map = HashMap::new();
for key in map.keys() {
map.insert(key.clone(), process(key)); // ERROR: map borrowed twice
}
// Clone to escape
let keys: Vec<_> = map.keys().cloned().collect();
for key in keys {
map.insert(key.clone(), process(&key)); // OK
}
```
But ask: "Is there a better design?" Often, restructuring is better than cloning.
### The "Make It Own" Pattern
When lifetimes get complex, make the struct own its data:
```rust
// Complex: struct with references
struct Parser<'a> {
input: &'a str,
current: &'a str,
}
// Simpler: struct owns data
struct Parser {
input: String,
position: usize,
}
```
### The "Split the Borrow" Pattern
```rust
struct Data {
field_a: Vec<i32>,
field_b: Vec<i32>,
}
// Can't borrow self mutably twice
fn process(&mut self) {
// for a in &self.field_a {
// self.field_b.push(*a); // ERROR
// }
// Split the borrow
let Data { field_a, field_b } = self;
for a in field_a.iter() {
field_b.push(*a); // OK: separate borrows
}
}
```
---
## The Rust Way
### Embrace the Type System
```rust
// Don't: stringly-typed
fn connect(host: &str, port: &str) { ... }
connect("8080", "localhost"); // oops, wrong order
// Do: strongly-typed
struct Host(String);
struct Port(u16);
fn connect(host: Host, port: Port) { ... }
// connect(Port(8080), Host("localhost".into())); // compile error!
```
### Make Invalid States Unrepresentable
```rust
// Don't: runtime checks
struct Connection {
socket: Option<Socket>,
connected: bool,
}
// Do: types enforce states
enum Connection {
Disconnected,
Connected { socket: Socket },
}
```
### Let the Compiler Guide You
```rust
// Start with what you want
fn process(data: ???) -> ???
// Let compiler errors tell you:
// - What types are needed
// - What lifetimes are needed
// - What bounds are needed
// The error messages are documentation!
```
---
## Summary: The Rust Mental Model
1. **Values have owners** - exactly one at a time
2. **Borrowing is lending** - temporary access, owner retains responsibility
3. **Lifetimes are scopes** - compiler tracks validity
4. **Types encode constraints** - use them to prevent bugs
5. **The compiler is your friend** - work with it, not against it
When stuck:
- Clone to make progress
- Restructure to own instead of borrow
- Ask: "What is the compiler trying to tell me?"