Ржавый, но не безнадёжный: как ИИ меняет Rust-разработку
Rust — язык, который обожают за безопасность памяти и скорость, но ненавидят за компилятор, который вечно требует «правильного» подхода. Написать сложный парсер, безопасный сетевой сервис или асинхронный движок с нуля — задача не для слабонервных. Но что, если часть этой работы можно переложить на плечи искусственного интеллекта?
Генерация кода с помощью ИИ — уже не фантастика, а рабочий инструмент. В 2025 году нейросети научились не просто «угадывать» следующий токен, а генерировать осмысленные, компилируемые фрагменты на Rust. В этой статье мы разберём, как использовать ИИ для ускорения разработки на Rust, где он реально полезен, а где — бесполезен. И да, будет много кода.
Почему Rust сложен для ИИ (и почему это меняется)
Большинство LLM (Large Language Models) обучаются на GitHub-репозиториях. Rust-кода там пока меньше, чем Python или JavaScript. Однако ситуация кардинально изменилась после выхода моделей GPT-4 Turbo, Claude 3.5 Sonnet и специализированных сборок Copilot. Теперь генерация кода с помощью ИИ для Rust — это не «сгенерировать что-то похожее на Rust», а получить рабочий код с учётом владения (ownership), времени жизни (lifetimes) и строгой типизации.
Секрет успеха — в качественных промптах. Rust требует точности: если вы попросите ИИ «напиши функцию, которая принимает строку», нейросеть может выдать fn foo(s: &str), а может — fn foo(s: String). Разница колоссальная. Поэтому мы будем учиться формулировать запросы правильно.
Инструменты для генерации Rust-кода: что выбрать?
Прежде чем погружаться в примеры, давайте определимся с инструментарием. Генерация кода с помощью ИИ доступна через несколько каналов:
- GitHub Copilot — лучший выбор для повседневной работы. Он понимает контекст файла, подсказывает типы и структуры.
- ChatGPT / Claude — идеальны для генерации целых модулей или объяснения сложных концепций.
- Codeium / Tabnine — бесплатные альтернативы с поддержкой Rust.
- Локальные модели (Code-Llama, DeepSeek Coder) — для тех, кто хочет сохранить приватность кода.
Мы будем использовать синтаксис, универсальный для любого инструмента: промпты на русском языке, которые можно скопировать и вставить.
Практические примеры: от простого к сложному
Пример 1: Генерация базовой структуры данных
Допустим, вам нужна структура для представления HTTP-запроса. Вместо того чтобы писать её вручную, можно использовать ИИ.
Промпт:
Напиши на Rust структуру HttpRequest с полями: method (строка), path (строка), headers (HashMap), body (Option Vec<u8>). Добавь метод new и метод для получения заголовка по ключу. Используй &str для строк, где это возможно.
Результат (сгенерирован ИИ):
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct HttpRequest {
pub method: String,
pub path: String,
pub headers: HashMap<String, String>,
pub body: Option<Vec<u8>>,
}
impl HttpRequest {
pub fn new(method: &str, path: &str) -> Self {
HttpRequest {
method: method.to_string(),
path: path.to_string(),
headers: HashMap::new(),
body: None,
}
}
pub fn get_header(&self, key: &str) -> Option<&String> {
self.headers.get(key)
}
}
Код компилируется «из коробки». Обратите внимание: ИИ сам выбрал HashMap<String, String> вместо BTreeMap и учёл, что &str нужно преобразовывать в String. Это уже хороший уровень понимания языка.
Пример 2: Генерация кода с использованием трейтов (traits)
Rust славится системой трейтов. Попросим ИИ реализовать трейт Serialize для нашей структуры.
Промпт:
Реализуй трейт Serialize из serde для структуры HttpRequest. Напиши код с использованием атрибутов serde. Добавь кастомную сериализацию для поля body: если body — None, то сериализуй как null, иначе как строку base64.
Результат:
use serde::{Serialize, Serializer};
use base64::{Engine as _, engine::general_purpose};
#[derive(Serialize)]
pub struct HttpRequest {
pub method: String,
pub path: String,
pub headers: HashMap<String, String>,
#[serde(serialize_with = "serialize_body")]
pub body: Option<Vec<u8>>,
}
fn serialize_body<S>(body: &Option<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match body {
Some(b) => {
let encoded = general_purpose::STANDARD.encode(b);
serializer.serialize_str(&encoded)
}
None => serializer.serialize_none(),
}
}
ИИ не только сгенерировал код, но и добавил зависимость от base64 в комментариях (хотя в реальном проекте её нужно прописать в Cargo.toml). Это показывает, что генерация кода с помощью ИИ становится «контекстно-зависимой».
Асинхронный Rust: где ИИ реально выручает
Асинхронное программирование в Rust — одна из самых сложных тем для новичков. Future, Pin, async/await, tokio — комбинации, которые легко запутать. ИИ отлично справляется с генерацией шаблонного кода для асинхронных задач.
Промпт:
Напиши асинхронную функцию на Rust с использованием tokio, которая принимает список URL, загружает их параллельно и возвращает HashMap, где ключ — URL, а значение — длина тела ответа. Используй reqwest. Обработай ошибки.
Результат:
use std::collections::HashMap;
use reqwest::Client;
use tokio::task;
pub async fn fetch_urls(urls: &[String]) -> HashMap<String, Result<usize, String>> {
let client = Client::new();
let mut handles = Vec::new();
for url in urls {
let client = client.clone();
let url = url.clone();
handles.push(task::spawn(async move {
match client.get(&url).send().await {
Ok(resp) => {
let len = resp.text().await.map(|t| t.len()).unwrap_or(0);
(url, Ok(len))
}
Err(e) => (url, Err(format!("Ошибка: {}", e))),
}
}));
}
let mut results = HashMap::new();
for handle in handles {
if let Ok((url, result)) = handle.