Pular para o conteúdo

Erro E0559 do Rust: variant has no field named X (campo da variante)

O E0559 quer dizer: você está criando um valor de enum com Enum::Variante { campo: valor }, e um dos campos que você escreveu não existe nessa variante. É a versão para enums do E0560, que é o mesmo engano em structs. Normalmente é um nome de campo abreviado ou escrito errado, um campo que pertence a outra variante, ou chaves numa variante que pede parênteses. A correção quase sempre é uma palavra só. (Esta página faz parte de Erros do compilador Rust explicados.)

error[E0559]: variant `Shape::Circle` has no field named `r`
--> src/main.rs:8:33
|
8 | let shape = Shape::Circle { r: 2.0 }; // ❌ o campo se chama `radius`
| ^ `Shape::Circle` does not have this field
|
= note: available fields are: `radius`

Em português: “a variante Shape::Circle não tem nenhum campo chamado r”. O rótulo diz “Shape::Circle não tem este campo”, e a nota lista os campos disponíveis: radius.

Este é o programa que gera o erro:

#[derive(Debug)]
enum Shape {
Circle { radius: f64 },
Rectangle { width: f64, height: f64 },
}
fn main() {
let shape = Shape::Circle { r: 2.0 }; // ❌ o campo se chama `radius`
println!("{:?}", shape);
}

A primeira linha diz o nome da variante (Shape::Circle) e o campo que você escreveu (r). O ^ aponta para esse campo dentro das chaves. O Rust olhou a definição Circle { radius: f64 } e não encontrou nenhum campo chamado r.

Cada variante de um enum tem a sua própria lista de campos. Shape::Circle tem radius, Shape::Rectangle tem width e height. Elas não compartilham campos, mesmo estando no mesmo enum.

Embaixo da seta, o rustc dá uma destas dicas. Leia a dica primeiro, porque ela costuma trazer a resposta:

  • note: available fields are: `radius` (os campos disponíveis são…): não há nenhum nome parecido. Esses são os campos desta variante que você ainda não preencheu.
  • help: a field with a similar name exists (existe um campo com um nome parecido): é erro de digitação, como kye em vez de key. O rustc mostra a linha corrigida.
  • help: `Message::Write` is a tuple variant, use the appropriate syntax (Message::Write é uma variante de tupla, use a sintaxe adequada): os campos da variante não têm nome, então ela precisa de ( ), e não de { }.
  • note: all struct fields are already assigned (todos os campos já foram preenchidos): você preencheu todos os campos de verdade, e este está sobrando.

É como pedir uma pizza e escrever “borda grande” quando o formulário só tem o campo “tamanho da borda”. A cozinha até entende o que você quis dizer, mas o formulário não tem nenhum campo com esse nome.

Uma variante de enum com campos nomeados, como Circle { radius: f64 }, funciona como uma pequena struct dentro do enum. Quando você cria uma, o Rust confere se você passou exatamente os campos dela: nenhum faltando, nenhum sobrando, nenhum escrito errado. Veja Enums podem guardar dados.

Isso faz mais diferença quando você usa match no enum depois. O braço Shape::Circle { radius } => ... só funciona se todo Circle tiver mesmo um radius. Se o Rust deixasse Shape::Circle { r: 2.0 } passar, essa garantia sumiria. Pegar o erro de digitação na compilação mantém completo todo Circle do seu programa.

Correção 1: Use o nome real do campo da variante

Seção intitulada “Correção 1: Use o nome real do campo da variante”

Escolha esta quando o rustc mostrar available fields are ou a field with a similar name exists. Use o nome que aparece na dica. Nomes de campos diferenciam maiúsculas de minúsculas e são escritos em snake_case, então Radius e radius são nomes diferentes.

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

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' };
|

O rótulo diz “campo desconhecido”, e a ajuda mostra a linha com o nome certo.

Um nome curto como r é diferente demais de radius para uma sugestão, então você recebe a lista de campos. De um jeito ou de outro, escreva o campo que a variante define:

#[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 }, // ✅ o nome real do campo
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);
}

Saída:

Circle { radius: 2.0 }
Rectangle { width: 3.0, height: 4.0 }
[KeyPress { key: 'a' }, Click { x: 10, y: 20 }]
▶ Experimente você mesmo

Cuidado com a forma abreviada de inicialização (field init shorthand). Shape::Circle { r } significa Shape::Circle { r: r }, então dá o mesmo E0559. Se a sua variável se chama r, escreva o campo por extenso: Shape::Circle { radius: r }. Ou renomeie a variável para radius e escreva Shape::Circle { radius }.

Correção 2: Use parênteses numa variante de tupla

