Erreur Rust E0559 : variant has no field named X (champ de variante inconnu)
E0559 veut dire : vous créez une valeur d’enum avec Enum::Variant { field: value }, et l’un des champs que vous avez écrits n’existe pas dans cette variante. C’est la version enum de E0560, qui est la même erreur pour les structs. En général, c’est un nom de champ trop court ou mal écrit, un champ qui appartient à une autre variante, ou des accolades sur une variante qui attend des parenthèses. La correction tient presque toujours en un mot. (Cette page fait partie de Les erreurs du compilateur Rust expliquées.)
Le message d’erreur
Section intitulée « Le message d’erreur »error[E0559]: variant `Shape::Circle` has no field named `r` --> src/main.rs:8:33 |8 | let shape = Shape::Circle { r: 2.0 }; // ❌ le champ s'appelle `radius` | ^ `Shape::Circle` does not have this field | = note: available fields are: `radius`Le compilateur vous dit : « la variante Shape::Circle n’a pas de champ nommé r ». L’étiquette « does not have this field » veut dire « n’a pas ce champ », et la note « available fields are » donne la liste des champs disponibles.
Voici le programme qui la provoque :
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn main() { let shape = Shape::Circle { r: 2.0 }; // ❌ le champ s'appelle `radius` println!("{:?}", shape);}Ce que ça veut dire
Section intitulée « Ce que ça veut dire »Le titre nomme la variante (Shape::Circle) et le champ que vous avez écrit (r). Le ^ pointe ce champ entre les accolades. Rust a regardé la définition Circle { radius: f64 } et n’a trouvé aucun champ appelé r.
Chaque variante d’un enum a sa propre liste de champs. Shape::Circle a radius, Shape::Rectangle a width et height. Elles ne partagent pas leurs champs, même à l’intérieur du même enum.
Sous la flèche, rustc vous donne l’un de ces indices. Lisez-le en premier, il contient souvent la réponse :
note: available fields are: `radius`(champs disponibles :radius) : aucun nom proche. Ce sont les champs de cette variante que vous n’avez pas encore remplis.help: a field with a similar name exists(un champ au nom proche existe) : une faute de frappe, commekyepourkey. rustc montre la ligne corrigée.help: `Message::Write` is a tuple variant, use the appropriate syntax(Message::Writeest une variante tuple, utilisez la syntaxe adaptée) : les champs de la variante n’ont pas de nom, il faut donc( )et pas{ }.note: all struct fields are already assigned(tous les champs sont déjà remplis) : vous avez rempli tous les vrais champs, et celui-ci est en trop.
C’est comme commander une pizza en demandant une « pâte large » alors que le menu ne propose qu’une « taille de pâte ». En cuisine, on comprend très bien ce que vous voulez dire, mais le bon de commande n’a aucune case qui porte ce nom.
Pourquoi Rust fait ça
Section intitulée « Pourquoi Rust fait ça »Une variante d’enum avec des champs nommés, comme Circle { radius: f64 }, fonctionne comme une petite struct à l’intérieur de l’enum. Quand vous en créez une, Rust vérifie que vous avez donné exactement ses champs : aucun qui manque, aucun en trop, aucun mal écrit. Voir Les enums peuvent contenir des données.
C’est surtout important quand vous faites un match sur l’enum plus tard. La branche Shape::Circle { radius } => ... ne peut marcher que si chaque Circle a vraiment un radius. Si Rust laissait passer Shape::Circle { r: 2.0 }, cette garantie disparaîtrait. En attrapant la faute de frappe à la compilation, Rust s’assure que chaque Circle de votre programme est complet.
Comment corriger
Section intitulée « Comment corriger »Solution 1 : utiliser le vrai nom du champ
Section intitulée « Solution 1 : utiliser le vrai nom du champ »Choisissez-la quand rustc affiche available fields are ou a field with a similar name exists. Prenez le nom donné par l’indice. Les noms de champs sont sensibles à la casse et s’écrivent en snake_case : Radius et radius sont donc deux noms différents.
Une faute de frappe donne l’indice « similar name » :
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' }; |Ici, « unknown field » veut dire « champ inconnu », et la ligne + montre le code corrigé.
Un nom court comme r est trop différent de radius pour une suggestion, alors vous recevez la liste des champs à la place. Dans les deux cas, écrivez le champ que la variante définit :
#[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 }, // ✅ le vrai nom du champ 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);}Sortie :
Circle { radius: 2.0 }Rectangle { width: 3.0, height: 4.0 }[KeyPress { key: 'a' }, Click { x: 10, y: 20 }]Attention à la syntaxe abrégée d’initialisation (field init shorthand). Shape::Circle { r } veut dire Shape::Circle { r: r }, et donne donc la même erreur E0559. Si votre variable s’appelle r, écrivez le champ en entier : Shape::Circle { radius: r }. Ou renommez la variable en radius et écrivez Shape::Circle { radius }.
Solution 2 : utiliser des parenthèses pour une variante tuple
Section intitulée « Solution 2 : utiliser des parenthèses pour une variante tuple »Choisissez-la quand rustc dit is a tuple variant, use the appropriate syntax. Une variante comme Write(String) a bien un champ, mais ce champ n’a pas de nom. N’importe quel nom écrit entre accolades est donc faux :
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 */); |L’étiquette « field does not exist » veut dire « ce champ n’existe pas », et « defined here » montre où la variante est définie. Le /* String */ de la suggestion est un emplacement à remplir : mettez-y votre valeur. Créez une variante tuple avec des parenthèses, dans le même ordre que sa définition :
#[derive(Debug)]enum Message { Move { x: i32, y: i32 }, // champs nommés : on utilise { } Write(String), // champ sans nom : on utilise ( ) Color(u8, u8, u8),}
fn main() { let messages = vec![ Message::Move { x: 1, y: 2 }, Message::Write(String::from("salut")), // ✅ des parenthèses Message::Color(255, 128, 0), ]; for m in &messages { match m { Message::Move { x, y } => println!("déplacement vers ({}, {})", x, y), Message::Write(text) => println!("écrire : {}", text), Message::Color(r, g, b) => println!("couleur : {} {} {}", r, g, b), } }}Sortie :
déplacement vers (1, 2)écrire : salutcouleur : 255 128 0Si vous préférez donner un nom au champ, changez la définition en Write { text: String }. Ensuite, Message::Write { text: ... } fonctionne. La confusion inverse, des parenthèses sur une variante à champs nommés comme Shape::Circle(2.0), donne une autre erreur : E0533, « expected value, found struct variant » (valeur attendue, variante de type struct trouvée).
Solution 3 : choisir la bonne variante, ou modifier la variante
Section intitulée « Solution 3 : choisir la bonne variante, ou modifier la variante »Choisissez-la quand le champ que vous avez écrit existe, mais dans une autre variante. Ici, radius appartient à Circle, pas à 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`Demandez-vous laquelle vous vouliez. Pour un cercle, utilisez Shape::Circle { radius: 2.0 }. Pour un carré, utilisez son champ : Shape::Square { side: 2.0 }.
Si vous voyez note: all struct fields are already assigned, la variante est complète et votre champ est en trop. Supprimez-le ou, si votre code en a vraiment besoin, ajoutez-le à la définition de la variante :
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Square { side: f64 },}
#[derive(Debug)]enum Message { Move { x: i32, y: i32, z: i32 }, // `z` ajouté, parce que le code en a besoin}
fn main() { let a = Shape::Circle { radius: 2.0 }; // un cercle a un rayon let b = Shape::Square { side: 2.0 }; // un carré a un côté println!("{:?} et {:?}", a, b);
let m = Message::Move { x: 1, y: 2, z: 3 }; println!("{:?}", m);}Sortie :
Circle { radius: 2.0 } et Square { side: 2.0 }Move { x: 1, y: 2, z: 3 }Dès que vous ajoutez un champ à une variante, chaque endroit qui crée cette variante doit aussi le remplir. rustc vous montrera chacun d’eux avec E0063, « missing field » (champ manquant).
Où vous le verrez souvent
Section intitulée « Où vous le verrez souvent »Les méthodes constructeurs avec Self::. Dans impl Shape, écrire fn circle(r: f64) -> Shape { Self::Circle { r } } donne E0559 pour r, à cause de la syntaxe abrégée. Correction : Self::Circle { radius: r }. Voir Les enums peuvent aussi avoir des méthodes.
Après avoir renommé un champ. Vous avez renommé Circle { r } en Circle { radius } dans l’enum, et chaque ancien Shape::Circle { r: ... } donne maintenant E0559 avec available fields are: `radius`. Cherchez l’ancien nom dans tout le projet et mettez à jour chaque endroit.
Dans un pattern de match. Écrire le mauvais nom de champ dans un pattern, comme Shape::Circle { r } => ..., est la même erreur, mais rustc utilise d’autres codes : E0026, « variant Shape::Circle does not have a field named r » (la variante n’a pas de champ nommé r), avec help: `Shape::Circle` has a field named `radius`, plus E0027, « pattern does not mention field radius » (le pattern ne mentionne pas le champ radius). Correction : Shape::Circle { radius } => ..., ou Shape::Circle { radius: r } => ... pour garder le nom court. Voir Le pattern matching.
Erreurs liées
Section intitulée « Erreurs liées »- E0560 : struct has no field named x : la même erreur pour un littéral de struct, comme
User { nmae: ... }. - E0063 : missing field in initializer : l’inverse, un champ de la variante que vous n’avez pas rempli.
- E0599 : no method named x found : rustc utilise ce code quand c’est le nom de la variante qui est faux, comme
Shape::Circel { ... }. Il écrit alors « no variant namedCircelfound for enumShape» (aucune variante nomméeCirceldans l’enumShape). - E0609 : no field on type : un mauvais nom de champ quand vous lisez un champ.
E0026: variant does not have a field named x: la même erreur dans un pattern dematch(voir plus haut).E0533: expected value, found struct variant: des parenthèses sur une variante à champs nommés, commeShape::Circle(2.0).- Toutes les erreurs du compilateur expliquées
Petit quiz
Section intitulée « Petit quiz »Petit quiz
1. Pour enum Message { Write(String) }, que doit devenir Message::Write { text: s } ?
2. Vous avez let r = 2.0; et vous écrivez Shape::Circle { r }, mais le champ s'appelle radius. Comment corriger ?
3. Shape::Square { radius: 2.0 } donne E0559, et la note ne liste que side. Que se passe-t-il ?
Score : 0 / 3
Pour aller plus loin
Section intitulée « Pour aller plus loin »- E0559 — Rust error codes index (en anglais) : l’explication officielle de cette erreur.
- Defining an Enum — The Rust Book (en anglais) : les variantes à champs nommés, les variantes tuple et les variantes sans données, avec l’exemple
Message. - Enums — Rust by Example (en anglais) : des exemples exécutables pour chaque sorte de variante.
- Struct expressions — The Rust Reference (en anglais) : les règles exactes de
Enum::Variant { field: value }, y compris la syntaxe abrégée. - E0026 — Rust error codes index (en anglais) : la page officielle de la même erreur dans un pattern.