Erro E0027 do Rust: pattern does not mention field X (campo fora do padrão)
O E0027 quer dizer: você está desmontando uma struct ou uma variante de enum com um padrão, como let Order { item, quantity } = order;, e não citou todos os campos. Em Rust, um padrão de struct precisa dar conta de todos os campos, seja citando cada um pelo nome, seja dizendo “e o resto” com ... Este é um dos erros mais amigáveis que existem: o rustc mostra a correção exata, e ela quase sempre é só dois pontos. (Esta página faz parte de Erros do compilador Rust explicados.)
A mensagem de erro
Seção intitulada “A mensagem de erro”error[E0027]: pattern does not mention fields `id`, `paid` --> src/main.rs:10:9 |10 | let Order { item, quantity } = order; // ❌ `id` e `paid` não foram citados | ^^^^^^^^^^^^^^^^^^^^^^^^ missing fields `id`, `paid` |help: include the missing fields in the pattern |10 | let Order { item, quantity, id, paid } = order; // ❌ `id` e `paid` não foram citados | ++++++++++help: if you don't care about these missing fields, you can explicitly ignore them |10 | let Order { item, quantity, id: _, paid: _ } = order; // ❌ `id` e `paid` não foram citados | ++++++++++++++++help: or always ignore missing fields here |10 | let Order { item, quantity, .. } = order; // ❌ `id` e `paid` não foram citados | ++++Em português: “o padrão não menciona os campos id e paid”. O rótulo diz que esses campos estão faltando, e as três ajudas sugerem: incluir os campos que faltam no padrão, ignorá-los de forma explícita, ou sempre ignorar os campos que faltam aqui.
Este é o programa que gera o erro:
struct Order { id: u32, item: String, quantity: u32, paid: bool,}
fn main() { let order = Order { id: 1, item: String::from("teclado"), quantity: 2, paid: true }; let Order { item, quantity } = order; // ❌ `id` e `paid` não foram citados println!("{} x {}", quantity, item);}O que significa
Seção intitulada “O que significa”A primeira linha lista os campos que o seu padrão deixou de fora (id e paid). O ^^^ sublinha o padrão inteiro, porque o problema não é uma palavra errada, é algo que está faltando.
Depois o rustc dá três sugestões help:. Todas são válidas, e cada uma quer dizer uma coisa diferente:
include the missing fields(inclua os campos que faltam): cite os campos, e você ganha também as variáveisidepaid.explicitly ignore them(ignore-os de forma explícita): escrevaid: _, paid: _. Você não ganha variáveis, mas listou todos os campos pelo nome.always ignore missing fields here(sempre ignore os campos que faltam aqui): escreva... Quer dizer “e qualquer outro campo, não me importo com eles”.
É como uma lista de presença na porta que diz “marque todas as caixas, ou marque Outros: pular”. Você não pode simplesmente deixar caixas em branco.
Por que o Rust faz isso
Seção intitulada “Por que o Rust faz isso”Um padrão de struct em Rust deve ser completo, a não ser que você diga o contrário. Isso deixa a sua intenção clara para quem ler o código depois. Order { item, quantity, .. } diz “só preciso destes dois”. Order { id, item, quantity, paid } diz “pensei em cada campo”. Veja Ignorando partes com _ e ...
A grande vantagem aparece quando a struct muda. Se alguém acrescentar um campo discount a Order, um padrão que lista todos os campos pelo nome quebra com E0027, e isso aponta para um código que talvez precise lidar com o campo novo. Um padrão com .. continua compilando. O Rust deixa você escolher qual comportamento quer, mas não vai adivinhar por você.
Como corrigir
Seção intitulada “Como corrigir”Correção 1: Acrescente .. para ignorar o resto
Seção intitulada “Correção 1: Acrescente .. para ignorar o resto”Escolha esta na maioria das vezes. Se você só precisa de alguns campos, termine o padrão com ... Funciona em let, match, if let e em parâmetros de funções, e precisa vir por último.
struct Order { id: u32, item: String, quantity: u32, paid: bool,}
fn main() { let order = Order { id: 1, item: String::from("teclado"), quantity: 2, paid: true }; let Order { item, quantity, .. } = order; // ✅ o `..` pula `id` e `paid` println!("{} x {}", quantity, item);
let orders = [ Order { id: 2, item: String::from("mouse"), quantity: 1, paid: false }, Order { id: 3, item: String::from("monitor"), quantity: 1, paid: true }, ]; for order in &orders { match order { Order { paid: true, item, .. } => println!("enviar o {}", item), Order { id, .. } => println!("o pedido #{} está aguardando pagamento", id), } }}Saída:
2 x tecladoo pedido #2 está aguardando pagamentoenviar o monitorRepare no paid: true do primeiro braço: um campo num padrão também pode ser comparado com um valor, e o .. continua cuidando dos outros.
Correção 2: Cite o campo que falta, ou ignore-o pelo nome com _
Seção intitulada “Correção 2: Cite o campo que falta, ou ignore-o pelo nome com _”Escolha esta quando você precisa mesmo do campo, ou quando você quer que o padrão quebre se um campo for acrescentado depois. O mesmo erro aparece num match sobre uma variante de enum com campos nomeados:
error[E0027]: pattern does not mention field `y` --> src/main.rs:9:9 |9 | Message::Move { x } => println!("mover para x = {}", x), // ❌ `y` não foi citado | ^^^^^^^^^^^^^^^^^^^ missing field `y`O rustc diz que o padrão não menciona o campo y.
O programa por trás dele:
enum Message { Move { x: i32, y: i32 }, Quit,}
fn main() { let m = Message::Move { x: 1, y: 2 }; match m { Message::Move { x } => println!("mover para x = {}", x), // ❌ `y` não foi citado Message::Quit => println!("sair"), }}Um movimento tem duas coordenadas, e o código deveria mesmo usar as duas. Então cite o y. Quando um campo realmente não importa, y: _ diz isso em voz alta, e ainda assim o lista pelo nome:
enum Message { Move { x: i32, y: i32 }, Quit,}
fn main() { let messages = [Message::Move { x: 1, y: 2 }, Message::Move { x: 5, y: 0 }, Message::Quit]; for m in &messages { match m { Message::Move { x, y: 0 } => println!("deslizar pelo chão até x = {}", x), Message::Move { x, y } => println!("mover para ({}, {})", x, y), // ✅ os dois campos Message::Quit => println!("sair"), } }
// todos os campos listados pelo nome: acrescentar um campo a `Move` quebra isto de propósito if let Message::Move { x, y: _ } = &messages[0] { println!("primeiro x = {}", x); }}Saída:
mover para (1, 2)deslizar pelo chão até x = 5sairprimeiro x = 1Se você cita um campo só para ignorá-lo, escreva y: _, e não um y simples. Um y simples que você nunca usa dá um aviso de “unused variable” (variável não usada).
Correção 3: Corrija um nome de campo escrito errado
Seção intitulada “Correção 3: Corrija um nome de campo escrito errado”Escolha esta quando o E0027 vem junto com o E0026 na mesma linha. Por exemplo, Shape::Circle { r } numa variante cujo campo é radius dá os dois: E0026 para r (esse campo não existe) e E0027 para radius (não foi citado). A ajuda do E0027 vai sugerir acrescentar radius ao lado de r, mas não é isso que você quer. A correção de verdade é trocar o nome errado: Shape::Circle { radius }, ou Shape::Circle { radius: r } para manter o nome curto da variável. Aí os dois erros somem de uma vez. Veja exemplos na página do E0026.
Onde você costuma ver esse erro
Seção intitulada “Onde você costuma ver esse erro”Depois de acrescentar um campo a uma struct. Você acrescenta created_at a Order, e todo padrão que listava todos os campos agora dá E0027. É a verificação fazendo o trabalho dela. Decida caso a caso: este código precisa de created_at? Se sim, cite o campo; se não, acrescente ...
Parâmetros de funções. fn print_order(&Order { item, quantity }: &Order) também dá E0027. Correção: &Order { item, quantity, .. }. Veja Padrões no let e nos parâmetros de funções.
Tuple structs e variantes de tupla. Para struct Color(u8, u8, u8);, o padrão Color(r) também está incompleto, mas o rustc mostra isso como E0023, “this pattern has 1 field, but the corresponding tuple struct has 3 fields” (este padrão tem 1 campo, mas a tuple struct correspondente tem 3). A ideia da correção é a mesma: Color(r, ..) ou Color(r, _, _).
Erros relacionados
Seção intitulada “Erros relacionados”- E0026: struct or variant does not have a field named x: um nome de campo no padrão que não existe. Muitas vezes aparece junto com o E0027.
- E0063: missing field in initializer: a mesma ideia ao criar uma struct: todo campo precisa de um valor (ou de
..Default::default()). - E0004: non-exhaustive patterns: um
matchque não cobre todas as variantes, enquanto o E0027 é sobre todos os campos. E0023: this pattern has N fields, but the corresponding tuple struct has M fields: a versão para tuple structs (veja acima).- Todos os erros do compilador explicados
Teste o que aprendeu
Seção intitulada “Teste o que aprendeu”Teste o que aprendeu
1. struct Point { x: i32, y: i32, z: i32 }. Qual padrão compila e dá a você só o x?
2. Qual é a diferença entre Order { item, .. } e Order { item, id: _, quantity: _, paid: _ }?
3. Você recebe E0026 para r e E0027 para radius na mesma linha. Qual é a melhor correção?
Pontuação: 0 / 3
Para saber mais
Seção intitulada “Para saber mais”- E0027 — Rust error codes index (em inglês): a explicação oficial deste erro.
- Pattern Syntax — The Rust Book (em inglês): como desestruturar structs e a seção “Ignoring Remaining Parts of a Value with
..”. - Destructuring structs — Rust by Example (em inglês): padrões de struct com
..para rodar. - Patterns — The Rust Reference (em inglês): as regras exatas dos padrões de struct e do padrão de resto.