Rustのエラー E0559: variant has no field named x(バリアントにないフィールド名)
E0559 は、Enum::Variant { field: value } で列挙型の値を作るときに書いたフィールドのどれかが、そのバリアントに存在しない、という意味のエラーです。構造体で同じ間違いをしたときの E0560 の、列挙型版です。たいていは、短すぎるかつづりの違うフィールド名、別のバリアントのフィールド、あるいはかっこ ( ) で作るバリアントに波かっこ { } を使った、のどれかです。直すのは、ほとんどの場合たった1語です。このシリーズのほかのエラーは、Rustのコンパイルエラー解説を見てください。
エラーメッセージ
Section titled “エラーメッセージ”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`「variant Shape::Circle has no field named r」は「バリアント Shape::Circle に r という名前のフィールドはない」という意味です。note は「使えるフィールドは 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);}コメントは「フィールドの名前は radius」という意味です(エラーになる例なので、コードはそのままにしています)。
エラーの意味
Section titled “エラーの意味”見出しには、バリアント(Shape::Circle)と自分が書いたフィールド(r)が出ています。^ は、波かっこの中のそのフィールドを指しています。Rust は Circle { radius: f64 } という定義を見て、r というフィールドを見つけられなかったのです。
列挙型(enum)のバリアントは、それぞれ自分だけのフィールドの一覧を持っています。Shape::Circle には radius、Shape::Rectangle には width と height があります。同じ列挙型の中でも、フィールドを共有することはありません。
矢印の下には、次のヒントのどれかが出ます。まずはこれを読みましょう。たいてい答えが書いてあります。
note: available fields are: `radius`(使えるフィールドはradius):近い名前がありません。このバリアントにあって、まだ値を入れていないフィールドの一覧です。help: a field with a similar name exists(似た名前のフィールドがある):keyをkyeと書いたようなタイプミスです。rustc が直した行を見せてくれます。help: `Message::Write` is a tuple variant, use the appropriate syntax(Message::Writeはタプルバリアントなので、それに合った書き方をしてください):そのバリアントのフィールドには名前がないので、{ }ではなく( )が必要です。note: all struct fields are already assigned(フィールドはすべて代入済み):本当のフィールドは全部埋めていて、このフィールドは余分です。
ピザを注文するときに、メニューには「生地のサイズ」しかないのに「大きい生地」と書くようなものです。お店の人には言いたいことがわかりますが、注文用紙にはその名前の欄がありません。
Rust がこうする理由
Section titled “Rust がこうする理由”Circle { radius: f64 } のように名前付きのフィールドを持つバリアントは、列挙型の中にある小さな構造体のように働きます。それを作るとき、Rust はちょうどそのフィールドが過不足なく書かれているかをチェックします。足りないものも、余分なものも、つづりの違うものもあってはいけません。詳しくは列挙型はデータを持てるを見てください。
これがいちばん効いてくるのは、あとでその列挙型を match するときです。Shape::Circle { radius } => ... というアームがうまく動くのは、どの Circle も本当に radius を持っているからです。もし Rust が Shape::Circle { r: 2.0 } を通してしまったら、その保証がなくなります。タイプミスをコンパイル時に見つけることで、プログラムの中のどの Circle も欠けのない状態に保たれるのです。
直し方1:バリアントの本当のフィールド名を使う
Section titled “直し方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' }; |unknown field は「知らないフィールド」という意味です。
r のような短い名前は radius とかけ離れすぎていて提案が出ないので、代わりにフィールドの一覧が表示されます。どちらの場合も、バリアントが定義しているフィールドを書きましょう。
#[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:タプルバリアントにはかっこを使う
Section titled “直し方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 */); |defined here は「ここで定義されている」、field does not exist は「フィールドが存在しない」という意味です。
提案の中の /* 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("hi")), // ✅ かっこ 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) へ移動書き込み: hi色: 255 128 0フィールドに名前を付けたいなら、定義を Write { text: String } に変えます。そうすれば Message::Write { text: ... } と書けます。逆の取り違え、つまり名前付きのフィールドを持つバリアントにかっこを使う Shape::Circle(2.0) は、別のエラーになります。E0533「expected value, found struct variant」(値が必要なのに、構造体形式のバリアントが見つかった)です。
直し方3:正しいバリアントを選ぶ、またはバリアントを変える
Section titled “直し方3:正しいバリアントを選ぶ、またはバリアントを変える”書いたフィールドは存在するけれど、別のバリアントのものだったときは、これを選びます。ここでは、radius は Square ではなく Circle のフィールドです。
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::Square` does not have this field は「Shape::Square にこのフィールドはない」という意味です。
どちらのつもりだったのか、考えてみましょう。円が欲しかったのなら 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」(フィールドが足りない)で1か所ずつ教えてくれます。
よく出会う場面
Section titled “よく出会う場面”Self:: を使うコンストラクタのメソッド。 impl Shape の中で fn circle(r: f64) -> Shape { Self::Circle { r } } と書くと、省略記法のせいで r について E0559 になります。直し方:Self::Circle { radius: r }。詳しくは列挙型にもメソッドを持たせられるを見てください。
フィールドの名前を変えたあと。 列挙型の Circle { r } を Circle { radius } に変えると、古い Shape::Circle { r: ... } がすべて available fields are: `radius` 付きの E0559 になります。プロジェクト全体で古い名前を検索して、1つずつ直しましょう。
match のパターンの中。 Shape::Circle { r } => ... のように、パターンに間違ったフィールド名を書くのも同じ間違いですが、rustc は別のコードを使います。E0026「variant Shape::Circle does not have a field named r」(バリアント Shape::Circle に r という名前のフィールドはない)と help: `Shape::Circle` has a field named `radius`(Shape::Circle には radius という名前のフィールドがある)、さらに E0027「pattern does not mention field radius」(パターンにフィールド radius が書かれていない)が出ます。直し方:Shape::Circle { radius } => ... と書くか、短い名前のままにしたいなら Shape::Circle { radius: r } => ... と書きます。詳しくはパターンマッチングを見てください。
関連するエラー
Section titled “関連するエラー”- E0560: struct has no field named x:
User { nmae: ... }のように、構造体で同じ間違いをした。 - E0063: missing field in initializer:逆のパターン。バリアントにあるフィールドに値を入れていない。
- E0599: no method named x found:
Shape::Circel { ... }のようにバリアントの名前が違うときも、rustc はこのコードを使います。「no variant namedCircelfound for enumShape」(列挙型ShapeにCircelという名前のバリアントはない)と表示されます。 - 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)のように、名前付きのフィールドを持つバリアントにかっこを使った。- コンパイルエラーの一覧:エラー解説ページの全リストです。
理解度チェック
Section titled “理解度チェック”理解度チェック
1. enum Message { Write(String) } のとき、Message::Write { text: s } はどう書き直せばいいですか?
2. let r = 2.0; があって Shape::Circle { r } と書きましたが、フィールドは radius です。どう直しますか?
3. Shape::Square { radius: 2.0 } が E0559 になり、注記には side しか出ていません。何が起きていますか?
スコア: 0 / 3
さらに詳しく
Section titled “さらに詳しく”- E0559 — Rust error codes index(英語):このエラーの公式の説明です。
- Enumを定義する — The Rust Programming Language 日本語版:名前付きのフィールドを持つバリアント、タプルバリアント、ユニットバリアントを、
Messageの例で説明している章です。 - 列挙型 — Rust By Example 日本語版:あらゆる種類のバリアントを、実行できる例で紹介しています。
- Struct expressions — The Rust Reference(英語):省略記法も含めた、
Enum::Variant { field: value }の正確なルールです。 - E0026 — Rust error codes index(英語):パターンの中で同じ間違いをしたときの公式ページです。