← ClaudeAtlas

rust-safetylisted

写 Rust 时使用。所有权、错误处理、unsafe 的正确实践。
Wade-DevCode/awesome-coding-skills-cn · ★ 3 · AI & Automation · score 78
Install: claude install-skill Wade-DevCode/awesome-coding-skills-cn
# Rust 安全实践 ## 何时用 - 写新的 Rust 函数、结构体或模块时。 - 设计数据结构,思考所有权与生命周期时。 - 处理错误传播、编写库 crate 时。 - 准备写 `unsafe` 块或评估是否真的需要 `unsafe` 时。 - 发现编译器报 borrow checker 错误,想靠 `clone`/`Rc` 强行绕过时。 ## 核心规则 ### 1. 顺着所有权/借用设计,不靠 `clone`/`Rc` 硬绕;理解生命周期 **规则:** 遇到借用检查报错时,先理解所有权模型要表达的约束,调整数据流或函数签名;只有在语义上确实需要共享所有权时才用 `Rc`/`Arc`,不把它们当"绕过编译器的万金油";`clone` 有性能代价,大结构体不随意 `clone`。 **为什么:** AI 面对 borrow checker 报错时最常见的反应是加 `.clone()` 或把类型换成 `Rc<RefCell<T>>`——这能让代码编译,但往往意味着绕开了编译器在帮你捕获的真实问题:可能是数据所有权设计不合理,可能是生命周期标注缺失。用 `RefCell` 把静态借用检查变成运行时 panic,在 Rust 里是倒退,不是进步。 **怎么做:** - 报 borrow 错误 → 先读错误信息,理解哪个变量的生命周期冲突,考虑重组代码顺序或拆分函数。 - 函数返回引用 → 正确标注生命周期参数,让编译器而非运行时来保证安全。 - 确实需要多所有者 → `Arc<T>`(多线程)或 `Rc<T>`(单线程),但要在注释里说明为何需要共享所有权。 --- ### 2. 错误用 `Result` + `?`,库代码不 `unwrap`/`panic`;用 `thiserror`/`anyhow` 分场景 **规则:** 可能失败的操作返回 `Result<T, E>`,通过 `?` 传播;库 crate 的公开 API 中不使用 `unwrap()`/`expect()`/`panic!()`(调用方无法捕获 panic);应用程序层用 `anyhow` 简化错误汇聚,库层用 `thiserror` 定义具体错误类型。 **为什么:** AI 写 Rust 时的典型懒惰:`let val = map.get("key").unwrap()`,在 happy path 下工作,一旦 key 不存在就 unwind panic,且调用方无法在类型层面知道这里会 panic。库的职责是把所有可能的失败都表达在类型里,让调用方决定怎么处理,而不是替调用方决定"遇到这种情况就崩溃"。 **怎么做:** - 库 crate:`#[derive(thiserror::Error)]` 定义枚举错误类型,每个变体对应一种具体失败场景。 - 应用 crate / 原型:`anyhow::Result<T>` + `?` 快速传播,`context()`/`with_context()` 添加现场信息。 - 确实不可能失败的 `unwrap` → 改写成 `expect("此处 key 在初始化时已保证存在")` 并写明原因,或用 `unreachable!` 配合注释。 --- ### 3. `unsafe` 最小化并注释不变量;能安全抽象就封装 **规则:** `unsafe` 块应尽可能小,仅包含无法用安全 API 表达的操作;每个 `unsafe` 块旁必须有注释,说明为何此处安全(维护的不变量是什么);能把 `uns