本章要回答的三个问题:Rust 的类型系统严格到什么程度?为什么变量默认不可变?函数与控制流有哪些和别的语言不一样的判例?
正式庭审(所有权)之前要先过初审:类型不匹配、可变性违规、隐式转换,这些"轻罪"占了新手报错的大头。初审的规则简单但执行得不留情面——Rust 不做隐式数值转换,一个 i32 塞给 u8 的形参当场驳回。把这些基础判例吃透,第 3 章的所有权庭审才不会被基础报错干扰。
| 节 | 回答哪个问题 | 关键产出 |
|---|---|---|
| 2.1 类型系统 | 有哪些类型、严格在哪 | 标量与复合类型对照、E0308 案例两则 |
| 2.2 变量与可变性 | 默认不可变是限制还是保护 | mut 声明、遮蔽与可变的区别 |
| 2.3 函数与控制流 | 语句与表达式怎么分 | 表达式求值写法、match 初见 |
类型与作用域就位后,第 3 章开庭审所有权——那里每个判例都建立在本章的作用域概念上。
第 2 章立的法条看似零散,落到排错时全都有编号可查,先备一张速查表。
| 主题 | 易错点 | 判罚编号 |
|---|---|---|
| 类型转换 | as 截断、期望与实际不符 | E0308 |
| 可变性 | 借不可变变量为可变 | E0596 |
| 遮蔽 | 误以为遮蔽等于原地修改 | 无报错,语义事故 |
| 溢出 | debug 与 release 判罚不同 | 无报错,方言陷阱 |
| 控制流 | match 不穷尽 | E0004 |
其中"无报错"的两条最危险:编译器无法替你把关,只能靠写法纪律——显式用 wrapping_*/checked_* 表达溢出意图,用类型不同的遮蔽链表达转换管线。
本章所有变量都在栈上办公,尚无人持有堆资源,所以判例都轻。第 3 章一旦引入 String 与 Vec,"赋值"就分化为复制与移动两种判决,E0382 会开始大量出庭。建议带着这个问题进入下一章:let s2 = s1; 之后 s1 还能用吗——如果这个问题让你犹豫超过两秒,说明该开庭了。
另立一条阅读纪律:本章的每个代码示例都应当亲手改坏一次。把 let 改成 const、把 match 少写一个分支、把 u8 相加到 300,看编译器如何逐条点名。报错读得越多,下一章的所有权庭审就越像复习而不是新案。
本章结束前逐项确认:能说清 as、try_into、clamp 三种转换的适用差异;能解释 shadowing 与 mut 的分界并各举一例;能默写三选题——i32 默认、usize 用途、char 宽度;能不用 _ 写出穷尽的 match;知道 debug 与 release 下溢出判罚为何不同。五项全过,第 3 章的所有权庭审就可以开庭了;任何一项含糊,对应小节重读十分钟就能补上,欠账到第 3 章会被借用检查器加倍追讨。
| 教材术语 | 对应概念 | 常见误称 |
|---|---|---|
| 遮蔽 | 同名新绑定顶替旧绑定 | "重新赋值" |
| 复制语义 | Copy 类型的按位复制 | "浅拷贝" |
| 穷尽性 | match 覆盖全部形态 | "分支完整" |
| turbofish | 调用处显式类型参数 ::<T> |
"泛型标注" |
误称不是咬文嚼字问题:把遮蔽说成重新赋值的人,往往也在期待旧值随新值改变,这正是下一个报错的种子。术语对齐之后,第 3 章的"移动"一词才能落在实处。