Clippy и rustfmt
| Язык | Rust |
|---|---|
| rustfmt | форматтер, команда cargo fmt |
| Clippy | линтер, команда cargo clippy; более 750 линтов |
| Установка | компоненты rustup (rustfmt, clippy) |
| Настройки | rustfmt.toml, clippy.toml, [lints] в Cargo.toml |
| Интеграция | rust-analyzer, pre-commit, CI |
rustfmt и Clippy — официальные инструменты экосистемы Rust, которые устанавливаются вместе с компилятором через rustup. rustfmt автоматически приводит код к единому стилю, описанному в Rust Style Guide, а Clippy — линтер с сотнями проверок, который находит ошибки, неидиоматичный код и упущенные возможности для оптимизации. Оба запускаются через Cargo одной командой и стали обязательной частью CI почти любого Rust-проекта.[1][3]
rustfmt
rustfmt следует официальному руководству по стилю Rust:[4] четыре пробела, максимальная ширина строки 100 символов, завершающие запятые в многострочных списках, упорядоченные импорты.
rustup component add rustfmt
cargo fmt # отформатировать весь проект
cargo fmt --check # только проверить (для CI), код возврата ≠ 0 при расхождениях
В отличие от gofmt, у rustfmt есть настройки в файле rustfmt.toml — но сообщество рекомендует почти ничего не менять, чтобы код всех проектов выглядел одинаково.[6]
# rustfmt.toml
edition = "2024"
max_width = 100
# nightly-опции:
# imports_granularity = "Crate"
# group_imports = "StdExternalCrate"
Многие опции доступны только в nightly-версии. Отдельный фрагмент можно исключить атрибутом #[rustfmt::skip] — например, вручную выровненную матрицу. Стиль привязан к редакции языка (style edition), поэтому обновление rustfmt не переформатирует код неожиданно.
Clippy
Clippy проверяет код на уровне, недоступном обычным предупреждениям компилятора. Название — отсылка к скрепке-помощнику из Microsoft Office.[1]
rustup component add clippy
cargo clippy # проверить
cargo clippy --all-targets --all-features -- -D warnings # строго, для CI
cargo clippy --fix # применить автоматические исправления
Группы линтов
Линты разделены на группы с разным уровнем по умолчанию:[2]
| Группа | По умолчанию | Что ловит |
|---|---|---|
correctness |
ошибка | почти наверняка баги |
suspicious |
предупреждение | подозрительный код |
style |
предупреждение | неидиоматичное написание |
complexity |
предупреждение | излишне сложный код |
perf |
предупреждение | лишние аллокации и копирования |
pedantic |
выкл. | строгие, иногда спорные проверки |
restriction |
выкл. | запреты под политику проекта (unwrap_used, print_stdout) |
nursery |
выкл. | экспериментальные линты |
cargo |
выкл. | проблемы метаданных Cargo.toml |
Примеры
// clippy::len_zero — используйте is_empty()
if v.len() == 0 { }
// clippy::needless_range_loop — итерируйтесь напрямую
for i in 0..v.len() { println!("{}", v[i]); }
// clippy::redundant_clone — лишнее копирование
let s2 = s.clone(); drop(s);
// clippy::manual_map
let y = match x { Some(v) => Some(v + 1), None => None }; // → x.map(|v| v + 1)
// clippy::unwrap_used (restriction) — запрет unwrap в продакшен-коде
let n: i32 = input.parse().unwrap();
Линты особенно полезны новичкам: они подсказывают идиомы — if let, итераторы, ? вместо ручного match (см. Обработка ошибок в Rust (Result, ?)) — и объясняют их ссылкой на документацию.
Настройка
С Rust 1.74 уровни линтов удобно задавать прямо в Cargo.toml — для одного крейта или для всего workspace:[5][7]
[lints.rust]
unsafe_code = "forbid"
[lints.clippy]
pedantic = { level = "warn", priority = -1 }
unwrap_used = "deny"
undocumented_unsafe_blocks = "deny"
module_name_repetitions = "allow"
Отдельные места можно разрешить атрибутом с объяснением:
#[expect(clippy::too_many_arguments, reason = "API повторяет C-функцию")]
fn ffi_wrapper(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) {}
Атрибут #[expect] (стабилен с Rust 1.81) лучше #[allow]: он выдаст предупреждение, если подавляемый линт перестал срабатывать и подавление стало ненужным. Числовые пороги (например, допустимая когнитивная сложность) задаются в clippy.toml.
Линт undocumented_unsafe_blocks требует комментарий // SAFETY: у каждого unsafe-блока — это стандартная практика для Unsafe Rust.
В CI и редакторе
Типичный набор шагов в GitHub Actions или GitLab CI:
cargo fmt --all --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-features
Флаг -D warnings превращает предупреждения в ошибки, чтобы новый код не добавлял замечаний. Версию инструментов стоит закрепить файлом rust-toolchain.toml: каждый релиз Rust добавляет новые линты, и без фиксации сборка может внезапно «покраснеть». В редакторе rust-analyzer умеет запускать Clippy вместо cargo check при сохранении и показывать замечания прямо в коде.
Аналоги
Похожую пару в Go образуют gofmt и go vet со staticcheck, в Python — Ruff (линтер и форматтер в одном), в JavaScript — Prettier и ESLint. Как и Ruff, Clippy умеет автоматически исправлять многие замечания.