Rust 错误 E0559:variant has no field named X(变体没有这个字段)
E0559 的意思是:你在用 Enum::Variant { field: value } 创建一个枚举值,而你写的某个字段在这个变体里并不存在。 它是 E0560 的枚举版本,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 的字段”。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);}这个错误是什么意思
Section titled “这个错误是什么意思”标题里写出了变体(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:拼写错误,比如把key写成了kye。rustc 会给出改正后的那一行。help: `Message::Write` is a tuple variant, use the appropriate syntax:这个变体的字段没有名字,所以要用( ),而不是{ }。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 是不同的。
拼写错误会得到“similar name”(相近的名字)提示:
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 }]小心字段初始化简写。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 */); |建议里的 /* 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 属于 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 } },因为简写的缘故,会对 r 报 E0559。修复: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”(模式里没有提到字段 radius)。修复:Shape::Circle { radius } => ...,或者想保留短名字就写 Shape::Circle { radius: r } => ...。参见模式匹配。
- E0560:struct has no field named x:结构体字面量里的同一种错误,比如
User { nmae: ... }。 - E0063:missing field in initializer:反过来的情况,变体有某个字段,而你没有填。
- E0599:no method named x found:变体名写错时,rustc 也用这个代码,比如
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)。- 所有编译错误详解
小测验
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,note 里只列出了 side。这是怎么回事?
得分: 0 / 3
- E0559 — Rust error codes index(英文):这个错误的官方解释。
- 定义枚举 — Rust 程序设计语言:带命名字段的变体、元组变体和单元变体,附有
Message示例。 - 枚举 — 通过例子学 Rust:每一种变体的可运行示例。
- Struct expressions — The Rust Reference(英文):
Enum::Variant { field: value }的确切规则,包括简写。 - E0026 — Rust error codes index(英文):模式里同一种错误的官方页面。