Ошибка Rust E0027: pattern does not mention field X (поле не упомянуто)
E0027 значит: ты разбираешь структуру или вариант перечисления образцом, например let Order { item, quantity } = order;, и упомянул не все поля. В Rust образец структуры должен учитывать все поля: либо называть их, либо говорить «и остальные» через ... Это одна из самых дружелюбных ошибок: rustc выводит точное исправление, и почти всегда это две точки. (Эта страница входит в серию Ошибки компилятора Rust с объяснениями.)
Сообщение об ошибке
Заголовок раздела «Сообщение об ошибке»error[E0027]: pattern does not mention fields `id`, `paid` --> src/main.rs:10:9 |10 | let Order { item, quantity } = order; // ❌ `id` and `paid` are not mentioned | ^^^^^^^^^^^^^^^^^^^^^^^^ missing fields `id`, `paid` |help: include the missing fields in the pattern |10 | let Order { item, quantity, id, paid } = order; // ❌ `id` and `paid` are not mentioned | ++++++++++help: if you don't care about these missing fields, you can explicitly ignore them |10 | let Order { item, quantity, id: _, paid: _ } = order; // ❌ `id` and `paid` are not mentioned | ++++++++++++++++help: or always ignore missing fields here |10 | let Order { item, quantity, .. } = order; // ❌ `id` and `paid` are not mentioned | ++++Компилятор говорит: образец не упоминает поля id и paid, — и предлагает три способа это исправить. Вот программа, которая выдаёт эту ошибку (комментарий значит «id и paid не упомянуты»):
struct Order { id: u32, item: String, quantity: u32, paid: bool,}
fn main() { let order = Order { id: 1, item: String::from("keyboard"), quantity: 2, paid: true }; let Order { item, quantity } = order; // ❌ `id` and `paid` are not mentioned println!("{} x {}", quantity, item);}Что это значит
Заголовок раздела «Что это значит»В заголовке перечислены поля, которые твой образец пропустил (id и paid). ^^^ подчёркивает весь образец, потому что проблема не в одном неверном слове, а в том, чего не хватает.
Дальше rustc даёт три подсказки help:. Все они правильные, и значат они разное:
include the missing fields(добавь пропущенные поля): назови их, и у тебя будут ещё и переменныеidиpaid.explicitly ignore them(явно проигнорируй их): напишиid: _, paid: _. Переменных не будет, но каждое поле перечислено по имени.always ignore missing fields here(всегда игнорируй пропущенные поля здесь): напиши... Это значит «и любые другие поля, они мне не важны».
Это как контрольный список у двери, где написано «отметь каждый пункт или отметь Прочее: пропустить». Оставить пункты пустыми нельзя.
Почему Rust так делает
Заголовок раздела «Почему Rust так делает»Образец структуры в Rust задуман полным, если ты не сказал иначе. Так твоё намерение понятно следующему читателю. Order { item, quantity, .. } говорит «мне нужны только эти два». Order { id, item, quantity, paid } говорит «я подумал о каждом поле». Смотри Пропускаем части с помощью _ и ...
Настоящая польза проявляется, когда структура меняется. Если кто-то добавит в Order поле discount, образец, который перечисляет все поля по имени, сломается с E0027 и укажет на код, которому, возможно, нужно обработать новое поле. Образец с .. продолжит компилироваться. Rust даёт тебе выбрать нужное поведение, но гадать за тебя не станет.
Как исправить
Заголовок раздела «Как исправить»Исправление 1: добавь .., чтобы пропустить остальные
Заголовок раздела «Исправление 1: добавь .., чтобы пропустить остальные»Выбирай этот вариант в большинстве случаев. Если тебе нужны только некоторые поля, закончи образец ... Это работает в let, match, if let и параметрах функций, и .. должно стоять последним.
struct Order { id: u32, item: String, quantity: u32, paid: bool,}
fn main() { let order = Order { id: 1, item: String::from("клавиатура"), quantity: 2, paid: true }; let Order { item, quantity, .. } = order; // ✅ `..` пропускает `id` и `paid` println!("{} шт.: {}", quantity, item);
let orders = [ Order { id: 2, item: String::from("мышь"), quantity: 1, paid: false }, Order { id: 3, item: String::from("монитор"), quantity: 1, paid: true }, ]; for order in &orders { match order { Order { paid: true, item, .. } => println!("отправить: {}", item), Order { id, .. } => println!("заказ №{} ждёт оплаты", id), } }}Вывод:
2 шт.: клавиатуразаказ №2 ждёт оплатыотправить: мониторОбрати внимание на paid: true в первой ветке: поле в образце можно ещё и сравнить со значением, а .. всё равно позаботится об остальных.
Исправление 2: назови пропущенное поле или проигнорируй его по имени через _
Заголовок раздела «Исправление 2: назови пропущенное поле или проигнорируй его по имени через _»Выбирай этот вариант, когда поле тебе действительно нужно или когда ты хочешь, чтобы образец сломался, если потом добавят поле. Та же ошибка появляется в match по варианту перечисления с именованными полями:
error[E0027]: pattern does not mention field `y` --> src/main.rs:9:9 |9 | Message::Move { x } => println!("move to x = {}", x), // ❌ `y` is not mentioned | ^^^^^^^^^^^^^^^^^^^ missing field `y`Программа, которая за ней стоит (комментарий значит «y не упомянут»):
enum Message { Move { x: i32, y: i32 }, Quit,}
fn main() { let m = Message::Move { x: 1, y: 2 }; match m { Message::Move { x } => println!("move to x = {}", x), // ❌ `y` is not mentioned Message::Quit => println!("quit"), }}У перемещения две координаты, и коду на самом деле стоит использовать обе. Так что назови y. Когда поле действительно не важно, y: _ говорит об этом вслух и всё равно перечисляет его по имени:
enum Message { Move { x: i32, y: i32 }, Quit,}
fn main() { let messages = [Message::Move { x: 1, y: 2 }, Message::Move { x: 5, y: 0 }, Message::Quit]; for m in &messages { match m { Message::Move { x, y: 0 } => println!("скользим по полу до x = {}", x), Message::Move { x, y } => println!("перемещаемся в ({}, {})", x, y), // ✅ оба поля Message::Quit => println!("выход"), } }
// каждое поле названо по имени: если добавить поле в `Move`, это нарочно сломается if let Message::Move { x, y: _ } = &messages[0] { println!("первый x = {}", x); }}Вывод:
перемещаемся в (1, 2)скользим по полу до x = 5выходпервый x = 1Если называешь поле только для того, чтобы его проигнорировать, пиши y: _, а не просто y. Просто y, которым ты не пользуешься, даёт предупреждение «unused variable» (неиспользуемая переменная).
Исправление 3: исправь опечатку в имени поля
Заголовок раздела «Исправление 3: исправь опечатку в имени поля»Выбирай этот вариант, когда E0027 приходит вместе с E0026 на той же строке. Например, Shape::Circle { r } для варианта с полем radius даёт обе: E0026 для r (такого поля нет) и E0027 для radius (не упомянуто). Подсказка rustc к E0027 предложит добавить radius рядом с r, но тебе нужно не это. Настоящее исправление — заменить неверное имя: Shape::Circle { radius } или Shape::Circle { radius: r }, чтобы оставить короткое имя переменной. Тогда обе ошибки исчезнут разом. Примеры — на странице E0026.
Где это обычно встречается
Заголовок раздела «Где это обычно встречается»После добавления поля в структуру. Ты добавляешь created_at в Order, и каждый образец, который перечислял все поля, теперь даёт E0027. Это проверка делает свою работу. Реши для каждого: нужно ли этому коду created_at? Если да — назови его, если нет — добавь ...
Параметры функций. fn print_order(&Order { item, quantity }: &Order) тоже даёт E0027. Исправление: &Order { item, quantity, .. }. Смотри Образцы в let и параметрах функций.
Кортежные структуры и кортежные варианты. Для struct Color(u8, u8, u8); образец Color(r) тоже неполный, но rustc сообщает об этом как E0023: «this pattern has 1 field, but the corresponding tuple struct has 3 fields» (в образце 1 поле, а у кортежной структуры 3). Идея исправления та же: Color(r, ..) или Color(r, _, _).
Связанные ошибки
Заголовок раздела «Связанные ошибки»- E0026: struct or variant does not have a field named x: имя поля в образце, которого не существует. Часто выводится вместе с E0027.
- E0063: missing field in initializer: та же идея при создании структуры: каждому полю нужно значение (или
..Default::default()). - E0004: non-exhaustive patterns:
match, который не покрывает каждый вариант, тогда как E0027 — про каждое поле. E0023: this pattern has N fields, but the corresponding tuple struct has M fields: версия для кортежных структур (смотри выше).- Все ошибки компилятора с объяснениями
Проверь себя
Заголовок раздела «Проверь себя»Проверь себя
1. struct Point { x: i32, y: i32, z: i32 }. Какой образец скомпилируется и даст только x?
2. Чем отличаются Order { item, .. } и Order { item, id: _, quantity: _, paid: _ }?
3. Ты получаешь E0026 для r и E0027 для radius на одной строке. Какое исправление лучше?
Результат: 0 / 3
Что почитать
Заголовок раздела «Что почитать»- E0027 — Rust error codes index (на английском): официальное объяснение этой ошибки.
- Синтаксис шаблона — книга «Язык программирования Rust» (перевод на русский): деструктуризация структур и игнорирование оставшихся частей значения через
... - Структуры — Rust на примерах (перевод на русский): запускаемые образцы для структур с
... - Patterns — The Rust Reference (на английском): точные правила для образцов структур и образца «остальное» (rest pattern).