Rust 错误 E0026:struct or variant does not have a field named x(模式中的字段名写错)
E0026 的意思是:你在模式里拆解一个结构体或枚举变体,比如 Shape::Circle { r },而你写的某个字段名根本不存在。它是 E0560 和 E0559 的模式版本,那两个错误在你创建值时抓的是同一种错误。rustc 通常会在 help: 行里告诉你正确的名字,所以修复往往只需要改一个词。这个系列的其他错误,请看 Rust 编译错误详解。
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`第一行的意思是“变体 Shape::Circle 没有名为 r 的字段”。help: 告诉你:Shape::Circle 有一个叫 radius 的字段。
产生这个错误的程序是这样的:
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 }));}同一行你还会看到第二个错误:E0027,“pattern does not mention field radius”(模式没有提到字段 radius)。这是从另一面看到的同一个错误。Rust 发现了一个你写了但不存在的字段(r),还发现了一个真实存在、你却没写的字段(radius)。把名字改对,两个错误就都没了。
这个错误是什么意思
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`:正好只有一个字段你没提到,所以 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,bug 要到很久以后、离拼错的地方很远的位置才冒出来。在 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` |背后的程序:
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; // ✅ 是 `name`,不是 `nmae` println!("{} 今年 {} 岁", name, age);}输出:
面积:12.56面积:12.00Ferris 今年 7 岁修复 2:用 字段: 变量名 保留你自己的变量名
Section titled “修复 2:用 字段: 变量名 保留你自己的变量名”如果你就是喜欢短名字 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`背后的程序:
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 逐一指出)。
给字段改名之后。 你在枚举里把 r 改成了 radius,结果每个 Shape::Circle { r } => ... 分支都报 E0026。在项目里搜索旧名字,逐个更新模式;或者写成 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)。参见解构带数据的枚举。
- E0027:pattern does not mention field:E0026 的孪生错误,模式漏掉了一个真实的字段。常常和 E0026 一起出现。
- E0559:variant has no field named x:创建枚举变体时写错了同一种名字。
- E0560:struct has no field named x:创建结构体时写错了同一种名字。
- E0609:no field on type:读取字段时写错了名字,比如
user.nmae。 - E0533:expected unit struct, unit variant or constant:变体是对的,但模式的形状不对(少了
{ })。 - 所有编译错误:错误页面的完整列表。
小测验
1. 对于 enum Shape { Circle { radius: f64 } },模式 Shape::Circle { r } 要的是什么?
2. 你想把 radius 字段放进叫 r 的变量里。哪个模式可以?
3. 如果字段叫 name,User { nmae, .. } 能编译吗?
得分: 0 / 3
- E0026 — Rust error codes index(英文):这个错误的官方解释。
- 模式语法 — Rust 程序设计语言:解构结构体和枚举,包括
字段: 变量和..的写法。 - 解构结构体 — 通过例子学 Rust:结构体模式的简短可运行示例。
- Patterns — The Rust Reference(英文):结构体模式和字段简写的确切规则。