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.)
A mensagem de erro
Seção intitulada “A mensagem de erro”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);}O que significa
Seção intitulada “O que significa”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, comokyeem vez dekey. 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.
Por que o Rust faz isso
Seção intitulada “Por que o Rust faz isso”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.
Como corrigir
Seção intitulada “Como corrigir”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 }]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: oicor: 255 128 0Se 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 }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).
Onde você costuma ver esse erro
Seção intitulada “Onde você costuma ver esse erro”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.
Erros relacionados
Seção intitulada “Erros relacionados”- E0560: struct has no field named x: o mesmo engano numa struct, como
User { nmae: ... }. - E0063: missing field in initializer: o contrário, um campo que a variante tem e que você não preencheu.
- E0599: no method named x found: o rustc usa esse código quando o nome da variante está errado, como
Shape::Circel { ... }. A mensagem é “no variant namedCircelfound for enumShape” (nenhuma variante chamadaCircelno enumShape). - E0609: no field on type: um nome de campo errado ao ler um campo.
E0026: variant does not have a field named x: o mesmo engano dentro de um padrão dematch(veja acima).E0533: expected value, found struct variant: parênteses numa variante com campos nomeados, comoShape::Circle(2.0).- Todos os erros do compilador explicados
Teste o que aprendeu
Seção intitulada “Teste o que aprendeu”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
Para saber mais
Seção intitulada “Para saber mais”- E0559 — Rust error codes index (em inglês): a explicação oficial deste erro.
- Defining an Enum — The Rust Book (em inglês): variantes com campos nomeados, variantes de tupla e variantes sem dados, com o exemplo
Message. - Enums — Rust by Example (em inglês): exemplos para rodar de cada tipo de variante.
- Struct expressions — The Rust Reference (em inglês): as regras exatas de
Enum::Variante { campo: valor }, incluindo a forma abreviada. - E0026 — Rust error codes index (em inglês): a página oficial do mesmo engano dentro de um padrão.