Erreur Rust E0433 : failed to resolve, use of undeclared type (type non déclaré)
E0433 veut dire que vous avez écrit un chemin comme HashMap::new() ou rand::rng(), et que Rust ne sait pas ce qu’est la première partie. Il manque presque toujours une seule ligne : un use, une dépendance dans Cargo.toml, ou une déclaration mod. Bonne nouvelle : rustc affiche en général cette ligne exacte, prête à copier. Cette page fait partie du guide des erreurs du compilateur Rust.
Le message d’erreur
Section intitulée « Le message d’erreur »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; |Le compilateur vous dit : « impossible de trouver le type HashMap dans cette portée », car c’est un type non déclaré. Il vous propose d’importer la struct avec use std::collections::HashMap;.
Voici le programme qui la provoque :
fn main() { let mut stock = HashMap::new(); stock.insert("apples", 12); println!("{:?}", stock.get("apples"));}Les anciennes versions de Rust affichent la même erreur sous la forme « failed to resolve: use of undeclared type HashMap » (échec de résolution : utilisation d’un type non déclaré). Selon ce qui manque, l’étiquette peut aussi dire use of unresolved module or unlinked crate (pour une crate ou un module) au lieu de use of undeclared type. Ce sont toutes des erreurs E0433, et elles se corrigent de la même façon.
Ce que ça veut dire
Section intitulée « Ce que ça veut dire »Les ^^^^^^^ désignent HashMap, la partie avant le ::. Pour appeler HashMap::new(), Rust doit d’abord trouver quelque chose qui s’appelle HashMap. Il a regardé tout ce qui est visible depuis la ligne 2 et n’a rien trouvé avec ce nom, il ne peut donc même pas commencer à chercher new.
La ligne help: est la partie importante. Rustc a fouillé la bibliothèque standard, trouvé une struct appelée HashMap dans std::collections, et vous montre la ligne use qui la rendrait visible. Le 1 + signifie « ajoutez ceci en ligne 1 ».
C’est comme demander à un bibliothécaire « le chapitre 3 de ce livre » sans dire de quel livre il s’agit. Il sait que beaucoup de livres ont un chapitre 3, mais il lui faut d’abord le titre.
Pourquoi Rust fait ça
Section intitulée « Pourquoi Rust fait ça »Seul un petit ensemble de noms est visible automatiquement dans chaque fichier Rust. On l’appelle le prélude (prelude) : Vec, String, Option, Some, None, Result, Ok, Err, Box et quelques traits. Tout le reste, y compris HashMap, HashSet, fs et Ordering, doit être importé avec use ou écrit avec son chemin complet.
Cela garde le prélude petit et évite les conflits de noms. La bibliothèque standard a par exemple deux types Ordering différents, et votre propre code peut avoir son Duration ou son Result. Rust ne devinera pas lequel vous vouliez. Vous le dites une fois en haut du fichier, et chaque lecteur voit d’où vient chaque nom.
C’est pareil pour les crates et les modules : une crate n’existe pour votre code qu’une fois listée dans Cargo.toml, et un module qu’après une ligne mod. Voir Les modules et Cargo et les crates.
Comment corriger
Section intitulée « Comment corriger »Solution 1 : ajouter la ligne use que rustc propose
Section intitulée « Solution 1 : ajouter la ligne use que rustc propose »Choisissez-la quand le help: dit consider importing (pensez à importer). C’est de loin la correction la plus fréquente. Copiez la ligne suggérée en haut du fichier :
use std::collections::HashMap;
fn main() { let mut stock = HashMap::new(); stock.insert("apples", 12); println!("{:?}", stock.get("apples"));}Sortie :
Some(12)L’autre option est d’écrire le chemin complet à l’endroit de l’appel, std::collections::HashMap::new(). Ça marche aussi, mais il faudrait le répéter partout : une ligne use est donc le choix normal. Plus d’informations sur ce type dans HashMap.
Si rustc propose plusieurs imports (consider importing one of these), lisez-les avant d’en choisir un. Ce sont des types différents qui portent le même nom, et un seul correspond à ce que vous vouliez.
Solution 2 : corriger le nom du type, ou déclarer le type
Section intitulée « Solution 2 : corriger le nom du type, ou déclarer le type »Choisissez-la quand le nom est celui d’un de vos propres types. S’il n’y a aucun help:, le type n’existe pas encore ; s’il y a une faute de frappe, rustc vous indique le nom semblable :
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(); | +Rustc vous signale qu’une struct au nom semblable existe. Le + sous la ligne montre la lettre manquante. Corrigez l’orthographe :
struct Inventory { items: Vec<String>,}
impl Inventory { fn new() -> Self { Inventory { items: Vec::new() } }}
fn main() { let stock = Inventory::new(); println!("{} articles", stock.items.len());}Sortie :
0 articlesSi Order::new() donne E0433 sans aucune suggestion, c’est que vous n’avez pas encore écrit struct Order (ou qu’elle se trouve dans un fichier que vous n’avez pas déclaré avec mod). Vérifiez aussi les majuscules : inventory::new() et Inventory::new() sont deux noms différents.
Solution 3 : nommer le module où vit le type
Section intitulée « Solution 3 : nommer le module où vit le type »Choisissez-la quand le type ou l’enum est défini dans un module et que vous l’utilisez depuis l’extérieur. Ici, l’enum est dans mod traffic, mais main écrit 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; |Rustc vous propose d’importer l’enum. Importez-la (ou écrivez traffic::Light::Green). Notez que vous importez l’enum, et que vous écrivez toujours Light::Green pour chaque variante :
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:?} : on peut passer = {}", can_go(&now));}Sortie :
Green : on peut passer = trueUn chemin de variante a exactement deux parties : Enum::Variante. Si vous en écrivez une de trop, comme Light::Red::Green, vous obtenez E0433 avec cannot find module `Red` in `Light` et l’étiquette `Red` is a variant, not a module (Red est une variante, pas un module). Voir Les enums.
Solution 4 : ajouter la crate, ou déclarer le module
Section intitulée « Solution 4 : ajouter la crate, ou déclarer le module »Choisissez-la quand l’étiquette dit use of unresolved module or unlinked crate. La première partie du chemin est une crate ou un module que Rust ne connaît pas :
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`Rustc ne trouve ni module ni crate rand, et vous suggère cargo add rand. Pour une crate de crates.io, lancez cargo add rand dans le dossier de votre projet. Pour un module de la bibliothèque standard comme fs, rustc propose plutôt use std::fs;. Et pour votre propre fichier, par exemple src/inventory.rs, l’aide dit to make use of source file src/inventory.rs, use `mod inventory` in this file to declare the module (pour utiliser ce fichier, déclarez le module avec mod inventory) :
src/├── main.rs inventory::count_items() ← il faut `mod inventory;` en haut└── inventory.rs pub fn count_items() -> u32 { 42 }Voici le même programme dans un seul fichier, avec le module écrit directement dedans pour qu’il tourne sur le Playground :
mod inventory { pub fn count_items() -> u32 { 42 }}
fn main() { println!("Articles en stock : {}", inventory::count_items());}Sortie :
Articles en stock : 42Avec un fichier séparé, le seul changement est que mod inventory { ... } devient mod inventory; et que le contenu part dans src/inventory.rs.
Et extern crate ?
Section intitulée « Et extern crate ? »Vous verrez peut-être extern crate rand; dans du vieux code. Depuis l’édition 2018, ce n’est plus nécessaire : une fois qu’une crate est dans Cargo.toml, vous pouvez l’utiliser directement. Ajouter extern crate ne corrige pas E0433. Sans la dépendance, cela change seulement l’erreur en E0463, can't find crate for rand (crate introuvable). La vraie correction, c’est cargo add.
Où vous le verrez souvent
Section intitulée « Où vous le verrez souvent »Comparer avec cmp. match a.cmp(&b) avec des branches Ordering::Less donne E0433, et rustc suggère deux imports : use std::cmp::Ordering; et use std::sync::atomic::Ordering;. Celui qu’il vous faut est std::cmp::Ordering ; l’autre, celui des atomiques, sert aux threads. Voir Match.
Les tests dans un bloc mod tests. Un module de test est un module enfant : il ne voit pas vos types sans les importer. Inventory::new() dans mod tests donne E0433 avec help: consider importing this struct et use crate::Inventory;. Correction : mettez use super::*; en haut du module de test. Voir Les tests.
Du code copié depuis une documentation ou un article de blog. Les exemples omettent souvent leurs lignes use. fs::read_to_string(...) échoue avec cannot find module or crate `fs` in this scope et l’aide use std::fs;. Correction : ajoutez l’import que rustc affiche, ou cherchez le chemin de l’élément sur sa page de documentation.
Erreurs liées
Section intitulée « Erreurs liées »- E0432 : le même genre de problème sur une ligne
use,unresolved import(import non résolu). - E0425 : une valeur ou une fonction introuvable (sans
::), comme une variable mal orthographiée. Le rustc actuel utilise aussi E0425 pour un type manquant à une position de type, commelet m: HashMap<&str, u32>; les anciennes versions appellent ça E0412. La même ligneusela corrige. - E0599 : le type a été trouvé, mais la méthode ou la variante après
::n’existe pas, commeLight::Blue. - E0463 :
can't find crate, à cause d’unextern cratesans la dépendance. - Toutes les erreurs du compilateur : la liste complète des pages d’erreurs.
Petit quiz
Section intitulée « Petit quiz »Petit quiz
1. Pourquoi HashSet::new() donne-t-il E0433 alors que Vec::new() marche sans aucun import ?
2. Rustc suggère à la fois use std::cmp::Ordering; et use std::sync::atomic::Ordering; pour votre match a.cmp(&b). Lequel choisissez-vous ?
3. rand::rng() donne E0433 avec l'étiquette « use of unresolved module or unlinked crate ». Qu'est-ce qui la corrige ?
Score : 0 / 3
Pour aller plus loin
Section intitulée « Pour aller plus loin »- E0433 — Rust error codes index (en anglais) : l’explication officielle, avec le cas du type non déclaré et celui de la crate non liée.
- Bringing Paths into Scope with the
useKeyword — The Rust Book (en anglais) : comment fonctionneuse, et pourquoi il est normal d’importer des types commeHashMap. - Paths for Referring to an Item in the Module Tree — The Rust Book (en anglais) : les chemins complets,
crate::etsuper::. std::prelude— documentation de la bibliothèque standard (en anglais) : la liste exacte des noms visibles sansuse.- Path and module changes in Rust 2018 — Edition Guide (en anglais) : pourquoi
extern craten’est plus nécessaire.