Salta ai contenuti

Errore Rust E0530: match bindings cannot shadow tuple variants (nome già usato)

E0530 significa: un nome nel tuo pattern è già occupato. Hai scritto un nome semplice, come Circle, dove di solito Rust crea una nuova variabile. Ma in questo scope Circle significa già un’altra cosa: una variante tupla, una tuple struct o una static. Rust si rifiuta di nasconderla in silenzio dietro una nuova variabile, perché non sarebbe quasi mai quello che intendevi. Il caso classico è un ramo di match Circle => dopo use Shape::*;, e di solito la correzione sono due caratteri: Circle(..). (Questa pagina fa parte di Errori del compilatore Rust spiegati.)

error[E0530]: match bindings cannot shadow tuple variants
--> src/main.rs:10:9
|
6 | use Shape::*;
| -------- the tuple variant `Circle` is imported here
...
10 | Circle => "circle", // ❌ `Circle` holds a value
| ^^^^^^
| |
| cannot be named the same as a tuple variant
| help: try specify the pattern arguments: `Circle(..)`

Il compilatore dice: le variabili create da un match non possono oscurare (shadowing) una variante tupla. Questo è il programma che produce l’errore:

enum Shape {
Circle(f64),
Square(f64),
}
use Shape::*;
fn name(shape: &Shape) -> &'static str {
match shape {
Circle => "circle", // ❌ `Circle` holds a value
Square(_) => "square",
}
}
fn main() {
println!("{}", name(&Circle(1.0)));
}

Il ^^^ indica Circle alla riga 10, e il --- alla riga 6 mostra da dove viene quel nome: use Shape::*; ha portato in scope la variante Shape::Circle.

In un pattern, un nome semplice come x o other crea una nuova variabile che corrisponde a qualsiasi cosa. Quindi Circle => potrebbe significare due cose:

  • «confronta con la variante Circle», ma Circle contiene un f64, quindi un pattern corretto ha bisogno delle tonde: Circle(_) o Circle(..).
  • «accetta qualsiasi cosa e chiamala Circle», una nuova variabile che nasconderebbe la variante.

Rust non tira a indovinare. La prima riga ti dice con che tipo di nome sei andato in conflitto, e la prima parola ti dice dove:

  • match bindings cannot shadow ...: in un ramo di match
  • let bindings cannot shadow ...: in un let o un if let
  • function parameters cannot shadow ...: nella lista dei parametri di una funzione

e finisce con tuple variants, tuple structs o statics.

È come chiamare il tuo cane «Dottore». Ogni volta che qualcuno grida «Dottore!» in sala d’attesa, nessuno sa a chi si riferisce.

Senza questa regola, Circle => sarebbe una nuova variabile chiamata Circle. Corrisponderebbe a ogni valore, e ogni ramo successivo sarebbe codice morto. Il programma compilerebbe, e poi stamperebbe «circle» anche per i quadrati. È un bug fastidioso che si nasconde dietro codice dall’aria corretta.

Per questo Rust dà errore ogni volta che una nuova variabile prenderebbe il nome di una variante tupla, di una tuple struct o di una static. O dici che cosa intendi con le tonde, o scegli un altro nome. Le varianti unit come None e le costanti (const) sono diverse: sono pattern validi da soli, quindi Rust le legge come «confronta con questo valore». Vedi Pattern matching in Rust ed Enum in Rust.

Soluzione 1: aggiungi (..) o (_) per confrontare la variante

Sezione intitolata “Soluzione 1: aggiungi (..) o (_) per confrontare la variante”

Scegli questa quando il messaggio dice tuple variants o tuple structs, il caso più comune. Intendevi la variante, quindi dalle le sue tonde, come suggerisce l’help di rustc. Scrivere il percorso completo, Shape::Circle(_), è ancora più chiaro:

enum Shape {
Circle(f64),
Square(f64),
}
use Shape::*;
fn name(shape: &Shape) -> &'static str {
match shape {
Circle(..) => "cerchio", // ✅ la variante, con qualsiasi valore dentro
Square(_) => "quadrato",
}
}
fn area(shape: &Shape) -> f64 {
match shape {
Shape::Circle(r) => 3.14 * r * r, // ✅ percorso completo, e usiamo il valore
Shape::Square(side) => side * side,
}
}
fn main() {
let shapes = [Circle(1.0), Square(2.0)];
for shape in &shapes {
println!("{}: {:.2}", name(shape), area(shape));
}
}

Output:

cerchio: 3.14
quadrato: 4.00
▶ Provalo tu

.. significa «qualunque cosa ci sia dentro», e continua a funzionare se in futuro la variante riceve altri valori. Vedi Pattern matching in Rust.

