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

Ошибка Rust E0560: struct has no field named X (неизвестное поле)

E0560 значит: ты создаёшь структуру через Name { field: value }, и одного из написанных полей в этой структуре нет. Обычно это опечатка, поле, которое переименовали, или поле из другой структуры. rustc часто сам подсказывает правильное имя, так что это одна из самых быстро исправляемых ошибок. (Эта страница входит в серию Ошибки компилятора Rust с объяснениями.)

error[E0560]: struct `User` has no field named `nmae`
--> src/main.rs:9:9
|
9 | nmae: String::from("Ferris"), // ❌ typo: the field is `name`
| ^^^^ unknown field
|
help: a field with a similar name exists
|
9 - nmae: String::from("Ferris"), // ❌ typo: the field is `name`
9 + name: String::from("Ferris"), // ❌ typo: the field is `name`
|

Компилятор говорит: у структуры User нет поля nmae, но есть поле с похожим именем, — и показывает строку с правильным именем. Вот программа, которая выдаёт эту ошибку (комментарий значит «опечатка: поле называется name»):

struct User {
name: String,
email: String,
active: bool,
}
fn main() {
let user = User {
nmae: String::from("Ferris"), // ❌ typo: the field is `name`
email: String::from("[email protected]"),
active: true,
};
println!("{}", user.email);
}

В заголовке названы структура (User) и поле, которое ты написал (nmae). ^^^^ показывает на это поле внутри блока User { ... }. Rust сравнил его со списком полей в struct User и не нашёл совпадения.

Под стрелкой будет одна из трёх подсказок. Каждая говорит о своём:

  • help: a field with a similar name exists (есть поле с похожим именем): опечатка. rustc показывает строку с правильным именем.
  • note: available fields are: `username` (доступные поля): близкого совпадения нет. Это поля, которые ты ещё не заполнил.
  • note: all struct fields are already assigned (все поля уже заданы): ты заполнил все настоящие поля, а это — лишнее.

Обрати внимание: rustc не жалуется ещё и на то, что name не заполнено. Исправь опечатку — и обе проблемы исчезнут разом.

Это как заполнять бумажную анкету и вписать номер телефона в графу «Факс». В анкете такой графы нет, и сотрудник возвращает её тебе.

Поля структуры фиксируются, когда ты пишешь struct User { ... }. Каждый раз, когда ты создаёшь User, Rust проверяет, что ты указал ровно эти поля: ни одного пропущенного, лишнего или написанного с ошибкой. Подробнее — в разделе Объявляем и создаём структуру.

Это ловит настоящие баги. В JavaScript { nmae: "Ferris" } молча создаёт объект с неправильным ключом, и user.name окажется undefined где-нибудь намного позже. В Rust опечатка не пройдёт мимо компилятора, так что у каждого User в твоей программе действительно есть name.

Выбирай этот вариант, когда видишь a field with a similar name exists. Возьми имя из строки help:. Имена полей чувствительны к регистру, а в Rust принят snake_case, так что userName и user_name — разные имена.

Следи и за сокращённой инициализацией полей (field init shorthand): User { nmae, email } значит User { nmae: nmae, email: email }, поэтому имя переменной должно совпадать с именем поля. Либо переименуй переменную, либо напиши поле полностью: User { name: nmae, email }.

struct User {
name: String,
email: String,
active: bool,
}
fn main() {
let user = User {
name: String::from("Ferris"), // ✅ настоящее имя поля
email: String::from("[email protected]"),
active: true,
};
println!("{} ({}) активен: {}", user.name, user.email, user.active);
// сокращённая запись: имена переменных совпадают с именами полей
let name = String::from("Ada");
let email = String::from("[email protected]");
let other = User { name, email, active: false };
println!("{} ({}) активен: {}", other.name, other.email, other.active);
}

Вывод:

Ferris ([email protected]) активен: true
Ada ([email protected]) активен: false
▶ Попробуй сам

Исправление 2: возьми новое имя поля или добавь поле

Заголовок раздела «Исправление 2: возьми новое имя поля или добавь поле»

Выбирай этот вариант, когда подсказки о похожем имени нет. Часто изменилась сама структура: кто-то переименовал name в username или удалил поле, а этот код всё ещё использует старое. rustc перечисляет, что осталось:

error[E0560]: struct `User` has no field named `name`
--> src/main.rs:8:9
|
8 | name: String::from("Ferris"),
| ^^^^ `User` does not have this field
|
= note: available fields are: `username`

Честных вариантов два. Если права структура, используй её текущее имя поля. Если прав твой код и структуре действительно нужно это поле, добавь его в определение структуры. Здесь Config выдал all struct fields are already assigned для debug, и исправление — добавить debug в структуру:

struct User {
username: String, // раньше называлось `name`: используем новое имя
email: String,
}
struct Config {
port: u16,
host: String,
debug: bool, // добавили в структуру, потому что оно нужно коду
}
fn main() {
let user = User {
username: String::from("ferris"),
email: String::from("[email protected]"),
};
println!("{} ({})", user.username, user.email);
let config = Config {
port: 8080,
host: String::from("localhost"),
debug: true,
};
println!("{}:{} debug={}", config.host, config.port, config.debug);
}

