Ошибка Rust E0026: struct or variant does not have a field named X (поле в образце)
E0026 значит: ты разбираешь структуру или вариант перечисления в образце, например Shape::Circle { r }, и одного из написанных имён полей не существует. Это версия E0560 и E0559 для образцов: те ловят ту же ошибку, когда ты создаёшь значение. Обычно rustc называет правильное имя в строке help:, так что исправление — часто одно слово. (Эта страница входит в серию Ошибки компилятора Rust с объяснениями.)
Сообщение об ошибке
Заголовок раздела «Сообщение об ошибке»error[E0026]: variant `Shape::Circle` does not have a field named `r` --> src/main.rs:8:25 |8 | Shape::Circle { r } => 3.14 * r * r, // ❌ the field is called `radius` | ^ | | | variant `Shape::Circle` does not have this field | help: `Shape::Circle` has a field named `radius`Компилятор говорит: у варианта Shape::Circle нет поля r, зато есть поле radius. Вот программа, которая выдаёт эту ошибку (комментарий значит «поле называется radius»):
enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { r } => 3.14 * r * r, // ❌ the field is called `radius` Shape::Rectangle { width, height } => width * height, }}
fn main() { println!("{}", area(&Shape::Circle { radius: 1.0 }));}Для той же строки ты увидишь и вторую ошибку: E0027, «pattern does not mention field radius» (образец не упоминает поле radius). Это та же ошибка, увиденная с другой стороны. Rust нашёл поле, которое ты назвал, но которого нет (r), и настоящее поле, которое ты не назвал (radius). Исправь имя — и обе ошибки исчезнут.
Что это значит
Заголовок раздела «Что это значит»В заголовке названы структура или вариант, с которым ты сопоставляешь (Shape::Circle), и поле, которое ты написал (r). ^ показывает на это имя внутри фигурных скобок образца.
В образце имена внутри { } — это имена полей, а не новые имена переменных, которые ты выбираешь сам. Shape::Circle { r } — сокращение от Shape::Circle { r: r }: «возьми поле с именем r и положи его в переменную с именем r». У Circle нет поля r, поэтому Rust останавливается.
Под стрелкой rustc даёт одну из этих подсказок:
help: `Shape::Circle` has a field named `radius`(уShape::Circleесть полеradius): ты не упомянул ровно одно поле, и rustc догадывается, что ты имел в виду его.help: a field with a similar name exists(есть поле с похожим именем): опечатка, напримерnmaeвместоname. rustc показывает исправленную строку.- Никакой подсказки: rustc не смог догадаться. Посмотри настоящие имена в определении структуры или перечисления.
Это как попросить библиотекаря «книгу с полки под названием Почти-фантастика». Он понимает, что тебе нужна какая-то полка, но подойти может только к тем полкам, которые действительно существуют.
Почему Rust так делает
Заголовок раздела «Почему Rust так делает»Образец вроде Shape::Circle { radius } — это обещание: «когда значение — Circle, дай мне его radius». При компиляции Rust сверяет это обещание с определением, так что образец никогда не сможет запросить данные, которых нет. Смотри Деструктуризация кортежей и структур.
В языках без такой проверки чтение несуществующего ключа даёт undefined или null, и баг проявляется намного позже, далеко от опечатки. В Rust опечатка не пройдёт мимо компилятора. Это защищает и тогда, когда кто-то переименовывает поле: каждый образец, который всё ещё использует старое имя, загорается ошибкой E0026, так что ни один не будет тихо забыт.
Как исправить
Заголовок раздела «Как исправить»Исправление 1: возьми настоящее имя поля
Заголовок раздела «Исправление 1: возьми настоящее имя поля»Выбирай этот вариант в большинстве случаев. Возьми имя из строки help: или посмотри определение. Имена полей чувствительны к регистру и пишутся в snake_case.
Для опечатки будет подсказка о похожем имени и исправленная строка:
error[E0026]: struct `User` does not have a field named `nmae` --> src/main.rs:8:16 |8 | let User { nmae, age } = user; // ❌ typo: the field is `name` | ^^^^ struct `User` does not have this field |help: a field with a similar name exists |8 - let User { nmae, age } = user; // ❌ typo: the field is `name`8 + let User { name, age } = user; // ❌ typo: the field is `name` |Программа, которая за ней стоит (комментарий значит «опечатка: поле называется name»):
struct User { name: String, age: u32,}
fn main() { let user = User { name: String::from("Ferris"), age: 7 }; let User { nmae, age } = user; // ❌ typo: the field is `name` println!("{} is {} years old", nmae, age);}Пиши имена полей точно так, как в определении. Тогда сокращённая запись работает, и ты получаешь переменные с теми же именами:
struct User { name: String, age: u32,}
enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius } => 3.14 * radius * radius, // ✅ настоящее имя поля Shape::Rectangle { width, height } => width * height, }}
fn main() { let shapes = [ Shape::Circle { radius: 2.0 }, Shape::Rectangle { width: 3.0, height: 4.0 }, ]; for shape in &shapes { println!("площадь: {:.2}", area(shape)); }
let user = User { name: String::from("Ferris"), age: 7 }; let User { name, age } = user; // ✅ `name`, а не `nmae` println!("{}: {} лет", name, age);}Вывод:
площадь: 12.56площадь: 12.00Ferris: 7 летИсправление 2: оставь своё имя переменной через field: name
Заголовок раздела «Исправление 2: оставь своё имя переменной через field: name»Выбирай этот вариант, когда тебе нравится короткое имя r и ты просто хочешь, чтобы переменная так называлась. Напиши настоящее имя поля, двоеточие, а потом имя переменной: Shape::Circle { radius: r }. Читай это как «возьми поле radius и назови его r».
enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius: r } => 3.14 * r * r, // ✅ поле `radius`, переменная `r` Shape::Rectangle { width: w, height: h } => w * h, }}
fn main() { let small = Shape::Circle { radius: 1.0 }; let wide = Shape::Rectangle { width: 10.0, height: 2.5 }; println!("маленький круг: {:.2}", area(&small)); println!("широкий прямоугольник: {:.2}", area(&wide));}Вывод:
маленький круг: 3.14широкий прямоугольник: 25.00Это удобно и тогда, когда поля иначе совпали бы по имени с уже существующими переменными или когда имя поля длинное.
Исправление 3: проверь, тот ли вариант ты сопоставляешь
Заголовок раздела «Исправление 3: проверь, тот ли вариант ты сопоставляешь»Выбирай этот вариант, когда поле, которое ты написал, настоящее, но в другом варианте. У каждого варианта перечисления свои поля. Здесь x принадлежит Click, а ветка сопоставляет KeyPress:
error[E0026]: variant `Event::KeyPress` does not have a field named `x` --> src/main.rs:9:27 |9 | Event::KeyPress { x, .. } => format!("key at {}", x), // ❌ `x` belongs to `Click` | ^ | | | variant `Event::KeyPress` does not have this field | help: `Event::KeyPress` has a field named `key`Программа, которая за ней стоит (комментарий значит «x принадлежит Click»):
enum Event { Click { x: i32, y: i32 }, KeyPress { key: char },}
fn describe(event: &Event) -> String { match event { Event::Click { x, y } => format!("click at ({}, {})", x, y), Event::KeyPress { x, .. } => format!("key at {}", x), // ❌ `x` belongs to `Click` }}
fn main() { println!("{}", describe(&Event::KeyPress { key: 'a' }));}Догадка rustc (key) — это просто «единственное поле, которое ты не упомянул», так что не принимай её вслепую. Спроси себя, что должна делать эта ветка. У нажатия клавиши нет координат, так что здесь правильное исправление — использовать поле, которое у KeyPress действительно есть:
enum Event { Click { x: i32, y: i32 }, KeyPress { key: char },}
fn describe(event: &Event) -> String { match event { Event::Click { x, y } => format!("клик в точке ({}, {})", x, y), Event::KeyPress { key } => format!("нажата клавиша '{}'", key), // ✅ у KeyPress есть `key` }}
fn main() { let events = [Event::Click { x: 10, y: 20 }, Event::KeyPress { key: 'a' }]; for event in &events { println!("{}", describe(event)); }}Вывод:
клик в точке (10, 20)нажата клавиша 'a'Если у нажатия клавиши действительно должны быть координаты, добавь поля в вариант: KeyPress { key: char, x: i32, y: i32 }. Тогда каждое место, где создаётся KeyPress, тоже должно их заполнить (rustc покажет на каждое ошибкой E0063).
Где это обычно встречается
Заголовок раздела «Где это обычно встречается»После переименования поля. Ты переименовал в перечислении r в radius, и каждая ветка Shape::Circle { r } => ... теперь даёт E0026. Найди по проекту старое имя и обнови каждый образец или напиши radius: r, чтобы оставить старое имя переменной.
В if let и let. if let Some(User { nmae, .. }) = find_user() даёт ту же ошибку. .. здесь не поможет: .. пропускает поля, которые ты не называешь, но каждое имя, которое ты пишешь, всё равно должно существовать. Исправление: User { name, .. }.
Фигурные скобки у кортежного варианта или кортежной структуры. Для struct Point(i32, i32); в образце Point { x, y } нет настоящих имён полей, с которыми можно сопоставить. rustc сообщает об этом другим кодом, E0769, «tuple variant Point written as struct variant», и предлагает Point(x, y). Смотри Деструктуризация перечислений с данными.
Связанные ошибки
Заголовок раздела «Связанные ошибки»- E0027: pattern does not mention field: близнец E0026 — настоящее поле, которое твой образец пропустил. Часто выводится вместе с E0026.
- E0559: variant has no field named x: то же неверное имя при создании варианта перечисления.
- E0560: struct has no field named x: то же неверное имя при создании структуры.
- E0609: no field on type: то же неверное имя при чтении поля, например
user.nmae. - E0533: expected unit struct, unit variant or constant: вариант правильный, но у образца не та форма (нет
{ }). - Все ошибки компилятора с объяснениями
Проверь себя
Заголовок раздела «Проверь себя»Проверь себя
1. Что запрашивает образец Shape::Circle { r } для enum Shape { Circle { radius: f64 } }?
2. Ты хочешь получить поле radius в переменной r. Какой образец сработает?
3. Скомпилируется ли User { nmae, .. }, если поле называется name?
Результат: 0 / 3
Что почитать
Заголовок раздела «Что почитать»- E0026 — Rust error codes index (на английском): официальное объяснение этой ошибки.
- Синтаксис шаблона — книга «Язык программирования Rust» (перевод на русский): деструктуризация структур и перечислений, включая
field: variableи... - Структуры — Rust на примерах (перевод на русский): маленькие запускаемые примеры образцов для структур.
- Patterns — The Rust Reference (на английском): точные правила для образцов структур и сокращённой записи полей.