Pular para o conteúdo

Erro E0026 do Rust: struct or variant does not have a field named X (padrão)

O E0026 quer dizer: você está desmontando uma struct ou uma variante de enum num padrão, como Shape::Circle { r }, e um dos nomes de campo que você escreveu não existe. É a versão para padrões do E0560 e do E0559, que pegam o mesmo engano quando você cria um valor. O rustc normalmente diz o nome certo numa linha help:, então a correção muitas vezes é uma palavra só. (Esta página faz parte de Erros do compilador Rust explicados.)

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, // ❌ o campo se chama `radius`
| ^
| |
| variant `Shape::Circle` does not have this field
| help: `Shape::Circle` has a field named `radius`

Em português: “a variante Shape::Circle não tem um campo chamado r”. O rótulo diz que a variante não tem este campo, e a ajuda diz que Shape::Circle tem um campo chamado radius.

Este é o programa que gera o erro:

enum Shape {
Circle { radius: f64 },
Rectangle { width: f64, height: f64 },
}
fn area(shape: &Shape) -> f64 {
match shape {
Shape::Circle { r } => 3.14 * r * r, // ❌ o campo se chama `radius`
Shape::Rectangle { width, height } => width * height,
}
}
fn main() {
println!("{}", area(&Shape::Circle { radius: 1.0 }));
}

Você também vai ver um segundo erro na mesma linha: o E0027, “pattern does not mention field radius” (o padrão não menciona o campo radius). É o mesmo engano visto pelo outro lado. O Rust encontrou um campo que você citou e que não existe (r) e um campo real que você não citou (radius). Corrija o nome e os dois erros somem.

A primeira linha diz o nome da struct ou variante que você está comparando (Shape::Circle) e o campo que você escreveu (r). O ^ aponta para esse nome dentro das chaves do padrão.

Num padrão, os nomes dentro de { } são nomes de campos, e não nomes novos de variáveis que você pode escolher à vontade. Shape::Circle { r } é uma forma curta de Shape::Circle { r: r }: “pegue o campo chamado r e coloque numa variável chamada r”. Circle não tem nenhum campo chamado r, então o Rust para.

Embaixo da seta, o rustc dá uma destas dicas:

  • help: `Shape::Circle` has a field named `radius` (Shape::Circle tem um campo chamado radius): sobrou exatamente um campo que você não citou, então o rustc imagina que você quis dizer esse.
  • help: a field with a similar name exists (existe um campo com um nome parecido): é erro de digitação, como nmae em vez de name. O rustc mostra a linha corrigida.
  • Nenhuma dica: o rustc não conseguiu adivinhar. Olhe a definição da struct ou do enum para ver os nomes reais.

É como pedir a um bibliotecário “o livro da estante Ficção-ou-quase”. Ele sabe que você quer alguma estante, mas só pode ir até estantes que existem de verdade.

Um padrão como Shape::Circle { radius } é uma promessa: “quando o valor for um Circle, me dê o radius dele”. O Rust confere essa promessa com a definição na hora de compilar, então um padrão nunca pode pedir dados que não estão lá. Veja Desestruturando tuplas e structs.

Em linguagens sem essa verificação, ler uma chave que não existe dá undefined ou null, e o bug só aparece bem depois, longe do erro de digitação. Em Rust o erro de digitação não passa pelo compilador. Isso também protege você quando alguém renomeia um campo: todo padrão que ainda usa o nome antigo acende com E0026, então nenhum deles fica esquecido em silêncio.

Escolha esta na maioria das vezes. Use o nome que aparece na linha help:, ou olhe a definição. Nomes de campos diferenciam maiúsculas de minúsculas e são escritos em snake_case.

Um erro de digitação ganha a dica de “nome parecido” e a linha corrigida:

error[E0026]: struct `User` does not have a field named `nmae`
--> src/main.rs:8:16
|
8 | let User { nmae, age } = user; // ❌ erro de digitação: o campo é `name`
| ^^^^ struct `User` does not have this field
|
help: a field with a similar name exists
|
8 - let User { nmae, age } = user; // ❌ erro de digitação: o campo é `name`
8 + let User { name, age } = user; // ❌ erro de digitação: o campo é `name`
|

O rustc diz que a struct User não tem este campo e mostra a linha com o nome parecido que existe: name.

O programa por trás dele:

struct User {
name: String,
age: u32,
}
fn main() {
let user = User { name: String::from("Ferris"), age: 7 };
let User { nmae, age } = user; // ❌ erro de digitação: o campo é `name`
println!("{} tem {} anos", nmae, age);
}

