Salta ai contenuti

Errori del compilatore Rust spiegati

Il compilatore Rust ti ha mostrato un errore rosso e non sai bene che cosa vuole? Sei nel posto giusto. Ogni sviluppatore Rust vede questi errori, spesso molte volte al giorno. La buona notizia: quelli che incontrerai di continuo sono solo una manciata, e una volta che li conosci smettono di fare paura.

Ogni pagina qui sotto prende un codice di errore, mostra il messaggio reale, lo spiega in parole semplici e ti dà soluzioni che puoi eseguire nel browser. Il compilatore scrive i messaggi in inglese, quindi nella tabella li trovi così come appaiono nel terminale.

Errore Che cosa dice il compilatore In parole semplici
E0382 borrow of moved value Hai ceduto un valore e poi hai provato a usarlo di nuovo
E0502 cannot borrow as mutable because it is also borrowed as immutable Stai modificando qualcosa mentre qualcuno lo sta ancora leggendo
E0499 cannot borrow as mutable more than once at a time Due punti del codice vogliono modificare la stessa cosa nello stesso momento
E0308 mismatched types Hai dato un tipo dove ne era atteso un altro
E0277 the trait bound is not satisfied Un tipo non sa fare una cosa che gli hai chiesto (stampare, confrontare, sommare…)
E0106 missing lifetime specifier Rust non riesce a capire per quanto tempo resta valido un riferimento restituito
E0425 cannot find value in this scope Un nome è scritto male, o è usato fuori dal blocco in cui vive
E0599 no method named … found Il metodo non esiste su quel tipo, oppure il suo trait non è importato
E0384 cannot assign twice to immutable variable Hai cambiato una variabile che non era dichiarata mut
E0596 cannot borrow as mutable, as it is not declared as mutable Hai provato a modificare qualcosa tramite una variabile o un riferimento che non è mut
E0597 borrowed value does not live long enough Un riferimento è ancora in uso dopo che il valore a cui punta è sparito
E0515 cannot return reference to local variable Hai restituito un riferimento a qualcosa che viene distrutto alla fine della funzione
E0373 closure may outlive the current function, but it borrows … Una closure (spesso un thread) prende in prestito una variabile locale che potrebbe sparire prima che la closure giri
E0369 binary operation == cannot be applied to type … Il tuo tipo non supporta (ancora) ==, <, + e simili
E0432 unresolved import Una riga use punta a un crate, un modulo o un elemento che non si trova
E0433 cannot find type … in this scope (older: failed to resolve) Un percorso come HashMap::new() usa un nome non importato o inesistente
E0424 self value is a keyword only available in methods with a self parameter Hai usato self in una funzione che non riceve self
E0061 this function takes N arguments but M arguments were supplied Hai passato troppi o troppo pochi argomenti (Rust non ha argomenti opzionali)
E0594 cannot assign to p.hp, as p is not declared as mutable Hai cambiato un campo o un valore dietro un & senza accesso mut
E0004 non-exhaustive patterns: X not covered Il tuo match non gestisce tutti i valori possibili
E0507 cannot move out of x which is behind a shared reference Hai provato a prendere l’ownership di qualcosa che hai solo in prestito
E0603 function x is private Hai usato una funzione, una struct o un modulo che non è pub
E0716 temporary value dropped while borrowed Hai tenuto un riferimento a un valore che viene buttato via alla fine della riga
E0463 can’t find crate for x Un crate (o la libreria standard per un target) non è installato
E0368 binary assignment operation += cannot be applied to type … Il tuo tipo non supporta +=, -= e simili
E0057 this function takes N arguments but M were supplied (note: closure defined here) Hai chiamato una closure con troppi o troppo pochi argomenti
E0282 type annotations needed Rust non riesce a dedurre un tipo da solo, quindi devi scriverlo tu
E0609 no field x on type T Il nome del campo è sbagliato, oppure il valore è avvolto in qualcos’altro (per esempio in un Option)
E0593 closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments Una closure riceve argomenti separati dove è attesa una tupla (o un numero diverso di argomenti)
E0631 type mismatch in closure arguments Il tipo di un parametro della closure non corrisponde a quello che riceve (spesso i32 invece di &i32)
E0005 refutable pattern in local binding let Some(x) = … può fallire, quindi un semplice let non lo accetta
E0615 attempted to take value of method len on type String Hai scritto s.len invece di s.len()
E0610 {integer} is a primitive type and therefore doesn’t have fields Hai usato .campo su un numero, un bool o un char
E0560 struct User has no field named nmae Un letterale di struct usa un campo che la struct non ha
E0616 field balance of struct Account is private Hai letto un campo non pub da fuori del suo modulo
E0451 field x of struct Y is private Hai creato una struct con un letterale mentre alcuni suoi campi sono privati
E0624 method x is private Hai chiamato un metodo o una funzione associata che non è pub
E0283 type annotations needed (cannot infer type … multiple impls satisfy this bound) Più tipi potrebbero andare bene (per esempio con .collect() o .sum()), quindi devi sceglierne uno
E0284 type annotations needed: cannot satisfy <_ as FromStr>::Err == _ "42".parse() non sa in quale tipo convertire
E0790 cannot call associated function on trait without specifying the corresponding impl type Hai scritto Default::default() o Trait::new() senza dire quale tipo
E0559 variant Shape::Circle has no field named r Il letterale di una variante di enum usa un campo che la variante non ha
E0063 missing field email in initializer of User Hai creato una struct dimenticando uno o più campi
E0689 can’t call method pow on ambiguous numeric type {integer} 2.pow(10) o 2.0.sqrt() hanno bisogno di un tipo numerico preciso, come i32 o f64
E0034 multiple applicable items in scope Due trait danno al tuo tipo un metodo con lo stesso nome, quindi Rust non sa quale scegliere
E0412 cannot find type X in this scope (Rust 1.93+ prints E0425) Il nome di un tipo è scritto male, non è importato o non è dichiarato
E0428 the name area is defined multiple times Due elementi hanno lo stesso nome; Rust non ha l’overloading delle funzioni
E0026 variant Shape::Circle does not have a field named r Un pattern nomina un campo che la struct o la variante non ha
E0027 pattern does not mention fields id, paid Un pattern di struct tralascia dei campi; aggiungili o termina con ..
E0533 expected unit struct, unit variant or constant, found struct variant Shape::Circle Una variante con campi (o una funzione) è usata dove serve un nome semplice; aggiungi { .. }
E0592 duplicate definitions with name reset Due blocchi impl definiscono un metodo con lo stesso nome
E0255 the name Error is defined multiple times Un use importa un nome uguale a quello di un tuo tipo o di una tua funzione
E0252 the name Result is defined multiple times Due righe use importano lo stesso nome; rinominane una con as
E0411 cannot find type Self in this scope Hai usato Self fuori da un impl o da un trait
E0405 cannot find trait Display in this scope Il nome di un trait è scritto male o non è importato (per esempio use std::fmt::Display;)
E0532 expected unit struct, unit variant or constant, found tuple variant Shape::Circle Un pattern nomina una variante tupla (o una struct) senza le sue ( ), o aggiunge ( ) dove non servono
E0164 expected tuple struct or tuple variant, found struct variant Shape::Circle Un pattern usa ( ) su una variante con campi o su un elemento associato; usa { } o una guardia
E0404 expected trait, found derive macro Debug Hai scritto impl X for o T: X dove X è una struct, un alias o una derive macro non importata
E0401 can’t use generic parameters from outer item Una fn interna usa il T o il Self della funzione esterna; dalle generici suoi o usa una closure
E0107 enum takes 2 generic arguments but 1 generic argument was supplied Result<u32>, HashMap<String> e simili: troppi o troppo pochi argomenti tra < >
E0530 match bindings cannot shadow tuple variants Il nome nudo di una variante come Circle => (dopo use Shape::*) non può diventare una nuova variabile
E0434 can’t capture dynamic environment in a fn item Una fn interna non vede le variabili locali esterne; usa una closure o passagliele
E0601 main function not found in crate main L’eseguibile non ha una fn main() (manca, è scritta male, sta dentro un mod, o in realtà è una libreria)
E0658 use of unstable library feature iter_intersperse Hai usato un’API solo nightly su Rust stabile; usa l’alternativa stabile o aggiorna
E0614 type u32 cannot be dereferenced Hai scritto *x dove x è già un valore semplice, non un riferimento
E0435 attempt to use a non-constant value in a constant Una const, la lunghezza di un array o una static usa una variabile let; rendila una const o usa un Vec
E0554 #![feature] may not be used on the stable release channel Hai copiato codice solo nightly; togli l’attributo e usa l’API stabile, oppure usa nightly di proposito

