Перейти к содержимому

Ошибки компилятора Rust с объяснениями

Компилятор Rust выдал красную ошибку, и непонятно, чего он хочет? Ты по адресу. Каждый разработчик на Rust видит эти ошибки, часто по многу раз в день. Хорошая новость: тех, что встречаются снова и снова, совсем немного, а когда ты их узнаешь, они перестанут пугать.

Каждая страница ниже посвящена одному коду ошибки: она показывает настоящее сообщение, объясняет его простыми словами и даёт исправления, которые можно запустить прямо в браузере. Сам компилятор всегда пишет по-английски, поэтому во второй колонке таблицы — его точные слова: их удобно искать.

Ошибка Что пишет компилятор Простыми словами
E0382 borrow of moved value Ты отдал значение, а потом попытался использовать его снова
E0502 cannot borrow as mutable because it is also borrowed as immutable Ты меняешь что-то, пока это ещё кто-то читает
E0499 cannot borrow as mutable more than once at a time Два места хотят менять одно и то же одновременно
E0308 mismatched types Ты передал один тип там, где ожидался другой
E0277 the trait bound is not satisfied Тип не умеет делать то, что ты от него просишь (выводиться, сравниваться, складываться…)
E0106 missing lifetime specifier Rust не может понять, как долго возвращаемая ссылка остаётся действительной
E0425 cannot find value in this scope Имя написано с опечаткой или используется вне блока, где оно живёт
E0599 no method named … found У этого типа нет такого метода, или его трейт не импортирован
E0384 cannot assign twice to immutable variable Ты изменил переменную, объявленную без mut
E0596 cannot borrow as mutable, as it is not declared as mutable Ты попытался что-то изменить через переменную или ссылку без mut
E0597 borrowed value does not live long enough Ссылка всё ещё используется, а значения, на которое она указывает, уже нет
E0515 cannot return reference to local variable Ты вернул ссылку на то, что удаляется в конце функции
E0373 closure may outlive the current function, but it borrows … Замыкание (часто — поток) заимствует локальную переменную, которой может не стать до его запуска
E0369 binary operation == cannot be applied to type … Твой тип (пока) не поддерживает ==, <, + и им подобные
E0432 unresolved import Строка use указывает на крейт, модуль или элемент, который не удаётся найти
E0433 cannot find type … in this scope (older: failed to resolve) Путь вроде HashMap::new() использует имя, которое не импортировано или не существует
E0424 self value is a keyword only available in methods with a self parameter Ты использовал self в функции, которая не принимает self
E0061 this function takes N arguments but M arguments were supplied Ты передал слишком много или слишком мало аргументов (необязательных аргументов в Rust нет)
E0594 cannot assign to p.hp, as p is not declared as mutable Ты изменил поле или значение за &, не имея доступа через mut
E0004 non-exhaustive patterns: X not covered Твой match обрабатывает не все возможные значения
E0507 cannot move out of x which is behind a shared reference Ты попытался забрать владение тем, что только заимствовал
E0603 function x is private Ты использовал функцию, структуру или модуль без pub
E0716 temporary value dropped while borrowed Ты сохранил ссылку на значение, которое выбрасывается в конце строки
E0463 can’t find crate for x Крейт (или стандартная библиотека для целевой платформы) не установлен
E0368 binary assignment operation += cannot be applied to type … Твой тип не поддерживает +=, -= и им подобные
E0057 this function takes N arguments but M were supplied (note: closure defined here) Ты вызвал замыкание со слишком большим или слишком малым числом аргументов
E0282 type annotations needed Rust не может сам вывести тип, поэтому его нужно указать
E0609 no field x on type T Имя поля написано с опечаткой, или значение во что-то обёрнуто (например, в Option)
E0593 closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments Замыкание принимает отдельные аргументы там, где ожидается кортеж (или другое их число)
E0631 type mismatch in closure arguments Тип параметра замыкания не совпадает с тем, что оно получает (часто i32 против &i32)
E0005 refutable pattern in local binding let Some(x) = … может не сработать, поэтому обычный let его не принимает
E0615 attempted to take value of method len on type String Ты написал s.len вместо s.len()
E0610 {integer} is a primitive type and therefore doesn’t have fields Ты обратился к .field у числа, bool или char
E0560 struct User has no field named nmae В литерале структуры есть поле, которого у структуры нет
E0616 field balance of struct Account is private Ты читаешь поле без pub за пределами его модуля
E0451 field x of struct Y is private Ты создаёшь структуру литералом, а некоторые её поля приватные
E0624 method x is private Ты вызвал метод или связанную функцию без pub
E0283 type annotations needed (cannot infer type … multiple impls satisfy this bound) Подходят несколько типов (например, для .collect(), .sum()), так что нужно выбрать один
E0284 type annotations needed: cannot satisfy <_ as FromStr>::Err == _ "42".parse() не знает, в какой тип разбирать строку
E0790 cannot call associated function on trait without specifying the corresponding impl type Ты написал Default::default() или Trait::new(), не сказав, для какого типа
E0559 variant Shape::Circle has no field named r В литерале варианта перечисления есть поле, которого у варианта нет
E0063 missing field email in initializer of User Ты создал структуру, но пропустил одно или несколько полей
E0689 can’t call method pow on ambiguous numeric type {integer} 2.pow(10) или 2.0.sqrt() нужен конкретный числовой тип вроде i32 или f64
E0034 multiple applicable items in scope Два трейта дают твоему типу метод с одним и тем же именем, и Rust не может выбрать
E0412 cannot find type X in this scope (Rust 1.93+ prints E0425) Имя типа написано с опечаткой, не импортировано или не объявлено
E0428 the name area is defined multiple times У двух элементов одно имя; перегрузки функций в Rust нет
E0026 variant Shape::Circle does not have a field named r Образец называет поле, которого нет у структуры или варианта
E0027 pattern does not mention fields id, paid В образце структуры не хватает полей; добавь их или закончи образец на ..
E0533 expected unit struct, unit variant or constant, found struct variant Shape::Circle Вариант-структура (или функция) стоит там, где ожидается простое имя; добавь { .. }
E0592 duplicate definitions with name reset Два блока impl определяют метод с одним и тем же именем
E0255 the name Error is defined multiple times Импорт через use называется так же, как твой собственный тип или функция
E0252 the name Result is defined multiple times Две строки use приносят одно и то же имя; переименуй одно через as
E0411 cannot find type Self in this scope Ты использовал Self вне impl или трейта
E0405 cannot find trait Display in this scope Имя трейта написано с опечаткой или не импортировано (например, use std::fmt::Display;)
E0532 expected unit struct, unit variant or constant, found tuple variant Shape::Circle Образец называет вариант-кортеж (или структуру) без ( ) или добавляет ( ) там, где их быть не должно
E0164 expected tuple struct or tuple variant, found struct variant Shape::Circle Образец использует ( ) у варианта-структуры или связанного элемента; нужны { } или условие-страж
E0404 expected trait, found derive macro Debug Ты написал impl X for или T: X, где X — структура, псевдоним или неимпортированный derive-макрос
E0401 can’t use generic parameters from outer item Внутренняя fn использует T или Self внешней функции; дай ей свои обобщённые параметры или используй замыкание
E0107 enum takes 2 generic arguments but 1 generic argument was supplied Result<u32>, HashMap<String> и им подобные: слишком мало или слишком много аргументов в < >
E0530 match bindings cannot shadow tuple variants Голое имя варианта вроде Circle => (после use Shape::*) не может стать новой переменной
E0434 can’t capture dynamic environment in a fn item Внутренняя fn не видит внешних локальных переменных; используй замыкание или передай их аргументами
E0601 main function not found in crate main В бинарном крейте нет fn main() (её нет, опечатка, она внутри mod или это на самом деле библиотека)
E0658 use of unstable library feature iter_intersperse Ты использовал API, доступный только в nightly, на стабильном Rust; возьми стабильную альтернативу или обновись
E0614 type u32 cannot be dereferenced Ты написал *x, хотя x — уже обычное значение, а не ссылка
E0435 attempt to use a non-constant value in a constant const, длина массива или static использует переменную из let; сделай её const или возьми Vec
E0554 #![feature] may not be used on the stable release channel Скопирован код только для nightly; убери атрибут и используй стабильный API или осознанно переходи на nightly

