Salta ai contenuti

Errore Rust E0027: pattern does not mention field X (campo mancante nel pattern)

E0027 significa: stai scomponendo una struct o una variante di enum con un pattern, come let Order { item, quantity } = order;, e non hai nominato tutti i campi. In Rust un pattern su una struct deve tenere conto di tutti i campi, nominandoli oppure dicendo «e tutto il resto» con ... È uno degli errori più gentili che ci siano: rustc stampa la correzione esatta, e quasi sempre sono due puntini. (Questa pagina fa parte di Errori del compilatore Rust spiegati.)

error[E0027]: pattern does not mention fields `id`, `paid`
--> src/main.rs:10:9
|
10 | let Order { item, quantity } = order; // ❌ `id` and `paid` are not mentioned
| ^^^^^^^^^^^^^^^^^^^^^^^^ missing fields `id`, `paid`
|
help: include the missing fields in the pattern
|
10 | let Order { item, quantity, id, paid } = order; // ❌ `id` and `paid` are not mentioned
| ++++++++++
help: if you don't care about these missing fields, you can explicitly ignore them
|
10 | let Order { item, quantity, id: _, paid: _ } = order; // ❌ `id` and `paid` are not mentioned
| ++++++++++++++++
help: or always ignore missing fields here
|
10 | let Order { item, quantity, .. } = order; // ❌ `id` and `paid` are not mentioned
| ++++

Il compilatore dice: il pattern non nomina i campi id e paid, e ti propone tre modi per sistemarlo. Questo è il programma che produce l’errore:

struct Order {
id: u32,
item: String,
quantity: u32,
paid: bool,
}
fn main() {
let order = Order { id: 1, item: String::from("keyboard"), quantity: 2, paid: true };
let Order { item, quantity } = order; // ❌ `id` and `paid` are not mentioned
println!("{} x {}", quantity, item);
}

La prima riga elenca i campi che il tuo pattern ha lasciato fuori (id e paid). Il ^^^ sottolinea tutto il pattern, perché il problema non è una parola sbagliata: è qualcosa che manca.

Poi rustc ti dà tre suggerimenti help:. Sono tutti validi, ma significano cose diverse:

  • include the missing fields (includi i campi mancanti): nominali, così ottieni anche le variabili id e paid.
  • explicitly ignore them (ignorali in modo esplicito): scrivi id: _, paid: _. Non ottieni variabili, ma hai elencato ogni campo per nome.
  • always ignore missing fields here (ignora sempre i campi mancanti qui): scrivi ... Significa «e tutti gli altri campi, non mi interessano».

È come un modulo all’ingresso che dice «spunta ogni casella, oppure spunta Altro: salta». Non puoi lasciare caselle vuote.

In Rust un pattern su una struct è pensato per essere completo, a meno che tu non dica il contrario. Così la tua intenzione è chiara a chi legge il codice dopo di te. Order { item, quantity, .. } dice «mi servono solo questi due». Order { id, item, quantity, paid } dice «ho pensato a ogni campo». Vedi Pattern matching in Rust.

Il vero vantaggio arriva quando la struct cambia. Se qualcuno aggiunge un campo discount a Order, un pattern che elenca ogni campo per nome si rompe con E0027, e ti indica il codice che forse deve gestire il nuovo campo. Un pattern con .. continua a compilare. Rust ti lascia scegliere il comportamento che vuoi, ma non lo indovina al posto tuo.

Scegli questa nella maggior parte dei casi. Se ti servono solo alcuni campi, chiudi il pattern con ... Funziona in let, match, if let e nei parametri delle funzioni, e deve stare per ultimo.

struct Order {
id: u32,
item: String,
quantity: u32,
paid: bool,
}
fn main() {
let order = Order { id: 1, item: String::from("tastiera"), quantity: 2, paid: true };
let Order { item, quantity, .. } = order; // ✅ `..` salta `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!("spedisci il {}", item),
Order { id, .. } => println!("l'ordine #{} aspetta il pagamento", id),
}
}
}

Output:

