Rust учит дисциплине, которая в других языках остаётся опциональной. Владение и заимствование — это не синтаксический сахар, а фундаментальная модель памяти, описанная в The Rust Programming Language. Именно поэтому первые недели часто проходят в войне с компилятором: код логически верный, но E0502 и E0499 не дают его собрать.
Хорошая новость: LLM уже видели миллионы трейсбеков и RFC. Если правильно сформулировать промт, модель превращается в терпеливого наставника, который объясняет не «что не так», а «почему система типов так устроена». Ниже — 14 промтов, проверенных на реальных проектах: от разбора borrow checker до async на Tokio.
Базовый уровень
1. Читаем трейсбек как инженер
Задача: понять ошибку компилятора, а не просто её заглушить.
Промт:
Ты — senior Rust-разработчик. Разбери ошибку компилятора по шагам:
1) что компилятор пытается доказать;
2) какое правило владения нарушено;
3) три способа исправить (clone, ссылка, рефакторинг API) с плюсами и минусами;
4) какой вариант идиоматичнее по Rust API Guidelines.
Вот код и ошибка:
<вставь код>
<вставь вывод cargo build>
Пример результата: для cannot borrow x as mutable more than once модель объясняет, что одновременно живут две &mut, показывает замену на split_at_mut и предупреждает, что clone() маскирует проблему проектирования.
2. Lifetimes на бытовой метафоре
Задача: перестать бояться 'a.
Промт:
Объясни lifetimes на примере функции, возвращающей &str из двух входных &str.
Дай: (а) сломанный вариант и текст ошибки; (б) версию с явными аннотациями;
(в) правило elision, которое позволяет их опустить. Без воды.
Результат: модель показывает fn longest<'a>(x: &'a str, y: &'a str) -> &'a str и объясняет правило №2 из Rust Reference.
3. Перевод с Python на Rust
Задача: перенести скрипт без потери смысла.
Промт:
Переведи Python-код на идиоматичный Rust. Сохрани поведение, но замени исключения на Result, а списки — на Vec или слайсы. Добавь комментарии, где Rust отличается семантически. Код: <вставь>
Результат: list comprehension превращается в итератор .map().collect(), а try/except — в ?-оператор.
4. Прогон через Clippy до коммита
Задача: писать код, который не стыдно ревьюить.
Промт:
Вот код. Сделай ревью как Clippy в режиме pedantic:
— перечисли предупреждения с lint-кодами;
— предложи исправления;
— отметь места, где правило можно нарушить осознанно, и почему.
Продвинутый уровень
5. Диагностика E0502 в async-контексте
Задача: понять, почему borrow checker «ломается» именно в async.
Промт:
Разбери, почему этот async-код не компилируется под Tokio:
<код>
Объясни роль будущего (Future) как состояния и почему &mut через .await запрещён.
Дай безопасный вариант через Arc<Mutex<>> и через канал mpsc. Сравни overhead.
Результат: таблица с Arc<Mutex<T>> vs tokio::sync::mpsc и рекомендация по нагрузке.
6. Tokio: от блокирующего кода к асинхронному
Задача: не блокировать runtime.
Промт:
Перепиши этот синхронный код на Tokio. Используй tokio::spawn, tokio::fs, tokio::time.
Покажи, где std::thread::sleep опасен, и замени на tokio::time::sleep.
Добавь graceful shutdown через tokio::signal. Код: <вставь>
Результат: модель добавляет select! и объясняет, почему блокировка воркера рушит throughput (см. Tokio tutorial).
7. Генерация кода с трейтами From/Into
Задача: идиоматичные конверсии.
Промт:
Спроектируй типы UserDTO и User (домен). Реализуй From/Into, TryFrom для валидации.
Покажи, где лучше TryFrom, а где — обычный From. Приведи тесты.
8. Обработка ошибок без unwrap
Задача: production-ready обработка.
Промт:
Перепиши этот код без unwrap/expect. Используй thiserror для библиотечных ошибок
и anyhow для приложения. Покажи, как сохранить контекст через .context().
Результат: два crate-а, разделение по слоям, #[from] для автоматических конверсий.
9. Собеседование: 20 вопросов по lifetimes
Задача: подготовиться к интервью.
Промт:
Сыграй роль интервьюера в Rust-команде. Задай 20 вопросов по владению, lifetimes и Send/Sync.
После каждого моего ответа дай оценку и укажи, что упущено. Не подсказывай заранее.
Экспертный уровень
10. Рефакторинг на zero-copy
Задача: убрать лишние аллокации.
Промт:
Проанализируй этот код на аллокации. Предложи zero-copy вариант через Cow<'a, str>,
&[u8] и lifetimes. Объясни, где Cow реально выигрывает, а где добавляет сложность.
11. Send/Sync и почему async требует их
Задача: понять ограничения tokio::spawn.
Промт:
Почему tokio::spawn требует Send + 'static? Объясни через модель исполнения.
Покажи тип, который НЕ является Send, и как это ломает spawn. Дай обходные пути.
12. Unsafe: минимальный и обоснованный
Задача: применять unsafe осознанно.
Промт:
Вот код с unsafe. Проверь его на нарушение memory safety. Напиши Safety-комментарий
по правилам из Rustonomicon. Предложи safe-альтернативу, если она есть.
Результат: ссылки на Rustonomicon и разбор инвариантов.
13. Тесты: property-based и fuzz
Задача: покрыть инварианты.
Промт:
Сгенерируй тесты для функции <код>: unit, integration, proptest и fuzz-цель для cargo-fuzz.
Опиши инварианты, которые проверяет каждый уровень.
14. Метрики и профилирование
Задача: найти узкое место.
Промт:
Предложи план профилирования Rust-сервиса на Tokio: cargo-flamegraph, tokio-console,
perf. Что смотреть в первую очередь при высоком p99? Дай команды и интерпретацию.
Результат: пошаговый чек-лист с командами cargo flamegraph и RUSTFLAGS.
Что действительно меняется
Промт — это не замена практике, а ускоритель понимания. Компилятор Rust строг ровно настолько, чтобы вы не выстрелили себе в ногу в проде; LLM помогает перевести его сообщения на человеческий и увидеть паттерны, которые иначе приходят месяцами проб. Начните с промтов №1–3, доведите их до автоматизма, а затем переходите к async и unsafe. И обязательно проверяйте сгенерированный код: cargo clippy -- -D warnings и cargo test остаются вашими лучшими ревьюерами.
Комментарии