Rust 编译器与运行时揭秘
从编译器视角拆解 Rust 语言的核心机制。
Rust 开发者每天都在使用所有权、借用、trait、async/await——但极少有人真正理解这些机制在编译器内部是如何实现的。为什么 borrow checker 能在编译期捕获悬垂引用?为什么 async fn 的返回值大小在编译期就能确定?为什么泛型函数调用没有运行时开销?
本专栏不教 Rust 语法。本专栏拆解 Rust 的编译器行为和运行时机制——从源码到 HIR、MIR、LLVM IR 再到机器码的完整链路中,每一个关键特性是如何被实现的。每一章聚焦一个核心机制,用"你写的代码"与"编译器生成的产物"对照的方式,让你真正理解 Rust 零成本抽象背后的工程实现。
这是 Rust 后端系列的第一个专栏。理解了 Rust 本身的编译期和运行时机制,后续阅读 Tokio、Axum、Pingora、MeiliSearch、TiKV 等项目的源码时,你将不会在任何 trait bound、lifetime、Pin 上卡住。
flowchart LR
SRC[你写的 Rust] --> HIR
subgraph HIR [HIR · 脱糖]
D1[".await 的真面目"] --- D2[闭包捕获]
end
HIR --> MIR
subgraph MIR [MIR · 语义检查与优化]
direction TB
BC["借用检查<br/>Place · BorrowSet"] --> LT[生命周期]
LT --> ST[StateTransform<br/>async fn → 状态机]
ST --> OPT[MIR 优化]
end
MIR --> MONO["单态化<br/>Instance · 收集算法"]
MONO --> LLVM[LLVM IR] --> MC[机器码]
LAY["类型布局<br/>Niche 优化 · 胖指针 · ZST"] -.贯穿.-> MIR
INC[增量编译] -.贯穿.-> MIR
这个专栏回答的是"编译器替我做了什么"。 borrow checker 凭什么在编译期就能断定悬垂引用?async fn 的返回值大小为什么编译期可知?泛型调用为什么没有运行时开销?—— 这三个问题的答案,分别在 MIR 上的借用检查算法、StateTransform 的六个步骤、和单态化收集里。
读完你能做到什么
- 说清借用检查到底在检查什么。 两条借用规则的数学基础、为什么运行在 MIR 上、
Place如何精确表示内存位置、BorrowSet记录了什么、算法怎么跑(第2章 所有权、第3章 借用检查器、第4章 生命周期)。 - 算得出一个类型占多少字节。 对齐与填充、struct 的两种字段排列策略、
repr属性、enum 的带标签联合体、Niche 优化怎么消除判别值、胖指针与 ZST,以及怎么亲手查看类型布局(第5章 内存布局)。 - 理解零成本抽象的代价在哪。 单态化为什么是 Rust 的选择、
Instance与收集算法、代码膨胀的真实成本,以及静态分发与 trait object 的分界(第6章 单态化、第7章 trait 分发、第8章 trait object)。 - 看穿
async fn。.await在 HIR 脱糖后的真面目、poll 协议、StateTransform 的六个步骤,以及 Pin / Waker / Future 三者的关系(第9章 async 状态机、第10章 Pin/Waker/Future)。 - 正确使用 unsafe。 五种 unsafe 超能力各解锁什么、安全契约、
UnsafetyVisitor怎么检查、unsafe fn与unsafe block的语义差别、裸指针体系(第12章 unsafe、第13章 FFI)。 - 理解闭包与宏。 闭包的三种捕获与它们生成的类型、宏在编译流程里的位置(第11章 闭包、第14章 宏)。
- 知道编译为什么慢、怎么快。 MIR 优化做了什么、LLVM 代码生成这一段、增量编译的粒度与失效条件(第15章 MIR 优化、第16章 LLVM codegen、第17章 增量编译)。
适合谁读
- Rust 开发者:已经能写 Rust 代码,但想理解编译器"在背后做了什么"
- 系统程序员:从 C/C++/Go 转向 Rust,想理解所有权模型和零成本抽象的实现原理
- 语言设计爱好者:对编程语言的编译期分析、类型系统、代码生成感兴趣
- 后端工程师:准备深入 Tokio、Axum 等 Rust 生态项目源码,需要先打好语言层面的基础
目录
第一部分:编译全景
第二部分:所有权与内存
第三部分:类型系统与泛型
第四部分:异步机制
第五部分:闭包、unsafe 与 FFI
第六部分:宏与元编程
第七部分:编译器后端与优化
第八部分:总结
源码版本
本专栏分析基于 Rust 1.96.0 stable(2026 年 5 月 28 日发布)和对应的 rustc 编译器源码。涉及的 MIR、LLVM IR 等中间表示均通过 cargo rustc -- --emit=mir、--emit=llvm-ir 等工具实际生成,读者可以自行验证。
版权声明
本专栏内容为 杨艺韬 版权所有,保留一切权利。未经书面许可,不得全文或大段转载、改编、翻译,或用于任何商业用途(含以本专栏内容训练模型、生成衍生课程或商品)。
欢迎分享本专栏的链接。引用少量内容用于评论、教学或研究时,请署名 杨艺韬 并附上原文链接。