2 x tastiera
l'ordine #2 aspetta il pagamento
spedisci il monitor
▶ Provalo tu

Nota paid: true nel primo ramo: un campo in un pattern può anche essere confrontato con un valore, e .. continua a occuparsi degli altri.

Soluzione 2: nomina il campo mancante, o ignoralo per nome con _

Sezione intitolata “Soluzione 2: nomina il campo mancante, o ignoralo per nome con _”

Scegli questa quando il campo ti serve davvero, o quando vuoi che il pattern si rompa se in futuro viene aggiunto un campo. Lo stesso errore compare in un match su una variante di enum con campi nominati:

error[E0027]: pattern does not mention field `y`
--> src/main.rs:9:9
|
9 | Message::Move { x } => println!("move to x = {}", x), // ❌ `y` is not mentioned
| ^^^^^^^^^^^^^^^^^^^ missing field `y`

Il programma che lo produce:

enum Message {
Move { x: i32, y: i32 },
Quit,
}
fn main() {
let m = Message::Move { x: 1, y: 2 };
match m {
Message::Move { x } => println!("move to x = {}", x), // ❌ `y` is not mentioned
Message::Quit => println!("quit"),
}
}

Uno spostamento ha due coordinate, e il codice dovrebbe proprio usarle entrambe. Quindi nomina y. Quando un campo davvero non conta, y: _ lo dice ad alta voce, e lo elenca comunque per 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!("scivola sul pavimento fino a x = {}", x),
Message::Move { x, y } => println!("vai a ({}, {})", x, y), // ✅ tutti e due i campi
Message::Quit => println!("esci"),
}
}
// ogni campo elencato per nome: aggiungere un campo a `Move` romperà questo di proposito
if let Message::Move { x, y: _ } = &messages[0] {
println!("primo x = {}", x);
}
}

Output:

vai a (1, 2)
scivola sul pavimento fino a x = 5
esci
primo x = 1
▶ Provalo tu

Se nomini un campo solo per ignorarlo, scrivi y: _, non un semplice y. Un y semplice che non usi mai ti dà un warning «unused variable» (variabile non usata).

Soluzione 3: correggi un nome di campo scritto male

Sezione intitolata “Soluzione 3: correggi un nome di campo scritto male”

Scegli questa quando E0027 arriva insieme a E0026 sulla stessa riga. Per esempio, Shape::Circle { r } per una variante il cui campo si chiama radius li dà tutti e due: E0026 per r (campo inesistente) ed E0027 per radius (non nominato). Il suggerimento di E0027 ti proporrà di aggiungere radius accanto a r, ma non è quello che vuoi. La vera correzione è sostituire il nome sbagliato: Shape::Circle { radius }, oppure Shape::Circle { radius: r } per tenere il nome di variabile corto. Così spariscono entrambi gli errori in un colpo. Trovi esempi nella pagina su E0026.

Dopo aver aggiunto un campo a una struct. Aggiungi created_at a Order, e ogni pattern che elencava tutti i campi ora dà E0027. È il controllo che fa il suo lavoro. Decidi caso per caso: questo codice ha bisogno di created_at? Se sì, nominalo; se no, aggiungi ...

Parametri di funzione. Anche fn print_order(&Order { item, quantity }: &Order) dà E0027. Correzione: &Order { item, quantity, .. }. Vedi Pattern matching in Rust.

Tuple struct e varianti tupla. Per struct Color(u8, u8, u8);, anche il pattern Color(r) è incompleto, ma rustc lo segnala come E0023, «this pattern has 1 field, but the corresponding tuple struct has 3 fields». La correzione segue la stessa idea: Color(r, ..) oppure Color(r, _, _).

Verifica veloce

1. struct Point { x: i32, y: i32, z: i32 }. Quale pattern compila e ti dà solo x?

2. Che differenza c'è tra Order { item, .. } e Order { item, id: _, quantity: _, paid: _ }?

3. Ricevi E0026 per r ed E0027 per radius sulla stessa riga. Qual è la correzione migliore?

Punteggio: 0 / 3