Salta ai contenuti

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.)

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.)

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, come kye per key. 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.

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.

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 }]
▶ Provalo tu

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: ciao
colore: 255 128 0
▶ Provalo tu

Se 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 }
▶ Provalo tu

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».

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.

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