Seção intitulada “Correção 2: Use parênteses numa variante de tupla”

Escolha esta quando o rustc disser is a tuple variant, use the appropriate syntax. Uma variante como Write(String) tem um campo, mas esse campo não tem nome. Então qualquer nome que você escrever entre chaves está errado:

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 */);
|

O rótulo diz “o campo não existe”, e o rustc mostra onde Message::Write foi definida.

O /* String */ na sugestão é um espaço para preencher: coloque o seu valor ali. Crie uma variante de tupla com parênteses, na mesma ordem da definição:

#[derive(Debug)]
enum Message {
Move { x: i32, y: i32 }, // campos com nome: use { }
Write(String), // campo sem nome: use ( )
Color(u8, u8, u8),
}
fn main() {
let messages = vec![
Message::Move { x: 1, y: 2 },
Message::Write(String::from("oi")), // ✅ parênteses
Message::Color(255, 128, 0),
];
for m in &messages {
match m {
Message::Move { x, y } => println!("mover para ({}, {})", x, y),
Message::Write(text) => println!("escrever: {}", text),
Message::Color(r, g, b) => println!("cor: {} {} {}", r, g, b),
}
}
}

Saída:

mover para (1, 2)
escrever: oi
cor: 255 128 0
▶ Experimente você mesmo

Se preferir dar nome ao campo, mude a definição para Write { text: String }. Aí Message::Write { text: ... } funciona. A confusão contrária, parênteses numa variante com campos nomeados como Shape::Circle(2.0), dá outro erro: E0533, “expected value, found struct variant” (era esperado um valor, foi encontrada uma variante de struct).

Correção 3: Escolha a variante certa, ou mude a variante

Seção intitulada “Correção 3: Escolha a variante certa, ou mude a variante”

Escolha esta quando o campo que você escreveu existe, só que em outra variante. Aqui radius pertence a Circle, e não a 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`

Pergunte a si mesmo qual você queria. Se queria um círculo, use Shape::Circle { radius: 2.0 }. Se queria um quadrado, use o campo dele: Shape::Square { side: 2.0 }.

Se aparecer note: all struct fields are already assigned, a variante já está completa e o seu campo está sobrando. Tire o campo ou, se o seu código precisa mesmo dele, acrescente-o na definição da variante:

#[derive(Debug)]
enum Shape {
Circle { radius: f64 },
Square { side: f64 },
}
#[derive(Debug)]
enum Message {
Move { x: i32, y: i32, z: i32 }, // `z` acrescentado, porque o código precisa dele
}
fn main() {
let a = Shape::Circle { radius: 2.0 }; // um círculo tem raio
let b = Shape::Square { side: 2.0 }; // um quadrado tem lado
println!("{:?} e {:?}", a, b);
let m = Message::Move { x: 1, y: 2, z: 3 };
println!("{:?}", m);
}

Saída:

Circle { radius: 2.0 } e Square { side: 2.0 }
Move { x: 1, y: 2, z: 3 }
▶ Experimente você mesmo

Quando você acrescenta um campo a uma variante, todo lugar que cria essa variante também precisa preenchê-lo. O rustc aponta cada um com o E0063, “missing field” (campo faltando).

Métodos construtores com Self::. Dentro de impl Shape, escrever fn circle(r: f64) -> Shape { Self::Circle { r } } dá E0559 para r, por causa da forma abreviada. Correção: Self::Circle { radius: r }. Veja Enums também podem ter métodos.

Depois de renomear um campo. Você renomeou Circle { r } para Circle { radius } no enum, e todo Shape::Circle { r: ... } antigo agora dá E0559 com available fields are: `radius`. Procure o nome antigo no projeto e atualize cada um.

Num padrão de match. Escrever o nome errado do campo num padrão, como Shape::Circle { r } => ..., é o mesmo engano, mas o rustc usa outros códigos: E0026, “variant Shape::Circle does not have a field named r” (a variante não tem um campo chamado r), com help: `Shape::Circle` has a field named `radius`, e também o E0027, “pattern does not mention field radius” (o padrão não menciona o campo radius). Correção: Shape::Circle { radius } => ..., ou Shape::Circle { radius: r } => ... para manter o nome curto. Veja Pattern matching.

Teste o que aprendeu

1. Para enum Message { Write(String) }, como Message::Write { text: s } precisa ficar?

2. Você tem let r = 2.0; e escreve Shape::Circle { r }, mas o campo é radius. Como corrigir?

3. Shape::Square { radius: 2.0 } dá E0559, e a nota lista só side. O que está acontecendo?

Pontuação: 0 / 3