Errore Rust E0433: failed to resolve, use of undeclared type (tipo non dichiarato)
E0433 significa che hai scritto un percorso come HashMap::new() o rand::rng(), e Rust non sa cosa sia la prima parte. Quasi sempre manca una riga: un use, una dipendenza in Cargo.toml o una dichiarazione mod. La buona notizia è che di solito rustc ti stampa proprio la riga da copiare. Questa pagina fa parte della guida agli errori del compilatore.
Il messaggio di errore
Sezione intitolata “Il messaggio di errore”error[E0433]: cannot find type `HashMap` in this scope --> src/main.rs:2:21 |2 | let mut stock = HashMap::new(); | ^^^^^^^ use of undeclared type `HashMap` |help: consider importing this struct |1 + use std::collections::HashMap; |Il compilatore dice: «non trovo il tipo HashMap in questo scope», e suggerisce l’import giusto. Questo è il programma che lo produce:
fn main() { let mut stock = HashMap::new(); stock.insert("apples", 12); println!("{:?}", stock.get("apples"));}Le versioni più vecchie di Rust stampano lo stesso errore come «failed to resolve: use of undeclared type HashMap» (risoluzione fallita: uso di un tipo non dichiarato). A seconda di cosa manca, l’etichetta può anche dire use of unresolved module or unlinked crate (per un crate o un modulo) invece di use of undeclared type. Sono tutti E0433, e si risolvono allo stesso modo.
Cosa significa
Sezione intitolata “Cosa significa”I ^^^^^^^ indicano HashMap, la parte prima dei ::. Per chiamare HashMap::new(), Rust deve prima trovare qualcosa che si chiama HashMap. Ha guardato tutto ciò che è visibile dalla riga 2 e non ha trovato niente con quel nome, quindi non può nemmeno cominciare a cercare new.
La riga help: è la parte importante. rustc ha cercato nella libreria standard, ha trovato una struct HashMap in std::collections e ti mostra la riga use che la renderebbe visibile. 1 + significa «aggiungi questa come riga 1».
È come chiedere a un bibliotecario «il capitolo 3 di quel libro» senza dire quale libro. Sa che il capitolo 3 esiste in un sacco di libri, ma prima gli serve il titolo.
Perché Rust si comporta così
Sezione intitolata “Perché Rust si comporta così”In ogni file Rust è visibile in automatico solo un piccolo insieme di nomi. Si chiama prelude: Vec, String, Option, Some, None, Result, Ok, Err, Box e qualche trait. Tutto il resto, compresi HashMap, HashSet, fs e Ordering, va portato nello scope con use o scritto con il percorso completo.
Così il prelude resta piccolo e si evitano conflitti di nomi. La libreria standard, per esempio, ha due tipi Ordering diversi, e anche il tuo codice potrebbe avere un suo Duration o un suo Result. Rust non tira a indovinare quale intendevi. Lo dici una volta in cima al file, e chiunque legga vede da dove arriva ogni nome.
Lo stesso vale per crate e moduli: un crate esiste per il tuo codice solo dopo che è elencato in Cargo.toml, e un modulo solo dopo una riga mod. Vedi Moduli e Cargo e crate.
Come risolverlo
Sezione intitolata “Come risolverlo”Soluzione 1: Aggiungi la riga use suggerita da rustc
Sezione intitolata “Soluzione 1: Aggiungi la riga use suggerita da rustc”Scegli questa quando l’help: dice consider importing (valuta di importare). È di gran lunga la soluzione più comune. Copia la riga suggerita in cima al file:
use std::collections::HashMap;
fn main() { let mut stock = HashMap::new(); stock.insert("mele", 12); println!("{:?}", stock.get("mele"));}Output:
Some(12)L’altra possibilità è il percorso completo nel punto della chiamata, std::collections::HashMap::new(). Funziona anche così, ma dovresti ripeterlo ovunque, quindi la scelta normale è una riga use. Trovi di più su questo tipo in HashMap.
Se rustc propone più import (consider importing one of these), leggili prima di sceglierne uno. Sono tipi diversi con lo stesso nome, e solo uno è quello che intendevi.
Soluzione 2: Correggi il nome del tipo, o dichiaralo
Sezione intitolata “Soluzione 2: Correggi il nome del tipo, o dichiaralo”Scegli questa quando il nome è un tipo tuo. Se non c’è nessun help:, il tipo non esiste ancora; se c’è un errore di battitura, rustc indica il nome simile:
error[E0433]: cannot find type `Invetory` in this scope --> src/main.rs:12:17 |12 | let stock = Invetory::new(); | ^^^^^^^^ use of undeclared type `Invetory` |help: a struct with a similar name exists |12 | let stock = Inventory::new(); | +Il + sotto la riga mostra la lettera mancante. Correggi l’ortografia:
struct Inventory { items: Vec<String>,}
impl Inventory { fn new() -> Self { Inventory { items: Vec::new() } }}
fn main() { let stock = Inventory::new(); println!("{} articoli", stock.items.len());}Output:
0 articoliSe Order::new() dà E0433 senza suggerimenti, non hai ancora scritto struct Order (oppure sta in un file che non hai dichiarato con mod). Controlla anche le maiuscole: inventory::new() e Inventory::new() sono nomi diversi.
Soluzione 3: Indica il modulo in cui vive il tipo
Sezione intitolata “Soluzione 3: Indica il modulo in cui vive il tipo”Scegli questa quando il tipo o l’enum è definito dentro un modulo e tu lo usi da fuori. Qui l’enum sta in mod traffic, ma main scrive Light::Green:
error[E0433]: cannot find type `Light` in this scope --> src/main.rs:11:15 |11 | let now = Light::Green; | ^^^^^ use of undeclared type `Light` |help: consider importing this enum | 1 + use crate::traffic::Light; |Importa l’enum (oppure scrivi traffic::Light::Green). Nota che importi l’enum, e poi per ogni variante scrivi comunque Light::Green:
mod traffic { #[derive(Debug)] pub enum Light { Red, Yellow, Green, }}
use crate::traffic::Light;
fn can_go(light: &Light) -> bool { match light { Light::Green => true, Light::Yellow | Light::Red => false, }}
fn main() { let now = Light::Green; println!("{now:?}: si passa = {}", can_go(&now));}Output:
Green: si passa = trueIl percorso di una variante ha esattamente due parti: Enum::Variante. Se ne scrivi una di troppo, come Light::Red::Green, ottieni E0433 con cannot find module `Red` in `Light` e l’etichetta `Red` is a variant, not a module (Red è una variante, non un modulo). Vedi Enum.
Soluzione 4: Aggiungi il crate, o dichiara il modulo
Sezione intitolata “Soluzione 4: Aggiungi il crate, o dichiara il modulo”Scegli questa quando l’etichetta dice use of unresolved module or unlinked crate. La prima parte del percorso è un crate o un modulo che Rust non conosce:
error[E0433]: cannot find module or crate `rand` in this scope --> src/main.rs:4:19 |4 | let mut rng = rand::rng(); | ^^^^ use of unresolved module or unlinked crate `rand` | = help: if you wanted to use a crate named `rand`, use `cargo add rand` to add it to your `Cargo.toml`Per un crate di crates.io, esegui cargo add rand nella cartella del progetto. Per un modulo della libreria standard come fs, rustc suggerisce invece use std::fs;. E per un tuo file, per esempio src/inventory.rs, l’help dice to make use of source file src/inventory.rs, use `mod inventory` in this file to declare the module:
src/├── main.rs inventory::count_items() ← serve `mod inventory;` in cima└── inventory.rs pub fn count_items() -> u32 { 42 }Ecco lo stesso programma in un solo file, con il modulo scritto in linea così gira nel Playground:
mod inventory { pub fn count_items() -> u32 { 42 }}
fn main() { println!("Articoli in magazzino: {}", inventory::count_items());}Output:
Articoli in magazzino: 42Con un file separato, l’unica differenza è che mod inventory { ... } diventa mod inventory; e il contenuto si sposta in src/inventory.rs.
E extern crate?
Sezione intitolata “E extern crate?”Nel codice vecchio potresti vedere extern crate rand;. Dall’edizione 2018 non serve più: una volta che il crate è in Cargo.toml, puoi usarlo direttamente. Aggiungere extern crate non risolve E0433. Senza la dipendenza cambia solo l’errore in E0463, can't find crate for rand. La vera soluzione è cargo add.
Dove lo incontri di solito
Sezione intitolata “Dove lo incontri di solito”Confrontare con cmp. match a.cmp(&b) con rami Ordering::Less dà E0433, e rustc suggerisce due import: use std::cmp::Ordering; e use std::sync::atomic::Ordering;. Ti serve std::cmp::Ordering; quello atomico è per i thread. Vedi Match.
I test in un blocco mod tests. Un modulo di test è un modulo figlio, quindi non vede i tuoi tipi se non li importi. Inventory::new() dentro mod tests dà E0433 con help: consider importing this struct e use crate::Inventory;. Soluzione: metti use super::*; in cima al modulo di test. Vedi Test.
Codice incollato dalla documentazione o da un blog. Gli esempi spesso saltano le righe use. fs::read_to_string(...) fallisce con cannot find module or crate `fs` in this scope e l’help use std::fs;. Soluzione: aggiungi l’import che mostra rustc, o cerca il percorso dell’elemento nella sua pagina di documentazione.
Errori correlati
Sezione intitolata “Errori correlati”- E0432: lo stesso tipo di problema su una riga
use,unresolved import. - E0425: non si trova un valore o una funzione (senza
::), come una variabile scritta male. Il rustc attuale usa E0425 anche per un tipo mancante in posizione di tipo, comelet m: HashMap<&str, u32>; le versioni più vecchie lo chiamano E0412. Lo risolve la stessa rigause. - E0599: il tipo è stato trovato, ma il metodo o la variante dopo
::non esiste, comeLight::Blue. - E0463:
can't find crate, daextern cratesenza la dipendenza. - Tutti gli errori del compilatore: l’elenco completo delle pagine sugli errori.
Verifica veloce
Sezione intitolata “Verifica veloce”Verifica veloce
1. Perché HashSet::new() dà E0433 mentre Vec::new() funziona senza nessun import?
2. Per il tuo match a.cmp(&b), rustc suggerisce sia use std::cmp::Ordering; sia use std::sync::atomic::Ordering;. Quale scegli?
3. rand::rng() dà E0433 con l'etichetta 'use of unresolved module or unlinked crate'. Cosa lo risolve?
Punteggio: 0 / 3
Per approfondire
Sezione intitolata “Per approfondire”- E0433 — Rust error codes index (in inglese): la spiegazione ufficiale, con i casi del tipo non dichiarato e del crate non collegato.
- Bringing Paths into Scope with the
useKeyword — The Rust Book (in inglese): come funzionause, e perché è normale importare tipi comeHashMap. - Paths for Referring to an Item in the Module Tree — The Rust Book (in inglese): percorsi completi,
crate::esuper::. std::prelude— standard library docs (in inglese): l’elenco esatto dei nomi visibili senzause.- Path and module changes in Rust 2018 — Edition Guide (in inglese): perché
extern cratenon serve più.