Erreur Rust E0027 : pattern does not mention field X (champ oublié dans un motif)
E0027 veut dire que vous décomposez une struct ou une variante d’enum avec un motif (pattern), comme let Order { item, quantity } = order;, et que vous n’avez pas mentionné tous les champs. En Rust, un motif de struct doit tenir compte de tous les champs, soit en les nommant, soit en disant « et le reste » avec ... C’est l’une des erreurs les plus sympathiques qui soient : rustc affiche la correction exacte, et c’est presque toujours deux points. Cette page fait partie du guide des erreurs du compilateur Rust.
Le message d’erreur
Section intitulée « Le message d’erreur »error[E0027]: pattern does not mention fields `id`, `paid` --> src/main.rs:10:9 |10 | let Order { item, quantity } = order; // ❌ `id` et `paid` ne sont pas mentionnés | ^^^^^^^^^^^^^^^^^^^^^^^^ missing fields `id`, `paid` |help: include the missing fields in the pattern |10 | let Order { item, quantity, id, paid } = order; // ❌ `id` et `paid` ne sont pas mentionnés | ++++++++++help: if you don't care about these missing fields, you can explicitly ignore them |10 | let Order { item, quantity, id: _, paid: _ } = order; // ❌ `id` et `paid` ne sont pas mentionnés | ++++++++++++++++help: or always ignore missing fields here |10 | let Order { item, quantity, .. } = order; // ❌ `id` et `paid` ne sont pas mentionnés | ++++Le compilateur vous dit : « le motif ne mentionne pas les champs id et paid ». La section « Ce que ça veut dire » ci-dessous explique les trois suggestions.
Voici le programme qui la provoque :
struct Order { id: u32, item: String, quantity: u32, paid: bool,}
fn main() { let order = Order { id: 1, item: String::from("clavier"), quantity: 2, paid: true }; let Order { item, quantity } = order; // ❌ `id` et `paid` ne sont pas mentionnés println!("{} x {}", quantity, item);}Ce que ça veut dire
Section intitulée « Ce que ça veut dire »Le titre de l’erreur liste les champs que votre motif a oubliés (id et paid). Le ^^^ souligne tout le motif, car le problème n’est pas un mot faux, mais quelque chose qui manque.
rustc donne ensuite trois suggestions help:. Elles sont toutes valables, et elles ne veulent pas dire la même chose :
include the missing fields(inclure les champs manquants) : nommez-les, et vous obtenez aussi des variablesidetpaid.explicitly ignore them(les ignorer explicitement) : écrivezid: _, paid: _. Vous n’obtenez pas de variables, mais vous avez listé chaque champ par son nom.always ignore missing fields here(toujours ignorer les champs manquants ici) : écrivez... Ça veut dire « et tous les autres champs, ils ne m’intéressent pas ».
C’est comme une liste de contrôle à l’entrée qui dit « cochez chaque case, ou cochez Autre : passer ». Vous ne pouvez pas simplement laisser des cases vides.
Pourquoi Rust fait ça
Section intitulée « Pourquoi Rust fait ça »En Rust, un motif de struct est censé être complet, sauf si vous dites le contraire. Ça rend votre intention claire pour la personne qui lira le code ensuite. Order { item, quantity, .. } dit « je n’ai besoin que de ces deux-là ». Order { id, item, quantity, paid } dit « j’ai pensé à chaque champ ». Voir Ignorer des parties avec _ et ...
Le vrai bénéfice arrive quand la struct change. Si quelqu’un ajoute un champ discount à Order, un motif qui liste chaque champ par son nom casse avec E0027, et vous montre ainsi du code qui doit peut-être gérer le nouveau champ. Un motif avec .. continue de compiler. Rust vous laisse choisir le comportement que vous voulez, mais il ne devine pas à votre place.
Comment corriger
Section intitulée « Comment corriger »Solution 1 : ajouter .. pour ignorer le reste
Section intitulée « Solution 1 : ajouter .. pour ignorer le reste »Choisissez-la la plupart du temps. Si vous n’avez besoin que de certains champs, terminez le motif par ... Ça marche dans let, match, if let et les paramètres de fonction, et .. doit venir en dernier.
struct Order { id: u32, item: String, quantity: u32, paid: bool,}
fn main() { let order = Order { id: 1, item: String::from("clavier"), quantity: 2, paid: true }; let Order { item, quantity, .. } = order; // ✅ `..` saute `id` et `paid` println!("{} x {}", quantity, item);
let orders = [ Order { id: 2, item: String::from("souris"), quantity: 1, paid: false }, Order { id: 3, item: String::from("écran"), quantity: 1, paid: true }, ]; for order in &orders { match order { Order { paid: true, item, .. } => println!("expédier : {}", item), Order { id, .. } => println!("la commande n°{} attend le paiement", id), } }}Sortie :
2 x clavierla commande n°2 attend le paiementexpédier : écranRemarquez paid: true dans la première branche : un champ d’un motif peut aussi être comparé à une valeur, et .. s’occupe toujours des autres.
Solution 2 : nommer le champ manquant, ou l’ignorer par son nom avec _
Section intitulée « Solution 2 : nommer le champ manquant, ou l’ignorer par son nom avec _ »Choisissez-la quand vous avez vraiment besoin du champ, ou quand vous voulez que le motif casse si un champ est ajouté plus tard. La même erreur apparaît dans un match sur une variante d’enum à champs nommés :
error[E0027]: pattern does not mention field `y` --> src/main.rs:9:9 |9 | Message::Move { x } => println!("aller en x = {}", x), // ❌ `y` n'est pas mentionné | ^^^^^^^^^^^^^^^^^^^ missing field `y`Le programme qui la provoque :
enum Message { Move { x: i32, y: i32 }, Quit,}
fn main() { let m = Message::Move { x: 1, y: 2 }; match m { Message::Move { x } => println!("aller en x = {}", x), // ❌ `y` n'est pas mentionné Message::Quit => println!("quitter"), }}Un déplacement a deux coordonnées, et le code devrait vraiment utiliser les deux. Nommez donc y. Quand un champ n’a vraiment aucune importance, y: _ le dit clairement, tout en le listant par son nom :
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!("glisser au sol jusqu'à x = {}", x), Message::Move { x, y } => println!("aller en ({}, {})", x, y), // ✅ les deux champs Message::Quit => println!("quitter"), } }
// chaque champ listé par son nom : ajouter un champ à `Move` cassera ce code, exprès if let Message::Move { x, y: _ } = &messages[0] { println!("premier x = {}", x); }}Sortie :
aller en (1, 2)glisser au sol jusqu'à x = 5quitterpremier x = 1Si vous nommez un champ juste pour l’ignorer, écrivez y: _, pas un simple y. Un y que vous n’utilisez jamais donne un avertissement « unused variable » (variable inutilisée).
Solution 3 : corriger un nom de champ mal écrit
Section intitulée « Solution 3 : corriger un nom de champ mal écrit »Choisissez-la quand E0027 arrive en même temps que E0026 sur la même ligne. Par exemple, Shape::Circle { r } pour une variante dont le champ s’appelle radius donne les deux : E0026 pour r (ce champ n’existe pas) et E0027 pour radius (pas mentionné). L’aide de rustc pour E0027 vous proposera d’ajouter radius à côté de r, mais ce n’est pas ce que vous voulez. La vraie correction est de remplacer le mauvais nom : Shape::Circle { radius }, ou Shape::Circle { radius: r } pour garder le nom de variable court. Les deux erreurs disparaissent alors d’un coup. Voir la page E0026 pour des exemples.
Où vous le verrez souvent
Section intitulée « Où vous le verrez souvent »Après avoir ajouté un champ à une struct. Vous ajoutez created_at à Order, et chaque motif qui listait tous les champs donne maintenant E0027. C’est la vérification qui fait son travail. Décidez au cas par cas : ce code a-t-il besoin de created_at ? Si oui, nommez-le ; sinon, ajoutez ...
Les paramètres de fonction. fn print_order(&Order { item, quantity }: &Order) donne aussi E0027. Correction : &Order { item, quantity, .. }. Voir Les motifs dans let et dans les paramètres de fonction.
Les structs tuples et les variantes tuples. Pour struct Color(u8, u8, u8);, le motif Color(r) est lui aussi incomplet, mais rustc le signale avec E0023, « this pattern has 1 field, but the corresponding tuple struct has 3 fields » (ce motif a 1 champ, mais la struct tuple correspondante en a 3). La correction suit la même idée : Color(r, ..) ou Color(r, _, _).
Erreurs liées
Section intitulée « Erreurs liées »- E0026 : struct or variant does not have a field named x : un nom de champ dans le motif qui n’existe pas. Souvent affichée avec E0027.
- E0063 : missing field in initializer : la même idée quand vous créez une struct : chaque champ a besoin d’une valeur (ou de
..Default::default()). - E0004 : non-exhaustive patterns : un
matchqui ne couvre pas chaque variante, alors que E0027 parle de chaque champ. E0023: this pattern has N fields, but the corresponding tuple struct has M fields: la version pour les structs tuples (voir plus haut).- Toutes les erreurs du compilateur : la liste complète des pages d’erreurs.
Petit quiz
Section intitulée « Petit quiz »Petit quiz
1. struct Point { x: i32, y: i32, z: i32 }. Quel motif compile et ne vous donne que x ?
2. Quelle est la différence entre Order { item, .. } et Order { item, id: _, quantity: _, paid: _ } ?
3. Vous obtenez E0026 pour r et E0027 pour radius sur la même ligne. Quelle est la meilleure correction ?
Score : 0 / 3
Pour aller plus loin
Section intitulée « Pour aller plus loin »- E0027 — Rust error codes index (en anglais) : l’explication officielle de cette erreur.
- Pattern Syntax — The Rust Book (en anglais) : déstructurer des structs et la partie « Ignoring Remaining Parts of a Value with
..». - Destructuring structs — Rust by Example (en anglais) : des motifs de structs exécutables avec
... - Patterns — The Rust Reference (en anglais) : les règles exactes des motifs de structs et du motif « reste »
...