Rust (langage de programmation) - Rust (programming language)
Paradigmes | Multi-paradigme : concurrent , fonctionnel , générique , impératif , structuré |
---|---|
Conçu par | Graydon Hoare |
Développeur | La Fondation de la rouille |
Première apparition | 7 juillet 2010 |
Version stable | |
Discipline de frappe | Affine , inférée , nominale , statique , forte |
Langage d'implémentation | Rouiller |
Plate-forme | AMD64 , i686 , arm , AArch64 , armv7 , mips , mips64 , mipsel , mips64el , powerpc , powerpc64 , powerpc64le , risc-v , s390x , WebAssembly |
Système d'exploitation | Windows , Linux , macOS , FreeBSD , NetBSD , Illumos , Haiku , Android , Redox , iOS , Fuchsia |
Licence | MIT ou Apache 2.0 |
Extensions de nom de fichier | .rs, .rlib |
Site Internet | www |
Influencé par | |
Influencé | |
Rust est un multi-paradigme , langage de programmation à usage général conçu pour la performance et la sécurité , en particulier la sécurité concurrency . Rust est syntaxiquement similaire à C++ , mais peut garantir la sécurité de la mémoire en utilisant un vérificateur d'emprunt pour valider les références . Rust assure la sécurité de la mémoire sans récupération de place et le comptage des références est facultatif. Rust a été appelé un langage de programmation système et en plus des fonctionnalités de haut niveau telles que la programmation fonctionnelle, il offre également des mécanismes de gestion de la mémoire de bas niveau .
Rust a été conçu à l'origine par Graydon Hoare de Mozilla Research, avec des contributions de Dave Herman, Brendan Eich et d'autres. Les concepteurs ont affiné le langage en écrivant le moteur de navigateur expérimental Servo et le compilateur Rust . Il est de plus en plus utilisé dans l'industrie et Microsoft a expérimenté le langage pour les composants logiciels sécurisés et critiques pour la sécurité.
Rust a été élu "langage de programmation le plus apprécié" dans le Stack Overflow Developer Survey chaque année depuis 2016, bien qu'il n'ait été utilisé que par 7 % des personnes interrogées en 2021.
Histoire
La langue est née d'un projet personnel commencé en 2006 par Graydon Hoare, employé de Mozilla. Hoare a déclaré que le projet portait peut-être le nom de champignons de la rouille et que le nom est également une sous-chaîne de « robuste ». Mozilla a commencé à sponsoriser le projet en 2009 et l'a annoncé en 2010. La même année, le travail est passé du compilateur initial (écrit en OCaml ) à un compilateur auto-hébergé basé sur LLVM écrit en Rust. Nommé rustc , il s'est compilé avec succès en 2011.
La première version pré-alpha numérotée du compilateur Rust a eu lieu en janvier 2012. Rust 1.0, la première version stable, a été publiée le 15 mai 2015. Après 1.0, les versions ponctuelles stables sont livrées toutes les six semaines, tandis que les fonctionnalités sont développées tous les soirs. Rust avec des versions quotidiennes, puis testé avec des versions bêta qui durent six semaines. Tous les 2 à 3 ans, une nouvelle "Edition" Rust est produite. Il s'agit de fournir un point de référence facile pour les modifications dues à la nature fréquente du calendrier de publication de Rust's Train, ainsi que de fournir une fenêtre pour apporter des modifications de rupture. Les éditions sont largement compatibles.
En plus du typage statique conventionnel , avant la version 0.4, Rust prenait également en charge les typesstates . Le système typestate modélisait les assertions avant et après les instructions du programme, grâce à l'utilisation d'une check
instruction spéciale . Des divergences pourraient être découvertes au moment de la compilation , plutôt qu'au moment de l' exécution , comme cela pourrait être le cas avec les assertions dans le code C ou C++. Le concept d'état de type n'était pas unique à Rust, car il a été introduit pour la première fois dans le langage NIL . Les états de type ont été supprimés car en pratique ils étaient peu utilisés, bien que la même fonctionnalité puisse être obtenue en tirant parti de la sémantique de déplacement de Rust .
Le style du système d'objets a considérablement changé dans les versions 0.2, 0.3 et 0.4 de Rust. La version 0.2 a introduit les classes pour la première fois, et la version 0.3 a ajouté plusieurs fonctionnalités, notamment les destructeurs et le polymorphisme via l'utilisation d'interfaces. Dans Rust 0.4, des traits ont été ajoutés comme moyen de fournir l' héritage ; les interfaces ont été unifiées avec des traits et supprimées en tant que fonctionnalité distincte. Les classes ont également été supprimées et remplacées par une combinaison d'implémentations et de types structurés .
À partir de Rust 0.9 et jusqu'à Rust 0.11, Rust avait deux types de pointeurs intégrés : ~
et @
, simplifiant le modèle de mémoire de base . Il a réimplémenté ces types de pointeur dans la bibliothèque standard en tant que Box
and (maintenant supprimé) Gc
.
En janvier 2014, avant la première version stable, Rust 1.0, le rédacteur en chef de Dr. Dobb's , Andrew Binstock, a commenté les chances de Rust de devenir un concurrent du C++ et des autres langages émergents D , Go , et Nim (alors Nimrod). Selon Binstock, alors que Rust était « largement considéré comme un langage remarquablement élégant », l'adoption a ralenti car il changeait à plusieurs reprises entre les versions.
Rust a une interface de fonction étrangère (FFI) qui peut être appelée depuis, par exemple, le langage C, et peut appeler C. Bien qu'appeler C++ ait toujours été difficile (depuis n'importe quel langage), Rust a une bibliothèque, CXX, pour permettre d'appeler ou de C++, et "CXX a une surcharge nulle ou négligeable."
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 causée par l'impact à long terme de la pandémie de COVID-19 . Parmi les personnes licenciées figuraient la plupart des membres de l'équipe Rust, tandis que l'équipe Servo était complètement dissoute. L'événement a soulevé des inquiétudes quant à l'avenir de Rust.
La semaine suivante, l'équipe Rust Core 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 s'approprier toutes les marques et noms de domaine , et d'assumer également la responsabilité financière de leurs coûts.
Le 8 février 2021, la formation de la Rust Foundation a été officiellement annoncée par ses cinq sociétés fondatrices ( AWS , Huawei , Google , Microsoft et Mozilla).
Le 6 avril 2021, Google a annoncé la prise en charge de Rust dans Android Open Source Project comme alternative à C/C++.
Syntaxe
Voici un "Hello, World!" programme écrit en Rust. La println!
macro imprime le message sur la sortie standard .
fn main() {
println!("Hello, World!");
}
La syntaxe de rouille est similaire à C et C ++ , avec des blocs de code délimité par des accolades , et le contrôle de flux des mots clés tels que if
, else
, while
et for
, bien que la syntaxe spécifique pour la définition des fonctions est plus semblable à Pascal . Malgré la ressemblance syntaxique avec C et C++, la sémantique de Rust est plus proche de celle de la famille de langages ML et du langage Haskell . Presque chaque partie d'un corps de fonction est une expression , même des opérateurs de flux de contrôle. Par exemple, l' if
expression ordinaire remplace également le conditionnel ternaire de C , un idiome utilisé par ALGOL 60 . Comme dans Lisp , une fonction n'a pas besoin de se terminer par une return
expression : dans ce cas, si le point-virgule est omis, la dernière expression de la fonction crée la valeur de retour , comme le montre l' implémentation récursive suivante de la fonction factorielle :
fn factorial(i: u64) -> u64 {
match i {
0 => 1,
n => n * factorial(n-1)
}
}
L' implémentation itérative suivante utilise l' ..=
opérateur pour créer une plage inclusive :
fn factorial(i: u64) -> u64 {
(2..=i).product()
}
Des fonctionnalités plus avancées dans Rust incluent l'utilisation de fonctions génériques pour réaliser le polymorphisme de type . Ce qui suit est un programme Rust pour calculer la somme de deux choses, pour lesquelles l'addition est implémentée, en utilisant une fonction générique :
use std::ops::Add;
fn Sum<T: Add<Output = T> + Copy> (num1: T, num2: T) -> T {
num1 + num2
}
fn main() {
let result1 = Sum(10,20);
println!("Sum is: {:?}", result1);
let result2 = Sum(10.23,20.45);
println!("Sum is: {:?}", result2);
}
Caractéristiques
Rust est destiné à être un langage pour les systèmes hautement concurrents et hautement sécurisés , et la programmation dans le grand , c'est-à-dire la création et le maintien de limites qui préservent l'intégrité du grand système. Cela a conduit à un ensemble de fonctionnalités mettant l'accent sur la sécurité, le contrôle de la disposition de la mémoire et la simultanéité .
Sécurité de la mémoire
Rust est conçu pour protéger la mémoire . Il n'autorise pas les pointeurs nuls , les pointeurs pendants ou les courses de données . Les valeurs de données ne peuvent être initialisées que via un ensemble fixe de formulaires, qui nécessitent tous que leurs entrées soient déjà initialisées. Pour répliquer des pointeurs valides ou NULL
, comme dans les structures de données de liste chaînée ou d' arborescence binaire , la bibliothèque principale de Rust fournit un type d' option , qui peut être utilisé pour tester si un pointeur a une valeur ou . Rust a ajouté une syntaxe pour gérer les durées de vie , qui sont vérifiées au moment de la compilation par le vérificateur d'emprunt . Un code dangereux peut subvertir certaines de ces restrictions à l'aide du mot - clé.
Some
None
unsafe
Gestion de la mémoire
Rust n'utilise pas le ramasse-miettes automatisé . La mémoire et les autres ressources sont gérées via l' acquisition de ressources selon la convention d' initialisation , avec un comptage de références facultatif . Rust fournit une gestion déterministe des ressources, avec une surcharge très faible . Rust favorise l' allocation des valeurs par pile et n'effectue pas de boxing implicite .
Il y a le concept de références (à l'aide du &
symbole), qui n'implique pas le comptage de références à l'exécution. La sécurité de ces pointeurs est vérifiée au moment de la compilation, empêchant les pointeurs pendants et d'autres formes de comportement indéfini . Le système de types de Rust sépare les pointeurs partagés et immuables du formulaire &T
des pointeurs uniques et mutables du formulaire &mut T
. Un pointeur mutable peut être contraint à un pointeur immuable, mais pas l'inverse.
La possession
Rust a un système de propriété où toutes les valeurs ont un propriétaire unique, et la portée de la valeur est la même que la portée du propriétaire. Les valeurs peuvent être passées par référence immuable, à l'aide de &T
, par référence mutable, à l'aide de &mut T
, ou par valeur, à l'aide de T
. À tout moment, il peut y avoir soit plusieurs références immuables, soit une seule référence mutable (un verrou de lecture-écriture implicite ). Le compilateur Rust applique ces règles au moment de la compilation et vérifie également que toutes les références sont valides.
Types et polymorphisme
Le système de types de Rust prend en charge un mécanisme appelé traits , inspiré des classes de types du langage Haskell . Les traits annotent les types et sont utilisés pour définir un comportement partagé entre différents types : par exemple, les flottants et les entiers peuvent tous deux implémenter un trait « Ajouter » car ils peuvent tous les deux être ajoutés ; et tout type pouvant être imprimé sous forme de chaîne implémente les traits « Affichage » ou « Débogage ». Cette facilité est connue sous le nom de polymorphisme ad hoc .
Rust utilise l' inférence de type pour les variables déclarées avec le mot - clélet
. De telles variables ne nécessitent pas qu'une valeur soit initialement affectée pour déterminer leur type. Une erreur de compilation se produit si une branche de code quitte la variable sans affectation. Les variables affectées plusieurs fois doivent être marquées avec le mot-clé mut
(abréviation de mutable).
Une fonction peut recevoir des paramètres génériques , ce qui permet d'appliquer la même fonction à différents types. Les fonctions génériques peuvent contraindre le type générique à implémenter un ou plusieurs traits particuliers ; par exemple, une fonction « ajouter un » peut nécessiter que le type implémente « Ajouter ». Cela signifie qu'une fonction générique peut être vérifiée de type dès qu'elle est définie.
L'implémentation des génériques Rust est similaire à l'implémentation typique des modèles C++ : une copie distincte du code est générée pour chaque instanciation. C'est ce qu'on appelle la monomorphisation et contraste avec le schéma d' effacement de type généralement utilisé en Java et Haskell. L'effacement de type de Rust est également disponible en utilisant le mot-clé dyn
. L'avantage de la monomorphisation est un code optimisé pour chaque cas d'utilisation spécifique ; l'inconvénient est l'augmentation du temps de compilation et de la taille des binaires résultants.
Dans Rust, les types définis par l'utilisateur sont créés avec le struct
mot - clé. Ces types contiennent généralement des champs de données comme des objets ou des classes dans d'autres langages. Le impl
mot-clé peut définir des méthodes pour la structure (les données et la fonction sont définies séparément dans une structure) ou implémenter un trait pour la structure. Un trait est un contrat selon lequel une structure a mis en œuvre certaines méthodes requises. Les traits sont utilisés pour restreindre les paramètres génériques et parce que les traits peuvent fournir une structure avec plus de méthodes que celles définies par l'utilisateur. Par exemple, le trait Iterator
requiert que la next
méthode soit définie pour le type. Une fois la next
méthode définie, le trait fournit des méthodes d'assistance fonctionnelles communes sur l'itérateur comme map
ou filter
.
Le système d'objets au sein de Rust est basé sur des implémentations, des traits et des types structurés. Les implémentations remplissent un rôle similaire à celui des classes dans d'autres langages et sont définies avec le mot-clé impl
. Les traits fournissent l'hérédité et le polymorphisme ; ils permettent des méthodes à définir et mélangés dans des mises en œuvre. Les types structurés sont utilisés pour définir les champs. Les implémentations et les traits ne peuvent pas définir les champs eux-mêmes, et seuls les traits peuvent fournir l'héritage. Entre autres avantages, cela évite le problème du diamant de l' héritage multiple , comme en C++. En d'autres termes, Rust prend en charge l'héritage d'interface mais remplace l'héritage d'implémentation par la composition ; voir la composition sur l'héritage .
Composants
Rust comporte un grand nombre de composants qui étendent l'ensemble des fonctionnalités de Rust et facilitent le développement de Rust. L'installation des composants est généralement gérée par rustup, un programme d' installation de la chaîne d'outils Rust développé par le projet Rust.
Cargaison
Cargo est le système de construction et le gestionnaire de paquets de Rust . Cargo gère le téléchargement des dépendances et la création de dépendances. Cargo agit également comme un emballage pour les composants clippy et autres Rust. Cela nécessite que les projets suivent une certaine structure de répertoires.
Les dépendances d'un package Rust sont spécifiées dans un Cargo. toml avec les exigences de version , indiquant à Cargo quelles versions de la dépendance sont compatibles avec le package. Par défaut, Cargo tire ses dépendances du registre crates.io fourni par l'utilisateur, mais les référentiels et packages Git du système de fichiers local peuvent également être spécifiés en tant que dépendances.
Rustfmt
Rustfmt est un formateur de code pour Rust. Il prend le code source de Rust en entrée et modifie les espaces et l' indentation pour produire du code formaté conformément au guide de style Rust ou aux règles spécifiées dans un fichier rustfmt.toml. Rustfmt peut être invoqué en tant que programme autonome ou sur un projet Rust via Cargo.
Clippy
Clippy est l' outil de linting intégré de Rust pour améliorer l'exactitude, les performances et la lisibilité du code Rust. Il a été créé en 2014 et nommé d'après la fonctionnalité éponyme de Microsoft Office . Depuis 2021, Clippy compte plus de 450 règles, qui peuvent être consultées en ligne et filtrées par catégorie. Certaines règles sont désactivées par défaut.
RLS
RLS est un serveur de langage qui fournit aux IDE et aux éditeurs de texte plus d'informations sur un projet Rust. Il fournit des contrôles de linting via Clippy , un formatage via Rustfmt, la complétion automatique du code via Racer , entre autres fonctions. Le développement de Racer a été ralenti au profit de l' analyseur de rouille .
Extensions de langue
Il est possible d'étendre le langage Rust en utilisant le mécanisme de macro procédural.
Les macros procédurales utilisent des fonctions Rust qui s'exécutent au moment de la compilation pour modifier le flux de jetons du compilateur. Cela complète le mécanisme de macro déclarative (également connu sous le nom de macros par exemple ), qui utilise la correspondance de modèles pour atteindre des objectifs similaires.
Les macros procédurales sont disponibles en trois versions :
- Macros de type fonction
custom!(...)
- Dériver des macros
#[derive(CustomDerive)]
- Macros d'attributs
#[custom_attribute]
La println!
macro est un exemple de macro de type fonction et serde_derive
est une bibliothèque couramment utilisée pour générer du code pour lire et écrire des données dans de nombreux formats tels que JSON . Les macros d'attributs sont couramment utilisées pour les liaisons de langage telles que la extendr
bibliothèque pour les liaisons Rust à R .
Le code suivant montre l'utilisation du Serialize
, Deserialize
et Debug
dérivent des macros de procédure à mettre en œuvre la lecture et l' écriture JSON ainsi que la possibilité de formater une structure pour le débogage.
use serde_json::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
println!("serialized = {}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("deserialized = {:?}", deserialized);
}
Performance
Rust vise "à être aussi efficace et portable que le C++ idiomatique , sans sacrifier la sécurité". Étant donné que Rust utilise LLVM , toutes les améliorations de performances dans LLVM sont également transférées à Rust.
Adoption
Rust a été adopté par de grandes sociétés d'ingénierie logicielle. Par exemple, Dropbox est maintenant écrit en Rust ainsi que certains composants chez Amazon , Facebook , Discord et la Fondation Mozilla . Rust était le troisième langage de programmation le plus apprécié dans l'enquête annuelle Stack Overflow de 2015 et a pris la première place pour la période 2016-2021.
Navigateurs et services Web
- Firefox a deux projets écrits en Rust : le moteur de navigation parallèle Servo développé par Mozilla en collaboration avec Samsung ; et Quantum , qui est composé de plusieurs sous-projets pour améliorer le moteur de navigation Gecko de Mozilla .
- OpenDNS utilise Rust dans deux de ses composants.
- Deno , un environnement d'exécution sécurisé pour JavaScript et TypeScript , est construit avec V8 , Rust et Tokio.
- Figma , un éditeur de graphiques vectoriels basé sur le Web, est écrit en Rust.
Systèmes d'exploitation
- Redox est un "système d'exploitation à part entière de type Unix" comprenant un micronoyau écrit en Rust.
- Theseus, un système d'exploitation expérimental à "conception intralingue", est écrit en Rust.
- Le système d'exploitation basé sur les capacités de Google Fuchsia dispose de certains outils écrits en Rust.
- Stratis est un gestionnaire de système de fichiers écrit en Rust pour Fedora et RHEL 8.
Autres projets et plateformes notables
- Discord utilise Rust pour des parties de son backend, ainsi que l'encodage vidéo côté client, pour augmenter l'infrastructure de base écrite en Elixir .
- Microsoft Azure IoT Edge, une plate-forme utilisée pour exécuter les services Azure et l'intelligence artificielle sur les appareils IoT, a des composants implémentés dans Rust.
- Polkadot (crypto-monnaie) est une plateforme blockchain écrite en Rust.
- TerminusDB , une base de données de graphes open source conçue pour la création et la conservation collaboratives de graphes de connaissances , est écrite en Prolog et Rust.
Gouvernance
Formation | 8 février 2021 |
---|---|
Fondateurs | |
Taper | Organisation à but non lucratif |
Emplacement | |
Shane Miller | |
Rébecca Rumbul | |
Site Internet | fondation |
La rouille Fondation est un but non lucratif organisation de membres incorporés dans le Delaware , États-Unis , les principaux objectifs de soutenir le maintien et le développement de la langue, la culture des membres de l' équipe du projet de Rust et des communautés d'utilisateurs, la gestion de l'infrastructure technique sous - jacente au développement de la rouille , et la gestion et la gestion de la marque Rust.
Il a été créé le 8 février 2021 avec cinq membres fondateurs (Amazon Web Services, Huawei, Google, Microsoft et Mozilla). Le conseil d'administration de la fondation est présidé par Shane Miller. À partir de fin 2021, sa directrice exécutive et PDG est Rebecca Rumbul. Avant cela, Ashley Williams était directrice exécutive par intérim.
Développement
Les conférences Rust incluent :
- RustConf : une conférence annuelle à Portland, Oregon . Tenue annuellement depuis 2016 (sauf en 2020 et 2021 en raison de la pandémie de COVID-19 ).
- Rust Belt Rust : une conférence #rustlang dans la Rust Belt
- RustFest : la conférence européenne @rustlang
- RustCon Asie
- Rouille LATAM
- Oxyder Global