Ошибка Rust E0559: variant has no field named X (поле варианта enum)
E0559 значит: ты создаёшь значение перечисления через Enum::Variant { field: value }, и одного из написанных полей в этом варианте нет. Это версия E0560 для перечислений — там та же ошибка, но со структурами. Обычно дело в сокращённом или неправильно написанном имени поля, в поле из другого варианта или в фигурных скобках у варианта, которому нужны круглые. Исправление почти всегда — одно слово. (Эта страница входит в серию Ошибки компилятора Rust с объяснениями.)
Сообщение об ошибке
Заголовок раздела «Сообщение об ошибке»error[E0559]: variant `Shape::Circle` has no field named `r` --> src/main.rs:8:33 |8 | let shape = Shape::Circle { r: 2.0 }; // ❌ the field is called `radius` | ^ `Shape::Circle` does not have this field | = note: available fields are: `radius`Компилятор говорит: у варианта Shape::Circle нет поля r, а доступное поле — radius. Вот программа, которая выдаёт эту ошибку (комментарий значит «поле называется radius»):
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn main() { let shape = Shape::Circle { r: 2.0 }; // ❌ the field is called `radius` println!("{:?}", shape);}Что это значит
Заголовок раздела «Что это значит»В заголовке названы вариант (Shape::Circle) и поле, которое ты написал (r). ^ показывает на это поле внутри фигурных скобок. Rust посмотрел на определение Circle { radius: f64 } и не нашёл поля с именем r.
У каждого варианта перечисления свой список полей. У Shape::Circle есть radius, у Shape::Rectangle — width и height. Общих полей у них нет, даже внутри одного перечисления.
Под стрелкой rustc даёт одну из этих подсказок. Прочитай её первой — обычно ответ там:
note: available fields are: `radius`(доступные поля): близкого совпадения нет. Это поля этого варианта, которые ты ещё не заполнил.help: a field with a similar name exists(есть поле с похожим именем): опечатка, напримерkyeвместоkey. rustc показывает исправленную строку.help: `Message::Write` is a tuple variant, use the appropriate syntax(это кортежный вариант): у полей варианта нет имён, поэтому ему нужны( ), а не{ }.note: all struct fields are already assigned(все поля уже заданы): ты заполнил все настоящие поля, а это — лишнее.
Это как заказывать пиццу и просить «большое тесто», когда в меню есть только «размер теста». На кухне прекрасно понимают, что ты имеешь в виду, но в бланке заказа нет графы с таким названием.
Почему Rust так делает
Заголовок раздела «Почему Rust так делает»Вариант перечисления с именованными полями, например Circle { radius: f64 }, работает как маленькая структура внутри перечисления. Когда ты его создаёшь, Rust проверяет, что ты указал ровно его поля: ни одного пропущенного, лишнего или написанного с ошибкой. Смотри Перечисления могут хранить данные.
Важнее всего это, когда ты потом делаешь match по перечислению. Ветка Shape::Circle { radius } => ... может работать, только если у каждого Circle действительно есть radius. Если бы Rust пропустил Shape::Circle { r: 2.0 }, этой гарантии бы не стало. Опечатка, пойманная при компиляции, означает, что каждый Circle в программе полный.
Как исправить
Заголовок раздела «Как исправить»Исправление 1: возьми настоящее имя поля варианта
Заголовок раздела «Исправление 1: возьми настоящее имя поля варианта»Выбирай этот вариант, когда rustc показывает available fields are или a field with a similar name exists. Возьми имя из подсказки. Имена полей чувствительны к регистру и пишутся в snake_case, так что Radius и radius — разные имена.
Для опечатки будет подсказка о похожем имени:
error[E0559]: variant `Event::KeyPress` has no field named `kye` --> src/main.rs:8:31 |8 | let e = Event::KeyPress { kye: 'a' }; | ^^^ unknown field |help: a field with a similar name exists |8 - let e = Event::KeyPress { kye: 'a' };8 + let e = Event::KeyPress { key: 'a' }; |Короткое имя вроде r слишком отличается от radius, чтобы rustc что-то предложил, поэтому вместо подсказки ты получаешь список полей. В любом случае пиши поле, которое объявлено в варианте:
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
#[derive(Debug)]enum Event { Click { x: i32, y: i32 }, KeyPress { key: char },}
fn main() { let shapes = [ Shape::Circle { radius: 2.0 }, // ✅ настоящее имя поля Shape::Rectangle { width: 3.0, height: 4.0 }, ]; for shape in &shapes { println!("{:?}", shape); }
let events = [Event::KeyPress { key: 'a' }, Event::Click { x: 10, y: 20 }]; println!("{:?}", events);}Вывод:
Circle { radius: 2.0 }Rectangle { width: 3.0, height: 4.0 }[KeyPress { key: 'a' }, Click { x: 10, y: 20 }]Следи за сокращённой инициализацией полей (field init shorthand). Shape::Circle { r } значит Shape::Circle { r: r }, так что это та же E0559. Если переменная называется r, напиши поле полностью: Shape::Circle { radius: r }. Или переименуй переменную в radius и пиши Shape::Circle { radius }.
Исправление 2: круглые скобки для кортежного варианта
Заголовок раздела «Исправление 2: круглые скобки для кортежного варианта»Выбирай этот вариант, когда rustc пишет is a tuple variant, use the appropriate syntax. У варианта вроде Write(String) есть поле, но у этого поля нет имени. Поэтому любое имя в фигурных скобках будет неверным:
error[E0559]: variant `Message::Write` has no field named `text` --> src/main.rs:8:30 |4 | Write(String), | ----- `Message::Write` defined here...8 | let m = Message::Write { text: String::from("hi") }; | ^^^^ field does not exist |help: `Message::Write` is a tuple variant, use the appropriate syntax |8 - let m = Message::Write { text: String::from("hi") };8 + let m = Message::Write(/* String */); |/* String */ в подсказке — заглушка: подставь туда своё значение. Кортежный вариант создают с круглыми скобками, в том же порядке, что и в определении:
#[derive(Debug)]enum Message { Move { x: i32, y: i32 }, // именованные поля: { } Write(String), // безымянное поле: ( ) Color(u8, u8, u8),}
fn main() { let messages = vec![ Message::Move { x: 1, y: 2 }, Message::Write(String::from("привет")), // ✅ круглые скобки Message::Color(255, 128, 0), ]; for m in &messages { match m { Message::Move { x, y } => println!("переместиться в ({}, {})", x, y), Message::Write(text) => println!("написать: {}", text), Message::Color(r, g, b) => println!("цвет: {} {} {}", r, g, b), } }}Вывод:
переместиться в (1, 2)написать: приветцвет: 255 128 0Если хочешь, чтобы у поля было имя, поменяй определение на Write { text: String }. Тогда Message::Write { text: ... } заработает. Обратная путаница — круглые скобки у варианта с именованными полями, например Shape::Circle(2.0), — даёт другую ошибку: E0533, «expected value, found struct variant».
Исправление 3: выбери правильный вариант или поменяй вариант
Заголовок раздела «Исправление 3: выбери правильный вариант или поменяй вариант»Выбирай этот вариант, когда поле, которое ты написал, существует, но в другом варианте. Здесь radius принадлежит Circle, а не Square:
error[E0559]: variant `Shape::Square` has no field named `radius` --> src/main.rs:8:29 |8 | let s = Shape::Square { radius: 2.0 }; | ^^^^^^ `Shape::Square` does not have this field | = note: available fields are: `side`Спроси себя, что ты имел в виду. Если нужен был круг, пиши Shape::Circle { radius: 2.0 }. Если квадрат — используй его поле: Shape::Square { side: 2.0 }.
Если видишь note: all struct fields are already assigned, значит, вариант уже заполнен полностью, а твоё поле — лишнее. Убери его или, если оно действительно нужно коду, добавь его в определение варианта:
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Square { side: f64 },}
#[derive(Debug)]enum Message { Move { x: i32, y: i32, z: i32 }, // добавили `z`, потому что он нужен коду}
fn main() { let a = Shape::Circle { radius: 2.0 }; // у круга есть радиус let b = Shape::Square { side: 2.0 }; // у квадрата есть сторона println!("{:?} и {:?}", a, b);
let m = Message::Move { x: 1, y: 2, z: 3 }; println!("{:?}", m);}Вывод:
Circle { radius: 2.0 } и Square { side: 2.0 }Move { x: 1, y: 2, z: 3 }Когда добавляешь поле в вариант, каждое место, где этот вариант создаётся, тоже должно его заполнить. rustc покажет на каждое такое место ошибкой E0063, «missing field».
Где это обычно встречается
Заголовок раздела «Где это обычно встречается»Методы-конструкторы с Self::. Внутри impl Shape запись fn circle(r: f64) -> Shape { Self::Circle { r } } даёт E0559 для r из-за сокращённой записи. Исправление: Self::Circle { radius: r }. Смотри У перечислений тоже бывают методы.
После переименования поля. Ты переименовал в перечислении Circle { r } в Circle { radius }, и каждое старое Shape::Circle { r: ... } теперь даёт E0559 с available fields are: `radius`. Найди по проекту старое имя и обнови каждое место.
В образце match. Неверное имя поля в образце, например Shape::Circle { r } => ..., — та же ошибка, но rustc использует другие коды: E0026, «variant Shape::Circle does not have a field named r», с help: `Shape::Circle` has a field named `radius`, плюс E0027, «pattern does not mention field radius». Исправление: Shape::Circle { radius } => ... или Shape::Circle { radius: r } => ..., чтобы оставить короткое имя. Смотри урок Сопоставление с образцом.
Связанные ошибки
Заголовок раздела «Связанные ошибки»- E0560: struct has no field named x: та же ошибка для литерала структуры, например
User { nmae: ... }. - E0063: missing field in initializer: обратная ситуация — поле, которое у варианта есть, но ты его не заполнил.
- E0599: no method named x found: rustc использует этот же код, когда неверно имя варианта, например
Shape::Circel { ... }. rustc пишет «no variant namedCircelfound for enumShape». - E0609: no field on type: неверное имя поля при чтении поля.
E0026: variant does not have a field named x: та же ошибка внутри образцаmatch(смотри выше).E0533: expected value, found struct variant: круглые скобки у варианта с именованными полями, напримерShape::Circle(2.0).- Все ошибки компилятора с объяснениями
Проверь себя
Заголовок раздела «Проверь себя»Проверь себя
1. Во что нужно превратить Message::Write { text: s } для enum Message { Write(String) }?
2. У тебя есть let r = 2.0;, и ты пишешь Shape::Circle { r }, но поле называется radius. Как исправить?
3. Shape::Square { radius: 2.0 } даёт E0559, и в пометке есть только side. Что происходит?
Результат: 0 / 3
Что почитать
Заголовок раздела «Что почитать»- E0559 — Rust error codes index (на английском): официальное объяснение этой ошибки.
- Определение Enum — книга «Язык программирования Rust» (перевод на русский): варианты с именованными полями, кортежные и единичные варианты, с примером
Message. - Перечисления — Rust на примерах (перевод на русский): запускаемые примеры всех видов вариантов.
- Struct expressions — The Rust Reference (на английском): точные правила для
Enum::Variant { field: value }, включая сокращённую запись. - E0026 — Rust error codes index (на английском): официальная страница о той же ошибке внутри образца.