extern crate et use en Rust : où est le piège et comment éviter les erreurs
\n\nSi vous avez déjà écrit ne serait-ce que quelques lignes en Rust, vous avez sûrement rencontré les constructions extern crate et use. À première vue, elles semblent faire la même chose — importer du code externe. Mais le diable, comme toujours, se cache dans les détails. Cette question fait partie des plus populaires sur Stack Overflow (des milliers de vues !), et les débutants s'y perdent constamment. Clarifions une fois pour toutes la différence entre extern crate et use, où se produit la magie et comment éviter les erreurs typiques.
L'essentiel en bref : qu'est-ce que quoi
\n\nImaginez que votre projet Rust est une grande maison. extern crate est la livraison des matériaux de construction sur le terrain. Vous dites au compilateur : « Hé, cette caisse de briques (crate), je veux l'utiliser, apporte-la ». Sans cette commande, le compilateur ne saura même pas qu'une bibliothèque externe existe.
use est la navigation interne dans la maison. Vous dites : « Je veux que la porte de cette pièce (module) mène directement à la cuisine (type ou fonction spécifique) ». use crée des alias (chemins courts) vers des modules et types déjà connus, pour ne pas avoir à écrire le chemin complet à chaque fois.
En termes simples : extern crate répond à la question « que pouvons-nous utiliser en général ? », tandis que use répond à « comment pouvons-nous y accéder plus facilement ? ».
Contexte historique : pourquoi tout le monde se trompe
\n\nLa confusion n'est pas apparue de nulle part. Dans les anciennes versions de Rust (avant l'édition 2018), extern crate était obligatoire pour toute crate externe. Cela ressemblait à ceci :
// Rust 2015 — ancien style\nextern crate serde;\nuse serde::{Serialize, Deserialize};\n\nÀ partir de Rust 2018 edition, le compilateur a appris à trouver lui-même les dépendances depuis Cargo.toml. Désormais, écrire extern crate pour la plupart des crates n'est pas nécessaire. Il suffit d'ajouter la dépendance dans Cargo.toml et d'utiliser directement use :
// Rust 2018+ — nouveau style (extern crate n'est pas obligatoire)\nuse serde::{Serialize, Deserialize};\n\nC'est là que l'enfer commence pour les débutants. Ils voient des exemples anciens où extern crate est utilisé, des nouveaux où il ne l'est pas, et essaient de comprendre quand il est vraiment nécessaire. Spoiler : il est nécessaire, mais dans des cas très rares.
Quand extern crate est-il encore nécessaire (et c'est important !)
\n\nIl y a trois situations où l'on ne peut pas se passer de extern crate :
- \n
- Liaison avec des bibliothèques système via
#[link]— si vous écrivez des bindings pour du code C/C++ et utilisez l'attribut#[link(name = "sqlite3")], alorsextern crateest obligatoire. \n - Macros globales — certaines crates (par exemple,
log) exportent des macros qui doivent être visibles dans tout le programme. En Rust 2018, pour cela, il faut écrireextern crate log;. \n - Compilation avec des noms de crates non standards — si vous utilisez
extern crate my_crate as foo;pour renommer une crate. \n
Dans tous les autres cas, extern crate est un artefact du passé. Mais de nombreux développeurs continuent à l'écrire par habitude, et les débutants copient le code d'anciens tutoriels.
Top 5 des erreurs avec extern crate et use
\n\nErreur n°1 : Utiliser extern crate là où il n'est pas nécessaire
\n\nLe problème le plus fréquent. Vous ajoutez une crate dans Cargo.toml, puis vous écrivez extern crate rand; — et le code fonctionne. Mais c'est une ligne superflue. Dans les projets modernes (Rust 2018+), elle ne fait qu'encombrer le code et peut dérouter les autres développeurs.
// Mauvais (redondant en Rust 20