Erreur Rust E0533 : expected unit struct, unit variant or constant, found struct variant
E0533 veut dire que vous avez écrit un nom comme Shape::Circle tout seul, alors qu’à cet endroit ce nom a besoin de plus que son nom. Le plus souvent, c’est une variante d’enum à champs nommés (Circle { radius: f64 }) écrite sans ses { }, soit dans une branche de match, soit au moment de créer une valeur. Plus rarement, c’est une fonction ou une méthode écrite là où seule une valeur fixe est permise. Les deux se corrigent vite une fois que vous savez ce que rustc demande. Cette page fait partie du guide des erreurs du compilateur Rust.
Le message d’erreur
Section intitulée « Le message d’erreur »error[E0533]: expected unit struct, unit variant or constant, found struct variant `Shape::Circle` --> src/main.rs:8:9 |8 | Shape::Circle => "cercle", // ❌ `Circle` a un champ | ^^^^^^^^^^^^^ not a unit struct, unit variant or constant |help: the struct variant's field is being ignored |8 | Shape::Circle { radius: _ } => "cercle", // ❌ `Circle` a un champ | +++++++++++++Le compilateur vous dit : « attendu une struct unité, une variante unité ou une constante, trouvé la variante struct Shape::Circle ». L’aide propose d’ignorer le champ de la variante.
Voici le programme qui la provoque :
enum Shape { Circle { radius: f64 }, Square { side: f64 },}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle => "cercle", // ❌ `Circle` a un champ Shape::Square { .. } => "carré", }}
fn main() { println!("{}", name(&Shape::Square { side: 2.0 }));}Ce que ça veut dire
Section intitulée « Ce que ça veut dire »Le ^^^ pointe Shape::Circle, et le titre de l’erreur explique ce qui était permis à cet endroit : un motif (pattern) qui n’est qu’un nom doit être l’une de ces trois choses :
- une struct unité (unit struct), comme
struct Empty; - une variante unité (unit variant), une variante sans données, comme
Shape::EmptyouNone - une constante, comme
const MAX: u32 = 100;
Shape::Circle n’est rien de tout ça. C’est une variante struct (struct variant) : elle porte un radius. Un Shape::Circle tout seul voudrait dire « un cercle », sans rien dire de son champ, et Rust veut que la forme du motif corresponde à la forme de la variante. La ligne help: montre la correction : ajouter les accolades.
L’autre forme de E0533 dit expected value, found struct variant (valeur attendue, variante struct trouvée). C’est la même confusion, mais au moment de créer une valeur, en général écrite avec des parenthèses, comme Shape::Circle(2.0).
C’est comme un formulaire de colis avec une case « Taille : S, M ou L », où vous auriez écrit « Sur mesure ». « Sur mesure » est une vraie option, mais il faut remplir les dimensions juste à côté.
Pourquoi Rust fait ça
Section intitulée « Pourquoi Rust fait ça »Les variantes d’enum existent sous trois formes, et chacune s’écrit à sa façon, aussi bien pour la créer que pour la filtrer avec match (voir Les enums peuvent contenir des données) :
| Variante | La créer | La filtrer |
|---|---|---|
Unité : Empty |
Shape::Empty |
Shape::Empty |
Tuple : Point(f64, f64) |
Shape::Point(1.0, 2.0) |
Shape::Point(x, y) ou Shape::Point(..) |
Struct : Circle { radius: f64 } |
Shape::Circle { radius: 2.0 } |
Shape::Circle { radius } ou Shape::Circle { .. } |
Des formes strictes, cela veut dire qu’un motif ressemble toujours à ce qu’il filtre : vous lisez un match et vous savez exactement quelles données chaque branche reçoit. Cela veut aussi dire que, quand une variante change de forme, par exemple quand Empty reçoit un champ, chaque endroit qui utilise l’ancienne forme est signalé, au lieu de faire la mauvaise chose en silence.
Comment corriger
Section intitulée « Comment corriger »Solution 1 : ajouter { .. } ou les champs au motif
Section intitulée « Solution 1 : ajouter { .. } ou les champs au motif »Choisissez-la quand l’erreur pointe une branche de match, de if let ou de matches! et dit found struct variant. Écrivez { .. } si vous n’avez pas besoin des champs, ou nommez-les si vous en avez besoin. La suggestion de rustc, { radius: _ }, marche aussi, et { .. } est la façon plus courte de dire la même chose.
enum Shape { Circle { radius: f64 }, Square { side: f64 }, Empty,}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle { .. } => "cercle", // ✅ « un cercle, quel que soit son rayon » Shape::Square { .. } => "carré", Shape::Empty => "rien", // une variante unité : pas besoin d'accolades }}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius } => 3.14 * radius * radius, // ✅ champs nommés, car on en a besoin Shape::Square { side } => side * side, Shape::Empty => 0.0, }}
fn main() { let shapes = [Shape::Circle { radius: 1.0 }, Shape::Square { side: 3.0 }, Shape::Empty]; for shape in &shapes { println!("{} : {:.2}", name(shape), area(shape)); } let circles = shapes.iter().filter(|s| matches!(s, Shape::Circle { .. })).count(); println!("{} cercle(s)", circles);}Sortie :
cercle : 3.14carré : 9.00rien : 0.001 cercle(s){ .. } marche pour toutes les variantes struct, quel que soit leur nombre de champs. Pour les variantes tuples, la même idée s’écrit (..). Voir Ignorer des parties avec _ et ...
Solution 2 : créer la valeur avec des accolades et les noms des champs
Section intitulée « Solution 2 : créer la valeur avec des accolades et les noms des champs »Choisissez-la quand le message dit expected value, found struct variant. Vous créez une variante struct comme si c’était une variante tuple (ou sans aucun champ) :
error[E0533]: expected value, found struct variant `Shape::Circle` --> src/main.rs:8:17 |8 | let shape = Shape::Circle(2.0); // ❌ `Circle` a un champ nommé | ^^^^^^^^^^^^^ not a value |help: you might have meant to create a new value of the struct |8 - let shape = Shape::Circle(2.0); // ❌ `Circle` a un champ nommé8 + let shape = Shape::Circle { radius: /* value */ }; // ❌ `Circle` a un champ nommé |Ici, « not a value » veut dire « ce n’est pas une valeur », et l’aide suggère que vous vouliez peut-être créer une nouvelle valeur de la struct.
Le programme qui la provoque :
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Square { side: f64 },}
fn main() { let shape = Shape::Circle(2.0); // ❌ `Circle` a un champ nommé println!("{:?}", shape);}Le /* value */ de la suggestion est un emplacement à remplacer par votre valeur. Les champs d’une variante struct se donnent par leur nom, entre accolades :
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Square { side: f64 },}
impl Shape { // un constructeur court, si vous voulez écrire `Shape::circle(2.0)` fn circle(radius: f64) -> Shape { Shape::Circle { radius } }}
fn main() { let a = Shape::Circle { radius: 2.0 }; // ✅ des accolades et le nom du champ let b = Shape::Square { side: 1.5 }; let c = Shape::circle(0.5); println!("{:?}", a); println!("{:?}", b); println!("{:?}", c);}Sortie :
Circle { radius: 2.0 }Square { side: 1.5 }Circle { radius: 0.5 }Si vous préférez écrire Shape::Circle(2.0), changez la définition en variante tuple : Circle(f64). C’est un bon choix pour un seul champ évident ; les champs nommés sont plus clairs quand il y en a plusieurs.
Solution 3 : utiliser une constante ou une garde de match à la place d’une fonction
Section intitulée « Solution 3 : utiliser une constante ou une garde de match à la place d’une fonction »Choisissez-la quand le message dit found associated function (fonction associée trouvée). Elle apparaît aussi pour les méthodes, comme String::len. Un motif doit être une valeur connue à la compilation. Un appel de fonction ne l’est pas, donc le nom d’une fonction ne peut pas servir de motif :
error[E0533]: expected unit struct, unit variant or constant, found associated function `Limits::max_users` --> src/main.rs:12:9 |12 | Limits::max_users => "plein", // ❌ une fonction ne peut pas être un motif | ^^^^^^^^^^^^^^^^^ not a unit struct, unit variant or constantLe programme qui la provoque :
struct Limits;
impl Limits { fn max_users() -> u32 { 100 }}
fn status(users: u32) -> &'static str { match users { 0 => "vide", Limits::max_users => "plein", // ❌ une fonction ne peut pas être un motif _ => "ouvert", }}
fn main() { println!("{}", status(100));}Si la valeur ne change jamais, faites-en une const. Les constantes peuvent servir de motifs. Si elle doit être calculée, gardez la fonction et faites la comparaison dans une garde de match (match guard) avec if :
struct Limits;
impl Limits { const MAX_USERS: u32 = 100; // une constante peut servir de motif
fn max_rooms(premium: bool) -> u32 { if premium { 20 } else { 5 } }}
fn status(users: u32) -> &'static str { match users { 0 => "vide", Limits::MAX_USERS => "plein", // ✅ une constante _ => "ouvert", }}
fn rooms_status(rooms: u32, premium: bool) -> &'static str { match rooms { n if n >= Limits::max_rooms(premium) => "plus de salle disponible", // ✅ appelée dans une garde _ => "vous pouvez ajouter une salle", }}
fn main() { println!("{}", status(0)); println!("{}", status(100)); println!("{}", status(42)); println!("{}", rooms_status(5, false)); println!("{}", rooms_status(5, true));}Sortie :
videpleinouvertplus de salle disponiblevous pouvez ajouter une salleLes gardes de match sont expliquées dans Les gardes : ajouter un if.
Où vous le verrez souvent
Section intitulée « Où vous le verrez souvent »Après qu’une variante unité a reçu des champs. Status::Done était une variante unité, et vous l’avez changée en Done { at: u64 }. Chaque branche Status::Done => et chaque let s = Status::Done; donne maintenant E0533. Correction : Status::Done { .. } => dans les motifs, Status::Done { at: 0 } (avec une vraie valeur) là où vous la créez.
En venant d’un autre langage. En Java ou en TypeScript, vous écririez peut-être case Circle: pour ne vérifier que le genre d’une valeur. En Rust, écrivez Shape::Circle { .. } =>, ou matches!(shape, Shape::Circle { .. }) pour obtenir vite un bool.
La version pour les variantes tuples. Pour une variante tuple comme Circle(f64), une branche Shape::Circle => toute seule donne un autre code, E0532, avec le même titre « expected unit struct, unit variant or constant, found tuple variant Shape::Circle ». La correction est Shape::Circle(_) ou Shape::Circle(..). Et des parenthèses sur une variante struct dans un motif, comme Shape::Circle(r) => pour Circle { radius: f64 }, donnent E0164, « expected tuple struct or tuple variant, found struct variant » (struct tuple ou variante tuple attendue, variante struct trouvée). Correction : Shape::Circle { radius: r } =>.
Erreurs liées
Section intitulée « Erreurs liées »- E0559 : variant has no field named x : les accolades sont là, mais un nom de champ à l’intérieur est faux.
- E0026 : struct or variant does not have a field named x : un mauvais nom de champ entre les accolades d’un motif.
- E0027 : pattern does not mention field x : des accolades dans un motif qui oublient des champs ; ajoutez
... - E0004 : non-exhaustive patterns : une fois les branches corrigées, le
matchdoit encore couvrir chaque variante. E0532: expected unit struct, unit variant or constant, found tuple variant: la version pour les variantes 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. Avec enum Shape { Circle { radius: f64 } }, quelle branche de match compile ?
2. let s = Shape::Circle(2.0); donne « expected value, found struct variant ». Quelle est la correction ?
3. Lequel de ces éléments peut servir tout seul de motif dans un match ?
Score : 0 / 3
Pour aller plus loin
Section intitulée « Pour aller plus loin »- E0533 — Rust error codes index (en anglais) : l’explication officielle de cette erreur.
- Pattern Syntax — The Rust Book (en anglais) : déstructurer des enums, ignorer des valeurs avec
.., et les gardes de match. - Destructuring enums — Rust by Example (en anglais) : filtrer des variantes unité, tuple et struct côte à côte.
- E0532 — Rust error codes index (en anglais) : la page officielle de la version « variante tuple » de cette erreur.
- Patterns — The Rust Reference (en anglais) : quels chemins sont permis comme motifs, et les règles des motifs de structs et de structs tuples.