Errore Rust E0533: expected unit struct, unit variant or constant, found struct variant
E0533 significa: hai scritto da solo un nome come Shape::Circle, ma in quel punto quel nome ha bisogno di qualcosa in più. Quasi sempre è una variante di enum con campi nominati (Circle { radius: f64 }) scritta senza le sue { }, in un ramo di match o quando crei un valore. Più di rado è una funzione o un metodo scritto dove può stare solo un valore fisso. In entrambi i casi la correzione è veloce, una volta capito che cosa chiede rustc. (Questa pagina fa parte di Errori del compilatore Rust spiegati.)
Il messaggio di errore
Sezione intitolata “Il messaggio di errore”error[E0533]: expected unit struct, unit variant or constant, found struct variant `Shape::Circle` --> src/main.rs:8:9 |8 | Shape::Circle => "circle", // ❌ `Circle` has a field | ^^^^^^^^^^^^^ not a unit struct, unit variant or constant |help: the struct variant's field is being ignored |8 | Shape::Circle { radius: _ } => "circle", // ❌ `Circle` has a field | +++++++++++++Il compilatore dice: qui si aspettava una unit struct, una variante senza dati o una costante, e invece ha trovato una variante con campi. Questo è il programma che produce l’errore:
enum Shape { Circle { radius: f64 }, Square { side: f64 },}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle => "circle", // ❌ `Circle` has a field Shape::Square { .. } => "square", }}
fn main() { println!("{}", name(&Shape::Square { side: 2.0 }));}Cosa significa
Sezione intitolata “Cosa significa”Il ^^^ indica Shape::Circle, e la prima riga spiega che cosa era ammesso lì: un pattern fatto solo di un nome deve essere una di queste tre cose:
- una unit struct, come
struct Empty; - una variante unit, cioè senza dati, come
Shape::EmptyoNone - una costante, come
const MAX: u32 = 100;
Shape::Circle non è nessuna delle tre. È una variante struct: porta con sé un radius. Un Shape::Circle nudo corrisponderebbe a «un cerchio» senza dire niente del suo campo, e Rust vuole che la forma del pattern corrisponda alla forma della variante. La riga help: ti mostra la correzione: aggiungi le graffe.
Il secondo tipo di E0533 dice expected value, found struct variant (atteso un valore, trovata una variante struct). È la stessa confusione, ma quando crei un valore, di solito scritto con le tonde come Shape::Circle(2.0).
È come un modulo per spedire un pacco con una casella «Taglia: S, M o L», dove tu hai scritto «Su misura». «Su misura» è un’opzione vera, ma accanto ci vanno scritte le misure.
Perché Rust si comporta così
Sezione intitolata “Perché Rust si comporta così”Le varianti di un enum hanno tre forme, e ognuna si scrive a modo suo, sia quando la crei sia quando la confronti (vedi Enum in Rust):
| Variante | Crearla | Confrontarla |
|---|---|---|
Unit: Empty |
Shape::Empty |
Shape::Empty |
Tupla: Point(f64, f64) |
Shape::Point(1.0, 2.0) |
Shape::Point(x, y) o Shape::Point(..) |
Struct: Circle { radius: f64 } |
Shape::Circle { radius: 2.0 } |
Shape::Circle { radius } o Shape::Circle { .. } |
Tenere le forme rigide significa che un pattern somiglia sempre alla cosa che confronta, quindi leggendo un match sai esattamente quali dati ha ogni ramo. Significa anche che, quando una variante cambia forma, per esempio quando Empty riceve un campo, ogni punto che usa la vecchia forma viene segnalato invece di fare in silenzio la cosa sbagliata.
Come risolverlo
Sezione intitolata “Come risolverlo”Soluzione 1: aggiungi { .. } o i campi al pattern
Sezione intitolata “Soluzione 1: aggiungi { .. } o i campi al pattern”Scegli questa quando l’errore indica un ramo di match, if let o matches! e dice found struct variant. Scrivi { .. } se i campi non ti servono, oppure nominali se ti servono. Anche il suggerimento di rustc { radius: _ } funziona, e { .. } è il modo più breve per dire la stessa cosa.
enum Shape { Circle { radius: f64 }, Square { side: f64 }, Empty,}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle { .. } => "cerchio", // ✅ «un cerchio, qualunque sia il raggio» Shape::Square { .. } => "quadrato", Shape::Empty => "niente", // una variante unit: niente graffe }}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius } => 3.14 * radius * radius, // ✅ campi nominati perché ci servono 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!("cerchi: {}", circles);}Output:
cerchio: 3.14quadrato: 9.00niente: 0.00cerchi: 1{ .. } funziona con ogni variante struct, qualunque sia il numero di campi. Per le varianti tupla la stessa idea si scrive (..). Vedi Pattern matching in Rust.
Soluzione 2: crea il valore con graffe e nomi dei campi
Sezione intitolata “Soluzione 2: crea il valore con graffe e nomi dei campi”Scegli questa quando il messaggio dice expected value, found struct variant. Stai creando una variante struct come se fosse una variante tupla (o senza nessun campo):
error[E0533]: expected value, found struct variant `Shape::Circle` --> src/main.rs:8:17 |8 | let shape = Shape::Circle(2.0); // ❌ `Circle` has a named field | ^^^^^^^^^^^^^ not a value |help: you might have meant to create a new value of the struct |8 - let shape = Shape::Circle(2.0); // ❌ `Circle` has a named field8 + let shape = Shape::Circle { radius: /* value */ }; // ❌ `Circle` has a named field |Il programma che lo produce:
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Square { side: f64 },}
fn main() { let shape = Shape::Circle(2.0); // ❌ `Circle` has a named field println!("{:?}", shape);}Il /* value */ nel suggerimento è un segnaposto per il tuo valore. I campi di una variante struct si impostano per nome, dentro le graffe:
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Square { side: f64 },}
impl Shape { // un costruttore corto, se vuoi scrivere `Shape::circle(2.0)` fn circle(radius: f64) -> Shape { Shape::Circle { radius } }}
fn main() { let a = Shape::Circle { radius: 2.0 }; // ✅ graffe e nome del campo let b = Shape::Square { side: 1.5 }; let c = Shape::circle(0.5); println!("{:?}", a); println!("{:?}", b); println!("{:?}", c);}Output:
Circle { radius: 2.0 }Square { side: 1.5 }Circle { radius: 0.5 }Se preferisci scrivere Shape::Circle(2.0), cambia la definizione in una variante tupla: Circle(f64). È una buona scelta per un solo campo ovvio; i campi con nome sono più chiari quando sono parecchi.
Soluzione 3: usa una costante o una match guard al posto di una funzione
Sezione intitolata “Soluzione 3: usa una costante o una match guard al posto di una funzione”Scegli questa quando il messaggio dice found associated function. Compare anche con i metodi, come String::len. Un pattern deve essere un valore noto in fase di compilazione. Una chiamata di funzione non lo è, quindi il nome di una funzione non può fare da pattern:
error[E0533]: expected unit struct, unit variant or constant, found associated function `Limits::max_users` --> src/main.rs:12:9 |12 | Limits::max_users => "full", // ❌ a function can't be a pattern | ^^^^^^^^^^^^^^^^^ not a unit struct, unit variant or constantIl programma che lo produce:
struct Limits;
impl Limits { fn max_users() -> u32 { 100 }}
fn status(users: u32) -> &'static str { match users { 0 => "empty", Limits::max_users => "full", // ❌ a function can't be a pattern _ => "open", }}
fn main() { println!("{}", status(100));}Se il valore non cambia mai, rendilo una const. Le costanti possono fare da pattern. Se va calcolato, tieni la funzione e confronta in una match guard con if:
struct Limits;
impl Limits { const MAX_USERS: u32 = 100; // una costante si può usare come pattern
fn max_rooms(premium: bool) -> u32 { if premium { 20 } else { 5 } }}
fn status(users: u32) -> &'static str { match users { 0 => "vuoto", Limits::MAX_USERS => "pieno", // ✅ una costante _ => "aperto", }}
fn rooms_status(rooms: u32, premium: bool) -> &'static str { match rooms { n if n >= Limits::max_rooms(premium) => "niente più stanze", // ✅ chiamala in una guard _ => "puoi aggiungere una stanza", }}
fn main() { println!("{}", status(0)); println!("{}", status(100)); println!("{}", status(42)); println!("{}", rooms_status(5, false)); println!("{}", rooms_status(5, true));}Output:
vuotopienoapertoniente più stanzepuoi aggiungere una stanzaLe match guard sono spiegate in Pattern matching in Rust.
Dove lo incontri di solito
Sezione intitolata “Dove lo incontri di solito”Dopo che una variante unit riceve dei campi. Status::Done era una variante unit, e l’hai cambiata in Done { at: u64 }. Ogni ramo Status::Done => e ogni let s = Status::Done; ora danno E0533. Correzione: Status::Done { .. } => nei pattern, Status::Done { at: 0 } (con un valore vero) dove lo crei.
Se arrivi da un altro linguaggio. In Java o TypeScript potresti scrivere case Circle: per controllare solo il tipo di un valore. In Rust scrivi Shape::Circle { .. } =>, oppure matches!(shape, Shape::Circle { .. }) per ottenere al volo un bool.
La versione con le varianti tupla. Per una variante tupla come Circle(f64), un ramo Shape::Circle => nudo dà un codice diverso, E0532, con la stessa prima riga «expected unit struct, unit variant or constant, found tuple variant Shape::Circle». La correzione è Shape::Circle(_) oppure Shape::Circle(..). E le tonde su una variante struct in un pattern, come Shape::Circle(r) => per Circle { radius: f64 }, danno E0164, «expected tuple struct or tuple variant, found struct variant». Correzione: Shape::Circle { radius: r } =>.
Errori correlati
Sezione intitolata “Errori correlati”- E0559: variant has no field named x: le graffe sono giuste, ma un nome di campo al loro interno è sbagliato.
- E0026: struct or variant does not have a field named x: un nome di campo sbagliato dentro le graffe di un pattern.
- E0027: pattern does not mention field x: graffe in un pattern che lasciano fuori dei campi; aggiungi
... - E0004: non-exhaustive patterns: dopo aver sistemato i rami, il
matchdeve comunque coprire ogni variante. E0532: expected unit struct, unit variant or constant, found tuple variant: la versione con le varianti tupla (vedi sopra).- Tutti gli errori del compilatore spiegati
Verifica veloce
Sezione intitolata “Verifica veloce”Verifica veloce
1. Con enum Shape { Circle { radius: f64 } }, quale ramo di match compila?
2. let s = Shape::Circle(2.0); dà "expected value, found struct variant". Qual è la correzione?
3. Quale di questi si può usare da solo come pattern di un match?
Punteggio: 0 / 3
Per approfondire
Sezione intitolata “Per approfondire”- E0533 — Rust error codes index (in inglese): la spiegazione ufficiale di questo errore.
- Pattern Syntax — The Rust Book (in inglese): scomporre gli enum, ignorare valori con
..e le match guard. - Destructuring enums — Rust by Example (in inglese): varianti unit, tupla e struct confrontate fianco a fianco.
- E0532 — Rust error codes index (in inglese): la pagina ufficiale della versione di questo sbaglio con le varianti tupla.
- Patterns — The Rust Reference (in inglese): quali percorsi sono ammessi come pattern e le regole dei pattern su struct e tuple struct.