EnglishРусский Map
Clippy

Конфигурация Clippy должна быть строже

title
Конфигурация Clippy должна быть строже
type
summary
summary
Выборочные lint'ы Clippy для возвращения ощущения "компилируется - значит работает", что особенно актуально, когда патчи пишут coding agents
parent
clippy
tags
rust, clippy, linting, coding-agents
created
2026-04-30
updated
2026-07-22
lang
ru
source_updated
2026-07-22
translated
2026-09-01
translator
lllm/antigravity/gemini-3.7-flash-medium

Эван Шварц, создатель сервиса персонализированных лент Scour, лишился пятничной рассылки дайджеста из-за паники Tokio worker'а: byte index 200 is not a char boundary. Функция обрезала аннотации статей по байтовому индексу без учёта границ символов UTF-8. Компилятор не мог этого поймать. Исправлением стала безопасная для UTF-8 обрезка, но более глубокий вопрос звучал так: какие lint'ы Clippy могли бы это предотвратить и какие ещё опасные паттерны ждут своего часа?

Повод для беспокойства шире одной ошибки. Он вспоминает громкий сбой в Cloudflare из-за unwrap в ноябре 2025 года как напоминание о том, что у принципа Rust "компилируется - значит работает" есть слабые места: паники, брошенные future, дедлоки, незаметные ошибки с числами. Более строгие lint'ы Clippy закрывают часть этих пробелов. Они ещё важнее, когда код генерирует coding agent: опытный инженер избегает таких паттернов на автомате, а вот агент или джуниор - нет, при этом включение новых lint'ов на легаси-кодовой базе - это как раз та рутинная работа, в которой агент особенно хорош.

Почему бы просто не включить категорию целиком

В Clippy входят сотни lint'ов, разделённых по категориям: Correctness, Suspicious, Complexity, Perf, Style, Pedantic, Restriction, Cargo, Nursery, Deprecated. Ни одна из них не сопоставляется напрямую с правилом "не дай этому упасть в панику в проде". В частности, категорию restriction в документации прямо не рекомендуют включать целиком: она содержит взаимоисключающие lint'ы (например, big_endian_bytes и little_endian_bytes). В статье предлагается подключать проверки точечно, lint за lint'ом.

Он также подмечает полезную мысль: lint, который не срабатывает сегодня, всё равно полезен - это растяжка на тот день, когда кто-то (вы сами, коллега или агент) напишет проблемный паттерн.

Lint'ы по назначению

Не паниковать. Отлавливать грабли с unwrap, срезами и индексацией. string_slice поймал бы исходный баг. А также: indexing_slicing, unwrap_used, panic, todo, unimplemented, unreachable, get_unwrap, unwrap_in_result, unchecked_time_subtraction, panic_in_result_fn. Он отмечает, что expect_used - спорный lint (сообщение в .expect() зачастую достаточно хорошо документирует инвариант), а arithmetic_side_effects в его кодовой базе давал примерно 85% шума на 15% реальных проблем.

Не молчать об ошибках. let_underscore_future (выброшенные future), let_underscore_must_use (проглоченный Result), unused_result_ok (отбрасывание ошибок через .ok()), map_err_ignore (потеря исходной ошибки в .map_err(|_| MyErr)), assertions_on_result_states (проверка is_ok в assert'ах без вывода текста ошибки).

Не творить дичь в асинхронном коде. await_holding_lock, await_holding_refcell_ref, if_let_mutex (только до редакции 2024), large_futures (слишком большие future приводят к переполнению стека).

Не делать опасных вещей с памятью. mem_forget, undocumented_unsafe_blocks (каждый блок unsafe {} требует комментария // SAFETY:), multiple_unsafe_ops_per_block (одна операция на блок, чтобы у каждой было отдельное обоснование), unnecessary_safety_doc / unnecessary_safety_comment.

Не делать потенциально некорректных операций с числами. float_cmp, float_cmp_const, lossy_float_literal, cast_sign_loss, invalid_upcast_comparisons. Опциональные и более строгие: cast_possible_wrap, cast_precision_loss, cast_possible_truncation - вместе они заставляют документировать числовые инварианты при каждом приведении типов с потерей данных.

Простые победы. rc_mutex (Rc<Mutex<_>> почти всегда ошибка), debug_assert_with_mut_call (расхождение в поведении между debug и release), iter_not_returning_iterator, expl_impl_clone_on_copy, infallible_try_from, dbg_macro.

Не давать обходить проверки через allow. allow_attributes (заставляет использовать #[expect(..., reason = "...")] вместо молчаливого #[allow]) и allow_attributes_without_reason. Эта пара - убойная комбинация именно против агентов: агент не сможет молча отключить lint, чтобы его код прошёл проверку, ему придётся явно обосновать причину.

Подводный камень с workspace'ами

Lint'ы уровня workspace в Cargo не наследуются автоматически. Каждый crate в составе workspace'а должен явно включить lints.workspace = true. В статье рекомендуется использовать cargo-workspace-lints (или скрипт в CI) для контроля этого правила; в nightly для той же цели есть missing_lints_inheritance.

Warn против deny

Автор предпочитает warn = "..." в сочетании с cargo clippy -- -D warnings на CI: так локальная разработка не блокируется, но планка при фиксации изменений остаётся той же.

Послабления для тестов

Файл clippy.toml в корне workspace'а ослабляет строгие lint'ы для тестов, где unwrap, panic и прямое индексирование - нормальная практика:

allow-indexing-slicing-in-tests = true
allow-panic-in-tests = true
allow-unwrap-in-tests = true
allow-expect-in-tests = true
allow-dbg-in-tests = true

Почему это не просто готовый конфиг

Акцент на агентах - это как раз то, что имеет общее значение. Статья неявно раскрывает тему clean-code-coding-agents с другой стороны: структура кода нужна не только для того, чтобы человеку приходилось меньше читать. Она сужает пространство плохих шаблонов, под которые может подстроиться агент. Lint, не позволяющий агенту выдать &s[..200], решает ту же задачу, что и функция со строгой сигнатурой: оба задают ограничения, повышающие вероятность того, что результат работы агента окажется верным.