Rust est un langage de programmation à usage général qui met l'accent sur les performances , la sécurité des types et la concurrence . Il impose la sécurité de la mémoire , ce qui signifie que toutes les références pointent vers une mémoire valide. Il le fait sans ramasse-miettes traditionnel ; à la place, les erreurs de sécurité de la mémoire et les courses de données sont évitées par le « vérificateur d'emprunt », qui suit la durée de vie de l'objet des références au moment de la compilation .
Rust n'impose pas de paradigme de programmation , mais a été influencé par des idées issues de la programmation fonctionnelle , notamment l'immuabilité , les fonctions d'ordre supérieur , les types de données algébriques et la correspondance de motifs . Il prend également en charge la programmation orientée objet via des structures, des énumérations , des traits et des méthodes. Il est populaire pour la programmation système .
Le développeur de logiciels Graydon Hoare a créé Rust dans le cadre d'un projet personnel alors qu'il travaillait chez Mozilla Research en 2006. Mozilla a officiellement parrainé le projet en 2009. Dans les années qui ont suivi la première version stable en mai 2015, Rust a été adopté par des entreprises telles qu'Amazon , Discord , Dropbox , Google ( Alphabet ) , Meta et Microsoft . En décembre 2022, il est devenu le premier langage autre que C et assembleur à être pris en charge dans le développement du noyau Linux .
Rust a été remarqué pour son adoption rapide et a été étudié dans la recherche théorique sur les langages de programmation .
Histoire
Les premières années (2006-2009)
Rust a commencé comme un projet personnel en 2006 par un employé de Mozilla, Graydon Hoare. Hoare a déclaré que Rust a été nommé d'après le groupe de champignons qui sont « sur-conçus pour survivre ». Pendant la période entre 2006 et 2009, Rust n'a pas été rendu public auprès des autres membres de Mozilla et a été écrit pendant le temps libre de Hoare ; Hoare a commencé à parler du langage vers 2009 après qu'un petit groupe de Mozilla se soit intéressé au projet. Hoare a souligné la priorité donnée aux bonnes idées des anciens langages plutôt qu'au nouveau développement, citant des langages tels que CLU (1974), BETA (1975), Mesa (1977), NIL (1981), Erlang (1987) , Newsqueak (1988), Napier (1988), Hermes (1990), Sather (1990), Alef (1992) et Limbo (1996) comme influences, affirmant que « de nombreux langages anciens [sont] meilleurs que les nouveaux », et décrivant le langage comme « une technologie du passé venue sauver le futur de lui-même ». Le premier développeur de Rust, Manish Goregaokar, a également décrit Rust comme étant basé sur « des recherches datant principalement de plusieurs décennies ».
Au cours des premières années, le compilateur Rust était écrit en environ 38 000 lignes d' OCaml . Les premiers Rust contenaient des fonctionnalités telles que la programmation orientée objet explicite via un objmot-clé (supprimé plus tard) et un système appelé typestates qui permettait de suivre les variables d'un type ainsi que les changements d'état (comme le passage de non initialisé à initialisé). Les fonctions étaient pures par défaut, ce qui signifie que les effets secondaires (tels que la lecture ou l'écriture dans un fichier) n'étaient pas autorisés sans une annotation explicite.
Parrainage de Mozilla (2009-2012)
Mozilla a officiellement sponsorisé le projet Rust en 2009. Brendan Eich et d'autres dirigeants, intrigués par la possibilité d'utiliser Rust pour un moteur de navigateur Web sécurisé , ont placé des ingénieurs sur le projet, dont Patrick Walton, Niko Matsakis, Felix Klock et Manish Goregaokar. Une salle de conférence occupée par les développeurs du projet a été surnommée « la caverne des nerds », avec un panneau placé devant la porte.
Durant cette période, le travail est passé du compilateur OCaml initial à un compilateur auto-hébergé , c'est-à -dire écrit en Rust, basé sur LLVM . Le système de propriété de Rust était également en place en 2010. Le logo Rust a été développé en 2011 sur la base d'un plateau de vélo .
La première version publique, Rust 0.1, a été publiée en janvier 2012. Le début des années 2010 a vu une implication croissante de volontaires open source en dehors de Mozilla et en dehors des États-Unis. Chez Mozilla, les dirigeants ont fini par employer plus d'une douzaine d'ingénieurs pour travailler sur Rust à plein temps au cours de la décennie suivante.
Évolution (2012-2015)
Les années 2012 à 2015 ont été marquées par des changements substantiels dans le système de types Rust , en particulier la suppression du système typestate, la consolidation d'autres fonctionnalités du langage et la suppression du garbage collector . La gestion de la mémoire via le système de propriété a été progressivement consolidée et étendue pour éviter les bogues liés à la mémoire. En 2013, la fonctionnalité de garbage collector était rarement utilisée et a été supprimée par l'équipe au profit du système de propriété. D'autres changements au cours de cette période comprenaient la suppression des fonctions pures , qui étaient déclarées par une pureannotation explicite, en mars 2013. La prise en charge de la syntaxe spécialisée pour les canaux et divers types de pointeurs a été supprimée pour simplifier le langage.
L'expansion et la consolidation de Rust ont été influencées par les développeurs venant de C++ (par exemple, les performances de bas niveau des fonctionnalités), les langages de script (par exemple, la gestion de cargo et de packages) et la programmation fonctionnelle (par exemple, le développement de systèmes de types).
Graydon Hoare a quitté Rust en 2013. Cela lui a permis d'évoluer de manière organique sous une structure de gouvernance plus fédérée, avec une « équipe principale » de 6 personnes au départ, 30 à 40 développeurs au total dans diverses autres équipes et un processus de demande de commentaires (RFC) pour les nouvelles fonctionnalités du langage ajouté en mars 2014. L'équipe principale s'agrandirait à 9 personnes d'ici 2016 avec plus de 1600 RFC proposées.
En janvier 2014, le rédacteur en chef du Dr. Dobb's Journal , Andrew Binstock, a commenté les chances de Rust de devenir un concurrent de C++ , aux côtés de D , Go et Nim (alors Nimrod). Selon Binstock, alors que Rust était « largement considéré comme un langage remarquablement élégant », son adoption a ralenti car il a radicalement changé d'une version à l'autre. Le développement de Rust à cette époque était axé sur la finalisation des fonctionnalités du langage et sur l'évolution vers la version 1.0 afin de pouvoir atteindre la compatibilité ascendante et produire le langage pour une adoption potentielle par l'industrie.
Six ans après que Mozilla ait sponsorisé son développement, la première version stable , Rust 1.0, a été publiée le 15 mai 2015. Un an après la sortie, le compilateur Rust avait accumulé plus de 1 400 contributeurs et plus de 5 000 bibliothèques tierces étaient publiées sur le site Web de gestion de paquets Rust Crates.io.
Servomoteur et adoption précoce (2015-2020)