I messaggi di errore di Rust sono famosi per essere utili, ma contengono parecchie informazioni. Eccone uno reale:

fn main() {
let name = String::from("Ferris");
let greeting = name;
println!("{name}");
}
error[E0382]: borrow of moved value: `name`
--> src/main.rs:4:16
|
2 | let name = String::from("Ferris");
| ---- move occurs because `name` has type `String`, which does not implement the `Copy` trait
3 | let greeting = name;
| ---- value moved here
4 | println!("{name}");
| ^^^^ value borrowed here after move
|
help: consider cloning the value if the performance cost is acceptable
|
3 | let greeting = name.clone();
| ++++++++

Leggilo in questo ordine:

  1. La prima riga è il riassunto: il codice di errore (E0382) e una descrizione di una riga. Qui: «prestito di un valore spostato».
  2. La riga con la freccia (--> src/main.rs:4:16) ti dice il file, la riga e la colonna dove le cose sono andate storte.
  3. I segni ^^^^ indicano il punto esatto dell’errore. I segni ---- raccontano la storia che ha portato fin lì. Qui dicono: il valore è stato creato alla riga 2, spostato alla riga 3 e poi usato alla riga 4.
  4. help: è la soluzione suggerita dal compilatore, spesso con il codice esatto da aggiungere (i segni ++++ mostrano i caratteri nuovi). Non è sempre la soluzione migliore, ma è un ottimo punto di partenza.

