| name | rust-quality |
| description | | Use when this capability is needed. |
Rust Quality - Quick Reference
When NOT to Use This Skill
- SonarQube setup - Use
sonarqube skill
- Security scanning - Use
rust-security skill
Deep Knowledge: Use mcp__documentation__fetch_docs with technology: rust for comprehensive documentation.
Tool Overview
| Tool | Focus | Command |
|---|
| rustfmt | Formatting | cargo fmt |
| Clippy | Linting | cargo clippy |
| rust-analyzer | IDE analysis | LSP |
| cargo-deny | Dependency policy | cargo deny |
| cargo-audit | Security audit | cargo audit |
Clippy Setup
Run Clippy
cargo clippy
cargo clippy -- -D warnings
cargo clippy -- -W clippy::pedantic
cargo clippy --fix
cargo clippy --all-targets --all-features
clippy.toml
cognitive-complexity-threshold = 15
too-many-lines-threshold = 50
too-many-arguments-threshold = 5
allowed-wildcard-imports = ["crate::prelude::*"]
Cargo.toml Lint Configuration
[lints.rust]
unsafe_code = "deny"
missing_docs = "warn"
[lints.clippy]
pedantic = { level = "warn", priority = -1 }
nursery = { level = "warn", priority = -1 }
unwrap_used = "warn"
expect_used = "warn"
panic = "warn"
todo = "warn"
dbg_macro = "warn"
module_name_repetitions = "allow"
must_use_candidate = "allow"
CI Configuration
cargo clippy --all-targets --all-features -- \
-D warnings \
-D clippy::pedantic \
-D clippy::nursery \
-A clippy::module_name_repetitions
rustfmt Setup
rustfmt.toml
edition = "2021"
max_width = 100
tab_spaces = 4
newline_style = "Unix"
imports_granularity = "Module"
group_imports = "StdExternalCrate"
reorder_imports = true
reorder_modules = true
reorder_impl_items = true
use_small_heuristics = "Default"
fn_single_line = false
where_single_line = false
struct_lit_single_line = true
comment_width = 100
wrap_comments = true
normalize_comments = true
format_macro_matchers = true
format_macro_bodies = true
Commands
cargo fmt
cargo fmt -- --check
rustfmt src/main.rs
Common Clippy Lints
unwrap_used / expect_used
let value = some_option.unwrap();
let result = some_result.expect("should work");
let value = some_option.ok_or(MyError::NotFound)?;
let result = some_result.map_err(|e| MyError::from(e))?;
let value = config.get("required_key")
.expect("required_key must be set in configuration");
clone_on_ref_ptr
let clone = arc_value.clone();
let clone = Arc::clone(&arc_value);
needless_pass_by_value
fn process(data: String) {
println!("{}", data);
}
fn process(data: &str) {
println!("{}", data);
}
cognitive_complexity
fn process(data: &Data) -> Result<Output, Error> {
if data.is_valid() {
if data.type_a() {
if data.has_value() {
}
}
}
}
fn process(data: &Data) -> Result<Output, Error> {
validate(data)?;
match data.data_type() {
DataType::A => process_type_a(data),
DataType::B => process_type_b(data),
}
}
missing_errors_doc
pub fn process(data: &Data) -> Result<Output, Error> { ... }
pub fn process(data: &Data) -> Result<Output, Error> { ... }
Common Code Smells & Fixes
1. Stringly Typed Code
fn set_status(status: &str) {
match status {
"active" => { ... }
"inactive" => { ... }
_ => panic!("unknown status"),
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Status {
Active,
Inactive,
}
fn set_status(status: Status) {
match status {
Status::Active => { ... }
Status::Inactive => { ... }
}
}
2. Error Handling
pub fn parse_config(path: &Path) -> Config {
let content = fs::read_to_string(path).unwrap();
serde_json::from_str(&content).unwrap()
}
#[derive(Debug, thiserror::Error)]
pub enum ConfigError {
#[error("failed to read config file: {0}")]
Io(#[from] std::io::Error),
#[error("failed to parse config: {0}")]
Parse(#[from] serde_json::Error),
}
pub fn parse_config(path: &Path) -> Result<Config, ConfigError> {
let content = fs::read_to_string(path)?;
let config = serde_json::from_str(&content)?;
Ok(config)
}
3. Builder Pattern
impl Server {
pub fn new(
host: String,
port: u16,
max_connections: usize,
timeout: Duration,
tls_config: Option<TlsConfig>,
) -> Self { ... }
}
#[derive(Default)]
pub struct ServerBuilder {
host: String,
port: u16,
max_connections: usize,
timeout: Duration,
tls_config: Option<TlsConfig>,
}
impl ServerBuilder {
pub fn host(mut self, host: impl Into<String>) -> Self {
self.host = host.into();
self
}
pub fn port(mut self, port: u16) -> Self {
self.port = port;
self
}
pub fn build(self) -> <Server, BuildError> {
}
}
= Server::()
.()
.()
.()?;
4. Newtype Pattern
fn create_user(email: String, name: String, age: u32) { ... }
#[derive(Debug, Clone)]
pub struct Email(String);
impl Email {
pub fn new(value: impl Into<String>) -> Result<Self, ValidationError> {
let value = value.into();
if !value.contains('@') {
return Err(ValidationError::InvalidEmail);
}
Ok(Self(value))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
fn create_user(email: Email, name: Name, age: Age) { ... }
5. Avoid clone() Abuse
fn process(data: &Vec<Item>) {
let owned = data.clone();
for item in owned {
}
}
fn process(data: &[Item]) {
for item in data {
}
}
fn process(data: Vec<Item>) {
for item in data {
}
}
Pre-commit Setup
.pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: cargo-fmt
name: cargo fmt
entry: cargo fmt --
language: system
types: [rust]
- id: cargo-clippy
name: cargo clippy
entry: cargo clippy --all-targets --all-features -- -D warnings
language: system
types: [rust]
pass_filenames: false
- id: cargo-test
name: cargo test
entry: cargo test
language: system
types: [rust]
pass_filenames: false
Makefile
.PHONY: fmt lint test check quality
fmt:
cargo fmt
lint:
cargo clippy --all-targets --all-features -- -D warnings
test:
cargo test
check:
cargo check --all-targets --all-features
quality: fmt check lint test
VS Code Settings
{
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer",
"editor.formatOnSave": true
},
"rust-analyzer.check.command": "clippy",
"rust-analyzer.check.extraArgs": ["--all-targets", "--all-features"],
"rust-analyzer.diagnostics.disabled": [],
"rust-analyzer.lens.run.enable": true,
"rust-analyzer.lens.debug.enable": true
}
Quality Metrics Targets
| Metric | Target | Tool |
|---|
| Cognitive Complexity | < 15 | Clippy |
| Function Lines | < 50 | Clippy |
| Arguments | < 5 | Clippy |
| unsafe blocks | Minimize | Clippy |
| Test Coverage | > 80% | cargo-tarpaulin |
CI/CD Integration
GitHub Actions
name: Quality
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Cache cargo
uses: Swatinem/rust-cache@v2
- name: Check formatting
run: cargo fmt -- --check
- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Run tests
run: cargo test --all-features
Anti-Patterns
| Anti-Pattern | Why It's Bad | Correct Approach |
|---|
unwrap() in library code | Panics propagate | Use ? operator |
Excessive clone() | Performance cost | Borrow when possible |
#[allow(clippy::all)] | Hides all issues | Allow specific lints |
unsafe without comment | Unclear safety | Document invariants |
| String for everything | No type safety | Use enums/newtypes |
| Giant functions | Hard to test/maintain | Extract smaller functions |
Quick Troubleshooting
| Issue | Likely Cause | Solution |
|---|
| Clippy false positive | Edge case or intended | #[allow(clippy::lint)] with comment |
| rustfmt changes code | Formatting opinion | Configure rustfmt.toml |
| Lint conflicts | Pedantic vs nursery | Prioritize in Cargo.toml |
| Slow compilation | Many dependencies | Use cargo-chef for caching |
| Dead code warnings | Unused exports | Add #[cfg(test)] or remove |
Related Skills
Source: claude-dev-suite/claude-dev-suite — distributed by TomeVault.