rust-review
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRust — Comprehensive Review
Rust — 全方位代码审查
Four review lenses. Pick the section that matches what you're reviewing — apply multiple if the file spans concerns (e.g. an async tokio service with FFI bindings).
| Lens | Section |
|---|---|
| Source code — ownership, errors, trait design, unsafe | Source review |
| Test code — unit, integration, async, mocking, proptest | Test review |
| tokio async — task mgmt, sync primitives, channels | Tokio async review |
| FFI — extern, repr(C), strings, callbacks, unsafe boundary | FFI review |
For writing or setting up Rust (not reviewing it), see .
rust-authorSource review
源代码审查
Rust Code Review
Rust代码审查
Review Workflow
审查流程
Follow this sequence to avoid false positives and catch edition-specific issues:
- Check — Note the Rust edition (2018, 2021, 2024) and MSRV if set. Edition 2024 introduces breaking changes to unsafe semantics, RPIT lifetime capture, temporary scoping, and
Cargo.tomltype fallback. This determines which patterns apply. Check workspace structure if present.! - Check dependencies — Note key crates (thiserror vs anyhow, tokio features, serde features). These inform which patterns are expected.
- Scan changed files — Read full functions, not just diffs. Many Rust bugs hide in ownership flow across a function.
- Check each category — Work through the checklist below, loading references as needed.
- Verify before reporting — Load beagle-rust:review-verification-protocol before submitting findings.
遵循以下步骤,避免误报并捕捉版本相关问题:
- 检查— 记录Rust版本(2018、2021、2024)以及设置的MSRV(最低支持Rust版本)。2024版本对unsafe语义、RPIT生命周期捕获、临时作用域和
Cargo.toml类型回退引入了破坏性变更。这将决定适用哪些模式。如果存在工作区结构,也需检查。! - 检查依赖项 — 记录关键 crate(thiserror vs anyhow、tokio特性、serde特性)。这些将明确预期的代码模式。
- 扫描变更文件 — 阅读完整函数,而非仅查看差异。许多Rust bug隐藏在函数内的所有权流转中。
- 检查每个类别 — 按照下方清单逐一检查,必要时查阅参考文档。
- 报告前验证 — 在提交审查结果前,加载。
beagle-rust:review-verification-protocol
Output Format
输出格式
Report findings as:
text
[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.按以下格式报告问题:
text
[文件:行号] 问题标题
严重程度: Critical | Major | Minor | Informational
问题描述及其影响。Quick Reference
快速参考
| Issue Type | Reference |
|---|---|
| Ownership transfers, borrowing, lifetimes, clone traps, iterators | references/ownership-borrowing.md |
| Lifetime variance, covariance/invariance, memory regions | references/lifetime-variance.md |
| Result/Option handling, thiserror, anyhow, error context, Error trait | references/error-handling.md |
| Async pitfalls, Send/Sync bounds, runtime blocking | references/async-concurrency.md |
| Send/Sync semantics, atomics, memory ordering, lock patterns | references/concurrency-primitives.md |
| Type layout, alignment, repr, PhantomData, generics vs dyn Trait | references/types-layout.md |
| Unsafe code, API design, derive patterns, clippy patterns | references/common-mistakes.md |
| Safety contracts, raw pointers, MaybeUninit, soundness, Miri | references/unsafe-deep.md |
For development guidance on performance, pointer types, type state, clippy config, iterators, generics, and documentation, use theskill.beagle-rust:rust-best-practices
| 问题类型 | 参考文档 |
|---|---|
| 所有权转移、借用、生命周期、克隆陷阱、迭代器 | references/ownership-borrowing.md |
| 生命周期方差、协变/不变性、内存区域 | references/lifetime-variance.md |
| Result/Option处理、thiserror、anyhow、错误上下文、Error trait | references/error-handling.md |
| 异步陷阱、Send/Sync约束、运行时阻塞 | references/async-concurrency.md |
| Send/Sync语义、原子操作、内存顺序、锁模式 | references/concurrency-primitives.md |
| 类型布局、对齐方式、repr、PhantomData、泛型vs dyn Trait | references/types-layout.md |
| Unsafe代码、API设计、derive模式、clippy模式 | references/common-mistakes.md |
| 安全契约、裸指针、MaybeUninit、安全性、Miri | references/unsafe-deep.md |
关于性能、指针类型、类型状态、clippy配置、迭代器、泛型和文档的开发指导,请使用技能。beagle-rust:rust-best-practices
Review Checklist
审查清单
Ownership and Borrowing
所有权与借用
- No unnecessary to silence the borrow checker (hiding design issues)
.clone() - No inside loops — prefer
.clone()or.cloned()on iterators.copied() - No cloning to avoid lifetime annotations (take ownership explicitly or restructure)
- References have appropriate lifetimes (not overly broad when shorter lifetime works)
'static - Edition 2024: RPIT () captures all in-scope lifetimes by default; use
-> impl Traitfor precise capture control+ use<'a> - preferred over
&str,Stringover&[T]in function parametersVec<T> - or
impl AsRef<T>used for flexible API parametersInto<T> - No dangling references or use-after-move
- Interior mutability (,
Cell,RefCell) used only when shared mutation is genuinely neededMutex - Small types (≤24 bytes) derive and are passed by value
Copy - used when ownership is ambiguous
Cow<'_, T> - Iterator chains preferred over index-based loops for collection transforms
- No premature — pass iterators directly when the consumer accepts them
.collect() - preferred over
.sum()for summation (compiler optimizes better).fold() - variants used when fallbacks involve allocation
_or_else - Edition 2024: temporaries drop at end of the
if let— code relying on temporaries living through the else branch needs restructuringif let - Edition 2024: implements
Box<[T]>— prefer direct iteration overIntoIteratorfirstinto_vec()
- 无不必要的来规避借用检查(这会隐藏设计问题)
.clone() - 循环内无— 优先在迭代器上使用
.clone()或.cloned().copied() - 无通过克隆来避免生命周期注解的情况(明确获取所有权或重构代码)
- 引用具有合适的生命周期(当较短生命周期可行时,不使用过于宽泛的)
'static - 2024版本:RPIT()默认捕获所有作用域内的生命周期;使用
-> impl Trait进行精确捕获控制+ use<'a> - 函数参数优先使用而非
&str,String而非&[T]Vec<T> - 使用或
impl AsRef<T>实现灵活的API参数Into<T> - 无悬垂引用或使用已转移所有权的值
- 仅在真正需要共享可变状态时使用内部可变性(、
Cell、RefCell)Mutex - 小型类型(≤24字节)派生并按值传递
Copy - 当所有权不明确时使用
Cow<'_, T> - 集合转换优先使用迭代器链而非基于索引的循环
- 避免过早调用— 当消费者支持时,直接传递迭代器
.collect() - 求和优先使用而非
.sum()(编译器优化效果更好).fold() - 当回退操作涉及内存分配时,使用变体
_or_else - 2024版本:中的临时值在
if let结束时销毁 — 依赖临时值贯穿else分支的代码需要重构if let - 2024版本:实现了
Box<[T]>— 优先直接迭代,而非先调用IntoIteratorinto_vec()
Error Handling
错误处理
- used for recoverable errors, not
Result<T, E>/panic!/unwrapexpect - Error types provide context (thiserror with or manual
#[error("...")])Display - operator used with proper
?implementations orFrom.map_err() - /
unwrap()only in tests, examples, or provably-safe contextsexpect() - Error variants are specific enough to be actionable by callers
- used in applications,
anyhowin libraries (or clear rationale for alternatives)thiserror - variants used when fallbacks involve allocation (
_or_else,ok_or_else)unwrap_or_else - used for early returns on failure (
let-else)let Ok(x) = expr else { return ... } - used for error logging,
inspect_errfor error transformationmap_err
- 可恢复错误使用,而非
Result<T, E>/panic!/unwrapexpect - 错误类型提供上下文(使用带的thiserror或手动实现
#[error("...")])Display - 运算符与正确的
?实现或From配合使用.map_err() - /
unwrap()仅用于测试、示例或可证明安全的场景expect() - 错误变体足够具体,便于调用方处理
- 应用程序使用,库使用
anyhow(或有明确理由选择其他方案)thiserror - 当回退操作涉及内存分配时,使用变体(
_or_else、ok_or_else)unwrap_or_else - 使用实现失败时的提前返回(
let-else)let Ok(x) = expr else { return ... } - 使用记录错误,使用
inspect_err转换错误map_err
Traits and Types
Trait与类型
- Traits are minimal and cohesive (single responsibility)
- macros appropriate for the type (
derive,Clone,Debugused correctly)PartialEq - Newtypes used to prevent primitive obsession (e.g., not bare
struct UserId(Uuid))Uuid - /
Fromimplementations are lossless and infallible;Intofor fallible conversionsTryFrom - Sealed traits used when external implementations shouldn't be allowed
- Default implementations provided where they make sense
- bounds verified for types shared across threads
Send + Sync - used on public traits to provide clear error messages when users forget to implement them
#[diagnostic::on_unimplemented]
- Trait保持最小化且内聚(单一职责)
- 宏适用于对应类型(正确使用
derive、Clone、Debug)PartialEq - 使用Newtype避免原始类型痴迷(例如而非裸
struct UserId(Uuid))Uuid - /
From实现是无损且无失败的;Into用于可失败的转换TryFrom - 当不允许外部实现时,使用密封Trait
- 在合理的情况下提供默认实现
- 验证跨线程共享类型的约束
Send + Sync - 公共Trait上使用,以便用户忘记实现时提供清晰的错误消息
#[diagnostic::on_unimplemented]
Unsafe Code
Unsafe代码
- blocks have safety comments explaining invariants
unsafe - is minimal — only the truly unsafe operation is inside the block
unsafe - Safety invariants are documented and upheld by surrounding safe code
- No undefined behavior (null pointer deref, data races, invalid memory access)
- trait implementations justify why the contract is upheld
unsafe - Edition 2024: bodies use explicit
unsafe fnblocks around unsafe ops (unsafe {}is deny)unsafe_op_in_unsafe_fn - Edition 2024: blocks written as
extern "C" {}unsafe extern "C" {} - Edition 2024: and
#[no_mangle]written as#[export_name]and#[unsafe(no_mangle)]#[unsafe(export_name)]
- 块带有安全注释,解释不变量
unsafe - 范围最小化 — 仅将真正不安全的操作放在块内
unsafe - 安全不变量已文档化,并由周围的安全代码维护
- 无未定义行为(空指针解引用、数据竞争、无效内存访问)
- trait实现需证明契约已被遵守
unsafe - 2024版本:主体在不安全操作周围使用显式
unsafe fn块(unsafe {}设为deny)unsafe_op_in_unsafe_fn - 2024版本:块需写成
extern "C" {}unsafe extern "C" {} - 2024版本:和
#[no_mangle]需写成#[export_name]和#[unsafe(no_mangle)]#[unsafe(export_name)]
Naming and Style
命名与风格
- Types are , functions/methods
PascalCase, constantssnake_caseSCREAMING_SNAKE_CASE - Modules use
snake_case - ,
is_,has_prefixes for boolean-returning methodscan_ - Builder pattern methods take and return (not
self) for chaining&mut self - Public items have doc comments ()
/// - on functions where ignoring the return value is likely a bug
#[must_use] - Imports ordered: std → external crates → workspace → crate/super
- preferred over
#[expect(clippy::...)]for lint suppression#[allow(...)]
- 类型使用,函数/方法使用
PascalCase,常量使用snake_caseSCREAMING_SNAKE_CASE - 模块使用
snake_case - 返回布尔值的方法使用、
is_、has_前缀can_ - Builder模式方法接收并返回(而非
self)以支持链式调用&mut self - 公共项带有文档注释()
/// - 对忽略返回值可能导致bug的函数使用
#[must_use] - 导入顺序:std → 外部crate → 工作区 → crate/super
- 抑制lint时优先使用而非
#[expect(clippy::...)]#[allow(...)]
Performance
性能
Detailed guidance:skill (references/performance.md)beagle-rust:rust-best-practices
- No unnecessary allocations in hot paths (prefer over
&str,Stringover&[T])Vec<T> - type is specified or inferable
collect() - Iterators preferred over indexed loops for collection transforms
- used when size is known
Vec::with_capacity() - No redundant /
.to_string()chains.to_owned() - No intermediate when passing iterators directly works
.collect() - preferred over
.sum()for summation.fold() - Static dispatch () used over dynamic (
impl Trait) unless flexibility requireddyn Trait
详细指导:技能(references/performance.md)beagle-rust:rust-best-practices
- 热路径中无不必要的内存分配(优先使用而非
&str,String而非&[T])Vec<T> - 的类型已指定或可推断
collect() - 集合转换优先使用迭代器而非索引循环
- 已知大小时使用
Vec::with_capacity() - 无冗余的/
.to_string()链式调用.to_owned() - 当可直接传递迭代器时,避免中间的
.collect() - 求和优先使用而非
.sum().fold() - 优先使用静态分发()而非动态分发(
impl Trait),除非需要灵活性dyn Trait
Clippy Configuration
Clippy配置
Detailed guidance:skill (references/clippy-config.md)beagle-rust:rust-best-practices
- Workspace-level lints configured in (
Cargo.tomlor[workspace.lints.clippy])[lints.clippy] - used over
#[expect(clippy::lint)]— warns when suppression becomes stale#[allow(...)] - Justification comment present when suppressing any lint
- Key lints enforced: ,
redundant_clone,large_enum_variant,needless_collectgroupperf - passes
cargo clippy --all-targets --all-features -- -D warnings - Doc lints enabled for library crates (,
missing_docs)broken_intra_doc_links
详细指导:技能(references/clippy-config.md)beagle-rust:rust-best-practices
- 工作区级lint在中配置(
Cargo.toml或[workspace.lints.clippy])[lints.clippy] - 使用而非
#[expect(clippy::lint)]— 当抑制不再需要时会发出警告#[allow(...)] - 抑制任何lint时都有理由注释
- 强制执行关键lint:、
redundant_clone、large_enum_variant、needless_collect组perf - 执行通过
cargo clippy --all-targets --all-features -- -D warnings - 库crate启用文档lint(、
missing_docs)broken_intra_doc_links
Type State Pattern
类型状态模式
Detailed guidance:skill (references/type-state-pattern.md)beagle-rust:rust-best-practices
- used for zero-cost compile-time state machines (not runtime enums/booleans)
PhantomData<State> - State transitions consume and return new state type (prevents reuse of old state)
self - Only applicable methods available per state (invalid operations are compile errors)
- Pattern used where it adds safety value (builders with required fields, connection states, workflows)
- Not overused for trivial state (simple enums are fine when runtime flexibility needed)
详细指导:技能(references/type-state-pattern.md)beagle-rust:rust-best-practices
- 使用实现零成本编译时状态机(而非运行时枚举/布尔值)
PhantomData<State> - 状态转换消耗并返回新状态类型(防止旧状态被重复使用)
self - 每个状态仅提供适用的方法(无效操作在编译时就会报错)
- 在能提升安全性的场景使用该模式(带有必填字段的Builder、连接状态、工作流)
- 不为 trivial 状态过度使用该模式(当需要运行时灵活性时,简单枚举即可)
Severity Calibration
严重程度校准
Critical (Block Merge)
Critical(阻止合并)
- code with unsound invariants or undefined behavior
unsafe - Use-after-free or dangling reference patterns
- on user input or external data in production code
unwrap() - Data races (concurrent mutation without synchronization)
- Memory leaks via circular without weak references
Arc<Mutex<...>>
- 存在不安全不变量或未定义行为的代码
unsafe - 使用已释放内存或悬垂引用的模式
- 生产代码中对用户输入或外部数据使用
unwrap() - 无同步的并发修改导致的数据竞争
- 无弱引用的循环导致内存泄漏
Arc<Mutex<...>>
Major (Should Fix)
Major(应修复)
- Errors returned without context (bare equivalent)
return err - masking ownership design issues in hot paths
.clone() - Missing /
Sendbounds on types used across threadsSync - for recoverable errors in library code
panic! - Overly broad lifetimes hiding API design issues
'static
- 返回无上下文的错误(等效于裸)
return err - 热路径中通过掩盖所有权设计问题
.clone() - 跨线程使用的类型缺少/
Send约束Sync - 库代码中对可恢复错误使用
panic! - 过于宽泛的生命周期隐藏API设计问题
'static
Minor (Consider Fixing)
Minor(考虑修复)
- Missing doc comments on public items
- parameter where
Stringor&strwould workimpl AsRef<str> - Derive macros missing for types that should have them
- Unused feature flags in
Cargo.toml - Suboptimal iterator chains (multiple allocations where one suffices)
- 公共项缺少文档注释
- 参数使用,而
String或&str更合适impl AsRef<str> - 应为类型派生的宏缺失
- 中存在未使用的特性标志
Cargo.toml - 次优的迭代器链(多次内存分配可合并为一次)
Informational (Note Only)
Informational(仅作提示)
- Suggestions to introduce newtypes for domain modeling
- Refactoring ideas for trait design
- Performance optimizations without measured impact
- Suggestions to add or
#[must_use]#[non_exhaustive]
- 建议为领域建模引入Newtype
- Trait设计的重构思路
- 无实测影响的性能优化建议
- 添加或
#[must_use]的建议#[non_exhaustive]
When to Load References
何时查阅参考文档
- Reviewing ownership, borrows, lifetimes, clone traps → ownership-borrowing.md
- Reviewing lifetime variance, covariance/invariance, multiple lifetime params → lifetime-variance.md
- Reviewing Result/Option handling, error types, Error trait impls → error-handling.md
- Reviewing async code, tokio usage, task management → async-concurrency.md
- Reviewing Send/Sync, atomics, memory ordering, mutexes, lock patterns → concurrency-primitives.md
- Reviewing type layout, alignment, repr, PhantomData, generics vs dyn → types-layout.md
- Reviewing unsafe code, API design, derive macros, clippy patterns → common-mistakes.md
- Reviewing safety contracts, raw pointers, MaybeUninit, soundness → unsafe-deep.md
- Reviewing performance, pointer types, type state, generics, iterators, documentation → skill
beagle-rust:rust-best-practices
- 审查所有权、借用、生命周期、克隆陷阱 → ownership-borrowing.md
- 审查生命周期方差、协变/不变性、多个生命周期参数 → lifetime-variance.md
- 审查Result/Option处理、错误类型、Error trait实现 → error-handling.md
- 审查异步代码、tokio使用、任务管理 → async-concurrency.md
- 审查Send/Sync、原子操作、内存顺序、互斥锁、锁模式 → concurrency-primitives.md
- 审查类型布局、对齐方式、repr、PhantomData、泛型vs dyn → types-layout.md
- 审查unsafe代码、API设计、derive宏、clippy模式 → common-mistakes.md
- 审查安全契约、裸指针、MaybeUninit、安全性 → unsafe-deep.md
- 审查性能、指针类型、类型状态、泛型、迭代器、文档 → 技能
beagle-rust:rust-best-practices
Valid Patterns (Do NOT Flag)
有效模式(无需标记)
These are acceptable Rust patterns — reporting them wastes developer time:
- in tests — Clarity over performance in test code
.clone() - in tests and examples — Acceptable where panicking on failure is intentional
unwrap() - in simple binaries — Not every application needs custom error types
Box<dyn Error> - fields in structs — Owned data in structs is correct;
Stringfields require lifetime parameters&str - during development — Common during iteration
#[allow(dead_code)] - /
todo!()in new code — Valid placeholder during active developmentunimplemented!() - with clear message — Self-documenting and acceptable for invariants
.expect("reason") - in test modules — Standard pattern for
use super::*modules#[cfg(test)] - Type aliases for complex types — is idiomatic
type Result<T> = std::result::Result<T, MyError> - in return position — Zero-cost abstraction, standard pattern
impl Trait - Turbofish syntax — is idiomatic when type inference needs help
collect::<Vec<_>>() - prefix for intentionally unused variables — Compiler convention
_ - with justification — Self-cleaning lint suppression
#[expect(clippy::...)] - — Explicit Arc cloning is idiomatic and recommended
Arc::clone(&arc) - for short critical sections in async — Tokio docs recommend this
std::sync::Mutex - loops over iterators — When early exit or side effects are needed
for - in trait definitions — Stable since 1.75;
async fncrate only needed forasync-traitor pre-1.75 MSRVdyn Trait - /
LazyCellfrom std — Stable since 1.80; replacesLazyLockandonce_cellfor new codelazy_static - precise capture syntax — Edition 2024 syntax for controlling RPIT lifetime capture
+ use<'a, T>
这些是可接受的Rust模式——报告它们会浪费开发者时间:
- 测试中的— 测试代码中清晰度优先于性能
.clone() - 测试和示例中的— 在失败时故意panic是可接受的
unwrap() - 简单二进制文件中的— 并非每个应用都需要自定义错误类型
Box<dyn Error> - 结构体中的字段 — 结构体中使用自有数据是正确的;
String字段需要生命周期参数&str - 开发期间的— 迭代开发中常见
#[allow(dead_code)] - 新代码中的/
todo!()— 活跃开发期间的有效占位符unimplemented!() - 带有清晰消息的— 自文档化,适用于不变量检查
.expect("reason") - 测试模块中的—
use super::*模块的标准模式#[cfg(test)] - 复杂类型的类型别名 — 是惯用写法
type Result<T> = std::result::Result<T, MyError> - 返回位置的— 零成本抽象,标准模式
impl Trait - Turbofish语法 — 当类型推断需要帮助时,是惯用写法
collect::<Vec<_>>() - 有意未使用变量的前缀 — 编译器约定
_ - 带有理由的— 自清理式lint抑制
#[expect(clippy::...)] - — 显式Arc克隆是惯用且推荐的写法
Arc::clone(&arc) - 异步代码中短临界区使用— Tokio文档推荐此做法
std::sync::Mutex - 迭代器上的循环 — 当需要提前退出或副作用时适用
for - Trait定义中的— 自1.75版本起稳定;仅当需要
async fn或MSRV低于1.75时才需要dyn Traitcrateasync-trait - std中的/
LazyCell— 自1.80版本起稳定;替代新代码中的LazyLock和once_celllazy_static - 精确捕获语法 — 2024版本中用于控制RPIT生命周期捕获的语法
+ use<'a, T>
Context-Sensitive Rules
上下文敏感规则
Only flag these issues when the specific conditions apply:
| Issue | Flag ONLY IF |
|---|---|
| Missing error context | Error crosses module boundary without context |
Unnecessary | In hot path or repeated call, not test/setup code |
| Missing doc comments | Item is |
| In production code path, not test/example/provably-safe |
Missing | Type is actually shared across thread/task boundaries |
| Overly broad lifetime | A shorter lifetime would work AND the API is public |
Missing | Function returns a value that callers commonly ignore |
Stale | Should be |
Missing | Type is ≤24 bytes with all-Copy fields and used frequently |
Edition 2024: | Match on |
Edition 2024: | Code uses |
仅当特定条件满足时才标记这些问题:
| 问题 | 仅在以下情况标记 |
|---|---|
| 缺少错误上下文 | 错误跨模块边界传递时无上下文 |
不必要的 | 位于热路径或重复调用中,而非测试/初始化代码 |
| 缺少文档注释 | 项为 |
| 位于生产代码路径中,而非测试/示例/可证明安全的场景 |
缺少 | 类型实际跨线程/任务边界共享 |
| 过于宽泛的生命周期 | 较短生命周期可行且API为公共API |
缺少 | 函数返回值常被调用方忽略 |
过时的 | 应使用 |
缺少 | 类型≤24字节且所有字段均为Copy类型,且频繁使用 |
2024版本: | 匹配 |
2024版本: | 代码使用 |
Before Submitting Findings
提交审查结果前
Load and follow before reporting any issue.
<!-- cross-ref:start -->beagle-rust:review-verification-protocol在报告任何问题前,加载并遵循。
<!-- cross-ref:start -->beagle-rust:review-verification-protocolSee also (related skills — Code review family)
另请参阅(相关技能 — 代码审查系列)
If your issue relates to:
- CodeRabbit-powered review (default) — check if appropriate.
code-review - auto-apply CodeRabbit review comments — check if appropriate.
autofix - Python + pytest review (type safety, async, fixtures) — check if appropriate.
python-code-review - Rust test review — check if appropriate.
rust-testing-code-review - tokio async review — check if appropriate.
tokio-async-code-review - Rust FFI review — check if appropriate.
ffi-code-review - Deep Agents code review — check if appropriate.
deepagents-code-review - SQLAlchemy 2.0 review — check if appropriate.
sqlalchemy-code-review
如果你的问题涉及:
- CodeRabbit驱动的审查(默认) — 若合适,请查看。
code-review - 自动应用CodeRabbit审查评论 — 若合适,请查看。
autofix - Python + pytest审查(类型安全、异步、fixtures) — 若合适,请查看。
python-code-review - Rust测试审查 — 若合适,请查看。
rust-testing-code-review - Tokio异步审查 — 若合适,请查看。
tokio-async-code-review - Rust FFI审查 — 若合适,请查看。
ffi-code-review - Deep Agents代码审查 — 若合适,请查看。
deepagents-code-review - SQLAlchemy 2.0审查 — 若合适,请查看。
sqlalchemy-code-review
Test review
测试代码审查
Rust Testing Code Review
Rust测试代码审查
Review Workflow
审查流程
- Check Rust edition — Note edition in (2021 vs 2024). Edition 2024 changes temporary scoping in
Cargo.tomland tail expressions, and makesif letthe preferred lint suppression#[expect] - Check test organization — Unit tests in modules, integration tests in
#[cfg(test)]directorytests/ - Check async test setup — for async tests, proper runtime configuration. Check for
#[tokio::test]on mocks that could use nativeasync-traitin traitsasync fn - Check assertions — Meaningful messages, correct assertion type. Review assertions for edition 2024 temporary scope changes
if let - Check test isolation — No shared mutable state between tests, proper setup/teardown. Prefer over
LazyLock/lazy_static!for shared fixturesonce_cell - Check coverage patterns — Error paths tested, edge cases covered
- 检查Rust版本 — 记录中的版本(2021 vs 2024)。2024版本改变了
Cargo.toml和尾表达式中的临时作用域,并将if let作为首选lint抑制方式#[expect] - 检查测试组织 — 单元测试位于模块中,集成测试位于
#[cfg(test)]目录下tests/ - 检查异步测试设置 — 异步测试使用,运行时配置正确。检查Mock是否可使用Trait中的原生
#[tokio::test],而非async fnasync-trait - 检查断言 — 消息有意义,断言类型正确。针对2024版本的临时作用域变化,审查断言
if let - 检查测试隔离 — 测试间无共享可变状态,设置/清理正确。共享fixture优先使用而非
LazyLock/lazy_static!once_cell - 检查覆盖模式 — 测试错误路径,覆盖边缘情况
Output Format
输出格式
Report findings as:
text
[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.按以下格式报告问题:
text
[文件:行号] 问题标题
严重程度: Critical | Major | Minor | Informational
问题描述及其影响。Quick Reference
快速参考
| Issue Type | Reference |
|---|---|
Unit tests, assertions, naming, snapshots, rstest, doc tests, | references/unit-tests.md |
Integration tests, async testing, fixtures, test databases, native | references/integration-tests.md |
| Fuzzing, property-based testing, Miri, Loom, benchmarking, compile_fail, custom harness, mocking strategies | references/advanced-testing.md |
| 问题类型 | 参考文档 |
|---|---|
单元测试、断言、命名、快照、rstest、文档测试、 | references/unit-tests.md |
集成测试、异步测试、fixtures、测试数据库、原生 | references/integration-tests.md |
| 模糊测试、基于属性的测试、Miri、Loom、基准测试、compile_fail、自定义测试 harness、Mock策略 | references/advanced-testing.md |
Review Checklist
审查清单
Test Structure
测试结构
- Unit tests in within source files
#[cfg(test)] mod tests - Integration tests in directory (one file per module or feature)
tests/ - in test modules to access parent module items
use super::* - Test function names describe the scenario:
test_<function>_<scenario>_<expected> - Tests are independent — no reliance on execution order
- 单元测试位于源文件内的中
#[cfg(test)] mod tests - 集成测试位于目录下(每个模块或功能对应一个文件)
tests/ - 测试模块中使用访问父模块项
use super::* - 测试函数名称描述场景:
test_<函数>_<场景>_<预期结果> - 测试相互独立 — 不依赖执行顺序
Async Tests
异步测试
- used for async test functions
#[tokio::test] - when testing multi-threaded behavior
#[tokio::test(flavor = "multi_thread")] - No inside async tests (use
block_ondirectly).await - Test timeouts set for tests that could hang
- Mock traits use native instead of
async fncrate (stable since Rust 1.75)async-trait
- 异步测试函数使用
#[tokio::test] - 测试多线程行为时使用
#[tokio::test(flavor = "multi_thread")] - 异步测试内无(直接使用
block_on).await - 为可能挂起的测试设置超时
- Mock Trait使用原生而非
async fncrate(自Rust 1.75起稳定)async-trait
Assertions
断言
- /
assert_eq!used for value comparisons (better error messages thanassert_ne!)assert! - Custom messages on assertions that aren't self-documenting
- macro used for enum variant checking
matches! - Error types checked with or pattern matching, not string comparison
matches! - One assertion per test where practical (easier to diagnose failures)
- assertions reviewed for edition 2024 temporary scope — temporaries in conditions drop earlier, may invalidate borrows
if let - Tail expression returns reviewed for edition 2024 — temporaries in tail expressions drop before local variables
- 值比较使用/
assert_eq!(比assert_ne!的错误消息更清晰)assert! - 非自文档化的断言带有自定义消息
- 枚举变体检查使用宏
matches! - 使用或模式匹配检查错误类型,而非字符串比较
matches! - 实际可行时,每个测试仅包含一个断言(便于诊断失败)
- 针对2024版本的临时作用域,审查断言 — 条件中的临时值销毁更早,可能使借用无效
if let - 针对2024版本,审查尾表达式返回值 — 尾表达式中的临时值在局部变量之前销毁
Mocking and Test Doubles
Mock与测试替身
- Traits used as seams for dependency injection (not concrete types)
- Mock implementations kept minimal — only what the test needs
- No mocking of types you don't own (wrap external dependencies behind your own trait)
- Test fixtures as helper functions, not global state
- used for shared test fixtures instead of
std::sync::LazyLockorlazy_static!(stable since Rust 1.80)once_cell
- 使用Trait作为依赖注入的 seam(而非具体类型)
- Mock实现保持最小化 — 仅包含测试所需的部分
- 不Mock不属于你的类型(将外部依赖包装在自己的Trait后再Mock)
- 测试fixture作为辅助函数,而非全局状态
- 共享测试fixture使用而非
std::sync::LazyLock或lazy_static!(自Rust 1.80起稳定)once_cell
Error Path Testing
错误路径测试
- variants tested, not just happy paths
Result::Err - Specific error variants checked (not just "is error")
- used sparingly — prefer
#[should_panic]-returning testsResult
- 测试变体,而非仅测试正常路径
Result::Err - 检查具体的错误变体(而非仅检查"是否为错误")
- 谨慎使用— 优先使用返回
#[should_panic]的测试Result
Lint Suppression in Tests
测试中的Lint抑制
- used instead of
#[expect(lint)]for test-specific suppressions (stable since Rust 1.81)#[allow(lint)] - Justification comment on every or
#[expect]in test code#[allow] - Stale attributes migrated to
#[allow]for self-cleaning behavior#[expect]
- 测试特定抑制使用而非
#[expect(lint)](自Rust 1.81起稳定)#[allow(lint)] - 测试代码中每个或
#[expect]都带有理由注释#[allow] - 将过时的属性迁移为
#[allow]以实现自清理#[expect]
Test Naming
测试命名
- Test names read like sentences describing behavior (not )
test_happy_path - Related tests grouped in nested blocks for organization
mod - Test names follow pattern:
<function>_should_<behavior>_when_<condition>
- 测试名称读起来像描述行为的句子(而非)
test_happy_path - 相关测试分组在嵌套块中以组织代码
mod - 测试名称遵循模式:
<函数>_should_<行为>_when_<条件>
Snapshot Testing
快照测试
- used for complex structural output (JSON, YAML, HTML, CLI output)
cargo insta - Snapshots are small and focused (not huge objects)
- Redactions used for unstable fields (timestamps, UUIDs)
- Snapshots committed to git in directory
snapshots/ - Simple values use , not snapshots
assert_eq!
- 复杂结构化输出(JSON、YAML、HTML、CLI输出)使用
cargo insta - 快照小巧且聚焦(而非庞大对象)
- 不稳定字段(时间戳、UUID)使用脱敏处理
- 快照提交到git的目录中
snapshots/ - 简单值使用,而非快照
assert_eq!
Parametrized Testing
参数化测试
- used to avoid duplicated test functions for similar inputs
rstest - with
#[rstest]attributes for descriptive parametrized tests#[case::name] - used for shared test setup when multiple tests need same construction
#[fixture] - Parametrized tests still have descriptive case names (not just )
#[case(1)] - Combined with async: for async parametrized tests
#[rstest] #[tokio::test]
- 使用避免为相似输入编写重复测试函数
rstest - 配合
#[rstest]属性实现描述性参数化测试#[case::name] - 当多个测试需要相同构造时,使用实现共享测试设置
#[fixture] - 参数化测试仍具有描述性的用例名称(而非仅)
#[case(1)] - 与异步结合:用于异步参数化测试
#[rstest] #[tokio::test]
Doc Tests
文档测试
- Public API functions have with runnable code
/// # Examples - Doc tests serve as both documentation and correctness checks
- Hidden setup lines prefixed with to keep examples clean
# - passes (nextest doesn't run doc tests)
cargo test --doc
- 公共API函数带有和可运行代码
/// # Examples - 文档测试同时作为文档和正确性检查
- 隐藏的设置行以为前缀,保持示例简洁
# - 执行通过(nextest不运行文档测试)
cargo test --doc
Severity Calibration
严重程度校准
Critical
Critical
- Tests that pass but don't actually verify behavior (assertions on wrong values)
- Shared mutable state between tests causing flaky results
- Missing error path tests for security-critical code
- 测试通过但未实际验证行为(断言错误的值)
- 测试间共享可变状态导致结果不稳定
- 安全关键代码缺少错误路径测试
Major
Major
- without
#[should_panic]message (catches any panic, including wrong ones)expected - in test setup that hides the real failure location
unwrap() - Tests that depend on execution order
- with inline temporary in assertion that breaks under edition 2024 temporary scoping
if let - on mock traits when native
async-traitin traits is available and project targets edition 2024async fn
- 未指定
#[should_panic]消息(捕获任何panic,包括错误的panic)expected - 测试设置中的隐藏了实际失败位置
unwrap() - 测试依赖执行顺序
- 断言中的内联临时值使用,在2024版本的临时作用域下会失效
if let - 当项目目标为2024版本且原生Trait可用时,Mock Trait仍使用
async fnasync-trait
Minor
Minor
- Missing assertion messages on complex comparisons
- instead of
assert!(x == y)(worse error messages)assert_eq!(x, y) - Test names that don't describe the scenario
- Redundant setup code that could be extracted to a helper
- used where
#[allow]would provide self-cleaning suppression#[expect] - or
lazy_static!used for test fixtures whenonce_cellis availableLazyLock
- 复杂比较缺少断言消息
- 使用而非
assert!(x == y)(错误消息更差)assert_eq!(x, y) - 测试名称未描述场景
- 可提取到辅助函数的冗余设置代码
- 可使用实现自清理抑制的场景中使用了
#[expect]#[allow] - 测试fixture可使用时仍使用
LazyLock或lazy_static!once_cell
Informational
Informational
- Suggestions to add property-based tests via or
proptestquickcheck - Suggestions to add snapshot testing for complex output
- Coverage improvement opportunities
- 建议通过或
proptest添加基于属性的测试quickcheck - 建议为复杂输出添加快照测试
- 覆盖率提升机会
Valid Patterns (Do NOT Flag)
有效模式(无需标记)
- /
unwrap()in tests — Panicking on unexpected errors is the correct test behaviorexpect() - in test modules — Standard pattern for accessing parent items
use super::* - on test helpers — Helper functions may not be used in every test
#[allow(dead_code)] - in tests — Clarity over performance
clone() - Large test functions — Integration tests can be long; extracting helpers isn't always clearer
- for boolean checks — Fine when the expression is clearly boolean (
assert!,.is_some()).is_empty() - Multiple assertions testing one logical behavior — Sometimes one behavior needs multiple checks
- on
unwrap()-returning test functions — Propagating withResultis also fine but not required? - on mock traits requiring
async-traitdispatch — Nativedynin traits doesn't supportasync fn;dyn Traitis still needed thereasync-trait - with justification on test helpers — Self-cleaning lint suppression is correct in test code
#[expect] - for expensive shared test fixtures — Thread-safe lazy init is appropriate for test globals
LazyLock
- 测试中的/
unwrap()— 意外错误时panic是正确的测试行为expect() - 测试模块中的— 访问父项的标准模式
use super::* - 测试辅助函数上的— 辅助函数可能并非在每个测试中都使用
#[allow(dead_code)] - 测试中的— 清晰度优先于性能
clone() - 大型测试函数 — 集成测试可以很长;提取辅助函数并不总是更清晰
- 布尔检查使用— 当表达式明确为布尔值时(
assert!、.is_some())是可行的.is_empty() - 测试一个逻辑行为时使用多个断言 — 有时一个行为需要多个检查
- 返回的测试函数中使用
Result— 使用unwrap()传播错误也可行,但非必须? - 需要分发的Mock Trait使用
dyn— 原生Traitasync-trait不支持async fn;此时仍需要dyn Traitasync-trait - 测试辅助函数上带有理由的— 测试代码中使用自清理式lint抑制是正确的
#[expect] - 昂贵的共享测试fixture使用— 线程安全的延迟初始化适用于测试全局变量
LazyLock
Before Submitting Findings
提交审查结果前
Load and follow before reporting any issue.
<!-- cross-ref:start -->beagle-rust:review-verification-protocol在报告任何问题前,加载并遵循。
<!-- cross-ref:start -->beagle-rust:review-verification-protocolSee also (related skills — Code review family)
另请参阅(相关技能 — 代码审查系列)
If your issue relates to:
- CodeRabbit-powered review (default) — check if appropriate.
code-review - auto-apply CodeRabbit review comments — check if appropriate.
autofix - Python + pytest review (type safety, async, fixtures) — check if appropriate.
python-code-review - Rust source review — check if appropriate.
rust-code-review - tokio async review — check if appropriate.
tokio-async-code-review - Rust FFI review — check if appropriate.
ffi-code-review - Deep Agents code review — check if appropriate.
deepagents-code-review - SQLAlchemy 2.0 review — check if appropriate.
sqlalchemy-code-review
如果你的问题涉及:
- CodeRabbit驱动的审查(默认) — 若合适,请查看。
code-review - 自动应用CodeRabbit审查评论 — 若合适,请查看。
autofix - Python + pytest审查(类型安全、异步、fixtures) — 若合适,请查看。
python-code-review - Rust源代码审查 — 若合适,请查看。
rust-code-review - Tokio异步审查 — 若合适,请查看。
tokio-async-code-review - Rust FFI审查 — 若合适,请查看。
ffi-code-review - Deep Agents代码审查 — 若合适,请查看。
deepagents-code-review - SQLAlchemy 2.0审查 — 若合适,请查看。
sqlalchemy-code-review
Tokio async review
Tokio异步审查
Tokio Async Code Review
Tokio异步代码审查
Review Workflow
审查流程
- Check Cargo.toml — Note tokio feature flags (,
full,rt-multi-thread,macros, etc.). Missing features cause confusing compile errors.sync - Check runtime setup — Is or manual runtime construction used? Multi-thread vs current-thread?
#[tokio::main] - Scan for blocking — Search for ,
std::fs,std::net, CPU-heavy loops in async functions.std::thread::sleep - Check channel usage — Match channel type to communication pattern (mpsc, broadcast, oneshot, watch).
- Check sync primitives — Verify correct mutex type, proper guard lifetimes, no deadlock potential.
- 检查Cargo.toml — 记录tokio特性标志(、
full、rt-multi-thread、macros等)。缺少特性会导致令人困惑的编译错误。sync - 检查运行时设置 — 使用还是手动构造运行时?多线程还是单线程?
#[tokio::main] - 扫描阻塞操作 — 在异步函数中搜索、
std::fs、std::net、CPU密集型循环。std::thread::sleep - 检查通道使用 — 通道类型与通信模式匹配(mpsc、broadcast、oneshot、watch)。
- 检查同步原语 — 验证互斥锁类型正确、守卫生命周期合理、无死锁风险。
Output Format
输出格式
Report findings as:
text
[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.按以下格式报告问题:
text
[文件:行号] 问题标题
严重程度: Critical | Major | Minor | Informational
问题描述及其影响。Quick Reference
快速参考
| Issue Type | Reference |
|---|---|
| Task spawning, JoinHandle, structured concurrency | references/task-management.md |
| Mutex, RwLock, Semaphore, Notify, Barrier | references/sync-primitives.md |
| mpsc, broadcast, oneshot, watch channel patterns | references/channels.md |
| Pin, cancellation, Future internals, select!, blocking bridge | references/pinning-cancellation.md |
| 问题类型 | 参考文档 |
|---|---|
| 任务生成、JoinHandle、结构化并发 | references/task-management.md |
| Mutex、RwLock、Semaphore、Notify、Barrier | references/sync-primitives.md |
| mpsc、broadcast、oneshot、watch通道模式 | references/channels.md |
| Pin、取消、Future内部实现、select!、阻塞桥接 | references/pinning-cancellation.md |
Review Checklist
审查清单
Runtime Configuration
运行时配置
- Tokio features in Cargo.toml match actual usage
- Runtime flavor matches workload (for I/O-bound,
multi_threadfor simpler cases)current_thread - used for async tests (not manual runtime construction)
#[tokio::test] - Worker thread count configured appropriately for production
- Cargo.toml中的Tokio特性与实际使用匹配
- 运行时类型与工作负载匹配(I/O密集型使用,简单场景使用
multi_thread)current_thread - 异步测试使用(而非手动构造运行时)
#[tokio::test] - 生产环境的工作线程数配置合理
Task Management
任务管理
- return values (
spawn) are tracked, not silently droppedJoinHandle - used for CPU-heavy or synchronous I/O operations
spawn_blocking - Tasks respect cancellation (via ,
CancellationToken, or shutdown channels)select! - (task panic or cancellation) is handled, not just unwrapped
JoinError - branches are cancellation-safe
tokio::select! - Native in traits used instead of
async fncrate where possible (stable since Rust 1.75)async-trait - RPIT lifetime capture reviewed in async contexts — now captures all in-scope lifetimes in edition 2024
-> impl Future
- 的返回值(
spawn)被跟踪,而非被静默丢弃JoinHandle - CPU密集型或同步I/O操作使用
spawn_blocking - 任务遵守取消机制(通过、
CancellationToken或关闭通道)select! - (任务panic或取消)被处理,而非仅unwrap
JoinError - 分支是可取消安全的
tokio::select! - 尽可能使用Trait中的原生而非
async fncrate(自Rust 1.75起稳定)async-trait - 审查异步上下文中的RPIT生命周期捕获 — 2024版本中现在捕获所有作用域内的生命周期
-> impl Future
Sync Primitives
同步原语
- used when lock is held across
tokio::sync::Mutex;.awaitfor short non-async sectionsstd::sync::Mutex - No mutex guard held across await points (deadlock risk)
- used for limiting concurrent operations (not ad-hoc counters)
Semaphore - used when read-heavy workload (many readers, infrequent writes)
RwLock - used for simple signaling (not channel overhead)
Notify - used instead of
std::sync::LazyLockoronce_cell::sync::Lazyfor runtime-initialized singletons (stable since Rust 1.80)lazy_static! - lock guard patterns reviewed for edition 2024 temporary scoping — temporaries drop earlier, may change borrow validity
if let
- 当锁跨持有使用
.await;短非异步段使用tokio::sync::Mutexstd::sync::Mutex - 互斥锁守卫不跨await点持有(有死锁风险)
- 使用限制并发操作(而非临时计数器)
Semaphore - 读密集型工作负载使用(多读者、少写者)
RwLock - 简单信号传递使用(避免通道开销)
Notify - 运行时初始化的单例使用而非
std::sync::LazyLock或once_cell::sync::Lazy(自Rust 1.80起稳定)lazy_static! - 针对2024版本的临时作用域,审查锁守卫模式 — 临时值销毁更早,可能改变借用有效性
if let
Channels
通道
- Channel type matches pattern: mpsc for back-pressure, broadcast for fan-out, oneshot for request-response, watch for latest-value
- Bounded channels have appropriate capacity (not too small = deadlock, not too large = memory)
- /
SendErrorhandled (indicates other side dropped)RecvError - Broadcast errors handled (receiver fell behind)
Lagged - Channel senders dropped when done to signal completion to receivers
- 通道类型与模式匹配:mpsc用于背压、broadcast用于扇出、oneshot用于请求响应、watch用于最新值
- 有界通道容量合理(过小会导致死锁,过大会占用内存)
- /
SendError被处理(表示另一端已断开)RecvError - Broadcast的错误被处理(接收方落后)
Lagged - 完成后丢弃通道发送方,向接收方发出完成信号
Timer and Sleep
定时器与睡眠
- used instead of
tokio::time::sleepstd::thread::sleep - wraps operations that could hang
tokio::time::timeout - used correctly (
tokio::time::intervalfor periodic work).tick().await
- 使用而非
tokio::time::sleepstd::thread::sleep - 可能挂起的操作使用包裹
tokio::time::timeout - 周期性工作正确使用(使用
tokio::time::interval).tick().await
Severity Calibration
严重程度校准
Critical
Critical
- Blocking I/O (,
std::fs::read) in async context withoutstd::net::TcpStreamspawn_blocking - Mutex guard held across point (deadlock potential)
.await - in async function (blocks runtime thread)
std::thread::sleep - Unbounded channel where back-pressure is needed (OOM risk)
- 异步上下文中无的阻塞I/O(
spawn_blocking、std::fs::read)std::net::TcpStream - 互斥锁守卫跨点持有(有死锁风险)
.await - 异步函数中使用(阻塞运行时线程)
std::thread::sleep - 需要背压的场景使用无界通道(有OOM风险)
Major
Major
- silently dropped (lost errors, zombie tasks)
JoinHandle - Missing cancellation safety consideration
select! - Wrong mutex type (std vs tokio) for the use case
- Missing timeout on network/external operations
- 被静默丢弃(丢失错误、僵尸任务)
JoinHandle - 未考虑取消安全
select! - 使用错误的互斥锁类型(std vs tokio)
- 网络/外部操作缺少超时
Minor
Minor
- for trivially small async blocks (overhead > benefit)
tokio::spawn - Overly large channel buffer without justification
- Manual runtime construction where suffices
#[tokio::main] - where contention is high enough to benefit from tokio's async mutex
std::sync::Mutex
- 对极小的异步块使用(开销大于收益)
tokio::spawn - 通道缓冲区过大且无理由
- 可使用的场景下手动构造运行时
#[tokio::main] - 当竞争足够高可从Tokio异步互斥锁受益时仍使用
std::sync::Mutex
Informational
Informational
- Suggestions to use utilities (e.g.,
tokio-util)CancellationToken - Tower middleware patterns for service composition
- Structured concurrency with
JoinSet - Migration from crate to native
async-traitin traitsasync fn - Migration from /
once_celltolazy_staticstd::sync::LazyLock - Using instead of
#[expect(lint)]for self-cleaning suppression#[allow(lint)]
- 建议使用工具(例如
tokio-util)CancellationToken - 服务组合的Tower中间件模式
- 使用实现结构化并发
JoinSet - 从crate迁移到Trait中的原生
async-traitasync fn - 从/
once_cell迁移到lazy_staticstd::sync::LazyLock - 使用而非
#[expect(lint)]实现自清理抑制#[allow(lint)]
Valid Patterns (Do NOT Flag)
有效模式(无需标记)
- for short critical sections — tokio docs recommend this when no
std::sync::Mutexis inside the lock.await - without explicit join — Valid for background tasks with proper shutdown signaling
tokio::spawn - Unbuffered channel capacity of 1 — Valid for synchronization barriers
- in simple binaries — Not every app needs multi-thread runtime
#[tokio::main(flavor = "current_thread")] - on
clone()beforeArc<T>— Required for moving into tasks, not unnecessary cloningspawn - Large broadcast channel capacity — Valid when lagged errors are expensive (event sourcing)
- Native in traits without
async fn— Stable since 1.75; the crate is still valid forasync-traitdispatch casesdyn - on
+ use<'a>returns — Correct edition 2024 precise capture syntax to limit lifetime capture-> impl Future - on complex async types — Self-cleaning alternative to
#[expect(clippy::type_complexity)], warns when suppression is no longer needed#[allow]
- 短临界区使用— Tokio文档推荐在锁内无
std::sync::Mutex时使用.await - 不显式join — 带有正确关闭信号的后台任务是有效的
tokio::spawn - 容量为1的无缓冲通道 — 同步屏障的有效模式
- 简单二进制文件中使用— 并非每个应用都需要多线程运行时
#[tokio::main(flavor = "current_thread")] - 前对
spawn调用Arc<T>— 移入任务所需,并非不必要的克隆clone() - 大容量broadcast通道 — 当滞后错误代价高昂时有效(例如事件溯源)
- Trait中使用原生而非
async fn— 自1.75起稳定;async-trait分发场景仍需使用该cratedyn - 返回值使用
-> impl Future— 2024版本中限制生命周期捕获的精确语法+ use<'a> - 复杂异步类型使用—
#[expect(clippy::type_complexity)]的自清理替代方案,当抑制不再需要时发出警告#[allow]
Before Submitting Findings
提交审查结果前
Load and follow before reporting any issue.
<!-- cross-ref:start -->beagle-rust:review-verification-protocol在报告任何问题前,加载并遵循。
<!-- cross-ref:start -->beagle-rust:review-verification-protocolSee also (related skills — Code review family)
另请参阅(相关技能 — 代码审查系列)
If your issue relates to:
- CodeRabbit-powered review (default) — check if appropriate.
code-review - auto-apply CodeRabbit review comments — check if appropriate.
autofix - Python + pytest review (type safety, async, fixtures) — check if appropriate.
python-code-review - Rust source review — check if appropriate.
rust-code-review - Rust test review — check if appropriate.
rust-testing-code-review - Rust FFI review — check if appropriate.
ffi-code-review - Deep Agents code review — check if appropriate.
deepagents-code-review - SQLAlchemy 2.0 review — check if appropriate.
sqlalchemy-code-review
如果你的问题涉及:
- CodeRabbit驱动的审查(默认) — 若合适,请查看。
code-review - 自动应用CodeRabbit审查评论 — 若合适,请查看。
autofix - Python + pytest审查(类型安全、异步、fixtures) — 若合适,请查看。
python-code-review - Rust源代码审查 — 若合适,请查看。
rust-code-review - Rust测试代码审查 — 若合适,请查看。
rust-testing-code-review - Rust FFI审查 — 若合适,请查看。
ffi-code-review - Deep Agents代码审查 — 若合适,请查看。
deepagents-code-review - SQLAlchemy 2.0审查 — 若合适,请查看。
sqlalchemy-code-review
FFI review
FFI审查
FFI Code Review
FFI代码审查
Review Workflow
审查流程
- Check Cargo.toml -- Note Rust edition (2024 has breaking changes to extern blocks and unsafe attributes), (bindgen, cc, pkg-config),
build-dependencies(crate-type,cdylib), andstaticlibkeylinks - Check build.rs -- Verify link directives (,
cargo:rustc-link-lib), bindgen configuration, and C source compilationcargo:rustc-link-search - Check extern blocks -- Verify calling conventions, symbol declarations, and safety annotations
- Check type layout -- Every type crossing FFI must be or a primitive FFI type
#[repr(C)] - Check string and pointer handling -- CStr/CString usage, null checks, ownership transfers
- Check callbacks -- pointers, panic safety across FFI boundary
extern "C" fn - Verify before reporting -- Load before submitting findings
beagle-rust:review-verification-protocol
- 检查Cargo.toml — 记录Rust版本(2024版本对extern块和unsafe属性有破坏性变更)、(bindgen、cc、pkg-config)、
build-dependencies(crate-type、cdylib)和staticlib键links - 检查build.rs — 验证链接指令(、
cargo:rustc-link-lib)、bindgen配置和C源代码编译cargo:rustc-link-search - 检查extern块 — 验证调用约定、符号声明和安全注解
- 检查类型布局 — 跨FFI的每个类型必须为或原生FFI类型
#[repr(C)] - 检查字符串和指针处理 — CStr/CString使用、空指针检查、所有权转移
- 检查回调 — 指针、跨FFI边界的panic安全
extern "C" fn - 报告前验证 — 在提交审查结果前,加载
beagle-rust:review-verification-protocol
Output Format
输出格式
Report findings as:
text
[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.按以下格式报告问题:
text
[文件:行号] 问题标题
严重程度: Critical | Major | Minor | Informational
问题描述及其影响。Quick Reference
快速参考
| Issue Type | Reference |
|---|---|
| C-to-Rust type mapping, repr(C) layout, enums, opaque types | references/type-mapping.md |
| Safe wrappers, ownership transfer, callbacks, build.rs, testing | references/safety-patterns.md |
| 问题类型 | 参考文档 |
|---|---|
| C到Rust类型映射、repr(C)布局、枚举、不透明类型 | references/type-mapping.md |
| 安全包装、所有权转移、回调、build.rs、测试 | references/safety-patterns.md |
Review Checklist
审查清单
extern Blocks and Calling Conventions
extern块与调用约定
- Foreign function declarations use (explicit, not bare
extern "C")extern - Edition 2024: blocks written as
extern "C" {}unsafe extern "C" {} - Functions exposed to C use (not default Rust calling convention)
extern "C" fn - Calling convention matches the foreign library (,
"C"for Win32 API)"system" - specifies the correct library name
#[link(name = "...")] - used when statically linking
#[link(name = "...", kind = "static")]
- 外部函数声明使用(显式,而非裸
extern "C")extern - 2024版本:块需写成
extern "C" {}unsafe extern "C" {} - 暴露给C的函数使用(而非默认Rust调用约定)
extern "C" fn - 调用约定与外部库匹配(、Win32 API使用
"C")"system" - 指定正确的库名称
#[link(name = "...")] - 静态链接时使用
#[link(name = "...", kind = "static")]
Symbol Management
符号管理
- Exported functions use to preserve symbol names
#[no_mangle] - Edition 2024: written as
#[no_mangle]#[unsafe(no_mangle)] - Edition 2024: written as
#[export_name = "..."]#[unsafe(export_name = "...")] - used when Rust name differs from C symbol
#[link_name = "..."] - Exported items are (only public
pubsymbols appear in library output)#[no_mangle]
- 导出函数使用保留符号名称
#[no_mangle] - 2024版本:需写成
#[no_mangle]#[unsafe(no_mangle)] - 2024版本:需写成
#[export_name = "..."]#[unsafe(export_name = "...")] - 当Rust名称与C符号不同时使用
#[link_name = "..."] - 导出项为(仅公共
pub符号会出现在库输出中)#[no_mangle]
Type Layout
类型布局
- Every struct/union crossing FFI has -- Rust's default layout is undefined
#[repr(C)] - Primitive types use /
std::ffiequivalents (std::os::raw,c_int,c_char)c_void - No bare where C uses
i32-- useint(width varies by platform)c_int - Quirky C types like use byte arrays (
__be32), not Rust integers[u8; 4] - Enums crossing FFI use or
#[repr(C)]/#[repr(u8)]with explicit discriminants#[repr(u32)] - C-style bitflag enums use a newtype around an integer (or crate), not a Rust enum
bitflags - on enums representing C enumerations that may gain new values
#[non_exhaustive]
- 跨FFI的每个结构体/联合体都带有— Rust默认布局未定义
#[repr(C)] - 原生类型使用/
std::ffi等效类型(std::os::raw、c_int、c_char)c_void - C使用时不使用裸
int— 使用i32(宽度因平台而异)c_int - 特殊C类型如使用字节数组(
__be32),而非Rust整数[u8; 4] - 跨FFI的枚举使用或带显式判别式的
#[repr(C)]/#[repr(u8)]#[repr(u32)] - C风格位标志枚举使用整数的Newtype(或crate),而非Rust枚举
bitflags - 代表C枚举且可能新增值的枚举使用
#[non_exhaustive]
String Handling
字符串处理
- C strings use (borrowed) or
CStr(owned), neverCStringor&strString - result is checked for interior null bytes (returns
CString::new()onErr)\0 - outlives any
CStringpointer derived from it via*const c_char.as_ptr() - Incoming validated with
*const c_charinsideCStr::from_ptr()unsafe - No assumption that C strings are valid UTF-8 -- use which returns
to_str()Result - OS paths use /
OsStrandOsString, notCStr&str
- C字符串使用(借用)或
CStr(自有),绝不使用CString或&strString - 检查的结果是否包含内部空字节(遇到
CString::new()返回\0)Err - 的生命周期长于通过
CString派生的.as_ptr()指针*const c_char - 传入的在
*const c_char内通过unsafe验证CStr::from_ptr() - 不假设C字符串为有效UTF-8 — 使用返回
to_str()Result - OS路径使用/
OsStr和OsString,而非CStr&str
Ownership and Allocation
所有权与分配
- Clear ownership contract: who allocates, who frees
- Rust-allocated memory freed by Rust (), C-allocated freed by C
Box::from_raw - /
Box::into_rawpaired correctly for heap transfersBox::from_raw - used when passing arrays to C (pointer + length + capacity)
Vec::into_raw_parts - Destructor functions exposed for every opaque Rust type given to C
- No running on C-allocated memory (and vice versa)
Drop
- 明确所有权契约:谁分配,谁释放
- Rust分配的内存由Rust释放(),C分配的由C释放
Box::from_raw - /
Box::into_raw正确配对以实现堆内存转移Box::from_raw - 向C传递数组时使用(指针+长度+容量)
Vec::into_raw_parts - 为每个提供给C的不透明Rust类型暴露析构函数
- C分配的内存不会运行Rust的(反之亦然)
Drop
Callbacks
回调
- Callback types are , not closures or
extern "C" fn(...)fn(...) - Callbacks use to prevent panics from unwinding across FFI
std::panic::catch_unwind - Callback context passed as with safe reconstruction at call site
*mut c_void - used for nullable function pointers (niche optimization)
Option<extern "C" fn(...)>
- 回调类型为,而非闭包或
extern "C" fn(...)fn(...) - 回调使用防止panic跨FFI边界展开
std::panic::catch_unwind - 回调上下文以传递,并在调用点安全重构
*mut c_void - 可空函数指针使用( niche优化)
Option<extern "C" fn(...)>
Bindgen and Build Scripts
Bindgen与构建脚本
- Bindgen output reviewed for correctness (auto-generated types may need adjustment)
- crate pattern used for raw bindings, separate crate for safe wrappers
-sys - uses
build.rsandcargo:rustc-link-libcorrectlycargo:rustc-link-search - key in
linksprevents duplicate linking of the same native libraryCargo.toml - Platform-specific bindings generated per-build (not checked in for a single platform)
- 审查Bindgen输出的正确性(自动生成的类型可能需要调整)
- 使用crate模式处理原始绑定,单独的crate处理安全包装
-sys - 正确使用
build.rs和cargo:rustc-link-libcargo:rustc-link-search - Cargo.toml中的键防止重复链接同一原生库
links - 按构建生成特定平台的绑定(而非仅为单一平台提交绑定)
Safety Documentation
安全文档
- Every block has a
unsafecomment explaining invariants// SAFETY: - Every public FFI wrapper function documents safety requirements
- Edition 2024: bodies use explicit
unsafe fnblocks around unsafe opsunsafe {}
- 每个块都带有
unsafe注释解释不变量// SAFETY: - 每个公共FFI包装函数都记录安全要求
- 2024版本:主体在不安全操作周围使用显式
unsafe fn块unsafe {}
Severity Calibration
严重程度校准
Critical (Block Merge)
Critical(阻止合并)
- Missing on types crossing FFI boundary (undefined memory layout)
#[repr(C)] - Wrong string handling: /
&strwhereString/CStrrequiredCString - Ownership confusion: freeing C-allocated memory with Rust's allocator (or vice versa)
- Panic unwinding across FFI boundary without
catch_unwind - Using Rust enum for C bitflags (invalid discriminant = undefined behavior)
- Passing closure where pointer required
extern "C" fn
- 跨FFI边界的类型缺少(内存布局未定义)
#[repr(C)] - 字符串处理错误:需要/
CStr时使用CString/&strString - 所有权混淆:用Rust分配器释放C分配的内存(反之亦然)
- 无时panic跨FFI边界展开
catch_unwind - 使用Rust枚举表示C位标志(无效判别式导致未定义行为)
- 需要指针时传递闭包
extern "C" fn
Major (Should Fix)
Major(应修复)
- Missing safety documentation on blocks or public FFI functions
unsafe - No null pointer check on incoming /
*const Tbefore dereferencing*mut T - dropped before its pointer is used by C (dangling pointer)
CString - Missing causing link failures on some platforms
#[link(name = "...")] - Edition 2024: block not marked
externunsafe extern - Edition 2024: not wrapped in
#[no_mangle]#[unsafe(...)]
- 块或公共FFI函数缺少安全文档
unsafe - 传入的/
*const T解引用前未做空指针检查*mut T - 在C使用其指针前被销毁(悬垂指针)
CString - 缺少导致部分平台链接失败
#[link(name = "...")] - 2024版本:块未标记
externunsafe extern - 2024版本:未包装在
#[no_mangle]中#[unsafe(...)]
Minor (Consider Fixing)
Minor(考虑修复)
- Using instead of
i32for Cc_int(correct on most platforms but not portable)int - Missing on enums mapping to extensible C enumerations
#[non_exhaustive] - Verbose manual bindings where bindgen would be more maintainable
- Checked-in bindings without platform guards
- C使用时使用
int而非i32(多数平台正确但不具可移植性)c_int - 映射到可扩展C枚举的枚举缺少
#[non_exhaustive] - 可使用bindgen的场景下使用冗长的手动绑定
- 提交的绑定无平台守卫
Informational
Informational
- Suggestions to split raw bindings into a crate
-sys - Suggestions to add opaque wrapper types for distinct pointers
*mut c_void - Suggestions to use for nullable pointers
Option<NonNull<T>>
- 建议将原始绑定拆分为crate
-sys - 建议为不同的指针添加不透明包装类型
*mut c_void - 建议使用处理可空指针
Option<NonNull<T>>
Valid Patterns (Do NOT Flag)
有效模式(无需标记)
- in edition 2024 -- correct form for foreign declarations
unsafe extern "C" {} - in edition 2024 -- correct form for symbol export
#[unsafe(no_mangle)] - for nullable callbacks -- niche optimization guaranteed
Option<extern "C" fn(...)> - for nullable pointers -- zero-cost nullable pointer pattern
Option<NonNull<T>> - for opaque C types -- standard when internal layout is irrelevant
*mut c_void - Distinct empty structs wrapping for type-safe opaque pointers -- prevents pointer confusion
c_void - with compile-time literal -- safe when literal is known null-terminated
CStr::from_bytes_with_nul_unchecked - for controlled unwinding -- valid per RFC 2945
extern "C-unwind" - in bindgen crates -- standard pattern
include!(concat!(env!("OUT_DIR"), "/bindings.rs")) - /
Box::into_rawpairs for ownership transfer -- correct pattern when pairedBox::from_raw
- 2024版本中的— 外部声明的正确形式
unsafe extern "C" {} - 2024版本中的— 符号导出的正确形式
#[unsafe(no_mangle)] - 可空回调使用— 保证niche优化
Option<extern "C" fn(...)> - 可空指针使用— 零成本可空指针模式
Option<NonNull<T>> - 不透明C类型使用— 内部布局无关时的标准做法
*mut c_void - 包装的不同空结构体用于类型安全的不透明指针 — 防止指针混淆
c_void - 编译时常量使用— 已知常量以空字符结尾时安全
CStr::from_bytes_with_nul_unchecked - 受控展开使用— 符合RFC 2945
extern "C-unwind" - Bindgen crate中使用— 标准模式
include!(concat!(env!("OUT_DIR"), "/bindings.rs")) - 所有权转移使用/
Box::into_raw配对 — 配对时的正确模式Box::from_raw
Before Submitting Findings
提交审查结果前
Load and follow before reporting any issue.
<!-- cross-ref:start -->beagle-rust:review-verification-protocol在报告任何问题前,加载并遵循。
<!-- cross-ref:start -->beagle-rust:review-verification-protocolSee also (related skills — Code review family)
另请参阅(相关技能 — 代码审查系列)
If your issue relates to:
- CodeRabbit-powered review (default) — check if appropriate.
code-review - auto-apply CodeRabbit review comments — check if appropriate.
autofix - Python + pytest review (type safety, async, fixtures) — check if appropriate.
python-code-review - Rust source review — check if appropriate.
rust-code-review - Rust test review — check if appropriate.
rust-testing-code-review - tokio async review — check if appropriate.
tokio-async-code-review - Deep Agents code review — check if appropriate.
deepagents-code-review - SQLAlchemy 2.0 review — check if appropriate.
sqlalchemy-code-review
如果你的问题涉及:
- CodeRabbit驱动的审查(默认) — 若合适,请查看。
code-review - 自动应用CodeRabbit审查评论 — 若合适,请查看。
autofix - Python + pytest审查(类型安全、异步、fixtures) — 若合适,请查看。
python-code-review - Rust源代码审查 — 若合适,请查看。
rust-code-review - Rust测试代码审查 — 若合适,请查看。
rust-testing-code-review - Tokio异步审查 — 若合适,请查看。
tokio-async-code-review - Deep Agents代码审查 — 若合适,请查看。
deepagents-code-review - SQLAlchemy 2.0审查 — 若合适,请查看。
sqlalchemy-code-review