Scegli questa quando volevi davvero una nuova variabile, e il suo nome coincide per caso con un tipo. Succede spesso con let e con i parametri di funzione, quando chiami una variabile come il suo tipo:

error[E0530]: let bindings cannot shadow tuple structs
--> src/main.rs:4:9
|
1 | struct Meters(f64);
| ------------------- the tuple struct `Meters` is defined here
...
4 | let Meters = 5.0; // ❌ `Meters` is a tuple struct
| ^^^^^^ cannot be named the same as a tuple struct

Il programma che lo produce:

struct Meters(f64);
fn main() {
let Meters = 5.0; // ❌ `Meters` is a tuple struct
println!("{}", Meters);
}

Lo stile dei nomi di Rust risolve il problema per te: tipi e varianti sono in CamelCase, le variabili in snake_case. Usa un nome minuscolo e il conflitto sparisce:

struct Meters(f64);
fn total(meters: &[Meters]) -> f64 {
meters.iter().map(|m| m.0).sum()
}
fn main() {
let meters = 5.0; // ✅ un nome di variabile minuscolo
println!("{} m", meters);
let Meters(height) = Meters(1.8); // ✅ oppure scomponi la tuple struct
println!("altezza: {} m", height);
println!("totale: {} m", total(&[Meters(2.0), Meters(3.5)]));
}

Output:

5 m
altezza: 1.8 m
totale: 5.5 m
▶ Provalo tu

Lo stesso vale per un parametro: fn show(Point: i32) dà function parameters cannot shadow tuple structs, e fn show(point: i32) lo risolve. Vedi Variabili in Rust.

Soluzione 3: usa una const (o una match guard) al posto di una static

Sezione intitolata “Soluzione 3: usa una const (o una match guard) al posto di una static”

Scegli questa quando il messaggio dice statics. Probabilmente volevi confrontare con un valore fisso. Una static non si può usare come pattern, una const sì:

error[E0530]: match bindings cannot shadow statics
--> src/main.rs:5:9
|
1 | static LIMIT: u32 = 100;
| ------------------------ the static `LIMIT` is defined here
...
5 | LIMIT => "full", // ❌ a static can't be a pattern
| ^^^^^ cannot be named the same as a static

Il programma che lo produce:

static LIMIT: u32 = 100;
fn status(users: u32) -> &'static str {
match users {
LIMIT => "full", // ❌ a static can't be a pattern
_ => "open",
}
}
fn main() {
println!("{}", status(100));
}

Cambia static in const. Se deve restare una static (per esempio perché altro codice ne prende l’indirizzo), lega il valore a un nome e confronta in una match guard:

const LIMIT: u32 = 100; // ✅ una const funziona come pattern
static MAX_USERS: u32 = 500; // una static resta una static
fn status(users: u32) -> &'static str {
match users {
LIMIT => "pieno",
_ => "aperto",
}
}
fn premium_status(users: u32) -> &'static str {
match users {
n if n >= MAX_USERS => "pieno", // ✅ confronta una static in una guard
_ => "aperto",
}
}
fn main() {
println!("{}", status(100));
println!("{}", status(42));
println!("{}", premium_status(500));
}

Output:

pieno
aperto
pieno
▶ Provalo tu

Per un semplice numero raramente ti serve una static. Di solito si sceglie const; vedi Variabili in Rust.

Ok => o Some => senza tonde. Ok, Err e Some sono varianti tupla del prelude, quindi match result { Ok => ... } dà E0530 con l’help try specify the pattern arguments: `Ok(..)` . Correzione: Ok(_) => oppure Ok(value) =>.

Dentro if let. if let Some(Some) = x cerca di chiamare Some il valore interno e dà let bindings cannot shadow tuple variants. Correzione: un nome minuscolo, if let Some(inner) = x.

Con il percorso completo è invece E0532. Shape::Circle => non può essere una nuova variabile (il nome di una variabile non contiene ::), quindi rustc segnala E0532, expected unit struct, unit variant or constant, found tuple variant. Stessa correzione: aggiungi (_) o (..).

Un let con il nome di una unit struct dà E0308. Con struct Guest;, la riga let Guest = "Ana"; non crea affatto una variabile: rustc legge Guest come la unit struct e segnala E0308 (tipi che non corrispondono), dicendo `Guest` is interpreted as a unit struct, not a new binding. Correzione: rinomina la variabile, let guest = "Ana";.

Verifica veloce

1. Dopo use Shape::*;, dove Circle(f64) è una variante, quale ramo di match compila?

2. rustc dice "let bindings cannot shadow tuple structs" per let Meters = 5.0;. Qual è la correzione più semplice?

3. static LIMIT: u32 = 100; non si può usare come pattern di un match. Che cosa invece sì?

Punteggio: 0 / 3