Rustのエラー E0560: struct has no field named x(構造体にないフィールド名)
E0560 は、Name { field: value } で構造体を作るときに書いたフィールドのどれかが、その構造体に存在しない、という意味のエラーです。たいていはタイプミスか、名前が変わったフィールドか、別の構造体のフィールドです。rustc が正しい名前をそのまま教えてくれることも多いので、いちばん早く直せるエラーのひとつです。このシリーズのほかのエラーは、Rustのコンパイルエラー解説を見てください。
エラーメッセージ
Section titled “エラーメッセージ”error[E0560]: struct `User` has no field named `nmae` --> src/main.rs:9:9 |9 | nmae: String::from("Ferris"), // ❌ タイプミス:フィールド名は `name` | ^^^^ unknown field |help: a field with a similar name exists |9 - nmae: String::from("Ferris"), // ❌ タイプミス:フィールド名は `name`9 + name: String::from("Ferris"), // ❌ タイプミス:フィールド名は `name` |「struct User has no field named nmae」は「構造体 User に nmae という名前のフィールドはない」という意味です。unknown field は「知らないフィールド」、help は「似た名前のフィールドがある」と教えてくれていて、正しい書き方も見せてくれています。
このエラーが出るのは、次のプログラムです。
struct User { name: String, email: String, active: bool,}
fn main() { let user = User { nmae: String::from("Ferris"), // ❌ タイプミス:フィールド名は `name` active: true, }; println!("{}", user.email);}エラーの意味
Section titled “エラーの意味”見出しには、構造体(User)と自分が書いたフィールド(nmae)が出ています。^^^^ は、User { ... } の中のそのフィールドを指しています。Rust はそれを struct User のフィールドの一覧と比べて、一致するものを見つけられなかったのです。
矢印の下には、次の3つのヒントのどれかが出ます。それぞれ伝えていることが違います。
help: a field with a similar name exists(似た名前のフィールドがある):タイプミスです。rustc が正しい名前の行を見せてくれます。note: available fields are: `username`(使えるフィールドはusername):近い名前がありません。まだ値を入れていないフィールドの一覧です。note: all struct fields are already assigned(構造体のフィールドはすべて代入済み):本当のフィールドは全部埋めていて、このフィールドは余分です。
rustc が、name が足りないことを別に指摘していない点に注目してください。タイプミスを直せば、両方の問題がいっぺんに消えます。
紙の申込書に記入していて、「FAX番号」という欄に電話番号を書こうとするようなものです。申込書にそんな欄はないので、窓口で書き直してくださいと返されてしまいます。
Rust がこうする理由
Section titled “Rust がこうする理由”構造体のフィールドは、struct User { ... } と書いた時点で決まります。User を作るたびに、Rust はちょうどそのフィールドが過不足なく書かれているかをチェックします。足りないものも、余分なものも、つづりの違うものもあってはいけません。詳しくは構造体を定義して作るを見てください。
これは本物のバグを防いでくれます。JavaScript では、{ nmae: "Ferris" } と書くと、間違ったキーのオブジェクトが黙って作られ、ずっとあとのどこかで user.name が undefined になります。Rust では、タイプミスはコンパイラを通り抜けられないので、プログラムの中のどの User も、本当に name を持っています。
直し方1:つづりを直す
Section titled “直し方1:つづりを直す”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"), // ✅ 本当のフィールド名 active: true, }; println!("{}({})有効: {}", user.name, user.email, user.active);
// 省略記法:変数名がフィールド名と一致している let name = String::from("Ada"); let other = User { name, email, active: false }; println!("{}({})有効: {}", other.name, other.email, other.active);}実行結果:
Ferris([email protected])有効: trueAda([email protected])有効: false直し方2:フィールドの新しい名前を使う、またはフィールドを追加する
Section titled “直し方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``User` does not have this field は「User にこのフィールドはない」という意味です。
まっとうな選択肢は2つです。構造体が正しいなら、今のフィールド名を使います。自分のコードが正しくて、構造体に本当にそのフィールドが必要なら、構造体の定義に追加します。次の例では、Config で debug に対して all struct fields are already assigned が出ていたので、構造体に 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"), }; println!("{} ({})", user.username, user.email);
let config = Config { port: 8080, host: String::from("localhost"), debug: true, }; println!("{}:{} debug={}", config.host, config.port, config.debug);}実行結果:
ferris ([email protected])localhost:8080 debug=true構造体が、アップデートしたばかりのクレートのものなら、新しいバージョンでフィールドの名前が変わったのかもしれません。そのバージョンの構造体を docs.rs(英語)で確認するか、クレートの変更履歴(changelog)を見てください。自分の構造体にフィールドを追加したら、その構造体を作っているすべての場所でも、そのフィールドに値を入れる必要があります。rustc が E0063 で1か所ずつ教えてくれます(下を見てください)。
直し方3:正しい構造体を使う
Section titled “直し方3:正しい構造体を使う”書いたフィールドは存在するけれど、別の構造体のものだったときは、これを選びます。title を持つ Product と name を持つ Customer のように、似た構造体が2つあると、取り違えやすくなります。
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("Keyboard"), // 商品には `title` がある price: 4900, }; let buyer = Customer { name: String::from("Ana"), // お客さんには `name` がある }; println!("{}さんが{}を{}セントで購入しました", buyer.name, keyboard.title, keyboard.price); println!("領収書の送り先: {}", buyer.email);}実行結果:
AnaさんがKeyboardを4900セントで購入しました領収書の送り先: [email protected]直し方4:タプル構造体にはかっこを使う
Section titled “直し方4:タプル構造体にはかっこを使う”構造体が struct Point(i32, i32); のようなタプル構造体のときは、これを選びます。タプル構造体のフィールドには名前がないので、Point { x: 1, y: 2 } と書くと、x と y の両方で E0560 になります。このとき help: `Point` is a tuple struct, use the appropriate syntax(Point はタプル構造体なので、それに合った書き方をしてください)と、Point(/* i32 */, /* i32 */) という提案が表示されます。Point(1, 2) のようにかっこで作り、.0 と .1 で読みましょう。名前を付けたいなら、定義を struct Point { x: i32, y: i32 } に変えます。詳しくはタプルと構造体の使い分けを見てください。
逆のパターン:E0063 missing field
Section titled “逆のパターン:E0063 missing field”E0560 の双子は E0063 です。構造体にあるフィールドなのに、値を入れていない、というエラーです。Rust がフィールドを勝手に埋めてくれることはないので、どのフィールドにも値が必要です。
error[E0063]: missing field `active` in initializer of `User` --> src/main.rs:8:16 |8 | let user = User { | ^^^^ missing `active`「missing field active in initializer of User」は「User の初期化で、フィールド active が足りない」という意味です。
いくつも足りないときは、missing fields `active`, `email` and `login_count` in initializer of `User` のように全部並べてくれます。直し方:すべてのフィールドに値を入れます。多くのフィールドに妥当なデフォルト値があるなら、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:ちょうどいい初期値を見てください。
よく出会う場面
Section titled “よく出会う場面”.. の構造体更新記法の中。 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`(バリアント Shape::Circle に r という名前のフィールドはない)と表示され、同じ available fields の注記やタイプミスのヒントが付きます。直し方:Shape::Circle { radius: 2.0 }。詳しくは列挙型はデータを持てるを見てください。
別のモジュールの構造体。 フィールドは存在するけれど pub ではない場合は、代わりに E0451「field balance of struct Account is private」(構造体 Account のフィールド balance は非公開)が出ます。直し方:Account::new(...) のような、モジュールが用意しているコンストラクタを使います。詳しくは何もしなければすべて非公開を見てください。
関連するエラー
Section titled “関連するエラー”- E0609: no field
xon typeT:同じタイプミスを、構造体を作るときではなく、フィールドを読むとき(user.nmae)にした。 - E0451: field is private in struct literal:フィールドは存在するけれど、ここからは値を入れられない。
- E0308: mismatched types:フィールド名は合っているけれど、値の型が違う。たとえば
Stringのフィールドに"Ferris"を入れたとき。 E0063: missing field in initializer:入れ忘れたフィールドがある(上を見てください)。E0559: variant has no field named x:列挙型のバリアント版の E0560 です。- コンパイルエラーの一覧:エラー解説ページの全リストです。
理解度チェック
Section titled “理解度チェック”理解度チェック
1. rustc が note: all struct fields are already assigned と言っています。どういう意味ですか?
2. let nmae = ...; があって、User { nmae, email } と書きました。どう直しますか?
3. active を書かずに User { name, email } のようにフィールドを省いたときに出るエラーはどれですか?
スコア: 0 / 3
さらに詳しく
Section titled “さらに詳しく”- E0560 — Rust error codes index(英語):このエラーの公式の説明です。
- 構造体を定義し、インスタンス化する — The Rust Programming Language 日本語版:構造体の作り方、フィールド初期化省略記法、構造体更新記法、タプル構造体を説明している章です。
- E0063 — Rust error codes index(英語):このエラーの双子、「フィールドが足りない」エラーの公式ページです。
- Struct expressions — The Rust Reference(英語):
Name { field: value }、省略記法、..baseの正確なルールです。 Default— 標準ライブラリのドキュメント(英語):#[derive(Default)]と..Default::default()のしくみです。