Errore Rust E0559: variant has no field named X (campo della variante)
E0559 significa: stai creando un valore di un enum con Enum::Variant { field: value }, e uno dei campi che hai scritto non esiste in quella variante. È la versione per gli enum di E0560, che è lo stesso errore per le struct. Di solito è un nome di campo abbreviato o scritto male, un campo che appartiene a un’altra variante, oppure le graffe su una variante che vuole le parentesi tonde. La soluzione è quasi sempre una parola sola. (Questa pagina fa parte di Errori del compilatore Rust spiegati.)
Il messaggio di errore
Sezione intitolata “Il messaggio di errore”error[E0559]: variant `Shape::Circle` has no field named `r` --> src/main.rs:8:33 |8 | let shape = Shape::Circle { r: 2.0 }; // ❌ the field is called `radius` | ^ `Shape::Circle` does not have this field | = note: available fields are: `radius`Il compilatore ti dice: «la variante Shape::Circle non ha nessun campo chiamato r», e ti ricorda che i campi disponibili sono: radius.
Ecco il programma che lo provoca:
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn main() { let shape = Shape::Circle { r: 2.0 }; // ❌ the field is called `radius` println!("{:?}", shape);}(Il commento dice: il campo si chiama radius.)
Cosa significa
Sezione intitolata “Cosa significa”La prima riga nomina la variante (Shape::Circle) e il campo che hai scritto (r). Il ^ indica quel campo dentro le graffe. Rust ha guardato la definizione Circle { radius: f64 } e non ha trovato nessun campo chiamato r.
Ogni variante di un enum ha il suo elenco di campi. Shape::Circle ha radius, Shape::Rectangle ha width e height. Non condividono i campi, nemmeno dentro lo stesso enum.
Sotto la freccia, rustc ti dà uno di questi suggerimenti. Leggilo per primo, di solito contiene la risposta:
note: available fields are: `radius`: nessun nome simile. Questi sono i campi di questa variante che non hai ancora compilato.help: a field with a similar name exists: un errore di battitura, comekyeperkey. rustc ti mostra la riga corretta.help: `Message::Write` is a tuple variant, use the appropriate syntax: i campi della variante non hanno nomi, quindi vuole( ), non{ }.note: all struct fields are already assigned: hai già compilato tutti i campi veri, e questo è in più.
È come ordinare una pizza chiedendo «crosta grande» quando nel menù c’è solo «dimensione della crosta». In cucina capiscono benissimo cosa vuoi, ma il modulo d’ordine non ha una casella con quel nome.
Perché Rust si comporta così
Sezione intitolata “Perché Rust si comporta così”Una variante di enum con campi nominati, come Circle { radius: f64 }, funziona come una piccola struct dentro l’enum. Quando ne crei una, Rust controlla che tu abbia dato esattamente i suoi campi: nessuno mancante, nessuno in più, nessuno scritto male. Vedi Enum.
Questo conta soprattutto quando più avanti fai match sull’enum. Il ramo Shape::Circle { radius } => ... può funzionare solo se ogni Circle ha davvero un radius. Se Rust lasciasse passare Shape::Circle { r: 2.0 }, quella garanzia sparirebbe. Intercettare l’errore di battitura in fase di compilazione fa sì che ogni Circle del tuo programma sia completo.
Come risolverlo
Sezione intitolata “Come risolverlo”Soluzione 1: usa il vero nome del campo della variante
Sezione intitolata “Soluzione 1: usa il vero nome del campo della variante”Scegli questa strada quando rustc mostra available fields are o a field with a similar name exists. Usa il nome del suggerimento. I nomi dei campi distinguono maiuscole e minuscole e si scrivono in snake_case, quindi Radius e radius sono diversi.
Un errore di battitura riceve il suggerimento del «nome simile»:
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' }; |Un nome corto come r è troppo diverso da radius per un suggerimento, quindi ottieni invece l’elenco dei campi. In entrambi i casi, scrivi il campo che la variante definisce:
#[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 }, // ✅ il vero nome del campo 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);}Output:
Circle { radius: 2.0 }Rectangle { width: 3.0, height: 4.0 }[KeyPress { key: 'a' }, Click { x: 10, y: 20 }]Attenzione alla forma abbreviata (field init shorthand). Shape::Circle { r } vuol dire Shape::Circle { r: r }, quindi dà lo stesso E0559. Se la tua variabile si chiama r, scrivi il campo per esteso: Shape::Circle { radius: r }. Oppure rinomina la variabile in radius e scrivi Shape::Circle { radius }.
Soluzione 2: usa le parentesi tonde per una variante tupla
Sezione intitolata “Soluzione 2: usa le parentesi tonde per una variante tupla”Scegli questa strada quando rustc dice is a tuple variant, use the appropriate syntax. Una variante come Write(String) ha un campo, ma il campo non ha un nome. Quindi qualsiasi nome tu scriva tra le graffe è sbagliato:
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 */); |Il /* String */ nel suggerimento è un segnaposto: mettici il tuo valore. Crea una variante tupla con le parentesi tonde, nello stesso ordine della sua definizione:
#[derive(Debug)]enum Message { Move { x: i32, y: i32 }, // campi con nome: usa { } Write(String), // campo senza nome: usa ( ) Color(u8, u8, u8),}
fn main() { let messages = vec![ Message::Move { x: 1, y: 2 }, Message::Write(String::from("ciao")), // ✅ parentesi tonde Message::Color(255, 128, 0), ]; for m in &messages { match m { Message::Move { x, y } => println!("sposta in ({}, {})", x, y), Message::Write(text) => println!("scrivi: {}", text), Message::Color(r, g, b) => println!("colore: {} {} {}", r, g, b), } }}Output:
sposta in (1, 2)scrivi: ciaocolore: 255 128 0Se preferisci dare un nome al campo, cambia la definizione in Write { text: String }. Allora Message::Write { text: ... } funziona. La confusione opposta, le parentesi tonde su una variante con campi nominati come Shape::Circle(2.0), dà un errore diverso: E0533, «expected value, found struct variant».
Soluzione 3: scegli la variante giusta, o cambia la variante
Sezione intitolata “Soluzione 3: scegli la variante giusta, o cambia la variante”Scegli questa strada quando il campo che hai scritto esiste, ma in un’altra variante. Qui radius appartiene a Circle, non a 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`Chiediti quale intendevi. Se volevi un cerchio, usa Shape::Circle { radius: 2.0 }. Se volevi un quadrato, usa il suo campo: Shape::Square { side: 2.0 }.
Se vedi note: all struct fields are already assigned, la variante è completa e il tuo campo è in più. Toglilo, oppure, se il tuo codice ne ha davvero bisogno, aggiungilo alla definizione della variante:
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Square { side: f64 },}
#[derive(Debug)]enum Message { Move { x: i32, y: i32, z: i32 }, // `z` aggiunto, perché il codice ne ha bisogno}
fn main() { let a = Shape::Circle { radius: 2.0 }; // un cerchio ha un raggio let b = Shape::Square { side: 2.0 }; // un quadrato ha un lato println!("{:?} e {:?}", a, b);
let m = Message::Move { x: 1, y: 2, z: 3 }; println!("{:?}", m);}Output:
Circle { radius: 2.0 } e Square { side: 2.0 }Move { x: 1, y: 2, z: 3 }Quando aggiungi un campo a una variante, anche ogni punto che crea quella variante deve compilarlo. rustc te li indica uno per uno con E0063, «missing field».
Dove lo incontri di solito
Sezione intitolata “Dove lo incontri di solito”Metodi costruttori con Self::. Dentro impl Shape, scrivere fn circle(r: f64) -> Shape { Self::Circle { r } } dà E0559 per r, per colpa della forma abbreviata. Soluzione: Self::Circle { radius: r }. Vedi Enum.
Dopo aver rinominato un campo. Hai rinominato Circle { r } in Circle { radius } nell’enum, e ora ogni vecchio Shape::Circle { r: ... } dà E0559 con available fields are: `radius`. Cerca il vecchio nome nel progetto e aggiornalo ovunque.
In un pattern di match. Scrivere il nome di campo sbagliato in un pattern, come Shape::Circle { r } => ..., è lo stesso errore, ma rustc usa altri codici: E0026, «variant Shape::Circle does not have a field named r», con help: `Shape::Circle` has a field named `radius`, più E0027 «pattern does not mention field radius». Soluzione: Shape::Circle { radius } => ..., oppure Shape::Circle { radius: r } => ... per tenere il nome corto. Vedi Pattern matching.
Errori correlati
Sezione intitolata “Errori correlati”- E0560: struct has no field named x: lo stesso errore per un letterale di struct, come
User { nmae: ... }. - E0063: missing field in initializer: l’opposto, un campo che la variante ha e che non hai compilato.
- E0599: no method named x found: rustc usa questo codice quando è sbagliato il nome della variante, come
Shape::Circel { ... }. rustc dice «no variant namedCircelfound for enumShape». - E0609: no field on type: un nome di campo sbagliato quando leggi un campo.
E0026: variant does not have a field named x: lo stesso errore dentro un pattern dimatch(vedi sopra).E0533: expected value, found struct variant: parentesi tonde su una variante con campi nominati, comeShape::Circle(2.0).- Tutti gli errori del compilatore spiegati
Verifica veloce
Sezione intitolata “Verifica veloce”Verifica veloce
1. Per enum Message { Write(String) }, cosa deve diventare Message::Write { text: s }?
2. Hai let r = 2.0; e scrivi Shape::Circle { r }, ma il campo è radius. Qual è la soluzione?
3. Shape::Square { radius: 2.0 } dà E0559, e la nota elenca solo side. Cosa sta succedendo?
Punteggio: 0 / 3
Per approfondire
Sezione intitolata “Per approfondire”- E0559 — Rust error codes index (in inglese): la spiegazione ufficiale di questo errore.
- Defining an Enum — The Rust Book (in inglese): varianti con campi nominati, varianti tupla e varianti unit, con l’esempio di
Message. - Enums — Rust by Example (in inglese): esempi eseguibili di ogni tipo di variante.
- Struct expressions — The Rust Reference (in inglese): le regole esatte di
Enum::Variant { field: value }, compresa la forma abbreviata. - E0026 — Rust error codes index (in inglese): la pagina ufficiale dello stesso errore dentro un pattern.