EDIT: 13/06/2017
Une issue sur le dépôt de Cargo a été ouverte, et les nouveaux flags annoncés pour ce dernier dans le billet de la version 1.18 étaient en fait prévus pour la 1.19. Ne soyez donc pas étonnés si vous ne parvenez pas à les utiliser dans votre version actuelle.
Une issue sur le dépôt de Cargo a été ouverte, et les nouveaux flags annoncés pour ce dernier dans le billet de la version 1.18 étaient en fait prévus pour la 1.19. Ne soyez donc pas étonnés si vous ne parvenez pas à les utiliser dans votre version actuelle.
Cette version est un agrégat de fonctionnalités venant fignoler ce qui avait été ajouté dans les versions précédentes, comme nous allons le voir plus bas, et ce n'est pas pour nous déplaire !
Réécriture du livre officiel
Commençons par les ressources gravitant autour du langage.
L'équipe Rust a annoncé la réécriture du livre officiel "The Rust Programming Language" jugeant, après ces deux dernières années, que de nouvelles explications devaient être apportées à propos des concepts abordés dans le livre.
Vous êtes, bien entendu, invité à consulter la seconde édition sur le site de la documentation officielle, mais gardez tout de même à l'esprit que vous lisez une ébauche et que de nouveaux chapitres seront apportés dans la version 1.19 de Rust.
Notez aussi qu'une version papier sera proposée, lors de la publication finale du livre.
Extension du mot-clé pub
Comme nous le savons, toutes les ressources d'un module rust sont, par défaut, privées et le mot-clé pub permet de remédier à cela.
Avec la 1.18, pub gagne en précision:
Code Rust : | Sélectionner tout |
pub(crate) bar;
Il est désormais possible grâce aux () de définir le contexte dans lequel une ressource (e.g. structures, énumérations, fonctions) peut être visible. En l'occurrence, lorsque vous utilisez le mot-clé crate, vous établissez la restriction suivante: bar est visible pour tous les composants du package, mais pas en-dehors.
Ces restrictions peuvent vous faciliter la tâche, si vous souhaitez user d'une API qui ne devrait communiquer qu'avec les composants de votre package.
Vous pouvez également spécifier un chemin comme ceci:
Code Rust : | Sélectionner tout |
pub(in a::b::c) foo;
Vous rendez donc visible cette ressource dans la hiérarchie a::b::c, mais nulle part ailleurs.
a, b et c doivent être, en revanche, des modules parents de foo.
Pour plus d'informations à propos de cette fonctionnalité, je vous invite à consulter sa RFC et la documentation officielle.
Support du flag /SUBSYSTEM
Pour les utilisateurs Windows, la 1.18 apporte l'attribut #![windows_subsystem]. Voici un exemple d'utilisation :
Code Rust : | Sélectionner tout |
1 2 3 | #![windows_subsystem(console)] #![windows_subsystem(windows)] |
Ces arguments vous permettent de contrôler le flag /SUBSYSTEM et de choisir l'environnement dans lequel sera exécuté votre programme. Ils peuvent donc être utiles, par exemple, lorsque vous développez une application supportant une interface graphique et que vous ne souhaitez plus voir la console clignoter au lancement de votre programme. Vous utiliserez donc windows pour régler ce problème.
Pour le moment, seuls les environnements console et windows sont supportés par Rust.
Rustc
Optimisation de l'alignement mémoire
Il est possible d'aligner des données pour réduire le temps des accès (i.e. lecture/écriture) sur ces dernières. Toutefois, lorsqu'elles ne le sont pas (alignées), le compilateur tentera de le faire à notre place, au prix d'une consommation de mémoire plus importante.
Code Rust : | Sélectionner tout |
struct Suboptimal(u8, u16, u8);
Dans les versions précédentes de Rust, sur une plateforme x86_64, cette structure consommait six octets. Pourtant, en visionnant le code source, vous n'en comptez que quatre.
Les deux autres octets viennent de la compensation effectuée par le compilateur; sachant que nous avons un entier u16 ici, il devrait être aligné sur une adresse paire.
On « décale » alors le premier entier u8 d'un octet, et, pour aligner correctement la structure, on fait de même pour le dernier u8. Ce qui nous donne: 1 + 1 (compensation) + 2 + 1 + 1 (compensation) = 6 octets.
Quid de cette structure, dans ce cas ?
Code Rust : | Sélectionner tout |
struct Optimal(u8, u8, u16);
Celle-ci est correctement alignée, l'entier u16 se trouve sur une adresse paire, l'intégralité de la structure est alignée, aucune compensation n'est requise. Ce qui nous donne : 1 + 1 + 2 = 4 octets.
Avec la 1.18, le compilateur est capable d'aligner (si possible) une structure sans compensation (i.e. d'appliquer la signature de Optimal à SubOptimal, en quelque sorte), épargnant la mémoire par la même occasion.
Code Rust : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | // compilé avec rustc 1.18 use std::mem; struct Optimal(u8, u8, u16); struct Suboptimal(u8, u16, u8); fn main() -> (){ println!("size of Optimal:{}bytes", mem::size_of::<Optimal>()); println!("size of Suboptimal:{}bytes", mem::size_of::<Suboptimal>()); } |
Code : | Sélectionner tout |
1 2 3 | size of Optimal:4bytes size of Suboptimal:4bytes |
Vous n'êtes pas très familier avec cette optimisation ? Vous trouverez des liens en bas de l'article, si vous souhaitez vous documenter.
Nouveau flag pour l'argument `--emit`
Pour examiner la MIR (Mid-level Intermediate Representation) d'un morceau de code, il était nécessaire, jusqu'ici, de consulter le compilateur en ligne. Ce n'est plus le cas !
Une fois votre compilateur mis à jour, il vous suffit de vous rendre dans le répertoire de votre choix et compiler le fichier désiré :
Code Rust : | Sélectionner tout |
rustc hello.rs --emit mir
Vous trouverez un fichier nommé hello.mir dans le répertoire courant, contenant la MIR :
Code Rust : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // WARNING: This output format is intended for human consumers only // and is subject to change without notice. Knock yourself out. fn main() -> () { let mut _0: (); // return pointer scope 1 { let _1: &str; // "foo" in scope 1 at hello.rs:3:6: 3:9 } bb0: { StorageLive(_1); // scope 0 at hello.rs:3:6: 3:9 _1 = const "Hello, there!"; // scope 0 at hello.rs:3:12: 3:27 _0 = (); // scope 1 at hello.rs:2:10: 4:2 StorageDead(_1); // scope 0 at hello.rs:4:2: 4:2 return; // scope 0 at hello.rs:4:2: 4:2 } } |
Cargo
Pijul
Le système de contrôle de version Pijul est désormais supporté par cargo !
Pour pouvoir créer un projet avec ce VCS, il vous suffit de taper la commande cargo new myAwesomeProject --vcs=pijul.
Pour plus d'informations, rendez-vous sur la pull request #3842.
Nouveaux flags
Le flag --all permet de compiler tous types de sources pouvant se trouver dans votre projet (i.e. exemples, sources du programme, tests, benchmarks). Vous pouvez maintenant cibler uniquement le type de sources que vous souhaitez compiler grâce aux quatre flags fraîchement débarqués :
- --bins: Compile toutes les sources;
- --examples: Compile tous les exemples;
- --tests: Compile tous les tests;
- --benches: Compile tous les benchmarks du projet.
Pour utiliser ces nouvelles fonctionnalités, il vous faudra mettre à jour cargo à la version 0.21.0.
Haiku et Android
Enfin, Cargo supporte Haiku et Android dans sa chaîne de build !
Le principal est ici, mais n'hésitez pas à consulter le billet de blog officiel si vous souhaitez vous rendre sur la release note ou encore les RFC de la version.
Source
Le blog du langage Rust
Fonctionnement de l'annotation #[repr(C)]
Ressources sur l'alignement mémoire
Vous n'êtes pas obligé de visiter tous les liens proposés pour comprendre ce qui a été rédigé. Chaque lien aborde simplement, d'une manière différente, ce concept.
Définition de l'alignement mémoire (en français)
Fonctionnement de l'alignement mémoire (en anglais)
Article d'IBM sur la manière dont le processeur gère la mémoire (en anglais)
Alignement mémoire avec C (en anglais)