【免费下载链接】tsrs
Rust port of the TypeScript 7 type checker
tsrs 是 TypeScript 7 类型检查器(type checker)的 Rust 移植版本。这篇文章带你快速上手它的三大调试利器:TSRS_ARENA_POISON 毒化模式、Miri 无定义行为检测、arena 回收回归检查,并顺带介绍 ThreadSanitizer 数据竞争门禁,帮助你在修改 tsrs 内存所有权相关代码时第一时间发现问题。
🧩 tsrs 为什么格外重视内存安全
tsrs 用 Rust 重写了 TypeScript 官方的 Go 版编译器核心,包含多线程并行 checker、自研 arena 分配器与 32 位指针压缩等高性能设计(见 README.md)。这类"快"的代价是:大量unsafe代码、跨线程共享的 arena 内存、以及可回收(recycle)的内存块。
一个小笔误(比如把一个引用参数当内存块释放)在普通构建里可能悄无声息,换个编译器版本却可能直接崩溃——tsrs 团队就真实遇到过:panic = "abort"构建下 44 个 conformance 测试段错误,根因是 LLVM 把一处基于无定义行为(UB)的"免链接"优化掉了,完整复盘记录在 notes/fix-arena-recycle-uaf.md。
正因为如此,项目建立了一套分层的调试与验证工具链:
| 工具 | 抓什么问题 | 典型场景 |
|---|---|---|
TSRS_ARENA_POISON=1 | 悬垂指针、读写已释放/回退的 arena 内存 | 改动内存所有权、回收逻辑后 |
| Miri | 编译器看不见的 UB(别名、借用违规) | arena 分配器/free-list 代码 |
| arena 回收回归测试 | 长生命周期场景下的陈旧访问 | 每次触碰 arena 所有权后 |
| ThreadSanitizer | 多线程数据竞争 | 改动 checker 线程共享逻辑后 |
⚡ 快速上手:构建与测试入口
先用 dev profile 构建 CLI 与测试运行器(官方文档明确:dev profile 用于日常开发,--release只用于测性能):
cargo build --profile dev -p tsrs_cli -p tsrs_testrunner cargo test -p tsrs_core完整的测试工作流说明在 docs/DEBUGGING.md,本文的三条命令线都出自其中的Arena recycling checks一节。
☠️ TSRS_ARENA_POISON:让悬垂指针"当场现形"
核心原理:tsrs 的 arena 会主动回收内存——已释放的块会挂到 free list 上供下次分配复用(见 crates/tsrs_core/src/arena.rs 开头的模块注释)。这意味着一个"手滑"的陈旧指针可能在复用后的内存上"读到看似正常的值",极难排查。
TSRS_ARENA_POISON=1的做法非常直白:
- 已释放的 arena 块、rewind(回退)掉的投机分配范围、整体释放的 region,全部填入毒字节
0xA5(实现里的POISON常量,arena.rs 第 54-55 行); - 且内存保持映射、永不复用,代码环境模式通过
poison_mode()(arena.rs 第 673-684 行)读取该环境变量决定。
于是任何对已释放内存的读取都会立刻崩溃,而不是污染数据。
怎么用:改动了"检查通过后还会读文件/读 checker 表"的代码(新增报告、新增全程序遍历循环等),在 fast 模式下对整个测试语料跑一遍毒化模式,输出必须与不毒化(如TSRS_FREE_LEAVES=0)的运行完全一致。相关实战案例见 notes/mem-free-leaf-files.md。
⚠️ 边界提醒:这些检查只覆盖陈旧访问(stale access),并不会扫描整个对象图里对已释放内存的所有引用——所以它要与 Miri、回收回归测试搭配使用,见 docs/DEBUGGING.md。
🔍 Miri:揪出"优化器看不见的 UB"
Miri 是 Rust nightly 自带的解释器,能精确模拟每条内存访问的别名/借用规则,把源码检查(source lint)抓不到的无定义行为揪出来。tsrs 用它专门验证 arena 的 free-list 代码——那里集中了项目约三分之一的unsafe。
官方 CI 与本地通用的一条命令(docs/RUST.md 与 arena_test.rs 均有记载):
cargo +nightly miri test -p tsrs_core --features plain-ptrs --lib arena::tests两个"为什么"值得新手理解:
- 为什么必须加
--features plain-ptrs:Miri 不支持压缩句柄的PROT_NONE内存保留,只能用普通指针构建; - 为什么 Miri 构建走系统分配器:Miri 无法运行 mimalloc,crates/tsrs_cli/src/main.rs 的头部注释专门说明了这一点,
system-alloc构建(sanitizer/Miri 场景)保留系统分配器。
测试文件里还有一个设计精巧的负向对照(arena_test.rs 第 49-57 行):miri_rejects_freeing_a_reference_parameter故意在 callee 中释放一个引用参数,并打上#[ignore]——CI 要求 Miri必须报告它违反借用规则。这等于给"Miri 本身还能看见这类 UB"上了保险。
这个真实战例的来源,就是那次panic = "abort"崩溃:引用参数在整个调用期间是受保护借用(protected borrow),往它指向的内存写 free-list 链接属于 UB,LLVM 有权删掉那次写入——最终修复是把参数改为裸切片*const [P<Type>]。
♻️ arena 回收检查:改动所有权后的必跑回归
tsrs 有三类"长生命周期回收"场景的集成回归,全部同时覆盖普通模式与毒化模式:
| 回归测试 | 覆盖场景 |
|---|---|
| recycle_checkers.rs | --maxMemory触发 checker 退役(retire)与替换,每个测试用例在毒化下也必须输出与 Go 参考一致 |
| free_leaf_files.rs | CLI--noEmit检查中"叶子文件"(测试、spec 等无人引用的文件)的 AST 树被逐文件释放 |
| lsp_edit_resolutions.rs | 语言服务器编辑场景下的模块解析生命周期 |
改动 arena 所有权后,按 docs/DEBUGGING.md 的推荐流程执行:
cargo build --profile dev -p tsrs_cli -p tsrs_testrunner cargo test -p tsrs_core cargo test -p tsrs_cli --test integration -- recycle_checkers free_leaf_files lsp_edit_resolutions其中cargo test -p tsrs_core顺带覆盖了 arena_test.rs 中的 free-list 复用、checkpoint/rewind、region 作用域等基础行为,是理解 arena 语义的绝佳阅读材料。
🧵 补充:ThreadSanitizer 数据竞争门禁
因为P<T>句柄是"按约定"(by decree)标记为Send/Sync的(crates/tsrs_core/src/ptr.rs),类型系统拦不住两个线程写同一个 arena 值。项目用 nightly 的 ThreadSanitizer 构建做门禁,覆盖 2/8 checker 类型检查、emit、-b多项目、--watch编辑与 LSP 会话,任何报告即失败,详见 docs/DEBUGGING.md。构建要点:-Zsanitizer=thread+plain-ptrs+system-alloc。
📋 一张表总结:tsrs 内存安全验证清单
| 我要验证 | 用什么 | 命令/入口 |
|---|---|---|
| 改动 arena 回收/所有权 | TSRS_ARENA_POISON + 回收回归 | 上文三行cargo test |
| free-list 代码的 UB | Miri | cargo +nightly miri test -p tsrs_core --features plain-ptrs --lib arena::tests |
| checker 线程数据竞争 | ThreadSanitizer | docs/DEBUGGING.md |
| 驻留内存构成分析 | TSRS_MEM_SPLIT=1 | crates/tsrs_core/src/memsplit.rs |
给新手的建议路径:先读 notes/fix-arena-recycle-uaf.md 这个真实事故复盘(根因 → 最小复现 → 修复 → 四层防护),再动手改 arena 相关代码;每次提交前跑一遍上面的回归清单,让0xA5毒字节和 Miri 替你值夜班。🛡️
【免费下载链接】tsrs
Rust port of the TypeScript 7 type checker
相关推荐
PyO3 调试实战指南:宏展开、Valgrind 内存检查、断点调试与线程安全 Sanitizer
PyO3 调试实战指南:宏展开、Valgrind 内存检查、断点调试与线程安全 Sanitizer 本指南面向使用 PyO3 编写 Python 扩展模块的 R
开发工具Awesome Transformers贡献指南:如何添加和更新Transformer模型
Awesome Transformers贡献指南:如何添加和更新Transformer模型 Awesome Transformers是一个精心策划的Transf
OpenBot 开发检查体系详解:tsrs 类型检查、暂存区精确选择与 CI 分道调度
OpenBot 开发检查体系详解:tsrs 类型检查、暂存区精确选择与 CI 分道调度 本文以仓库中的 docs/development checks.md h
桌面应用AI Agent人工智能多智能体代码智能体浏览器控制本地部署MCP 服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考