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.
Le message d’erreur
Section intitulée « Le message d’erreur »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 |
Ce que ça veut dire
Section intitulée « Ce que ça veut dire »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.
Pourquoi Rust fait ça
Section intitulée « Pourquoi Rust fait ça »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.
Comment corriger
Section intitulée « Comment corriger »Solution 1 : ajouter la crate avec cargo add
Section intitulée « Solution 1 : ajouter la crate avec cargo add »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 :
cargo add randCargo 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 : trueDeux 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.
Solution 2 : corriger l’orthographe du chemin
Section intitulée « Solution 2 : corriger l’orthographe du chemin »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)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.
Solution 3 : déclarer le module avec mod
Section intitulée « Solution 3 : déclarer le module avec mod »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 : 42Dé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 : 3use 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::.
Où vous le verrez souvent
Section intitulée « Où vous le verrez souvent »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 rootRustc 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 functionRustc 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.
Erreurs liées
Section intitulée « Erreurs liées »- E0433 : un chemin dans votre code (comme
HashMap::new()ourand::rng()) ne peut pas être résolu. Mêmes causes, mais pas sur une ligneuse. - 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 avecextern crate rand;quand la crate n’est pas dansCargo.toml. - Toutes les erreurs du compilateur : la liste complète des pages d’erreurs.
Petit quiz
Section intitulée « Petit quiz »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
Pour aller plus loin
Section intitulée « Pour aller plus loin »- E0432 — Rust error codes index (en anglais) : l’explication officielle, y compris les changements de chemins de Rust 2018.
- Bringing Paths into Scope with the
useKeyword — The Rust Book (en anglais) : comment fonctionneuse, avec les paquets externes et les chemins imbriqués. - Paths for Referring to an Item in the Module Tree — The Rust Book (en anglais) : les chemins absolus en
crate::, les chemins relatifs etsuper. - Separating Modules into Different Files — The Rust Book (en anglais) : où placer
modquand un module vit dans son propre fichier. cargo add— The Cargo Book (en anglais) : toutes les options pour ajouter des dépendances, y compris les features.