Aller au contenu

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.

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.

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.

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.

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)
▶ Essayez par vous-même

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 articles
▶ Essayez par vous-même

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

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 = true
▶ Essayez par vous-même

Un 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 : 42
▶ Essayez par vous-même

Avec un fichier séparé, le seul changement est que mod inventory { ... } devient mod inventory; et que le contenu part dans src/inventory.rs.

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.

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.

  • 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, comme let m: HashMap<&str, u32> ; les anciennes versions appellent ça E0412. La même ligne use la corrige.
  • E0599 : le type a été trouvé, mais la méthode ou la variante après :: n’existe pas, comme Light::Blue.
  • E0463 : can't find crate, à cause d’un extern crate sans la dépendance.
  • Toutes les erreurs du compilateur : la liste complète des pages d’erreurs.

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