Salta ai contenuti

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

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`
email: String::from("[email protected]"),
active: true,
};
println!("{}", user.email);
}

(Il commento dice: errore di battitura, il campo si chiama name.)

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.

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.

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
email: String::from("[email protected]"),
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 email = String::from("[email protected]");
let other = User { name, email, active: false };
println!("{} ({}) attivo: {}", other.name, other.email, other.active);
}

Output:

Ferris ([email protected]) attivo: true
Ada ([email protected]) attivo: false
▶ Provalo tu

Soluzione 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"),
email: String::from("[email protected]"),
};
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:

localhost:8080 debug=true
▶ Provalo tu

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

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`
email: String::from("[email protected]"),
};
println!("{} compra: {}, per {} centesimi", buyer.name, keyboard.title, keyboard.price);
println!("Ricevuta inviata a {}", buyer.email);
}

Output:

Ana compra: Tastiera, per 4900 centesimi
Ricevuta inviata a [email protected]
▶ Provalo tu

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.

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

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.

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.

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