Escreva os nomes dos campos exatamente como na definição. Aí a forma curta funciona, e você ganha variáveis com os mesmos nomes:

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, // ✅ o nome real do campo
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!("área: {:.2}", area(shape));
}
let user = User { name: String::from("Ferris"), age: 7 };
let User { name, age } = user; // ✅ `name`, e não `nmae`
println!("{} tem {} anos", name, age);
}

Saída:

área: 12.56
área: 12.00
Ferris tem 7 anos
▶ Experimente você mesmo

Correção 2: Mantenha o seu nome de variável com campo: nome

Seção intitulada “Correção 2: Mantenha o seu nome de variável com campo: nome”

Escolha esta quando você gosta do nome curto r e só quer que a variável se chame assim. Escreva o nome real do campo, dois-pontos e depois o nome da sua variável: Shape::Circle { radius: r }. Leia como “pegue o campo radius e chame de 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, // ✅ campo `radius`, variável `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!("pequeno: {:.2}", area(&small));
println!("largo: {:.2}", area(&wide));
}

Saída:

pequeno: 3.14
largo: 25.00
▶ Experimente você mesmo

Isso também ajuda quando dois campos iriam se chocar com variáveis que você já tem, ou quando o nome do campo é comprido.

Correção 3: Confira se você está comparando a variante certa

Seção intitulada “Correção 3: Confira se você está comparando a variante certa”

Escolha esta quando o campo que você escreveu existe, só que numa variante diferente. Cada variante de um enum tem os seus próprios campos. Aqui x pertence a Click, mas o braço compara com KeyPress:

error[E0026]: variant `Event::KeyPress` does not have a field named `x`
--> src/main.rs:9:27
|
9 | Event::KeyPress { x, .. } => format!("tecla em {}", x), // ❌ `x` pertence a `Click`
| ^
| |
| variant `Event::KeyPress` does not have this field
| help: `Event::KeyPress` has a field named `key`

O rustc diz que a variante Event::KeyPress não tem este campo, e que ela tem um campo chamado key.

O programa por trás dele:

enum Event {
Click { x: i32, y: i32 },
KeyPress { key: char },
}
fn describe(event: &Event) -> String {
match event {
Event::Click { x, y } => format!("clique em ({}, {})", x, y),
Event::KeyPress { x, .. } => format!("tecla em {}", x), // ❌ `x` pertence a `Click`
}
}
fn main() {
println!("{}", describe(&Event::KeyPress { key: 'a' }));
}

O palpite do rustc (key) é só “o único campo que você não citou”, então não aceite sem pensar. Pergunte a si mesmo o que este braço deveria fazer. Uma tecla pressionada não tem posição, então aqui a correção certa é usar o campo que KeyPress tem de verdade:

enum Event {
Click { x: i32, y: i32 },
KeyPress { key: char },
}
fn describe(event: &Event) -> String {
match event {
Event::Click { x, y } => format!("clique em ({}, {})", x, y),
Event::KeyPress { key } => format!("tecla '{}' pressionada", key), // ✅ KeyPress tem `key`
}
}
fn main() {
let events = [Event::Click { x: 10, y: 20 }, Event::KeyPress { key: 'a' }];
for event in &events {
println!("{}", describe(event));
}
}

Saída:

clique em (10, 20)
tecla 'a' pressionada
▶ Experimente você mesmo

Se uma tecla pressionada deveria mesmo ter uma posição, acrescente os campos à variante: KeyPress { key: char, x: i32, y: i32 }. Aí todo lugar que cria um KeyPress também precisa preenchê-los (o rustc aponta cada um com E0063).

Depois de renomear um campo. Você renomeou r para radius no enum, e agora todo braço Shape::Circle { r } => ... dá E0026. Procure o nome antigo no projeto e atualize cada padrão, ou use radius: r para manter o nome antigo da variável.

Em if let e let. if let Some(User { nmae, .. }) = find_user() dá o mesmo erro. Acrescentar .. não ajuda aqui: o .. pula os campos que você não cita, mas todo nome que você escreve ainda precisa existir. Correção: User { name, .. }.

Chaves numa variante de tupla ou numa tuple struct. Para struct Point(i32, i32);, o padrão Point { x, y } não tem nomes de campos reais para comparar. O rustc avisa isso com outro código, o E0769, “tuple variant Point written as struct variant” (variante de tupla Point escrita como variante de struct), e sugere Point(x, y). Veja Desestruturando enums com dados.

Teste o que aprendeu

1. Para enum Shape { Circle { radius: f64 } }, o que o padrão Shape::Circle { r } pede?

2. Você quer o campo radius numa variável chamada r. Qual padrão funciona?

3. User { nmae, .. } compila se o campo se chama name?

Pontuação: 0 / 3