clippy, rustfmt и miri
Заключительный блок про инженерную гигиену: линтеры, безопасность зависимостей, фиксация тулчейна, образы для прода. Вопросы простые, но по ответам видно, работал ли человек в команде с CI.
Стержень: у каждой задачи свой инструмент, и они не заменяют друг друга.
// Формулировки: «что делает clippy?», «как следите за уязвимостями?», «зачем rust-toolchain.toml?»
Кто за что отвечает
clippy - линтер идиоматичности: лишний clone, ручной цикл вместо итератора, unwrap там, где просится разбор, подозрительные сравнения. Часть подсказок применяется автоматически через --fix. rustfmt форматирует, и спорить о стиле в ревью больше не приходится.
Безопасность зависимостей - cargo audit по базе RustSec (известные уязвимости и заброшенные крейты) плюс cargo deny для политики: лицензии, дубли версий, разрешённые источники. Неопределённое поведение в unsafe ловит Miri. Всё это отдельные шаги в CI, компилятор ими не занимается.
// Полезная привычка: clippy в CI с deny(warnings) на изменённом коде. Иначе правила расходятся между разработчиками, и линтер превращается в шум.
- clippy
- линтер идиоматичности поверх проверок компилятора
- cargo audit
- проверка зависимостей по базе уязвимостей RustSec
Версии тулчейна и сборка образа
rust-toolchain.toml фиксирует версию компилятора и нужные компоненты: у всех разработчиков и в CI одинаковые предупреждения clippy и одинаковое поведение форматирования. Это не то же самое, что rust-version в Cargo.toml - там указывается минимальная поддерживаемая версия для пользователей библиотеки.
Для прода часто нужен маленький образ. Цель x86_64-unknown-linux-musl даёт статический бинарник, который кладётся в scratch или distroless и работает без системных библиотек. Плата - аллокатор musl медленнее на многопоточной нагрузке, и это стоит замерить, а не принять на веру.
// В цикле разработки главный инструмент скорости - cargo check: он останавливается до кодогенерации и потому в разы быстрее полной сборки. На нём же работает rust-analyzer в редакторе.
- rust-toolchain.toml
- фиксация версии компилятора для проекта
- MSRV
- minimum supported Rust version: самая старая версия компилятора, на которой крейт обязан собираться
Как отвечать: «Как в проекте следят за уязвимостями в зависимостях?»
Отдельным шагом в CI: cargo audit сверяет Cargo.lock с базой RustSec и сообщает про известные уязвимости и заброшенные крейты. Рядом обычно ставят cargo deny - он добавляет политику по лицензиям, дублирующимся версиям и источникам зависимостей. Компилятор такими проверками не занимается, поэтому без этих шагов проблему просто не увидят. Если уязвимость нашлась в транзитивной зависимости и обновления нет, смотрю, можно ли поднять версию промежуточного крейта, временно закрепить патч через секцию patch или зафиксировать исключение с явным сроком пересмотра.
Ты называешь инструменты, разводишь их роли и отвечаешь на неудобное продолжение - что делать, когда обновления нет. Это уже эксплуатационная зрелость.
На чём валятся
- −Считают, что clippy проверяет безопасность зависимостей.
- −Гоняют линтер локально, но не ставят в CI - правила расходятся между разработчиками.
- −Путают rust-toolchain и rust-version.
- −Берут musl ради размера образа, не замерив влияние аллокатора.
- −Не знают про cargo check и ждут полной сборки ради проверки типов.
Проверьте себя
Пять вопросов из банка по этой подтеме. Всего их 13, остальные разбираются в тренажёре.
- Зачем в проекте фиксируют версию тулчейна в rust-toolchain.toml?A)Чтобы все разработчики и CI собирали проект одним компиляторомB)Чтобы ускорить сборку за счёт кэша компилятораC)Чтобы задать минимальную поддерживаемую версию для пользователей крейтаD)Чтобы запретить использование нестабильных возможностей языка
показать ответ и разбор
+A)Чтобы все разработчики и CI собирали проект одним компилятором// разбор: Файл заставляет rustup взять указанную версию и нужные компоненты автоматически: у всех одинаковые предупреждения clippy, одинаковое поведение форматирования и одинаковый набор стабильных возможностей. Минимальная поддерживаемая версия — это отдельное поле rust-version в Cargo.toml, и служит оно другой цели.
- Как в CI отслеживают уязвимости в зависимостях Rust-проекта?A)Скриптом сравнения версий с последними на crates.ioB)Встроенной проверкой cargo build при сборке в releaseC)Анализом бинарника внешним сканером после сборкиD)cargo audit по базе RustSec, политика — в cargo deny
показать ответ и разбор
+D)cargo audit по базе RustSec, политика — в cargo deny// разбор: cargo audit сверяет Cargo.lock с базой RustSec и сообщает про известные уязвимости и заброшенные крейты. cargo deny добавляет правила по лицензиям, дублирующимся версиям и источникам зависимостей. Оба гоняют в CI как отдельный шаг — сам компилятор такими проверками не занимается.
- Нужен маленький образ для сервиса. Что даёт сборка с musl?A)Ускорение работы за счёт более быстрой реализации аллокатораB)Статический бинарник для образа без системных библиотекC)Уменьшение бинарника вдвое за счёт удаления отладочных символовD)Кросс-компиляцию под ARM без дополнительных тулчейнов
показать ответ и разбор
+B)Статический бинарник для образа без системных библиотек// разбор: Цель x86_64-unknown-linux-musl собирает бинарник без зависимости от glibc, поэтому он кладётся в scratch или distroless и запускается без окружения. Плата — аллокатор musl медленнее на многопоточной нагрузке, и это иногда заметно. Альтернатива — обычная сборка поверх тонкого базового образа с нужными библиотеками.
- Чем cargo check полезнее cargo build во время разработки?A)Он проверяет типы и заимствования без кодогенерацииB)Он проверяет код без учёта зависимостей проектаC)Он собирает только изменившиеся файлы, пропуская остальныеD)Он запускает тесты вместе с проверкой компиляции
показать ответ и разбор
+A)Он проверяет типы и заимствования без кодогенерации// разбор: Дольше всего в Rust идёт кодогенерация и оптимизация, а разработчику при правке чаще нужен ответ «типы сходятся, заимствования корректны». cargo check останавливается до кодогенерации и потому в разы быстрее — на нём и построена проверка в редакторе через rust-analyzer. Бинарник он не производит.
- Что делает cargo fix?A)Исправляет форматирование кода по правилам rustfmt во всех файлахB)Восстанавливает повреждённый Cargo.lock по манифесту проекта и его зависимостямC)Пересобирает проект с нуля, очищая каталог target от старых артефактовD)Автоматически применяет исправления, предложенные компилятором и линтами
показать ответ и разбор
+D)Автоматически применяет исправления, предложенные компилятором и линтами// разбор: Многие предупреждения компилятора и clippy содержат машинно-применимое исправление, и cargo fix раскатывает их по коду. Главное применение — переход на новую редакцию: --edition правит идиомы, которые изменились. Форматированием занимается cargo fmt, очисткой — cargo clean, а lock восстанавливается обычной сборкой.
дальше
Теорию прочитали. Навык ставится повторением
В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.