Le développement du moteur de navigateur Servo s'est poursuivi en parallèle avec Rust, financé conjointement par Mozilla et Samsung . Les équipes derrière les deux projets ont travaillé en étroite collaboration ; de nouvelles fonctionnalités de Rust ont été testées par l'équipe Servo, et de nouvelles fonctionnalités de Servo ont été utilisées pour donner leur avis à l'équipe Rust. La première version de Servo a été publiée en 2016. Le navigateur Web Firefox a été livré avec du code Rust à partir de 2016 (version 45) ; , mais les composants de Servo ne sont apparus dans Firefox qu'en septembre 2017 (version 57) dans le cadre des projets Gecko et Quantum .
Des améliorations ont été apportées à l'écosystème de la chaîne d'outils Rust au cours des années qui ont suivi la version 1.0, notamment Rustfmt, l'intégration d'un environnement de développement intégré , un cycle régulier de tests et de publication du compilateur, un code de conduite communautaire et une discussion communautaire organisée via un chat IRC .
Les premières adoptions en dehors de Mozilla ont été réalisées par des projets individuels chez Samsung, Facebook (maintenant Meta Platforms ), Dropbox et d'autres, dont Tilde, Inc. (la société à l'origine d' ember.js ). Amazon Web Services a suivi en 2020. Les ingénieurs ont cité les performances, l'absence de ramasse-miettes, la sécurité et le plaisir de travailler dans le langage comme raisons de l'adoption, tout en reconnaissant qu'il s'agissait d'un pari risqué car Rust était une nouvelle technologie. Les développeurs d'Amazon ont cité le fait que Rust utilise deux fois moins d'électricité qu'un code similaire écrit en Java , derrière seulement C , comme l'a révélé une étude de l' Université du Minho , de l' Université NOVA de Lisbonne et de l' Université de Coimbra .
Licenciements chez Mozilla et Rust Foundation (2020-présent)
En août 2020, Mozilla a licencié 250 de ses 1 000 employés dans le monde, dans le cadre d’une restructuration d’entreprise provoquée par la pandémie de COVID-19 . L’équipe derrière Servo a été dissoute. L’événement a suscité des inquiétudes quant à l’avenir de Rust, en raison du chevauchement entre les deux projets. La semaine suivante, l’équipe principale de Rust a reconnu le grave impact des licenciements et a annoncé que des plans pour une fondation Rust étaient en cours. Le premier objectif de la fondation serait de prendre possession de toutes les marques et noms de domaine , et d’assumer la responsabilité financière de leurs coûts.
Le 8 février 2021, la création de la Rust Foundation a été annoncée par cinq sociétés fondatrices : Amazon Web Services , Google , Huawei , Microsoft et Mozilla . La fondation, dirigée par Shane Miller pendant ses deux premières années, a offert des subventions de 20 000 $ et d'autres formes de soutien aux programmeurs travaillant sur les principales fonctionnalités de Rust. Dans un article de blog publié le 6 avril 2021, Google a annoncé la prise en charge de Rust au sein du projet Android Open Source comme alternative au C/C++.
Le 22 novembre 2021, l'équipe de modération, chargée de faire respecter le code de conduite de la communauté, a annoncé sa démission « en signe de protestation contre le fait que l'équipe principale se place sans responsabilité envers quiconque sauf elle-même ». En mai 2022, l'équipe principale de Rust, d'autres programmeurs principaux et certains membres du conseil d'administration de la Fondation Rust ont mis en œuvre des réformes de gouvernance en réponse à l'incident.
La Fondation Rust a publié le 6 avril 2023 un projet de nouvelle politique de marque, comprenant des règles sur la manière dont le logo et le nom Rust peuvent être utilisés, ce qui a suscité des réactions négatives de la part des utilisateurs et des contributeurs de Rust.
Syntaxe et fonctionnalités
La syntaxe de Rust est similaire à celle de C et C++, bien que de nombreuses fonctionnalités aient été influencées par des langages de programmation fonctionnels tels que OCaml . Hoare a décrit Rust comme ciblant les développeurs C++ frustrés et a mis l'accent sur des fonctionnalités telles que la sécurité, le contrôle de la disposition de la mémoire et la concurrence . La sécurité dans Rust inclut les garanties de sécurité de la mémoire, de sécurité des types et d'absence de courses de données.
Programme Hello World
Vous trouverez ci-dessous un programme « Hello, World! » en Rust. Le fnmot-clé désigne une fonction et la println!
macro (voir § Macros) imprime le message sur la sortie standard . Les instructions en Rust sont séparées par des points-virgules .
fn main () { println! ( "Bonjour, monde !" ); }
Variables
Les variables dans Rust sont définies via le letmot-clé. L'exemple ci-dessous attribue une valeur à la variable avec le nom foo.
fn main () { let foo = 10 ; println! ( "La valeur de foo est {foo}" ); }
Les variables sont immuables par défaut, et l'ajout du mutmot-clé permet à la variable d'être mutée. L'exemple suivant utilise //, qui désigne le début d'un commentaire .
fn main () { let mut foo = 10 ; // Ce code ne serait pas compilé sans l'ajout de "mut". println! ( "La valeur de foo est {foo}" ); foo = 20 ; println! ( "La valeur de foo est {foo}" ); }
Plusieurs letexpressions peuvent définir plusieurs variables portant le même nom, ce que l'on appelle l'ombrage de variables . L'ombrage de variables permet de transformer des variables sans avoir à les nommer différemment. L'exemple ci-dessous déclare une nouvelle variable portant le même nom et dont la valeur est le double de la valeur d'origine :
fn main () { let foo = 10 ; println! ( "La valeur de foo est {foo}" ); let foo = foo * 2 ; println! ( "La valeur de foo est {foo}" ); }
L'ombrage variable est également possible pour des valeurs de différents types, allant d'une chaîne à sa longueur :
fn main () { laissez les espaces = ; laissez les espaces = les espaces . len (); }
Mots-clés et flux de contrôle
En Rust, les blocs de code sont délimités par des accolades .
ifblocs
Une if
expression conditionnelle exécute du code selon que la valeur donnée est true. elsepeut être utilisée lorsque la valeur est évaluée à false, et peut être utilisée pour combiner plusieurs expressions. elseif
fn main () { let x = 10 ; if x > 5 { println! ( "la valeur est supérieure à cinq" ); } si x % 7 == 0 { println! ( "la valeur est divisible par 7" ); } sinon si x % 5 == 0 { println! ( "la valeur est divisible par 5" ); } sinon { println! ( "la valeur n'est pas divisible par 7 ou 5" ); } }
whileboucles
whilepeut être utilisé pour répéter un bloc de code lorsqu'une condition est remplie.
fn main () { // Itérer sur tous les entiers de 4 à 10 let mut value = 4 ; while value <= 10 { println! ( "value = {value}" ); value += 1 } }
forboucles et itérateurs
Les boucles For dans Rust parcourent les éléments d'une collection. Les expressions « For » fonctionnent sur n'importe quel type d'itérateur .
fn main () { // Utilisation de `for` avec la syntaxe de plage pour la même fonctionnalité que ci-dessus pour la valeur dans 4 ..= 10 { println! ( "value = {value}" ); } }
Dans le code ci-dessus, 4..=10il s'agit d'une valeur de type Rangequi implémente le Iteratortrait. Le code entre accolades est appliqué à chaque élément renvoyé par l'itérateur.
Les itérateurs peuvent être combinés avec des fonctions sur des itérateurs comme map, filteret sum. Par exemple, ce qui suit additionne tous les nombres compris entre 1 et 100 qui sont des multiples de 3 :
( 1 ..= 100 ). filtre ( |& x | x % 3 == 0 ). somme ()
loopet breakdéclarations
Plus généralement, le loopmot-clé permet de répéter une portion de code jusqu'à ce qu'un breakévénement se produise. breakpeut éventuellement quitter la boucle avec une valeur. Les étiquettes désignées par peuvent être utilisées pour rompre une boucle externe lorsque les boucles sont imbriquées. 'label_name
fn main () { let value = 456 ; let mut x = 1 ; let y = loop { x *= 10 ; if x > value { break x / 10 ; } }; println! ( "plus grande puissance de dix qui est inférieure ou égale à value: {y}" ); laissez mut up = 1 ; ' externe : boucle { laissez mut down = 120 ; boucle { si up > 100 { cassez 'externe ; } si en bas < 4 { pause ; } bas /= 2 ; haut += 1 ; println! ( "haut : {haut}, bas : {bas}" ); } haut *= 2 ; } }
Expressions
Rust est orienté expression , avec presque chaque partie d'un corps de fonction étant une expression , y compris les opérateurs de flux de contrôle. L' ifexpression est utilisée pour fournir l' opérateur conditionnel ternaire . Les retours étant implicites, une fonction n'a pas besoin de se terminer par une returnexpression ; si le point-virgule est omis, la valeur de la dernière expression de la fonction est utilisée comme valeur de retour , récursive suivante de la fonction factorielle :
fn factorielle ( i : u64 ) -> u64 { si i == 0 { 1 } sinon { i * factorielle ( i - 1 ) } }
L' implémentation itérative suivante utilise l' ..=opérateur pour créer une plage inclusive :
fn factorielle ( i : u64 ) -> u64 { ( 2 ..= i ). produit () }
Correspondance de motifs
Les expressions matchet peuvent être utilisées pour la recherche de motifs . Par exemple, elles peuvent être utilisées pour doubler une valeur entière facultative si elle est présente, et renvoyer zéro dans le cas contraire : ifletmatch
fn double ( x : Option < u64 > ) -> u64 { correspond à x { Certains ( x ) => x * 2 , Aucun => 0 , } }
De manière équivalente, ceci peut être écrit avec et : ifletelse
fn double ( x : Option < u64 > ) - > u64 { si Soit ( x ) = x { x * 2 } sinon { 0 } }
Types
Rust est fortement typé et typé statiquement . Les types de toutes les variables doivent être connus au moment de la compilation ; l'attribution d'une valeur d'un type particulier à une variable typée différemment provoque une erreur de compilation . L'inférence de type est utilisée pour déterminer le type des variables si elles ne sont pas spécifiées.
Le type entier par défaut est i32, et le type à virgule flottante par défaut est f64. Si le type d'un nombre littéral n'est pas fourni explicitement, il est déduit du contexte ou le type par défaut est utilisé.
Types primitifs
Les types entiers dans Rust sont nommés en fonction de la signature et du nombre de bits que le type prend. Par exemple, i32est un entier signé qui prend 32 bits de stockage, alors que u8est non signé et ne prend que 8 bits de stockage. isizeet usizeprennent du stockage en fonction de l'architecture de l'ordinateur qui exécute le code, par exemple, sur les ordinateurs avec des architectures 32 bits , les deux types prendront 32 bits d'espace.
Par défaut, les littéraux entiers sont en base 10, mais différentes racines sont prises en charge avec des préfixes, par exemple 0b11pour les nombres binaires , 0o567pour les octaux et 0xDBpour les hexadécimaux . Par défaut, les littéraux entiers ont par défaut i32comme type. Des suffixes tels que 4u32peuvent être utilisés pour définir explicitement le type d'un littéral. Les littéraux d'octets tels que b'X'sont disponibles pour représenter la valeur ASCII (en u8) d'un caractère spécifique.
Le type booléen est appelé boolqui peut prendre une valeur de trueou false. A charoccupe 32 bits d'espace et représente une valeur scalaire Unicode : un point de code Unicode qui n'est pas un substitut . IEEE 754 sont pris en charge avec f32pour les flottants à simple précision et f64pour les flottants à double précision .
Types définis par l'utilisateur
Les types définis par l'utilisateur sont créés avec les mots-clés structou enum. Le structmot-clé est utilisé pour désigner un type d'enregistrement qui regroupe plusieurs valeurs liées. enum Les types peuvent prendre différentes variantes lors de l'exécution, avec des capacités similaires aux types de données algébriques trouvés dans les langages de programmation fonctionnelle. Les structures et les énumérations peuvent contenir des champs de types différents. Des noms alternatifs pour le même type peuvent être définis avec le typemot-clé.
Le implmot clé peut définir des méthodes pour un type défini par l'utilisateur. Les données et les fonctions sont définies séparément. Les implémentations remplissent un rôle similaire à celui des classes dans d'autres langages.
Bibliothèque standard
| Taper | Description | Exemples | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
String
|
Chaînes codées en UTF-8 (dynamiques) | ||||||||||||||||
| Chaînes natives de la plateforme (empruntées et dynamiques ) | |||||||||||||||||
| Chemins (empruntés et dynamiques ) | |||||||||||||||||
| Chaînes compatibles C , terminées par un caractère nul (empruntées et dynamiques ) | |||||||||||||||||
Vec<T>
|
Tableaux dynamiques | ||||||||||||||||
Option<T>
|
Type d'option | ||||||||||||||||
Result<T,E>
|
Gestion des erreurs à l'aide d'un type de résultat | ||||||||||||||||
Box<T>
|
Un pointeur vers une valeur allouée au tas . Similaire à std::unique_ptr de C++. | laissez boxed : Box < u8 > = Box :: new ( 5 ); laissez val : u8 = * boxed ; | |||||||||||||||
Rc<T>
|
Pointeur de comptage de référence | laissez cinq = Rc :: new ( 5 ); laissez aussi_cinq = cinq . clone (); | |||||||||||||||
Arc<T>
|
Pointeur de comptage de référence atomique et thread-safe | laissez foo = Arc :: new ( vec! [ 1.0 , 2.0 ]); laissez a = foo . clone (); // a peut être envoyé à un autre thread | |||||||||||||||
Cell<T>
|
Un emplacement de mémoire mutable | laissez c = Cellule :: nouvelle ( 5 ); c . ensemble ( 10 ); | |||||||||||||||
Mutex<T>
|
Un verrou mutex pour les données partagées contenues à l'intérieur. | laissez mutex = Mutex :: new ( 0_ u32 ); laissez _guard = mutex . lock (); | |||||||||||||||
RwLock<T>
|
Verrouillage des lecteurs et des écrivains | laissez lock = RwLock :: new ( 5 ); laissez r1 = lock . read (). unwrap (); | |||||||||||||||
Condvar
|
Un moniteur conditionnel pour les données partagées | let ( lock , cvar ) = ( Mutex :: new ( true ), Condvar :: new ()); // Tant que la valeur à l'intérieur de `Mutex<bool>` est `true`, nous attendons. let _guard = cvar . wait_while ( lock . lock (). unwrap (), | en attente | { * en attente }). unwrap (); | |||||||||||||||
Duration
|
Type qui représente une période de temps | Durée :: from_millis ( 1 ) // 1ms | |||||||||||||||
HashMap<K,V>
|
Table de hachage | laissez mut player_stats = HashMap :: new (); player_stats . insert ( "dommages" , 1 ); player_stats . entry ( "santé" ). or_insert ( 100 ); | |||||||||||||||
BTreeMap<K,V>
|
Arbre B | laissez mut solar_distance = BTreeMap :: from ([ ( "Mercure" , 0.4 ), ( "Vénus" , 0.7 ), ]); solar_distance . entry ( "Terre" ). or_insert ( 1.0 );
fn main () { let name1 : Option <& str > = None ; // Dans ce cas, rien ne sera imprimé si let Some ( name ) = name1 { println! ( "{name}" ); } let name2 : Option <& str > = Some ( "Matthew" ); // Dans ce cas, le mot "Matthew" sera imprimé si let Some ( name ) = name2 { println! ( "{name}" ); } } Pointeurs
|





