Errore Rust E0560: struct has no field named X (campo inesistente)
E0560 significa: stai creando una struct con Name { field: value }, e uno dei campi che hai scritto non esiste in quella struct. Di solito è un errore di battitura, un campo che è stato rinominato, oppure un campo che appartiene a un’altra struct. Spesso rustc ti dice il nome esatto che intendevi, quindi è uno degli errori più veloci da risolvere. (Questa pagina fa parte di Errori del compilatore Rust spiegati.)
Il messaggio di errore
Sezione intitolata “Il messaggio di errore”error[E0560]: struct `User` has no field named `nmae` --> src/main.rs:9:9 |9 | nmae: String::from("Ferris"), // ❌ typo: the field is `name` | ^^^^ unknown field |help: a field with a similar name exists |9 - nmae: String::from("Ferris"), // ❌ typo: the field is `name`9 + name: String::from("Ferris"), // ❌ typo: the field is `name` |Il compilatore ti dice: «la struct User non ha nessun campo chiamato nmae». Poi aggiunge che esiste un campo con un nome simile e ti mostra la riga corretta.
Ecco il programma che lo provoca:
struct User { name: String, email: String, active: bool,}
fn main() { let user = User { nmae: String::from("Ferris"), // ❌ typo: the field is `name` active: true, }; println!("{}", user.email);}(Il commento dice: errore di battitura, il campo si chiama name.)
Cosa significa
Sezione intitolata “Cosa significa”La prima riga nomina la struct (User) e il campo che hai scritto (nmae). I ^^^^ indicano quel campo dentro il blocco User { ... }. Rust lo ha confrontato con l’elenco dei campi di struct User e non ha trovato corrispondenze.
Sotto la freccia trovi uno di tre suggerimenti. Ognuno ti dice una cosa diversa:
help: a field with a similar name exists: un errore di battitura. rustc ti mostra la riga con il nome giusto.note: available fields are: `username`: nessun nome simile. Questi sono i campi che non hai ancora compilato.note: all struct fields are already assigned: hai già dato un valore a tutti i campi veri, e questo è in più.
Nota che rustc non si lamenta anche del fatto che manca name. Correggi l’errore di battitura e spariscono tutti e due i problemi insieme.
È come compilare un modulo di carta e scrivere il tuo numero di telefono in una casella chiamata «Fax». Il modulo non ha quella casella, quindi l’impiegato te lo restituisce.
Perché Rust si comporta così
Sezione intitolata “Perché Rust si comporta così”I campi di una struct sono fissati quando scrivi struct User { ... }. Ogni volta che crei un User, Rust controlla che tu abbia dato esattamente quei campi: nessuno mancante, nessuno in più, nessuno scritto male. Vedi Struct.
Questo intercetta bug veri. In JavaScript, { nmae: "Ferris" } crea in silenzio un oggetto con la chiave sbagliata, e user.name sarà undefined da qualche parte, molto più avanti. In Rust l’errore di battitura non supera il compilatore, quindi ogni User del tuo programma ha davvero un name.
Come risolverlo
Sezione intitolata “Come risolverlo”Soluzione 1: correggi il nome
Sezione intitolata “Soluzione 1: correggi il nome”Scegli questa strada quando vedi a field with a similar name exists. Usa il nome della riga help:. I nomi dei campi distinguono maiuscole e minuscole, e Rust usa lo snake_case, quindi userName e user_name sono nomi diversi.
Attenzione anche alla forma abbreviata (field init shorthand): User { nmae, email } vuol dire User { nmae: nmae, email: email }, quindi il nome della variabile deve coincidere con il nome del campo. Rinomina la variabile oppure scrivi il campo per esteso: User { name: nmae, email }.
struct User { name: String, email: String, active: bool,}
fn main() { let user = User { name: String::from("Ferris"), // ✅ il vero nome del campo active: true, }; println!("{} ({}) attivo: {}", user.name, user.email, user.active);
// forma abbreviata: i nomi delle variabili coincidono con quelli dei campi let name = String::from("Ada"); let other = User { name, email, active: false }; println!("{} ({}) attivo: {}", other.name, other.email, other.active);}Output:
Ferris ([email protected]) attivo: trueAda ([email protected]) attivo: falseSoluzione 2: usa il nuovo nome del campo, o aggiungi il campo
Sezione intitolata “Soluzione 2: usa il nuovo nome del campo, o aggiungi il campo”Scegli questa strada quando non c’è il suggerimento del «nome simile». Spesso è cambiata la struct: qualcuno ha rinominato name in username, oppure ha tolto un campo, ma questo codice usa ancora quello vecchio. rustc elenca quello che resta:
error[E0560]: struct `User` has no field named `name` --> src/main.rs:8:9 |8 | name: String::from("Ferris"), | ^^^^ `User` does not have this field | = note: available fields are: `username`Hai due scelte oneste. Se la struct è giusta, usa il nome attuale del campo. Se è giusto il tuo codice e la struct ha davvero bisogno del campo, aggiungilo alla definizione della struct. Qui Config ha dato all struct fields are already assigned per debug, e la soluzione è aggiungere debug alla struct:
struct User { username: String, // rinominato da `name`: usa il nuovo nome email: String,}
struct Config { port: u16, host: String, debug: bool, // aggiunto alla struct, perché il codice ne ha bisogno}
fn main() { let user = User { username: String::from("ferris"), }; println!("{} ({})", user.username, user.email);
let config = Config { port: 8080, host: String::from("localhost"), debug: true, }; println!("{}:{} debug={}", config.host, config.port, config.debug);}Output:
ferris ([email protected])localhost:8080 debug=trueSe la struct arriva da un crate che hai appena aggiornato, il campo potrebbe essere stato rinominato nella nuova versione. Controlla la struct su docs.rs (in inglese) per quella versione, oppure il changelog del crate. Quando aggiungi un campo a una tua struct, anche ogni punto che la crea deve compilarlo. rustc te li indicherà uno per uno con E0063 (vedi sotto).
Soluzione 3: usa la struct giusta
Sezione intitolata “Soluzione 3: usa la struct giusta”Scegli questa strada quando il campo che hai scritto esiste, ma in un’altra struct. Con due struct simili, come un Product con un title e un Customer con un name, è facile confonderle:
error[E0560]: struct `Product` has no field named `name` --> src/main.rs:13:9 |13 | name: String::from("Keyboard"), | ^^^^ `Product` does not have this field | = note: available fields are: `title`Guarda la nota available fields (campi disponibili). Se elenca campi che non ti aspettavi, stai costruendo la struct sbagliata. Usa il nome della struct giusta, oppure il nome del campo della struct che intendevi:
struct Product { title: String, price: u32, // in centesimi}
struct Customer { name: String, email: String,}
fn main() { let keyboard = Product { title: String::from("Tastiera"), // i prodotti hanno un `title` price: 4900, }; let buyer = Customer { name: String::from("Ana"), // i clienti hanno un `name` }; println!("{} compra: {}, per {} centesimi", buyer.name, keyboard.title, keyboard.price); println!("Ricevuta inviata a {}", buyer.email);}Output:
Ana compra: Tastiera, per 4900 centesimiRicevuta inviata a [email protected]Soluzione 4: usa le parentesi per una tuple struct
Sezione intitolata “Soluzione 4: usa le parentesi per una tuple struct”Scegli questa strada quando la struct è una tuple struct, come struct Point(i32, i32);. I suoi campi non hanno nomi, quindi Point { x: 1, y: 2 } dà E0560 sia per x sia per y, con help: `Point` is a tuple struct, use the appropriate syntax e il suggerimento Point(/* i32 */, /* i32 */). Creala con le parentesi, Point(1, 2), e leggila con .0 e .1. Se preferisci i nomi, cambia la definizione in struct Point { x: i32, y: i32 }. Vedi Tuple.
L’opposto: E0063, campo mancante
Sezione intitolata “L’opposto: E0063, campo mancante”Il gemello di E0560 è E0063: un campo che la struct ha, ma che non hai compilato. Rust non compila mai i campi al posto tuo, quindi ogni campo ha bisogno di un valore:
error[E0063]: missing field `active` in initializer of `User` --> src/main.rs:8:16 |8 | let user = User { | ^^^^ missing `active`Se mancano più campi, li elenca tutti: missing fields `active`, `email` and `login_count` in initializer of `User`. Soluzione: dai un valore a ogni campo. Se molti campi hanno valori predefiniti sensati, deriva Default e usa la sintassi di aggiornamento .. (struct update syntax) per compilare il resto:
#[derive(Debug, Default)]struct Settings { volume: u8, dark_mode: bool, language: String,}
fn main() { // tutti i campi scritti per esteso let full = Settings { volume: 80, dark_mode: false, language: String::from("it") };
// solo i campi che ti interessano, il resto da Default let quick = Settings { dark_mode: true, ..Default::default() };
// copia il resto da un altro valore let louder = Settings { volume: 100, ..full };
println!("{:?}", quick); println!("{:?}", louder);}Output:
Settings { volume: 0, dark_mode: true, language: "" }Settings { volume: 100, dark_mode: false, language: "it" }Il valore predefinito di un numero è 0, per bool è false, e per String è la stringa vuota. Se vuoi altri valori predefiniti, scrivi tu impl Default for Settings. Vedi Trait comuni.
Dove lo incontri di solito
Sezione intitolata “Dove lo incontri di solito”Dentro la sintassi di aggiornamento ... Anche Settings { dark: true, ..defaults } dà E0560. Qui la nota elenca tutti i campi (available fields are: `volume`, `dark_mode`, `language`), e potrebbe non esserci il suggerimento del «nome simile» quando i nomi sono troppo diversi. Soluzione: dark_mode: true.
Varianti di enum con campi nominati. Per enum Shape { Circle { radius: f64 } }, scrivere Shape::Circle { r: 2.0 } è lo stesso errore, ma rustc usa un codice diverso: E0559, variant `Shape::Circle` has no field named `r`, con la stessa nota available fields e gli stessi suggerimenti per gli errori di battitura. Soluzione: Shape::Circle { radius: 2.0 }. Vedi Enum.
Una struct di un altro modulo. Se il campo esiste ma non è pub, ottieni invece E0451, «field balance of struct Account is private». Soluzione: usa il costruttore del modulo, come Account::new(...). Vedi Moduli.
Errori correlati
Sezione intitolata “Errori correlati”- E0609: no field
xon typeT: lo stesso errore di battitura, ma quando leggi un campo (user.nmae) invece di creare la struct. - E0451: field is private in struct literal: il campo esiste, ma da qui non puoi impostarlo.
- E0308: mismatched types: il nome del campo è giusto, ma il valore ha il tipo sbagliato, come
"Ferris"per un campoString. E0063: missing field in initializer: un campo che hai dimenticato (vedi sopra).E0559: variant has no field named x: E0560 per le varianti di enum.- Tutti gli errori del compilatore spiegati
Verifica veloce
Sezione intitolata “Verifica veloce”Verifica veloce
1. rustc dice note: all struct fields are already assigned. Cosa significa?
2. Hai let nmae = ...; e scrivi User { nmae, email }. Come lo correggi?
3. Che errore ottieni quando ometti un campo, come User { name, email } senza active?
Punteggio: 0 / 3
Per approfondire
Sezione intitolata “Per approfondire”- E0560 — Rust error codes index (in inglese): la spiegazione ufficiale di questo errore.
- Defining and Instantiating Structs — The Rust Book (in inglese): letterali di struct, forma abbreviata dei campi, sintassi di aggiornamento e tuple struct.
- E0063 — Rust error codes index (in inglese): la pagina ufficiale del gemello «campo mancante» di questo errore.
- Struct expressions — The Rust Reference (in inglese): le regole esatte di
Name { field: value }, della forma abbreviata e di..base. Default— libreria standard di Rust (in inglese): come funzionano#[derive(Default)]e..Default::default().