Salta ai contenuti

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.

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

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.

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.

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:

Terminal window
cargo add rand

Cargo 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: true
▶ Provalo tu

Qui 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.

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)
▶ Provalo tu

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.

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: 42
▶ Provalo tu

Dichiara 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: 3
▶ Provalo tu

Qui 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::.

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 root

Soluzione: 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 function

Soluzione: aggiungi pub davanti a fn (e davanti a ogni mod lungo il percorso, perché un modulo privato dà module `prices` is private). Vedi Moduli.

  • E0433: un percorso dentro il tuo codice (come HashMap::new() o rand::rng()) non si può risolvere. Stesse cause, ma non su una riga use.
  • 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 da extern crate rand; quando il crate non è in Cargo.toml.
  • Tutti gli errori del compilatore: l’elenco completo delle pagine sugli errori.

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