Community写作与编辑github.com

Rust 编码工作流与惯用法

用于编写、审查或重构 Rust 代码,以及编辑 Cargo.toml 时的技能指南。

Rust 编码工作流与惯用法 是什么?

该技能为 AI 代理(如 Claude Code、Cursor 等)提供了一套结构化的 Rust 编码工作流,涵盖了从项目初始化、类型设计、实现、验证到代码审查的完整步骤。它强调了 Rust 的独特性,如所有权、类型安全、错误处理和最新惯用法(截至 Rust 2024 版本)。技能文档包含了具体的规则、当前推荐做法与旧模式的对比表格,以及指向更详细参考文件的链接。支持任何能够读取和使用本地 Markdown 文件的 AI 代理平台,特别适合在开发环境中辅助编写高质量的 Rust 代码。通过遵循这些规则,AI 代理可以帮助用户避免常见陷阱,提高代码质量,并保持与最新 Rust 生态的一致性。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/spnngl/agent-skills/tree/HEAD/skills/rust/rs-coding

Installed? Explore more 写作与编辑 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Rust 编码

工作流

  1. 了解全局。 开始编写代码前,先阅读项目的权威文件:rust-toolchain.toml、Cargo.toml(edition、rust-version、[lints]、[workspace])、clippy.toml、rustfmt.toml、.cargo/config.toml,以及 CI 配置、justfile、Makefile 或 xtask 中的规范检查命令。阅读你要修改的模块及其相邻模块;重用它们的辅助函数、错误类型和模式。 完成标志: 你能说出 edition、MSRV、lint 策略、每一个 disallowed-methods / disallowed-types 条目,以及项目的检查命令。

  2. 设计类型。 遵循类型章节,先设计数据再设计控制流。如果修改库的公开 API,请阅读 references/api.md。 完成标志: 变更所依赖的每个不变量都已编码到类型中,或者由一个注明其名称的 expect 维护。

  3. 在紧凑循环中实现。 小步前进,每步后运行 cargo check。阅读完整的诊断信息:它的 help: 行通常指出了修复方法,rustc --explain E0502 会展开错误码。对于依赖项的 API,在其锁定版本(Cargo.lock)下的 $CARGO_HOME/registry/src/ 目录中阅读源代码。批量重命名通过 rust-analyzer 重命名或 ast-grep 进行;cargo clippy --fix 可应用机器建议的修复。Bug 修复: 先编写回归测试并看到它变红。 完成标志: 变更编译通过且你修改的行没有警告,并且任何回归测试在修复前为红色,修复后为绿色。

  4. 验证。 运行步骤 1 中的项目命令;否则:

    cargo fmt --all
    cargo clippy --workspace --all-targets --all-features -- -D warnings
    cargo test --workspace --all-features
    
    • 没有 [lints] 策略的项目:另外运行 cargo clippy --all-targets -- -W clippy::pedantic 并修复你修改的行上的提示。
    • 互斥特性:将 --all-features 替换为 CI 测试的每个特性集。
    • cargo nextest 会跳过文档测试:添加 cargo test --doc。
    • 公共文档更改:RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features。
    • 触及了 unsafe:运行 references/unsafe.md。
    • 从根本上修复 lint。当有必要抑制时,将 #[expect(clippy::lint_name, reason = "...")] 限定在最小的代码项上。 完成标志: 每条命令都以 0 退出,你修改的行不引发任何警告,并且每个新的抑制都带有 reason。
  5. 自检差异。 重新阅读完整的 git diff(而不是你的记忆),对照规则以及差异所触及的每个引用文件的规则进行检查。 完成标志: 每个块都是任务必需的,原型代码和 dbg! / todo! 已清理,文档注释与行为一致,并且每条适用规则对每个块都成立。

审查他人代码:运行步骤 1,尽可能运行步骤 4 的命令,然后对其差异应用步骤 5。以 path:line、规则和修复方式报告每个发现。

规则

所有权

  • 参数中使用借用:&str、&[T]、&Path、&T。仅当函数需要存储或消费值时,才按值获取 String、Vec<T> 或 T。
  • 每个 .clone() 都应有其合理性:调用方需要所有权,或者该值是一个廉价的句柄(Arc::clone(&handle))。
  • 当借用检查器报错时,首先重构:缩短借用、分别借用不相交的字段、使用 std::mem::take / replace、使用索引访问 Vec。共享可变所有权(Rc<RefCell<_>>、Arc<Mutex<_>>)是最后的手段。
  • 当调用方仅需迭代时,返回 impl Iterator<Item = T>。

类型

  • 使非法状态不可表示:使用带有每个状态数据的 enum,而不是 bool 标志加上 Option 字段;为 ID、单位和经过验证的值使用 newtype(struct Port(NonZeroU16))。
  • 解析,而非验证:在边界处一次性转换不可信输入(TryFrom、FromStr、#[serde(try_from = "Raw")]),并向内传递已解析的类型。
  • 对所有属于你的枚举进行穷举匹配。仅当未来的变体也应该走那个分支时,才使用 _ 分支。
  • 使用 From / TryFrom 转换整数;as 会静默截断和改变符号位。

错误与恐慌

  • 库:每个错误域使用一个 thiserror 枚举。二进制程序:使用 anyhow::Result 并配合 .context(...)。
  • 恐慌意味着 bug。unwrap() 只用于测试;生产代码使用 ?,或使用 expect("...") 说明使失败变得不可能的不可变条件。

当前惯用法

较旧的模式在训练数据中占主导地位。当 rust-version 允许时,优先使用当前形式;新 crate 使用 edition = "2024"。clippy::incompatible_msrv 只能捕获较新的标准库 API;语言和 Cargo 特性需要使用 cargo +<msrv> check。

优先使用而不是自版本
std::sync::LazyLock、OnceLocklazy_static!、once_cell1.80、1.70
let Some(x) = opt else { return ... };match + 提前返回1.65
if let Some(x) = a && x > 0嵌套 if let1.88,edition 2024
trait 中的原生 async fn#[async_trait],对于 dyn Trait 仍然需要1.75
`async{} 闭包、AsyncFn` 约束
#[expect(lint, reason = "...")]#[allow(lint)]1.81
&raw const x、&raw mut xptr::addr_of!1.82
opt.is_some_and(f)、opt.is_none_or(f)map_or(false, f)、map_or(true, f)1.70、1.82
std::hint::black_boxcriterion::black_box1.66
Cargo.toml 中的 [lints] 用于共享策略每个 crate 根中的 #![warn(...)]1.74
cargo:: 构建脚本指令cargo:1.77

文档与注释

  • 公开项使用 /// 文档:可能出错的函数写 # Errors,可能恐慌的函数写 # Panics,示例作为文档测试使用 ?。
  • 注释解释原因;代码展示内容。

依赖

  • 重用工作空间已有的依赖([workspace.dependencies]、cargo tree -i <crate>),在标准库可以满足需求时优先使用标准库。
  • 使用 cargo add 添加依赖(考虑 MSRV),仅启用你需要的特性。

引用文件

加载与你当前所在分支匹配的文件:

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

相关技能