Rust 1.99.0 est disponible depuis le 1er octobre 2026. Cette version stable élargit les possibilités d’interopérabilité avec le C, complète plusieurs outils de manipulation de la mémoire et ajoute des fonctions pratiques à la bibliothèque standard. Cargo évolue également, avec un nouveau profil de compilation nommé debug.
Pour un développeur d’applications, toutes ces nouveautés n’ont pas la même importance. Les fonctions variadiques concernent surtout les échanges avec du code natif ; les améliorations des collections et des chaînes peuvent être utiles dans des programmes beaucoup plus ordinaires. Je vous propose de regarder ce que cette version permet réellement, avec quelques exemples et les points à vérifier avant de l’adopter.
Rust peut désormais définir des fonctions variadiques compatibles avec le C
Une fonction variadique accepte un nombre variable d’arguments. L’exemple classique côté C est une fonction de formatage à laquelle on transmet des valeurs supplémentaires selon le texte à produire. Rust savait déjà appeler des fonctions de ce genre définies ailleurs. Avec Rust 1.99.0, il devient possible d’en écrire directement en Rust avec les conventions d’appel extern "C" et extern "C-unwind".
La différence porte donc sur le sens de l’interopérabilité : le langage ne se contente plus d’être client de certaines interfaces C, il peut aussi en fournir une implémentation variadique. La liste variable d’arguments est représentée par VaList, avec une compatibilité prévue avec le va_list du C. Les types que l’on peut en extraire sont encadrés par le trait VaArgSafe.
Cette possibilité conserve les contraintes du monde C. La présence d’arguments et leur type doivent correspondre à ce que la fonction attend. Elle ne transforme pas une interface variadique en collection automatiquement vérifiée de valeurs Rust. Les contrats de sécurité restent à documenter et à respecter.
Je vois surtout cette nouveauté comme un outil pour les bibliothèques natives et les interfaces existantes. Pour concevoir une API entièrement Rust, une tranche ou un itérateur exprime souvent le besoin de façon plus claire. Il n’y a pas de raison de remplacer une interface typée qui fonctionne par une convention C simplement parce que la nouvelle version le permet.
SUR LA CHAÎNE · NOUVELLE VIDÉO JBL Charge 3 : NON à l’obsolescence programmée ! je change la batterie et port de charge Voir la vidéo → Taille et alignement : de nouvelles API pour les pointeurs bruts
Rust 1.99.0 stabilise Layout::for_value_raw, size_of_val_raw et align_of_val_raw. Ces fonctions permettent d’obtenir des informations sur l’organisation mémoire d’une valeur à partir d’un pointeur brut, y compris pour des types dont la taille n’est pas connue statiquement.
La taille indique l’espace occupé ; l’alignement précise les contraintes de placement en mémoire. Ces notions deviennent importantes lorsque l’on écrit des abstractions de stockage ou du code qui gère directement des allocations. Pour une application utilisant surtout les collections habituelles, elles restent généralement cachées derrière des interfaces de plus haut niveau.
Le suffixe raw ne signifie pas qu’un pointeur quelconque devient exploitable. Les exigences de sécurité dépendent du type et de ses métadonnées. Certaines situations sont triviales avec un type Sized, mais les types dynamiques demandent de respecter les conditions documentées. La stabilisation fournit un contrat utilisable sur le canal stable ; elle ne dispense pas d’analyser les préconditions.
Box::leak : une recommandation à prendre au sérieux
La documentation évolue aussi sur un schéma plus subtil : utiliser Box::leak, puis tenter de récupérer plus tard la propriété de l’allocation pour la libérer. Rust 1.99.0 recommande d’éviter cette manière de procéder, en raison d’interactions problématiques avec les optimisations actuelles ou envisagées du compilateur.
Cette mise à jour de la documentation ne constitue pas, à elle seule, un changement de la sémantique du langage. Elle indique en revanche qu’il vaut mieux choisir une API exprimant directement l’opération souhaitée. Si vous comptez transférer la propriété puis reprendre l’allocation, Box::into_raw ou Box::into_non_null sont les pistes à examiner.
L’intérêt est de rendre le cycle de propriété lisible. Faire « fuir » une allocation et organiser un transfert temporaire sont deux intentions différentes. Je conseille aux auteurs de code unsafe de rechercher ce motif dans leurs abstractions, puis de revoir les garanties de reconstruction et de libération avant de modifier le code.
Des transferts de propriété mieux exprimés avec NonNull
La bibliothèque standard stabilise notamment Box::into_non_null, Box::from_non_null, Vec::into_parts et Vec::from_parts. Pour le vecteur, les composants sont un pointeur NonNull, la longueur et la capacité. Cette représentation expose les informations nécessaires à la reconstruction.
Le type NonNull indique que le pointeur n’est pas nul. Il ne garantit pas à lui seul que l’allocation existe encore, qu’elle correspond au bon type ou que les éléments sont initialisés. Ces responsabilités restent du côté du code qui effectue le transfert.
Décomposer un vecteur fait sortir son allocation du cycle de destruction ordinaire de l’objet. Il faut donc prévoir correctement sa reprise. Reconstruire deux propriétaires d’une même allocation, ou utiliser une longueur incohérente, n’est pas rendu acceptable par ces nouvelles API.
Ces fonctions intéressent surtout les auteurs d’abstractions bas niveau. Pour stocker une liste de données dans une application classique, conserver un Vec et ses méthodes sûres reste une excellente solution. La nouveauté est un outil supplémentaire pour les situations qui exigent un contrôle précis, pas une invitation à descendre systématiquement d’un niveau.
VecDeque::retain_back garde les derniers éléments
Voici une nouveauté plus immédiate : VecDeque::retain_back raccourcit une file à double entrée en conservant ses derniers éléments. La méthode reçoit le nombre d’éléments à garder. Elle ne reçoit pas un prédicat de filtrage, contrairement à ce que le nom pourrait faire imaginer si l’on pense à retain.
Un historique limité aux événements les plus récents illustre bien son intérêt :
use std::collections::VecDeque;
fn main() {
let mut historique: VecDeque<u32> = (10..=14).collect();
historique.retain_back(3);
assert_eq!(
historique.into_iter().collect::<Vec<_>>(),
vec![12, 13, 14]
);
}
Dans cet exemple illustratif, les deux premiers éléments sont retirés. Une limite supérieure ou égale à la longueur ne change rien ; une limite de zéro ne conserve aucun élément. Cela permet d’exprimer directement une politique de conservation à la fin de la collection.
Le choix dépend du sens dans lequel votre programme ajoute ses données. Garder la fin signifie conserver les derniers éléments dans l’ordre de la collection, pas deviner automatiquement lesquels sont les plus récents selon votre application.
Une conversion UTF-8 avec perte qui prend possession des octets
String::from_utf8_lossy_owned transforme un Vec<u8> en chaîne de caractères et remplace les séquences UTF-8 invalides par le caractère de remplacement. À la différence d’une conversion stricte, elle permet de produire un texte même lorsque certains octets ne sont pas valides.
fn main() {
let octets = vec![b'O', b'K', b' ', 0xff];
let texte = String::from_utf8_lossy_owned(octets);
assert_eq!(texte, "OK �");
}
Cette conversion peut convenir à l’affichage d’un diagnostic ou d’un contenu que l’on accepte de dégrader. Elle est moins adaptée si chaque octet doit être conservé pour un traitement ultérieur. Le mot lossy compte : l’opération ne restitue pas une information d’encodage devenue invalide.
La fonction prend possession du vecteur, mais ne garantit pas la réutilisation de son allocation. Je n’en déduis donc pas un gain de performance systématique. Rust stabilise aussi FromUtf8Error::into_utf8_lossy, utile lorsque l’on a d’abord essayé une conversion stricte avant de choisir une représentation avec remplacement.
Les autres ajouts pratiques de la bibliothèque standard
Les tableaux placés dans une Box bénéficient de nouvelles implémentations d’IntoIterator, pour le propriétaire et pour les références partagées ou mutables. Cela rend plus directe leur intégration dans les constructions qui attendent un objet itérable, sans confondre déplacement des éléments et emprunt.
Pour les fichiers, std::fs::set_times et set_times_nofollow complètent les opérations sur les horodatages à partir d’un chemin. La variante nofollow permet de distinguer le traitement d’un lien symbolique de celui de sa cible. Ce choix compte notamment pour les outils qui manipulent des arborescences.
Ces ajouts sont moins spectaculaires qu’une nouvelle syntaxe, mais ils réduisent les petits écarts entre un besoin courant et ce que la bibliothèque fournit directement. Avant d’en profiter dans une bibliothèque publiée, pensez toutefois à la version minimale de Rust promise à ses utilisateurs.
Cargo ajoute un profil debug, sans révolution immédiate
Cargo introduit un profil intégré nommé debug, destiné aux exécutables utilisés avec un débogueur. On peut le sélectionner explicitement :
cargo build --profile debug
Dans cette version, les valeurs par défaut de debug ne diffèrent pas de celles de dev. L’ajout prépare une distinction future entre le développement courant et le débogage. Il ne faut donc pas promettre une compilation plus rapide simplement en changeant le nom du profil.
Deux autres évolutions méritent l’attention des équipes. Les membres d’un workspace utilisant l’édition 2024 ou une édition ultérieure peuvent désactiver les fonctionnalités par défaut d’une dépendance héritée, même si la définition du workspace les active. La compilation incrémentale est également désactivée par défaut lorsque Cargo détecte un environnement d’intégration continue via la variable CI.
Pour une application multiplateforme, je regarderais ces changements dans les tâches de construction autant que dans le code Rust. Une configuration héritée ou un pipeline peut être concerné sans que la logique de l’application ait changé.
Passer à Rust 1.99.0 sans mélanger tous les changements
Si Rust est installé avec rustup, la mise à jour du canal stable s’effectue avec :
rustup update stable
Pour essayer précisément cette version, sans changer la sélection par défaut de tous vos projets, vous pouvez installer la chaîne d’outils correspondante :
rustup toolchain install 1.99.0
cargo +1.99.0 check
cargo +1.99.0 test
Exécutez les commandes Cargo dans le répertoire contenant le Cargo.toml du projet. Le préfixe +1.99.0 sélectionne explicitement cette chaîne d’outils pour la commande. Un projet peut autrement rester attaché à une version différente par son fichier rust-toolchain.toml ou une configuration de répertoire.
Vérifiez ensuite vos constructions de production et les plateformes réellement distribuées. Pour un logiciel desktop, une compilation locale réussie ne remplace pas les contrôles propres à Windows, macOS ou Linux. Je conseille aussi de séparer cette migration d’une mise à jour générale des dépendances : lorsqu’un échec apparaît, il devient plus facile de savoir quel changement examiner.
La version du compilateur utilisée pour développer et la version minimale déclarée dans rust-version sont deux choix distincts. Adopter une API apparue en 1.99.0 peut imposer de relever cette exigence. Mettre à jour son poste, à lui seul, ne signifie pas que tous les utilisateurs de la bibliothèque doivent immédiatement faire de même.
Une version particulièrement intéressante pour le code système
Je retiens surtout de Rust 1.99.0 une amélioration des interfaces aux frontières du langage : échanges avec le C, représentation des allocations et manipulation de données moins bien structurées. Les fonctions de collections et de texte apportent en parallèle des raccourcis utiles au quotidien.
Pour choisir quoi adopter, partez d’un besoin présent dans votre projet. Une nouvelle méthode sûre qui remplace une petite manipulation manuelle mérite un essai ; une API de pointeurs demande une revue de ses invariants. La mise à jour est une occasion de simplifier le code, à condition de garder les contrats de sécurité et la compatibilité aussi visibles que les nouveautés.
À lire aussi
ARTICLE · 22 SEPT. Corriger une erreur « cannot borrow as mutable » en Rust
VIDÉO · 8 AVR. RustMusic : Mon 1er Logiciel Libre , Lecteur Musical HD Multiplateforme (Windows, macOS, Linux)
ARTICLE · 6 OCT. GNOME 52 « Terengganu » vise le 17 mars 2027 : voici le calendrier
ARTICLE · 3 OCT. Ubuntu 26.10 bêta : GNOME 51, Linux 7.3 et Rust, mais faut-il déjà l’installer ?

Commentaires
0