Сообщения об ошибках в Rust знамениты своей полезностью, но в них много всего. Вот настоящее:

fn main() {
let name = String::from("Ferris");
let greeting = name;
println!("{name}");
}
error[E0382]: borrow of moved value: `name`
--> src/main.rs:4:16
|
2 | let name = String::from("Ferris");
| ---- move occurs because `name` has type `String`, which does not implement the `Copy` trait
3 | let greeting = name;
| ---- value moved here
4 | println!("{name}");
| ^^^^ value borrowed here after move
|
help: consider cloning the value if the performance cost is acceptable
|
3 | let greeting = name.clone();
| ++++++++

Читай его в таком порядке:

  1. Первая строка — это сводка: код ошибки (E0382) и описание в одну строку. Здесь: «заимствование перемещённого значения name».
  2. Строка со стрелкой (--> src/main.rs:4:16) показывает файл, строку и столбец, где что-то пошло не так.
  3. Значки ^^^^ указывают на точное место ошибки. Значки ---- рассказывают предысторию. Здесь они говорят: значение создано в строке 2, перемещено (moved) в строке 3, а затем использовано в строке 4.
  4. help: — исправление, которое предлагает компилятор, часто с точным кодом, который нужно добавить (значки ++++ показывают новые символы). Это не всегда лучшее исправление, но отличная отправная точка.

Начинай читать с первой ошибки. Одна оплошность может вызвать целую цепочку последующих ошибок, и после исправления первой остальные часто исчезают сами.

  • Проси у компилятора подробностей. У каждого кода ошибки есть встроенное подробное объяснение. Выполни в терминале:

    Terminal window
    rustc --explain E0382

    Ты получишь короткое описание, сломанный пример и исправленный (на английском).

  • Проверяй почаще. cargo check находит ошибки, не собирая всю программу, поэтому он намного быстрее cargo build. Если запускать его каждые несколько строк, ошибки будут встречаться по одной, а не по двадцать. См. Cargo и крейты.

  • Пусть редактор показывает ошибки прямо при наборе. С расширением rust-analyzer ошибки появляются прямо в коде, с тем же текстом подсказок. См. Инструменты и установка.

Большинство этих ошибок существует потому, что Rust ещё до запуска программы проверяет то, что другие языки обнаруживают только во время работы (или никогда): использование освобождённой памяти, два потока, которые меняют одни и те же данные, забытую проверку на null. Каждая исправленная ошибка — это баг, который никогда не дойдёт до твоих пользователей.

Поэтому многие говорят: в Rust вся борьба происходит во время компиляции, а потом программа просто работает. Правила, которые стоят за самыми частыми ошибками, разобраны в уроках Владение, Заимствование и Времена жизни.

Проверь себя

1. Ошибка Rust показывает несколько проблем. Какую исправлять первой?

2. Что делает rustc --explain E0382?

3. Что показывают значки ^^^^ в сообщении об ошибке?

Результат: 0 / 3