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

Ошибка 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 (все поля уже заданы): ты заполнил все настоящие поля, а это — лишнее.

Это как заказывать пиццу и просить «большое тесто», когда в меню есть только «размер теста». На кухне прекрасно понимают, что ты имеешь в виду, но в бланке заказа нет графы с таким названием.

Вариант перечисления с именованными полями, например 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 } => ..., чтобы оставить короткое имя. Смотри урок Сопоставление с образцом.

Проверь себя

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