Aller au contenu

Erreur Rust E0432 : unresolved import (import non résolu)

E0432 veut dire qu’une de vos lignes use désigne quelque chose que Rust ne trouve pas. Peut-être que la crate n’est pas encore dans Cargo.toml, peut-être qu’il y a une petite faute de frappe dans le chemin, ou peut-être qu’un fichier existe mais que Rust ne sait pas que c’est un module. Ça a l’air effrayant, mais la correction tient presque toujours en une ligne, et le compilateur vous dit en général laquelle. Cette page fait partie du guide des erreurs du compilateur Rust.

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`

Le compilateur vous dit : « import non résolu rand ». Il ne connaît aucun module ni aucune crate liée qui s’appelle rand, et il vous suggère cargo add rand pour l’ajouter à votre Cargo.toml.

Voici le programme qui la provoque, dans un projet tout neuf créé avec cargo new, sans rien sous [dependencies] :

use rand::random_range;
fn main() {
let roll = random_range(1..=6);
println!("You rolled {roll}");
}

Le texte sous les ^^^^ change selon la cause. Chacun de ces messages est une erreur E0432, et chacun mène à une solution différente ci-dessous :

Ce que dit l’étiquette Ce qui s’est généralement passé Solution
use of unresolved module or unlinked crate crate absente de Cargo.toml, ou fichier sans ligne mod Solution 1 ou 3
could not find `collection` in `std` une faute de frappe au milieu du chemin Solution 2
no `Hashmap` in `collections` une faute de frappe (ou une mauvaise casse) dans le dernier nom Solution 2
could not find `inventory` in the crate root un chemin crate:: vers un module non déclaré Solution 3
no external crate le chemin part du mauvais module Solution 4

Une ligne use est un raccourci. use rand::random_range; veut dire « à partir de maintenant, random_range désigne l’élément situé à rand::random_range ». Avant de pouvoir créer ce raccourci, Rust doit parcourir le chemin morceau par morceau : d’abord trouver rand, puis trouver random_range à l’intérieur.

Les ^^^^ désignent le premier morceau qui a échoué. Ici, c’est rand, le tout premier segment : Rust n’a donc même pas cherché random_range. La ligne help: devine pourquoi : rand est une crate de crates.io, et ce projet ne l’a pas ajoutée.

C’est comme donner à un chauffeur de taxi l’adresse « 12 rue du Port, Marseile ». Si le nom de la ville est faux, le chauffeur ne peut même pas commencer à chercher la rue.

Rust résout chaque chemin à la compilation, pas pendant l’exécution du programme. Rien n’est chargé « au cas où ». Votre code ne peut voir que trois sortes de choses : les crates listées dans Cargo.toml (plus std), les modules que vous avez déclarés avec mod, et les éléments qu’ils contiennent. Si une ligne use nomme quelque chose en dehors de cet ensemble, Rust s’arrête tout de suite au lieu de deviner.

C’est une bonne chose. En Python ou en JavaScript, un import mal écrit n’échoue souvent qu’au moment où cette ligne s’exécute enfin, parfois en production. En Rust, le programme ne compile même pas. Cela veut aussi dire qu’une crate que vous n’avez jamais ajoutée ne peut jamais se glisser dans votre programme.

Depuis l’édition 2018, un chemin use commence à l’un de ces endroits : le nom d’une crate (std, rand), crate (la racine de votre propre crate), self (le module actuel), super (le module parent), ou un module déclaré dans le module actuel. La leçon Les modules l’explique en détail, et Cargo et les crates parle des dépendances.

Choisissez-la quand le premier segment est une crate de crates.io, comme rand, serde ou regex, et que la ligne help: parle de cargo add. C’est la cause la plus fréquente, surtout quand vous copiez du code depuis un article de blog. Lancez cette commande dans le dossier qui contient Cargo.toml :

Terminal window
cargo add rand

Cargo trouve la version la plus récente et ajoute une ligne à Cargo.toml pour vous :

[dependencies]
rand = "0.10.3"

Maintenant, le même code compile. Cette version affiche une vérification plutôt que le résultat du lancer lui-même, pour que la sortie soit toujours la même :

use rand::random_range;
fn main() {
let roll = random_range(1..=6);
println!("Le lancer est entre 1 et 6 : {}", (1..=6).contains(&roll));
}

Sortie :

Le lancer est entre 1 et 6 : true
▶ Essayez par vous-même

Deux pièges reviennent souvent ici. D’abord, les noms de crate avec un tiret s’écrivent avec un tiret bas dans le code : vous faites cargo add tracing-subscriber, mais vous écrivez use tracing_subscriber::.... Ensuite, si la crate est une dépendance de votre workspace, elle doit quand même être listée dans le Cargo.toml du paquet qui l’utilise.

Choisissez-la quand l’étiquette dit could not find `X` in `Y` ou no `X` in `Y`. Quelque chose au milieu ou à la fin du chemin est mal écrit. Un grand classique :

error[E0432]: unresolved import `std::collection`
--> src/main.rs:1:10
|
1 | use std::collection::HashMap;
| ^^^^^^^^^^ could not find `collection` in `std`

Rustc ne trouve pas collection dans std. Le module s’appelle collections, avec un s. Les noms sont aussi sensibles à la casse : use std::collections::Hashmap; échoue avec no `Hashmap` in `collections`, et rustc ajoute help: a similar name exists in the module (un nom semblable existe dans le module) avec la bonne orthographe. L’import corrigé :

use std::collections::HashMap;
fn main() {
let mut stock: HashMap<&str, u32> = HashMap::new();
stock.insert("apples", 12);
println!("{:?}", stock.get("apples"));
}

Sortie :

Some(12)
▶ Essayez par vous-même

Si vous n’êtes pas sûr du chemin exact, cherchez dans la documentation de la bibliothèque standard (en anglais). La page de chaque élément affiche son chemin complet tout en haut. Voir HashMap pour en savoir plus sur ce type.

Choisissez-la quand vous avez créé un nouveau fichier, par exemple src/inventory.rs, et que use inventory::... ne le trouve pas. En Rust, un fichier n’est pas un module tant qu’un fichier parent ne le déclare pas. Votre projet ressemble à ceci :

src/
├── main.rs use inventory::count_items; ← pas de `mod inventory;`
└── inventory.rs pub fn count_items() -> u32 { 42 }

Et rustc dit exactement ce qui manque :

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;
|

La ligne help: explique que, pour utiliser le fichier src/inventory.rs, il faut déclarer le module avec mod inventory dans ce fichier. Ajoutez mod inventory; en haut de src/main.rs (ou de src/lib.rs, si le module fait partie de votre bibliothèque). Écrire use crate::inventory::count_items; à la place n’aide pas : cela échoue avec could not find `inventory` in the crate root, parce que le module n’est toujours pas déclaré.

Sur le Playground, tout tient dans un seul fichier, alors ici le module est écrit directement avec mod inventory { ... }. Cela fonctionne exactement comme le fichier séparé :

mod inventory {
pub fn count_items() -> u32 {
42
}
}
use inventory::count_items;
fn main() {
println!("Articles en stock : {}", count_items());
}

Sortie :

Articles en stock : 42
▶ Essayez par vous-même

Déclarez chaque module une seule fois, dans son parent. Les autres fichiers y accèdent ensuite avec use crate::inventory::.... N’ajoutez pas mod inventory; dans chaque fichier qui l’utilise.

Solution 4 : faire partir le chemin du bon endroit

Section intitulée « Solution 4 : faire partir le chemin du bon endroit »

Choisissez-la quand l’import se trouve dans un module et que l’élément vit dans un autre module de votre propre crate. Ici, receipt est dans shop et veut shop::store_name :

mod shop {
pub fn store_name() -> &'static str {
"Ferris Fruits"
}
pub mod receipt {
use store_name; // ❌ cherche au mauvais endroit
pub fn header() -> String {
format!("== {} ==", store_name())
}
}
}
error[E0432]: unresolved import `store_name`
--> src/main.rs:7:13
|
7 | use store_name; // ❌ cherche au mauvais endroit
| ^^^^^^^^^^ no external crate `store_name`

Rustc dit qu’il n’existe aucune crate externe store_name. Un nom seul au début d’un chemin use signifie « une crate, ou quelque chose déclaré ici même, dans ce module ». store_name n’est ni l’un ni l’autre, alors Rust a cherché une crate portant ce nom. Dites-lui plutôt d’où partir :

Préfixe Part de Exemple
crate:: la racine de votre crate (main.rs ou lib.rs) use crate::shop::prices::price_of;
super:: le module parent use super::store_name;
self:: le module actuel use self::lines::line;

Les trois dans un même programme :

mod shop {
pub fn store_name() -> &'static str {
"Ferris Fruits"
}
pub mod prices {
pub fn price_of(item: &str) -> u32 {
if item == "pomme" { 3 } else { 5 }
}
}
pub mod receipt {
use super::store_name; // module parent : shop
use crate::shop::prices::price_of; // depuis la racine de la crate
use self::layout::line; // enfant de ce module
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("pomme");
}

Sortie :

== Ferris Fruits ==
pomme : 3
▶ Essayez par vous-même

use layout::line; marcherait aussi ici, parce que layout est déclaré dans le module actuel ; self:: le rend simplement explicite. En cas de doute, crate:: suivi du chemin complet fonctionne toujours, depuis n’importe où dans votre crate, et rustc le suggère souvent : help: a similar path exists (un chemin semblable existe), suivi de la version en crate::.

Du code écrit pour une ancienne version d’une crate. Beaucoup de tutoriels utilisent rand 0.8. Avec rand 0.10, vous obtenez :

error[E0432]: unresolved import `rand::thread_rng`
--> src/main.rs:1:5
|
1 | use rand::thread_rng;
| ^^^^^^^^^^^^^^^^ no `thread_rng` in the root

Rustc ne trouve pas thread_rng à la racine de la crate. Correction : consultez la documentation de la crate sur docs.rs pour la version indiquée dans votre Cargo.toml. Ici, le nouveau nom est rand::rng(). Voir Les nombres aléatoires.

Un paquet avec à la fois main.rs et lib.rs. Ce sont deux crates séparées. Dans main.rs, crate:: désigne le binaire, donc use crate::inventory::count_items; échoue avec could not find `inventory` in the crate root, même si lib.rs contient pub mod inventory;. Correction : utilisez le nom du paquet, use shop_app::inventory::count_items; (avec les tirets remplacés par des tirets bas).

L’élément existe mais il est privé. C’est une autre erreur, E0603, pas E0432 :

error[E0603]: function `count_items` is private
--> src/main.rs:7:16
|
7 | use inventory::count_items;
| ^^^^^^^^^^^ private function

Rustc dit que la fonction count_items est privée. Correction : ajoutez pub devant le fn (et devant chaque mod sur le chemin, car un module privé donne module `prices` is private). Voir Les modules.

  • E0433 : un chemin dans votre code (comme HashMap::new() ou rand::rng()) ne peut pas être résolu. Mêmes causes, mais pas sur une ligne use.
  • E0425 : une valeur ou une fonction introuvable, souvent corrigée par la même ligne use.
  • E0603 : l’import a été trouvé, mais il est privé. Ajoutez pub.
  • E0463 : can't find crate (crate introuvable), que vous obtenez avec extern crate rand; quand la crate n’est pas dans Cargo.toml.
  • Toutes les erreurs du compilateur : la liste complète des pages d’erreurs.

Petit quiz

1. Vous avez copié use serde::Serialize; dans un nouveau projet et vous obtenez une erreur E0432 qui dit que la crate serde n'est pas résolue ou pas liée. Quelle est la correction ?

2. Vous avez créé src/billing.rs, mais use billing::total; dans main.rs échoue. Que manque-t-il ?

3. Dans mod shop { mod receipt { ... } }, comment receipt importe-t-il une fonction définie directement dans shop ?

Score : 0 / 3