Errore Rust E0432: unresolved import (import non risolto)
E0432 significa che una delle tue righe use punta a qualcosa che Rust non riesce a trovare. Forse il crate non è ancora in Cargo.toml, forse c’è un piccolo errore di battitura nel percorso, o forse un file esiste ma Rust non sa che è un modulo. Fa un po’ paura, ma quasi sempre si risolve con una riga, e di solito il compilatore ti dice anche quale. Questa pagina fa parte della guida agli errori del compilatore.
Il messaggio di errore
Sezione intitolata “Il messaggio di errore”error[E0432]: unresolved import `rand` --> src/main.rs:1:5 |1 | use rand::random_range; | ^^^^ 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`Il compilatore dice: «import non risolto rand», e suggerisce cargo add rand. Questo è il programma che lo produce, in un progetto appena creato con cargo new e senza niente sotto [dependencies]:
use rand::random_range;
fn main() { let roll = random_range(1..=6); println!("You rolled {roll}");}Il testo sotto i ^^^^ cambia a seconda della causa. Sono tutti E0432, e ognuno porta a una soluzione diversa qui sotto:
| Cosa dice l’etichetta | Cosa è andato storto di solito | Soluzione |
|---|---|---|
use of unresolved module or unlinked crate |
manca il crate in Cargo.toml, oppure un file non ha la riga mod |
Soluzione 1 o 3 |
could not find `collection` in `std` |
un errore di battitura a metà del percorso | Soluzione 2 |
no `Hashmap` in `collections` |
un errore di battitura (o di maiuscole) nell’ultimo nome | Soluzione 2 |
could not find `inventory` in the crate root |
percorso crate:: verso un modulo non dichiarato |
Soluzione 3 |
no external crate |
il percorso parte dal modulo sbagliato | Soluzione 4 |
Cosa significa
Sezione intitolata “Cosa significa”Una riga use è una scorciatoia. use rand::random_range; dice «da ora in poi, random_range significa la cosa che si trova in rand::random_range». Prima di poter creare la scorciatoia, Rust deve percorrere il percorso un pezzo alla volta: prima trovare rand, poi trovare random_range al suo interno.
I ^^^^ indicano il primo pezzo che non è stato trovato. Qui è rand, il primissimo segmento, quindi Rust non ha nemmeno cercato random_range. La riga help: ipotizza il perché: rand è un crate di crates.io, e questo progetto non l’ha aggiunto.
È come dare a un tassista l’indirizzo «Via del Porto 12, Springfeld». Se il nome della città è sbagliato, il tassista non può nemmeno cominciare a cercare la via.
Perché Rust si comporta così
Sezione intitolata “Perché Rust si comporta così”Rust risolve ogni percorso durante la compilazione, non quando il programma è in esecuzione. Niente viene caricato «per sicurezza». Il tuo codice vede solo tre tipi di cose: i crate elencati in Cargo.toml (più std), i moduli che hai dichiarato con mod, e gli elementi al loro interno. Se una riga use nomina qualcosa fuori da questo insieme, Rust si ferma subito invece di tirare a indovinare.
È un bene. Un import scritto male in Python o JavaScript spesso fallisce solo quando quella riga viene finalmente eseguita, magari in produzione. In Rust il programma non compila nemmeno. E significa anche che un crate che non hai mai aggiunto non può infilarsi di nascosto nel tuo programma.
Dall’edizione 2018, un percorso use parte da uno di questi punti: il nome di un crate (std, rand), crate (la radice del tuo crate), self (il modulo corrente), super (il modulo genitore), oppure un modulo dichiarato nel modulo corrente. La lezione Moduli lo spiega nel dettaglio, e Cargo e crate spiega le dipendenze.
Come risolverlo
Sezione intitolata “Come risolverlo”Soluzione 1: Aggiungi il crate con cargo add
Sezione intitolata “Soluzione 1: Aggiungi il crate con cargo add”Scegli questa quando il primo segmento è un crate di crates.io, come rand, serde o regex, e la riga help: cita cargo add. È la causa più comune, soprattutto quando copi codice da un articolo di blog. Esegui questo comando nella cartella che contiene Cargo.toml:
cargo add randCargo trova la versione più recente e aggiunge per te una riga a Cargo.toml:
[dependencies]rand = "0.10.3"Ora lo stesso codice compila. Questa versione stampa un controllo invece del numero uscito, così l’output è sempre lo stesso:
use rand::random_range;
fn main() { let roll = random_range(1..=6); println!("Il lancio è tra 1 e 6: {}", (1..=6).contains(&roll));}Output:
Il lancio è tra 1 e 6: trueQui due cose mettono spesso in difficoltà. Primo: i nomi dei crate con il trattino usano il trattino basso nel codice: fai cargo add tracing-subscriber ma scrivi use tracing_subscriber::.... Secondo: se il crate è una dipendenza del tuo workspace, deve comunque essere elencato nel Cargo.toml del pacchetto che lo usa.
Soluzione 2: Correggi l’ortografia del percorso
Sezione intitolata “Soluzione 2: Correggi l’ortografia del percorso”Scegli questa quando l’etichetta dice could not find `X` in `Y` o no `X` in `Y`. Qualcosa a metà o alla fine del percorso è scritto male. Un classico:
error[E0432]: unresolved import `std::collection` --> src/main.rs:1:10 |1 | use std::collection::HashMap; | ^^^^^^^^^^ could not find `collection` in `std`Il modulo si chiama collections, con la s. I nomi distinguono anche tra maiuscole e minuscole: use std::collections::Hashmap; fallisce con no `Hashmap` in `collections`, e rustc aggiunge help: a similar name exists in the module con l’ortografia giusta. L’import corretto:
use std::collections::HashMap;
fn main() { let mut stock: HashMap<&str, u32> = HashMap::new(); stock.insert("mele", 12); println!("{:?}", stock.get("mele"));}Output:
Some(12)Se non sei sicuro del percorso esatto, cerca nella documentazione della libreria standard (in inglese). La pagina di ogni elemento mostra in alto il suo percorso completo. Vedi HashMap per saperne di più su questo tipo.
Soluzione 3: Dichiara il modulo con mod
Sezione intitolata “Soluzione 3: Dichiara il modulo con mod”Scegli questa quando hai creato un nuovo file, per esempio src/inventory.rs, e use inventory::... non lo trova. In Rust un file non è un modulo finché un file genitore non lo dichiara. Il tuo progetto è fatto così:
src/├── main.rs use inventory::count_items; ← manca `mod inventory;`└── inventory.rs pub fn count_items() -> u32 { 42 }E rustc ti dice esattamente cosa manca:
error[E0432]: unresolved import `inventory` --> src/main.rs:1:5 |1 | use inventory::count_items; | ^^^^^^^^^ use of unresolved module or unlinked crate `inventory` |help: to make use of source file src/inventory.rs, use `mod inventory` in this file to declare the module |1 + mod inventory; |Aggiungi mod inventory; all’inizio di src/main.rs (o di src/lib.rs, se il modulo appartiene alla tua libreria). Scrivere invece use crate::inventory::count_items; non aiuta: fallisce con could not find `inventory` in the crate root, perché il modulo non è ancora dichiarato.
Nel Playground tutto sta in un solo file, quindi qui il modulo è scritto in linea con mod inventory { ... }. Funziona esattamente come il file separato:
mod inventory { pub fn count_items() -> u32 { 42 }}
use inventory::count_items;
fn main() { println!("Articoli in magazzino: {}", count_items());}Output:
Articoli in magazzino: 42Dichiara ogni modulo una sola volta, nel suo genitore. Gli altri file poi lo raggiungono con use crate::inventory::.... Non aggiungere mod inventory; in ogni file che lo usa.
Soluzione 4: Fai partire il percorso dal punto giusto
Sezione intitolata “Soluzione 4: Fai partire il percorso dal punto giusto”Scegli questa quando l’import sta dentro un modulo e l’elemento vive in un modulo diverso del tuo crate. Qui receipt sta dentro shop e vuole shop::store_name:
mod shop { pub fn store_name() -> &'static str { "Ferris Fruits" }
pub mod receipt { use store_name; // ❌ looks in the wrong place
pub fn header() -> String { format!("== {} ==", store_name()) } }}error[E0432]: unresolved import `store_name` --> src/main.rs:7:13 |7 | use store_name; // ❌ looks in the wrong place | ^^^^^^^^^^ no external crate `store_name`Un nome semplice all’inizio di un percorso use significa «un crate, oppure qualcosa dichiarato proprio qui in questo modulo». store_name non è né l’uno né l’altro, quindi Rust ha cercato un crate con quel nome (da qui «no external crate», nessun crate esterno). Digli invece da dove partire:
| Prefisso | Parte da | Esempio |
|---|---|---|
crate:: |
la radice del tuo crate (main.rs o lib.rs) |
use crate::shop::prices::price_of; |
super:: |
il modulo genitore | use super::store_name; |
self:: |
il modulo corrente | use self::lines::line; |
Tutti e tre in un solo programma:
mod shop { pub fn store_name() -> &'static str { "Frutta di Ferris" }
pub mod prices { pub fn price_of(item: &str) -> u32 { if item == "mela" { 3 } else { 5 } } }
pub mod receipt { use super::store_name; // modulo genitore: shop use crate::shop::prices::price_of; // dalla radice del crate use self::layout::line; // figlio di questo modulo
mod layout { pub fn line(item: &str, price: u32) -> String { format!("{item}: {price}") } }
pub fn print(item: &str) { println!("== {} ==", store_name()); println!("{}", line(item, price_of(item))); } }}
fn main() { shop::receipt::print("mela");}Output:
== Frutta di Ferris ==mela: 3Qui funzionerebbe anche use layout::line;, perché layout è dichiarato nel modulo corrente; self:: lo rende solo esplicito. Nel dubbio, crate:: con il percorso completo funziona sempre, da qualsiasi punto del tuo crate, e rustc spesso lo suggerisce: help: a similar path exists seguito dalla versione con crate::.
Dove lo incontri di solito
Sezione intitolata “Dove lo incontri di solito”Codice scritto per una versione più vecchia di un crate. Molti tutorial usano rand 0.8. Con rand 0.10 ottieni:
error[E0432]: unresolved import `rand::thread_rng` --> src/main.rs:1:5 |1 | use rand::thread_rng; | ^^^^^^^^^^^^^^^^ no `thread_rng` in the rootSoluzione: controlla su docs.rs la documentazione del crate per la versione indicata nel tuo Cargo.toml. Qui il nuovo nome è rand::rng(). Vedi Numeri casuali.
Un pacchetto con sia main.rs sia lib.rs. Sono due crate separati. Dentro main.rs, crate:: indica il binario, quindi use crate::inventory::count_items; fallisce con could not find `inventory` in the crate root anche se lib.rs ha pub mod inventory;. Soluzione: usa il nome del pacchetto, use shop_app::inventory::count_items; (con i trattini trasformati in trattini bassi).
L’elemento esiste ma è privato. È un errore diverso, E0603, non E0432:
error[E0603]: function `count_items` is private --> src/main.rs:7:16 |7 | use inventory::count_items; | ^^^^^^^^^^^ private functionSoluzione: aggiungi pub davanti a fn (e davanti a ogni mod lungo il percorso, perché un modulo privato dà module `prices` is private). Vedi Moduli.
Errori correlati
Sezione intitolata “Errori correlati”- E0433: un percorso dentro il tuo codice (come
HashMap::new()orand::rng()) non si può risolvere. Stesse cause, ma non su una rigause. - E0425: non si trova un valore o una funzione; spesso lo risolve la stessa riga
use. - E0603: l’import è stato trovato ma è privato. Aggiungi
pub. - E0463:
can't find crate, che ottieni daextern crate rand;quando il crate non è inCargo.toml. - Tutti gli errori del compilatore: l’elenco completo delle pagine sugli errori.
Verifica veloce
Sezione intitolata “Verifica veloce”Verifica veloce
1. Hai copiato use serde::Serialize; in un progetto nuovo e ottieni E0432, che dice che il crate serde non è risolto o non è collegato. Qual è la soluzione?
2. Hai creato src/billing.rs, ma use billing::total; in main.rs fallisce. Cosa manca?
3. Dentro mod shop { mod receipt { ... } }, come fa receipt a importare una funzione definita direttamente in shop?
Punteggio: 0 / 3
Per approfondire
Sezione intitolata “Per approfondire”- E0432 — Rust error codes index (in inglese): la spiegazione ufficiale, compreso come sono cambiati i percorsi in Rust 2018.
- Bringing Paths into Scope with the
useKeyword — The Rust Book (in inglese): come funzionause, con i pacchetti esterni e i percorsi annidati. - Paths for Referring to an Item in the Module Tree — The Rust Book (in inglese): percorsi assoluti con
crate::, percorsi relativi esuper. - Separating Modules into Different Files — The Rust Book (in inglese): dove va
modquando un modulo vive in un file tutto suo. cargo add— The Cargo Book (in inglese): tutte le opzioni per aggiungere dipendenze, comprese le feature.