Erro E0560 do Rust: struct has no field named X (campo desconhecido)
O E0560 quer dizer: você está criando uma struct com Nome { campo: valor }, e um dos campos que você escreveu não existe nessa struct. Normalmente é um erro de digitação, um campo que foi renomeado ou um campo que pertence a outra struct. O rustc muitas vezes diz o nome exato que você queria, então este é um dos erros mais rápidos de corrigir. (Esta página faz parte de Erros do compilador Rust explicados.)
A mensagem de erro
Seção intitulada “A mensagem de erro”error[E0560]: struct `User` has no field named `nmae` --> src/main.rs:9:9 |9 | nmae: String::from("Ferris"), // ❌ erro de digitação: o campo é `name` | ^^^^ unknown field |help: a field with a similar name exists |9 - nmae: String::from("Ferris"), // ❌ erro de digitação: o campo é `name`9 + name: String::from("Ferris"), // ❌ erro de digitação: o campo é `name` |Em português: “a struct User não tem nenhum campo chamado nmae”. O rótulo diz “campo desconhecido”, e a ajuda diz “existe um campo com um nome parecido”, mostrando a linha corrigida.
Este é o programa que gera o erro:
struct User { name: String, email: String, active: bool,}
fn main() { let user = User { nmae: String::from("Ferris"), // ❌ erro de digitação: o campo é `name` active: true, }; println!("{}", user.email);}O que significa
Seção intitulada “O que significa”A primeira linha diz o nome da struct (User) e o campo que você escreveu (nmae). O ^^^^ aponta para esse campo dentro do bloco User { ... }. O Rust comparou o nome com a lista de campos de struct User e não encontrou nenhum igual.
Embaixo da seta vem uma de três dicas. Cada uma diz uma coisa diferente:
help: a field with a similar name exists(existe um campo com um nome parecido): é erro de digitação. O rustc mostra a linha com o nome certo.note: available fields are: `username`(os campos disponíveis são…): não há nenhum nome parecido. Esses são os campos que você ainda não preencheu.note: all struct fields are already assigned(todos os campos da struct já foram preenchidos): você preencheu todos os campos de verdade, e este está sobrando.
Repare que o rustc não reclama também que falta o name. Corrija a digitação e os dois problemas somem de uma vez.
É como preencher um formulário de papel e escrever seu telefone num campo chamado “Fax”. O formulário não tem esse campo, então o atendente te devolve o papel.
Por que o Rust faz isso
Seção intitulada “Por que o Rust faz isso”Os campos de uma struct ficam fixos quando você escreve struct User { ... }. Toda vez que você cria um User, o Rust confere se você passou exatamente esses campos: nenhum faltando, nenhum sobrando, nenhum escrito errado. Veja Definindo e criando uma struct.
Isso pega bugs de verdade. Em JavaScript, { nmae: "Ferris" } cria sem avisar um objeto com a chave errada, e user.name vira undefined em algum lugar bem mais adiante. Em Rust, o erro de digitação não passa pelo compilador, então todo User do seu programa tem mesmo um name.
Como corrigir
Seção intitulada “Como corrigir”Correção 1: Corrija a grafia
Seção intitulada “Correção 1: Corrija a grafia”Escolha esta quando aparecer a field with a similar name exists. Use o nome da linha help:. Nomes de campos diferenciam maiúsculas de minúsculas, e o Rust usa snake_case, então userName e user_name são nomes diferentes.
Cuidado também com a forma abreviada de inicialização (field init shorthand): User { nmae, email } significa User { nmae: nmae, email: email }, então o nome da variável precisa ser igual ao nome do campo. Renomeie a variável ou escreva o campo por extenso: User { name: nmae, email }.
struct User { name: String, email: String, active: bool,}
fn main() { let user = User { name: String::from("Ferris"), // ✅ o nome real do campo active: true, }; println!("{} ({}) ativo: {}", user.name, user.email, user.active);
// forma abreviada: os nomes das variáveis são iguais aos dos campos let name = String::from("Ada"); let other = User { name, email, active: false }; println!("{} ({}) ativo: {}", other.name, other.email, other.active);}Saída:
Ferris ([email protected]) ativo: trueAda ([email protected]) ativo: falseCorreção 2: Use o novo nome do campo, ou acrescente o campo
Seção intitulada “Correção 2: Use o novo nome do campo, ou acrescente o campo”Escolha esta quando não houver a dica de “nome parecido”. Muitas vezes a struct mudou: alguém renomeou name para username, ou um campo foi removido, mas este código ainda usa o antigo. O rustc lista o que sobrou:
error[E0560]: struct `User` has no field named `name` --> src/main.rs:8:9 |8 | name: String::from("Ferris"), | ^^^^ `User` does not have this field | = note: available fields are: `username`O rótulo diz “User não tem este campo”, e a nota lista os campos disponíveis.
Você tem duas escolhas honestas. Se a struct está certa, use o nome atual do campo. Se o seu código está certo e a struct precisa mesmo do campo, acrescente-o na definição da struct. Aqui, Config deu all struct fields are already assigned para debug, e a correção é acrescentar debug à struct:
struct User { username: String, // renomeado de `name`: use o novo nome email: String,}
struct Config { port: u16, host: String, debug: bool, // acrescentado à struct, porque o código precisa dele}
fn main() { let user = User { username: String::from("ferris"), }; println!("{} ({})", user.username, user.email);
let config = Config { port: 8080, host: String::from("localhost"), debug: true, }; println!("{}:{} debug={}", config.host, config.port, config.debug);}Saída:
ferris ([email protected])localhost:8080 debug=trueSe a struct vem de um crate que você acabou de atualizar, o campo pode ter sido renomeado na nova versão. Confira a struct no docs.rs (em inglês) para essa versão, ou o changelog do crate. Quando você acrescenta um campo a uma struct sua, todo lugar que a cria também precisa preenchê-lo. O rustc vai apontar cada um com o E0063 (veja abaixo).
Correção 3: Use a struct certa
Seção intitulada “Correção 3: Use a struct certa”Escolha esta quando o campo que você escreveu existe, só que em outra struct. Com duas structs parecidas, como um Product com title e um Customer com name, é fácil confundir:
error[E0560]: struct `Product` has no field named `name` --> src/main.rs:13:9 |13 | name: String::from("Keyboard"), | ^^^^ `Product` does not have this field | = note: available fields are: `title`Olhe a nota available fields. Se ela lista campos que você não esperava, você está montando a struct errada. Use o nome da struct certa, ou o nome do campo da struct que você queria:
struct Product { title: String, price: u32, // em centavos}
struct Customer { name: String, email: String,}
fn main() { let keyboard = Product { title: String::from("teclado"), // produtos têm `title` price: 4900, }; let buyer = Customer { name: String::from("Ana"), // clientes têm `name` }; println!("{} compra um {} por {} centavos", buyer.name, keyboard.title, keyboard.price); println!("Recibo enviado para {}", buyer.email);}Saída:
Ana compra um teclado por 4900 centavosRecibo enviado para [email protected]Correção 4: Use parênteses numa tuple struct
Seção intitulada “Correção 4: Use parênteses numa tuple struct”Escolha esta quando a struct é uma tuple struct, como struct Point(i32, i32);. Os campos dela não têm nome, então Point { x: 1, y: 2 } dá E0560 tanto para x quanto para y, com help: `Point` is a tuple struct, use the appropriate syntax (Point é uma tuple struct, use a sintaxe adequada) e a sugestão Point(/* i32 */, /* i32 */). Crie com parênteses, Point(1, 2), e leia com .0 e .1. Se preferir nomes, mude a definição para struct Point { x: i32, y: i32 }. Veja Quando usar uma tupla e quando usar uma struct.
O contrário: E0063, campo faltando
Seção intitulada “O contrário: E0063, campo faltando”O gêmeo do E0560 é o E0063: um campo que a struct tem, mas que você não preencheu. O Rust nunca preenche campos por você, então todo campo precisa de um valor:
error[E0063]: missing field `active` in initializer of `User` --> src/main.rs:8:16 |8 | let user = User { | ^^^^ missing `active`Em português: “falta o campo active na inicialização de User”. Com vários campos faltando, ele lista todos: missing fields `active`, `email` and `login_count` in initializer of `User`. Correção: dê um valor para cada campo. Se muitos campos têm valores padrão sensatos, derive Default e use a sintaxe de atualização de struct .. para preencher o resto:
#[derive(Debug, Default)]struct Settings { volume: u8, dark_mode: bool, language: String,}
fn main() { // todos os campos escritos por extenso let full = Settings { volume: 80, dark_mode: false, language: String::from("pt") };
// só os campos que importam, o resto vem do Default let quick = Settings { dark_mode: true, ..Default::default() };
// copia o resto de outro valor let louder = Settings { volume: 100, ..full };
println!("{:?}", quick); println!("{:?}", louder);}Saída:
Settings { volume: 0, dark_mode: true, language: "" }Settings { volume: 100, dark_mode: false, language: "pt" }O padrão de um número é 0, de um bool é false, e de uma String é vazia. Se quiser outros valores padrão, escreva você mesmo um impl Default for Settings. Veja Default: um valor inicial sensato.
Onde você costuma ver esse erro
Seção intitulada “Onde você costuma ver esse erro”Dentro da sintaxe de atualização ... Settings { dark: true, ..defaults } também dá E0560. Aqui a nota lista todos os campos (available fields are: `volume`, `dark_mode`, `language`), e pode não haver a dica de “nome parecido” quando os nomes são diferentes demais. Correção: dark_mode: true.
Variantes de enum com campos nomeados. Para enum Shape { Circle { radius: f64 } }, escrever Shape::Circle { r: 2.0 } é o mesmo engano, mas o rustc usa outro código: E0559, variant `Shape::Circle` has no field named `r` (a variante Shape::Circle não tem campo chamado r), com a mesma nota available fields e as mesmas dicas de digitação. Correção: Shape::Circle { radius: 2.0 }. Veja Enums podem guardar dados.
Uma struct de outro módulo. Se o campo existe, mas não é pub, você recebe o E0451, “field balance of struct Account is private” (o campo balance da struct Account é privado). Correção: use o construtor do módulo, como Account::new(...). Veja Tudo é privado por padrão.
Erros relacionados
Seção intitulada “Erros relacionados”- E0609: no field
xon typeT: o mesmo erro de digitação, mas ao ler um campo (user.nmae) em vez de criar a struct. - E0451: field is private in struct literal: o campo existe, mas você não pode preenchê-lo daqui.
- E0308: mismatched types: o nome do campo está certo, mas o valor tem o tipo errado, como
"Ferris"num campoString. E0063: missing field in initializer: um campo que você esqueceu (veja acima).E0559: variant has no field named x: o E0560 das variantes de enum.- Todos os erros do compilador explicados
Teste o que aprendeu
Seção intitulada “Teste o que aprendeu”Teste o que aprendeu
1. O rustc diz note: all struct fields are already assigned. O que isso significa?
2. Você tem let nmae = ...; e escreve User { nmae, email }. Como corrigir?
3. Qual erro aparece quando você deixa um campo de fora, como User { name, email } sem active?
Pontuação: 0 / 3
Para saber mais
Seção intitulada “Para saber mais”- E0560 — Rust error codes index (em inglês): a explicação oficial deste erro.
- Defining and Instantiating Structs — The Rust Book (em inglês): criação de structs, a forma abreviada de inicialização, a sintaxe de atualização e as tuple structs.
- E0063 — Rust error codes index (em inglês): a página oficial do gêmeo “campo faltando” deste erro.
- Struct expressions — The Rust Reference (em inglês): as regras exatas de
Nome { campo: valor }, da forma abreviada e do..base. Default— documentação da biblioteca padrão (em inglês): como#[derive(Default)]e..Default::default()funcionam.