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

Ошибка 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 задуман полным, если ты не сказал иначе. Так твоё намерение понятно следующему читателю. 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, _, _).

Проверь себя

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