Aller au contenu

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.

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 }));
}

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::Empty ou None
  • 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é.

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.

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.14
carré : 9.00
rien : 0.00
1 cercle(s)
▶ Essayez par vous-même

{ .. } 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 }
▶ Essayez par vous-même

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 constant

Le 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 :

vide
plein
ouvert
plus de salle disponible
vous pouvez ajouter une salle
▶ Essayez par vous-même

Les gardes de match sont expliquées dans Les gardes : ajouter un if.

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 } =>.

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