Salta ai contenuti

Errore Rust E0026: struct or variant does not have a field named X (campo inesistente nel pattern)

E0026 significa: stai scomponendo una struct o una variante di enum con un pattern, come Shape::Circle { r }, e uno dei nomi di campo che hai scritto non esiste. È la versione per i pattern di E0560 e E0559, che segnalano lo stesso sbaglio quando crei un valore. Di solito rustc ti dice il nome giusto in una riga help:, quindi spesso basta cambiare una sola parola. (Questa pagina fa parte di Errori del compilatore Rust spiegati.)

error[E0026]: variant `Shape::Circle` does not have a field named `r`
--> src/main.rs:8:25
|
8 | Shape::Circle { r } => 3.14 * r * r, // ❌ the field is called `radius`
| ^
| |
| variant `Shape::Circle` does not have this field
| help: `Shape::Circle` has a field named `radius`

Il compilatore dice: la variante Shape::Circle non ha un campo chiamato r, mentre ne ha uno chiamato radius. Questo è il programma che produce l’errore:

enum Shape {
Circle { radius: f64 },
Rectangle { width: f64, height: f64 },
}
fn area(shape: &Shape) -> f64 {
match shape {
Shape::Circle { r } => 3.14 * r * r, // ❌ the field is called `radius`
Shape::Rectangle { width, height } => width * height,
}
}
fn main() {
println!("{}", area(&Shape::Circle { radius: 1.0 }));
}

Per la stessa riga vedrai anche un secondo errore: E0027, «pattern does not mention field radius» (il pattern non nomina il campo radius). È lo stesso sbaglio visto dall’altra parte. Rust ha trovato un campo che hai nominato ma che non esiste (r) e un campo vero che non hai nominato (radius). Correggi il nome e spariscono tutti e due.

La prima riga nomina la struct o variante che stai confrontando (Shape::Circle) e il campo che hai scritto (r). Il ^ indica quel nome dentro le graffe del pattern.

In un pattern, i nomi dentro { } sono nomi di campo, non nomi di variabili nuove che scegli tu. Shape::Circle { r } è l’abbreviazione di Shape::Circle { r: r }: «prendi il campo chiamato r e mettilo in una variabile chiamata r». Circle non ha nessun campo r, quindi Rust si ferma.

Sotto la freccia, rustc ti dà uno di questi suggerimenti:

  • help: `Shape::Circle` has a field named `radius`: c’è esattamente un campo che non hai nominato, quindi rustc immagina che intendessi quello.
  • help: a field with a similar name exists: un errore di battitura, come nmae al posto di name. rustc ti mostra la riga corretta.
  • Nessun suggerimento: rustc non è riuscito a indovinare. Guarda la definizione della struct o dell’enum per trovare i nomi veri.

È come chiedere a un bibliotecario «il libro sullo scaffale Narrativa-più-o-meno». Lui capisce che vuoi uno scaffale, ma può andare solo a quelli che esistono davvero.

Un pattern come Shape::Circle { radius } è una promessa: «quando il valore è un Circle, dammi il suo radius». Rust controlla questa promessa sulla definizione mentre compila, così un pattern non può mai chiedere dati che non ci sono. Vedi Pattern matching in Rust.

Nei linguaggi senza questo controllo, leggere una chiave che manca ti dà undefined o null, e il bug salta fuori molto più tardi, lontano dall’errore di battitura. In Rust l’errore di battitura non supera il compilatore. Ti protegge anche quando qualcuno rinomina un campo: ogni pattern che usa ancora il vecchio nome si accende con E0026, così nessuno viene dimenticato in silenzio.

Scegli questa nella maggior parte dei casi. Usa il nome che trovi nella riga help:, oppure guarda la definizione. I nomi dei campi distinguono maiuscole e minuscole e si scrivono in snake_case.

Un errore di battitura riceve il suggerimento «similar name» (nome simile) e la riga corretta:

error[E0026]: struct `User` does not have a field named `nmae`
--> src/main.rs:8:16
|
8 | let User { nmae, age } = user; // ❌ typo: the field is `name`
| ^^^^ struct `User` does not have this field
|
help: a field with a similar name exists
|
8 - let User { nmae, age } = user; // ❌ typo: the field is `name`
8 + let User { name, age } = user; // ❌ typo: the field is `name`
|

Il programma che lo produce:

struct User {
name: String,
age: u32,
}
fn main() {
let user = User { name: String::from("Ferris"), age: 7 };
let User { nmae, age } = user; // ❌ typo: the field is `name`
println!("{} is {} years old", nmae, age);
}

Scrivi i nomi dei campi esattamente come nella definizione. Così l’abbreviazione funziona e ottieni variabili con gli stessi nomi:

struct User {
name: String,
age: u32,
}
enum Shape {
Circle { radius: f64 },
Rectangle { width: f64, height: f64 },
}
fn area(shape: &Shape) -> f64 {
match shape {
Shape::Circle { radius } => 3.14 * radius * radius, // ✅ il nome vero del campo
Shape::Rectangle { width, height } => width * height,
}
}
fn main() {
let shapes = [
Shape::Circle { radius: 2.0 },
Shape::Rectangle { width: 3.0, height: 4.0 },
];
for shape in &shapes {
println!("area: {:.2}", area(shape));
}
let user = User { name: String::from("Ferris"), age: 7 };
let User { name, age } = user; // ✅ `name`, non `nmae`
println!("{} ha {} anni", name, age);
}