Вывод:

localhost:8080 debug=true
▶ Попробуй сам

Если структура пришла из крейта, который ты только что обновил, поле могли переименовать в новой версии. Посмотри структуру на docs.rs (на английском) для этой версии или список изменений (changelog) крейта. Когда добавляешь поле в свою структуру, каждое место, где она создаётся, тоже должно его заполнить. rustc покажет на каждое такое место ошибкой E0063 (смотри ниже).

Исправление 3: возьми правильную структуру

Заголовок раздела «Исправление 3: возьми правильную структуру»

Выбирай этот вариант, когда поле, которое ты написал, существует, но в другой структуре. Когда есть две похожие структуры, например Product с полем title и Customer с полем name, их легко перепутать:

error[E0560]: struct `Product` has no field named `name`
--> src/main.rs:13:9
|
13 | name: String::from("Keyboard"),
| ^^^^ `Product` does not have this field
|
= note: available fields are: `title`

Посмотри на пометку available fields. Если там поля, которых ты не ждал, значит, ты создаёшь не ту структуру. Возьми правильное имя структуры или имя поля той структуры, которую ты имел в виду:

struct Product {
title: String,
price: u32, // в центах
}
struct Customer {
name: String,
email: String,
}
fn main() {
let keyboard = Product {
title: String::from("Клавиатура"), // у товаров есть `title`
price: 4900,
};
let buyer = Customer {
name: String::from("Аня"), // у покупателей есть `name`
email: String::from("[email protected]"),
};
println!("{} покупает товар «{}» за {} центов", buyer.name, keyboard.title, keyboard.price);
println!("Чек отправлен на {}", buyer.email);
}

Вывод:

Аня покупает товар «Клавиатура» за 4900 центов
Чек отправлен на [email protected]
▶ Попробуй сам

Исправление 4: круглые скобки для кортежной структуры

Заголовок раздела «Исправление 4: круглые скобки для кортежной структуры»

Выбирай этот вариант, когда структура — кортежная (tuple struct), например struct Point(i32, i32);. У её полей нет имён, поэтому Point { x: 1, y: 2 } даёт E0560 и для x, и для y, с подсказкой help: `Point` is a tuple struct, use the appropriate syntax и предложением Point(/* i32 */, /* i32 */). Создавай её с круглыми скобками, Point(1, 2), а читай через .0 и .1. Если тебе удобнее имена, поменяй определение на struct Point { x: i32, y: i32 }. Смотри урок Кортежи — там есть совет, когда выбирать кортеж, а когда структуру.

Близнец E0560 — E0063: поле, которое у структуры есть, но ты его не заполнил. Rust никогда не заполняет поля за тебя, так что каждому полю нужно значение:

error[E0063]: missing field `active` in initializer of `User`
--> src/main.rs:8:16
|
8 | let user = User {
| ^^^^ missing `active`

Если не хватает нескольких полей, перечисляются все: missing fields `active`, `email` and `login_count` in initializer of `User`. Исправление: дай значение каждому полю. Если у многих полей есть разумные значения по умолчанию, выведи (derive) Default и заполни остальное синтаксисом обновления структуры ..:

#[derive(Debug, Default)]
struct Settings {
volume: u8,
dark_mode: bool,
language: String,
}
fn main() {
// все поля написаны явно
let full = Settings { volume: 80, dark_mode: false, language: String::from("en") };
// только нужные поля, остальное — из Default
let quick = Settings { dark_mode: true, ..Default::default() };
// остальное копируем из другого значения
let louder = Settings { volume: 100, ..full };
println!("{:?}", quick);
println!("{:?}", louder);
}

Вывод:

Settings { volume: 0, dark_mode: true, language: "" }
Settings { volume: 100, dark_mode: false, language: "en" }
▶ Попробуй сам

Значение по умолчанию для числа — 0, для bool — false, а для String — пустая строка. Если нужны другие значения по умолчанию, напиши impl Default for Settings сам. Смотри Default: разумное начальное значение.

Внутри синтаксиса обновления ... Settings { dark: true, ..defaults } тоже даёт E0560. Здесь пометка перечисляет все поля (available fields are: `volume`, `dark_mode`, `language`), а подсказки о похожем имени может не быть, если имена слишком разные. Исправление: dark_mode: true.

Варианты перечисления с именованными полями. Для enum Shape { Circle { radius: f64 } } запись Shape::Circle { r: 2.0 } — та же ошибка, но rustc выдаёт другой код: E0559, variant `Shape::Circle` has no field named `r`, с той же пометкой available fields и подсказками об опечатках. Исправление: Shape::Circle { radius: 2.0 }. Смотри Перечисления могут хранить данные.

Структура из другого модуля. Если поле существует, но не pub, вместо этого получишь E0451, «field balance of struct Account is private». Исправление: используй конструктор модуля, например Account::new(...). Смотри Всё по умолчанию приватное.

Проверь себя

1. rustc пишет note: all struct fields are already assigned. Что это значит?

2. У тебя есть let nmae = ...;, и ты пишешь User { nmae, email }. Как исправить?

3. Какую ошибку ты получишь, если пропустишь поле, например User { name, email } без active?

Результат: 0 / 3