Rust Code Quality Standards¶
Type: Reference (Information-Oriented)
Code quality standards, lint rules, and idioms enforced across all amplihack-rs
Rust crates. These standards are checked automatically in CI and must pass before
any PR is merged.
Quality Gates¶
Every PR must satisfy all four gates before merging:
| Gate | Command | Expectation |
|---|---|---|
| Lint | cargo clippy -- -D warnings |
Zero warnings, zero errors |
| Format | cargo fmt --all --check |
No format drift |
| Tests | cargo test --workspace |
All tests pass, no regressions |
| Dead code | Enforced via clippy | No unused items without annotation |
Run locally in sequence:
Clippy Lint Rules¶
Zero-warnings policy¶
The entire workspace compiles with -D warnings, which promotes every clippy
warning to a hard error. No warnings are permitted without an explicit,
documented #[allow(...)] attribute.
Inlined format arguments (uninlined_format_args)¶
Use inlined variable syntax in all format strings:
// ✅ correct
let msg = format!("{name} failed with {code}");
tracing::warn!("{path} not found");
// ❌ wrong — triggers uninlined_format_args
let msg = format!("{} failed with {}", name, code);
tracing::warn!("{} not found", path);
This applies to format!, println!, eprintln!, write!, writeln!,
tracing::info!, tracing::warn!, tracing::error!, and all similar macros.
To batch-fix the entire workspace at once:
Design Patterns¶
Associated functions vs methods¶
Prefer associated functions (no self) for pure transformations that do not
need instance state. Use &self only when the function actually reads from
self.
// ✅ correct — pure transformation, no instance state needed
impl SettingsGenerator {
pub fn merge_settings(base: &Value, overrides: &Value) -> Value {
// ...
}
}
// Call site
let merged = SettingsGenerator::merge_settings(&base, &overrides);
// ❌ wrong — unnecessarily borrows self
impl SettingsGenerator {
pub fn merge_settings(&self, base: &Value, overrides: &Value) -> Value {
// never reads self fields
}
}
The only_used_in_recursion clippy lint will flag methods where self is
passed through recursion but never actually read. Convert these to associated
functions.
Error Handling¶
See CONTRIBUTING_RUST.md for the error strategy
table. In summary:
| Crate type | Error crate | Pattern |
|---|---|---|
Library (amplihack-* without binary) |
thiserror |
Typed enum Error |
| Binary / CLI | anyhow |
.context("what we were doing") |
Never use Box<dyn Error> or unwrap() in library crates.
Format Style¶
rustfmt.toml sets the workspace format configuration. Key settings:
| Option | Value | Effect |
|---|---|---|
edition |
2024 |
Rust 2024 edition formatting |
max_width |
100 |
Line length cap |
Run cargo fmt --all to apply; cargo fmt --all --check to verify.
CI Integration¶
The quality gates run in .github/workflows/ on every push and PR:
lint job → cargo clippy -- -D warnings
fmt job → cargo fmt --all --check
test job → cargo test --workspace
All three must pass for the merge button to be enabled. There are no optional quality gates — all are required.
Common Fixes Reference¶
| Warning | Root cause | Fix |
|---|---|---|
uninlined_format_args |
format!("{}", x) |
Change to format!("{x}") |
only_used_in_recursion |
&self method that never reads self |
Convert to associated function |
dead_code on constant |
Constant with no call site | Remove the constant (do not annotate with #[allow(dead_code)] to silence) |
needless_pass_by_ref_mut |
&mut T param that isn't mutated |
Change to &T |
clippy::redundant_closure |
\|x\| f(x) |
Replace with f |
clippy::match_wildcard_for_single_variants |
_ => in exhaustive enum match |
Add explicit arms |