Output:

area: 12.56
area: 12.00
Ferris ha 7 anni
▶ Provalo tu

Soluzione 2: tieni il tuo nome di variabile con campo: nome

Sezione intitolata “Soluzione 2: tieni il tuo nome di variabile con campo: nome”

Scegli questa quando il nome corto r ti piace e vuoi solo che la variabile si chiami così. Scrivi il nome vero del campo, i due punti e poi il nome della variabile: Shape::Circle { radius: r }. Leggilo come «prendi il campo radius e chiamalo r».

enum Shape {
Circle { radius: f64 },
Rectangle { width: f64, height: f64 },
}
fn area(shape: &Shape) -> f64 {
match shape {
Shape::Circle { radius: r } => 3.14 * r * r, // ✅ campo `radius`, variabile `r`
Shape::Rectangle { width: w, height: h } => w * h,
}
}
fn main() {
let small = Shape::Circle { radius: 1.0 };
let wide = Shape::Rectangle { width: 10.0, height: 2.5 };
println!("piccolo: {:.2}", area(&small));
println!("largo: {:.2}", area(&wide));
}

Output:

piccolo: 3.14
largo: 25.00
▶ Provalo tu

È comodo anche quando due campi andrebbero in conflitto con variabili che hai già, o quando il nome del campo è lungo.

Soluzione 3: controlla di confrontare la variante giusta

Sezione intitolata “Soluzione 3: controlla di confrontare la variante giusta”

Scegli questa quando il campo che hai scritto esiste davvero, ma in una variante diversa. Ogni variante di un enum ha i suoi campi. Qui x appartiene a Click, ma il ramo confronta KeyPress:

error[E0026]: variant `Event::KeyPress` does not have a field named `x`
--> src/main.rs:9:27
|
9 | Event::KeyPress { x, .. } => format!("key at {}", x), // ❌ `x` belongs to `Click`
| ^
| |
| variant `Event::KeyPress` does not have this field
| help: `Event::KeyPress` has a field named `key`

Il programma che lo produce:

enum Event {
Click { x: i32, y: i32 },
KeyPress { key: char },
}
fn describe(event: &Event) -> String {
match event {
Event::Click { x, y } => format!("click at ({}, {})", x, y),
Event::KeyPress { x, .. } => format!("key at {}", x), // ❌ `x` belongs to `Click`
}
}
fn main() {
println!("{}", describe(&Event::KeyPress { key: 'a' }));
}

Il suggerimento di rustc (key) significa solo «l’unico campo che non hai nominato», quindi non seguirlo alla cieca. Chiediti che cosa deve fare questo ramo. La pressione di un tasto non ha una posizione, quindi qui la correzione giusta è usare il campo che KeyPress ha davvero:

enum Event {
Click { x: i32, y: i32 },
KeyPress { key: char },
}
fn describe(event: &Event) -> String {
match event {
Event::Click { x, y } => format!("clic in ({}, {})", x, y),
Event::KeyPress { key } => format!("tasto '{}' premuto", key), // ✅ KeyPress ha `key`
}
}
fn main() {
let events = [Event::Click { x: 10, y: 20 }, Event::KeyPress { key: 'a' }];
for event in &events {
println!("{}", describe(event));
}
}

Output:

clic in (10, 20)
tasto 'a' premuto
▶ Provalo tu

Se la pressione di un tasto deve davvero avere una posizione, aggiungi invece i campi alla variante: KeyPress { key: char, x: i32, y: i32 }. Poi ogni punto che crea un KeyPress deve compilarli (rustc te li indica uno per uno con E0063).

Dopo aver rinominato un campo. Hai rinominato r in radius nell’enum, e ogni ramo Shape::Circle { r } => ... ora dà E0026. Cerca il vecchio nome nel progetto e aggiorna ogni pattern, oppure usa radius: r per tenere il vecchio nome di variabile.

In if let e let. if let Some(User { nmae, .. }) = find_user() dà lo stesso errore. Aggiungere .. qui non aiuta: .. salta i campi che non nomini, ma ogni nome che scrivi deve comunque esistere. Correzione: User { name, .. }.

Graffe su una variante tupla o una tuple struct. Per struct Point(i32, i32);, il pattern Point { x, y } non ha nomi di campo veri da confrontare. rustc lo segnala con un codice diverso, E0769, «tuple variant Point written as struct variant», e suggerisce Point(x, y). Vedi Pattern matching in Rust.

Verifica veloce

1. Con enum Shape { Circle { radius: f64 } }, che cosa chiede il pattern Shape::Circle { r }?

2. Vuoi il campo radius in una variabile chiamata r. Quale pattern funziona?

3. User { nmae, .. } compila se il campo si chiama name?

Punteggio: 0 / 3