Rustのエラー E0026: struct or variant does not have a field named x(パターンのフィールド名の間違い)
E0026 は、Shape::Circle { r } のようなパターンで構造体や列挙型のバリアントを分解しようとしたけれど、書いたフィールド名の1つが存在しない、という意味のエラーです。値を作るときの同じ間違いを捕まえる E0560 や E0559 の、パターン版だと考えてください。たいてい rustc が help: の行で正しい名前を教えてくれるので、直すのは1単語だけで済むことがほとんどです。このシリーズのほかのエラーは、Rustのコンパイルエラー解説を見てください。
エラーメッセージ
Section titled “エラーメッセージ”error[E0026]: variant `Shape::Circle` does not have a field named `r` --> src/main.rs:8:25 |8 | Shape::Circle { r } => 3.14 * r * r, // ❌ the field is called `radius` | ^ | | | variant `Shape::Circle` does not have this field | help: `Shape::Circle` has a field named `radius`「variant Shape::Circle does not have a field named r」は「バリアント Shape::Circle には r という名前のフィールドがない」という意味です。
このエラーが出るのは、次のプログラムです。
enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { r } => 3.14 * r * r, // ❌ the field is called `radius` Shape::Rectangle { width, height } => width * height, }}
fn main() { println!("{}", area(&Shape::Circle { radius: 1.0 }));}コメントは「フィールドの名前は radius」という意味です(エラーになる例なので、コードはそのままにしています)。
同じ行で、もう1つのエラー E0027「pattern does not mention field radius」(パターンがフィールド radius に触れていない)も表示されます。これは同じ間違いを反対側から見たものです。Rust は、書かれたのに存在しないフィールド(r)と、存在するのに書かれていないフィールド(radius)の両方を見つけたのです。名前を直せば、2つのエラーはどちらも消えます。
エラーの意味
Section titled “エラーの意味”見出しの行には、マッチしようとしている構造体またはバリアント(Shape::Circle)と、あなたが書いたフィールド名(r)が出ています。^ は、パターンの波かっこの中のその名前を指しています。
パターンの { } の中にある名前はフィールド名で、自由に選べる新しい変数名ではありません。Shape::Circle { r } は Shape::Circle { r: r } の省略形で、「r という名前のフィールドを取り出して、r という変数に入れる」という意味になります。Circle には r というフィールドがないので、Rust はそこで止まります。
矢印の下に、rustc は次のどれかのヒントを出します。
help: `Shape::Circle` has a field named `radius`(Shape::Circleにはradiusというフィールドがある):書かれていないフィールドがちょうど1つなので、rustc はそれのつもりだったのだろうと推測しています。help: a field with a similar name exists(似た名前のフィールドがある):nameをnmaeと書いたようなタイプミスです。rustc は直した行を見せてくれます。- ヒントなし:rustc が推測できなかった場合です。構造体や列挙型の定義を見て、本当の名前を確かめましょう。
図書館で「フィクションっぽい棚の本をください」と頼むようなものです。司書さんは、あなたがどこかの棚の本が欲しいことはわかっています。でも、行けるのは本当にある棚だけです。
Rust がこうする理由
Section titled “Rust がこうする理由”Shape::Circle { radius } のようなパターンは、「値が Circle だったら、その radius をください」という約束です。Rust はコンパイルのときに、この約束を定義と照らし合わせて確かめます。だから、パターンが存在しないデータを求めることは絶対にありません。詳しくはタプルと構造体の分解を見てください。
このチェックがない言語では、ないキーを読むと undefined や null が返ってきて、バグはずっとあとになって、タイプミスから遠く離れた場所で表に出てきます。Rust では、タイプミスがコンパイラを通り抜けることはできません。誰かがフィールドの名前を変えたときにも守ってくれます。古い名前を使っているパターンはすべて E0026 で光るので、どれも黙って忘れられることがありません。
直し方1:本当のフィールド名を使う
Section titled “直し方1:本当のフィールド名を使う”たいていはこれを選びます。help: の行に出ている名前を使うか、定義を見て確かめましょう。フィールド名は大文字と小文字を区別し、snake_case で書きます。
タイプミスの場合は、「似た名前」のヒントと、直した行が表示されます。
error[E0026]: struct `User` does not have a field named `nmae` --> src/main.rs:8:16 |8 | let User { nmae, age } = user; // ❌ typo: the field is `name` | ^^^^ struct `User` does not have this field |help: a field with a similar name exists |8 - let User { nmae, age } = user; // ❌ typo: the field is `name`8 + let User { name, age } = user; // ❌ typo: the field is `name` |- の行が元の行、+ の行が rustc の提案する直した行です(コメントは「タイプミス:フィールドは name」という意味です)。
このエラーが出るプログラムです。
struct User { name: String, age: u32,}
fn main() { let user = User { name: String::from("Ferris"), age: 7 }; let User { nmae, age } = user; // ❌ typo: the field is `name` println!("{} is {} years old", nmae, age);}フィールド名を定義のとおりに書きましょう。そうすれば省略形がそのまま使えて、フィールドと同じ名前の変数が手に入ります。
struct User { name: String, age: u32,}
enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius } => 3.14 * radius * radius, // ✅ 本当のフィールド名 Shape::Rectangle { width, height } => width * height, }}
fn main() { let shapes = [ Shape::Circle { radius: 2.0 }, Shape::Rectangle { width: 3.0, height: 4.0 }, ]; for shape in &shapes { println!("面積: {:.2}", area(shape)); }
let user = User { name: String::from("Ferris"), age: 7 }; let User { name, age } = user; // ✅ `nmae` ではなく `name` println!("{}は{}歳です", name, age);}実行結果:
面積: 12.56面積: 12.00Ferrisは7歳です直し方2:field: name で自分の変数名を使う
Section titled “直し方2:field: name で自分の変数名を使う”r という短い名前が気に入っていて、変数をその名前にしたいだけなら、これを選びます。本当のフィールド名、コロン、変数名の順に書きます。Shape::Circle { radius: r } です。「radius フィールドを取り出して、r と呼ぶ」と読みましょう。
enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius: r } => 3.14 * r * r, // ✅ フィールドは `radius`、変数は `r` Shape::Rectangle { width: w, height: h } => w * h, }}
fn main() { let small = Shape::Circle { radius: 1.0 }; let wide = Shape::Rectangle { width: 10.0, height: 2.5 }; println!("小さい円: {:.2}", area(&small)); println!("横長の長方形: {:.2}", area(&wide));}実行結果:
小さい円: 3.14横長の長方形: 25.00この書き方は、フィールド名がすでにある変数とぶつかってしまうときや、フィールド名が長いときにも便利です。
直し方3:正しいバリアントにマッチしているか確かめる
Section titled “直し方3:正しいバリアントにマッチしているか確かめる”書いたフィールドは実在するけれど、別のバリアントのものだった、というときはこれを選びます。列挙型のバリアントは、それぞれ自分のフィールドを持っています。ここでは x は Click のフィールドなのに、アームは KeyPress にマッチしようとしています。
error[E0026]: variant `Event::KeyPress` does not have a field named `x` --> src/main.rs:9:27 |9 | Event::KeyPress { x, .. } => format!("key at {}", x), // ❌ `x` belongs to `Click` | ^ | | | variant `Event::KeyPress` does not have this field | help: `Event::KeyPress` has a field named `key`このエラーが出るプログラムです(コメントは「x は Click のもの」という意味です)。
enum Event { Click { x: i32, y: i32 }, KeyPress { key: char },}
fn describe(event: &Event) -> String { match event { Event::Click { x, y } => format!("click at ({}, {})", x, y), Event::KeyPress { x, .. } => format!("key at {}", x), // ❌ `x` belongs to `Click` }}
fn main() { println!("{}", describe(&Event::KeyPress { key: 'a' }));}rustc の推測(key)は「書かれていない唯一のフィールド」というだけなので、そのまま信じないようにしましょう。このアームで何をしたいのかを考えます。キーを押すことに位置はないので、ここでは KeyPress が本当に持っているフィールドを使うのが正しい直し方です。
enum Event { Click { x: i32, y: i32 }, KeyPress { key: char },}
fn describe(event: &Event) -> String { match event { Event::Click { x, y } => format!("({}, {}) をクリック", x, y), Event::KeyPress { key } => format!("キー '{}' が押されました", key), // ✅ KeyPress が持っているのは `key` }}
fn main() { let events = [Event::Click { x: 10, y: 20 }, Event::KeyPress { key: 'a' }]; for event in &events { println!("{}", describe(event)); }}実行結果:
(10, 20) をクリックキー 'a' が押されましたキーを押したときにも本当に位置が必要なら、バリアントのほうにフィールドを追加します。KeyPress { key: char, x: i32, y: i32 } です。そうすると、KeyPress を作っているすべての場所で、そのフィールドも埋める必要があります(rustc がそれぞれの場所を E0063 で指してくれます)。
よく出会う場面
Section titled “よく出会う場面”フィールドの名前を変えたあと。 列挙型の r を radius に変えたら、Shape::Circle { r } => ... というアームがすべて E0026 になった、という場合です。プロジェクト全体で古い名前を検索して、パターンを1つずつ直しましょう。古い変数名のままにしたいなら radius: r と書きます。
if let や let の中。 if let Some(User { nmae, .. }) = find_user() でも同じエラーになります。ここで .. を足しても直りません。.. は書かなかったフィールドを飛ばすだけで、書いた名前はやはりすべて存在している必要があるからです。直し方:User { name, .. }。
タプル構造体やタプルバリアントに波かっこを使った場合。 struct Point(i32, i32); には名前付きのフィールドがないので、Point { x, y } というパターンは合いません。rustc はこれを別のコード E0769「tuple variant Point written as struct variant」(タプルバリアント Point が構造体バリアントとして書かれている)で報告し、Point(x, y) を提案します。詳しくはデータを持つenumの分解を見てください。
関連するエラー
Section titled “関連するエラー”- E0027:パターンがフィールドに触れていない:E0026 の双子で、パターンで書き漏らした実在のフィールドです。E0026 と一緒に表示されることがよくあります。
- E0559:バリアントにないフィールド名:列挙型のバリアントを作るときの、同じ名前の間違いです。
- E0560:構造体にないフィールド名:構造体を作るときの、同じ名前の間違いです。
- E0609:型にそのフィールドがない:
user.nmaeのように、フィールドを読むときの同じ名前の間違いです。 - E0533:ユニット構造体・ユニットバリアント・定数が必要:バリアントは合っているのに、パターンの形が違う(
{ }がない)場合です。 - コンパイルエラーの一覧:エラー解説ページの全リストです。
理解度チェック
Section titled “理解度チェック”理解度チェック
1. enum Shape { Circle { radius: f64 } } に対して、パターン Shape::Circle { r } は何を求めていますか?
2. radius フィールドを r という変数に入れたいとき、使えるパターンはどれですか?
3. フィールドの名前が name のとき、User { nmae, .. } はコンパイルできますか?
スコア: 0 / 3
さらに詳しく
Section titled “さらに詳しく”- E0026 — Rust error codes index(英語):このエラーの公式の説明です。
- パターン記法 — The Rust Programming Language 日本語版:構造体や enum の分配(分解)について。
フィールド: 変数や..の書き方も載っています。 - 構造体 — Rust By Example 日本語版:構造体のパターンの、実行できる小さな例です。
- Patterns — The Rust Reference(英語):構造体パターンとフィールドの省略形の、正確なルールです。