Comincia a leggere dal primo errore. Un solo sbaglio può provocare una catena di errori successivi, e correggere il primo spesso fa sparire anche gli altri.

  • Chiedi di più al compilatore. Ogni codice di errore ha una spiegazione più lunga già integrata. Esegui questo in un terminale:

    Terminal window
    rustc --explain E0382

    Otterrai una breve descrizione (in inglese), un esempio sbagliato e uno corretto.

  • Controlla spesso. cargo check trova gli errori senza compilare l’intero programma, quindi è molto più veloce di cargo build. Se lo esegui ogni poche righe, incontri un errore alla volta, non venti. Vedi Cargo e crate.

  • Fai mostrare gli errori all’editor mentre scrivi. Con l’estensione rust-analyzer gli errori compaiono direttamente nel codice, con lo stesso testo di aiuto. Vedi Strumenti e configurazione.

La maggior parte di questi errori esiste perché Rust controlla, prima che il programma parta, cose che altri linguaggi scoprono solo durante l’esecuzione (o mai): usare memoria già liberata, due thread che modificano gli stessi dati, un controllo sul null dimenticato. Ogni errore che correggi è un bug che non arriverà mai ai tuoi utenti.

Per questo molti dicono: in Rust la battaglia si combatte durante la compilazione, e poi il programma semplicemente funziona. Le regole dietro gli errori più comuni sono spiegate in Ownership, Prestito (borrowing) e Lifetime.

Verifica veloce

1. Un errore di Rust mostra diversi problemi. Quale dovresti correggere per primo?

2. Che cosa fa rustc --explain E0382?

3. In un messaggio di errore, che cosa indicano i segni ^^^^?

Punteggio: 0 / 3