Ошибки компилятора 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
Заголовок раздела «Как читать ошибку Rust»Сообщения об ошибках в 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` trait3 | let greeting = name; | ---- value moved here4 | println!("{name}"); | ^^^^ value borrowed here after move |help: consider cloning the value if the performance cost is acceptable |3 | let greeting = name.clone(); | ++++++++Читай его в таком порядке:
- Первая строка — это сводка: код ошибки (
E0382) и описание в одну строку. Здесь: «заимствование перемещённого значенияname». - Строка со стрелкой (
--> src/main.rs:4:16) показывает файл, строку и столбец, где что-то пошло не так. - Значки
^^^^указывают на точное место ошибки. Значки----рассказывают предысторию. Здесь они говорят: значение создано в строке 2, перемещено (moved) в строке 3, а затем использовано в строке 4. help:— исправление, которое предлагает компилятор, часто с точным кодом, который нужно добавить (значки++++показывают новые символы). Это не всегда лучшее исправление, но отличная отправная точка.
Начинай читать с первой ошибки. Одна оплошность может вызвать целую цепочку последующих ошибок, и после исправления первой остальные часто исчезают сами.
Три полезные привычки
Заголовок раздела «Три полезные привычки»-
Проси у компилятора подробностей. У каждого кода ошибки есть встроенное подробное объяснение. Выполни в терминале:
Terminal window rustc --explain E0382Ты получишь короткое описание, сломанный пример и исправленный (на английском).
-
Проверяй почаще.
cargo checkнаходит ошибки, не собирая всю программу, поэтому он намного быстрееcargo build. Если запускать его каждые несколько строк, ошибки будут встречаться по одной, а не по двадцать. См. Cargo и крейты. -
Пусть редактор показывает ошибки прямо при наборе. С расширением rust-analyzer ошибки появляются прямо в коде, с тем же текстом подсказок. См. Инструменты и установка.
Почему в Rust так много ошибок
Заголовок раздела «Почему в Rust так много ошибок»Большинство этих ошибок существует потому, что Rust ещё до запуска программы проверяет то, что другие языки обнаруживают только во время работы (или никогда): использование освобождённой памяти, два потока, которые меняют одни и те же данные, забытую проверку на null. Каждая исправленная ошибка — это баг, который никогда не дойдёт до твоих пользователей.
Поэтому многие говорят: в Rust вся борьба происходит во время компиляции, а потом программа просто работает. Правила, которые стоят за самыми частыми ошибками, разобраны в уроках Владение, Заимствование и Времена жизни.
Проверь себя
Заголовок раздела «Проверь себя»Проверь себя
1. Ошибка Rust показывает несколько проблем. Какую исправлять первой?
2. Что делает rustc --explain E0382?
3. Что показывают значки ^^^^ в сообщении об ошибке?
Результат: 0 / 3
Что почитать
Заголовок раздела «Что почитать»- Rust Compiler Error Index (на английском): официальный список всех кодов ошибок, у каждого — сломанный и исправленный пример.
- Понимание владения — книга «Язык программирования Rust» (перевод на русский): правила, которые стоят за самыми частыми ошибками заимствования и перемещения.
- Обработка ошибок — книга «Язык программирования Rust» (перевод на русский): как Rust обрабатывает ошибки в твоих программах (
Resultиpanic!), а не только ошибки компилятора. - What is rustc? — The rustc Book (на английском): как устроен компилятор, включая его флаги и уровни линтов.