Rust 1.99 stabilise la définition de fonctions C-variadic
Rust 1.99.0, sorti le 1er octobre 2026, permet à Rust stable de définir des fonctions C-variadic comme printf, passe à LLVM 23 et fait de no_mangle sur les génériques une erreur.
4 min de lecture

En chiffres
- new code-generation backend
- LLVM 23
- average Rustdoc speedup on trait impl filtering
- 20%
- best-case Rustdoc speedup on some crates
- 40%
- release that first warned about no_mangle on generics
- 1.56
L'équipe Rust a publié Rust 1.99.0 le 1er octobre 2026. Son changement phare permet à Rust stable de définir des fonctions C-variadic, c'est-à-dire des fonctions qui acceptent un nombre quelconque d'arguments, comme printf en C. Cela comble une lacune pour le code Rust qui doit fonctionner main dans la main avec C.
Cette version fait aussi passer le compilateur à LLVM 23, accélère l'outil de documentation et transforme un avertissement de longue date en erreur bloquante.
Ce qu'apportent les définitions C-variadic
Une fonction variadique accepte un nombre variable d'arguments. C les utilise largement, et Rust sait les appeler depuis longtemps. En définir une en Rust était une autre affaire. « Rust pouvait déjà appeler des fonctions variadiques définies en externe (par exemple libc::printf). Avec Rust 1.99, ces fonctions peuvent désormais être écrites en Rust même », indique l'annonce officielle.
La syntaxe utilise ... comme dernier paramètre. ByteIOTA donne la forme d'une définition : unsafe extern "C" fn my_logger(count: u32, mut args: ...) -> i32. Dans la fonction, les arguments supplémentaires arrivent sous la forme d'un core::ffi::VaList, qui, selon le blog Rust, est compatible au niveau binaire avec le type va_list de C. Linux Compatible indique que le code lit chaque argument avec next_arg::<T>().
Un trait nommé VaArgSafe contrôle les types qui peuvent passer. Il marque les types qui peuvent être lus sans risque depuis la liste d'arguments, ce qui aide à éviter les incohérences de type. Selon le blog Rust et releases.rs, la version permet aussi aux fonctions naked d'utiliser des signatures variadiques. Une fonction naked est une fonction que le compilateur émet sans code de préparation. Le code bas niveau et embarqué s'en sert pour contrôler précisément la convention d'appel.
Nouvelles API de bibliothèque stabilisées
Le blog Rust cite notamment ces API désormais disponibles en version stable :
- Disposition mémoire :
Layout::for_value_raw,mem::size_of_val_raw,mem::align_of_val_raw - Collections et Box :
Box::into_non_null,Vec::into_parts,Vec::from_parts,VecDeque::retain_back - Système de fichiers :
std::fs::set_times,std::fs::set_times_nofollow
Les fonctions set_times modifient les horodatages d'un fichier depuis la bibliothèque standard. Comme son nom l'indique, la variante _nofollow ne suit pas les liens symboliques.
Changements du compilateur, des plateformes et des outils
Rust 1.99 passe à LLVM 23, la bibliothèque de génération de code qui transforme Rust en code machine. ByteIOTA fait état d'une baisse moyenne de 1,2 % du temps réel de compilation sur l'ensemble des benchmarks, dans le cadre d'un gain de 4,57 % sur deux mois.
Autres changements, d'après Linux Compatible et releases.rs :
| Domaine | Changement |
|---|---|
| Plateformes | Linux RISC-V 64 bits avec musl passe au niveau de support Tier 2 |
| Édition de liens | Les exécutables statiques indépendants de la position sont activés sur les cibles GNU et musl |
| Rustdoc | Le filtrage des implémentations de traits est environ 20 % plus rapide en moyenne, jusqu'à 40 % sur certains crates |
| Macros | Les macros d'attribut fonctionnent désormais sur les modules définis dans un fichier séparé, comme #[my_macro] mod foo; |
| Assembleur inline | Les entiers de 128 bits peuvent être passés dans des registres vectoriels sur x86 |
Cargo, l'outil de build de Rust, reçoit trois changements. Il réserve un nouveau profil debug, que releases.rs décrit comme une préparation pour éloigner le profil dev du débogage « afin d'offrir une valeur par défaut plus raisonnable ». Il désactive la compilation incrémentale quand la variable d'environnement CI est définie, et ByteIOTA note que CARGO_INCREMENTAL=1 la réactive. Les membres d'un workspace sur l'édition 2024 peuvent aussi remplacer les valeurs par défaut héritées pour les dépendances.
Ce qui pourrait casser
La version comporte plusieurs changements de compatibilité :
| Changement | Détail |
|---|---|
#[no_mangle] sur des éléments génériques | Désormais une erreur bloquante ; un avertissement existait depuis Rust 1.56, selon ByteIOTA |
| Anciens modules d'entiers | Désormais entièrement dépréciés |
| Statics externes | Les emprunts ne sont plus promus automatiquement en 'static, rapporte ByteIOTA |
| Blocs de code des commentaires de documentation | Les attributs qu'ils contiennent doivent avoir des cibles valides, sinon la génération de la documentation échoue |
RangeInclusive | Son itération est mieux optimisée, ce qui modifie le comportement d'un intervalle déjà épuisé |
Pin::new_unchecked | Ses règles de sécurité sont formulées plus précisément |
C'est la dernière étape d'une année chargée pour le langage. En août, Rust a stabilisé le type never après dix ans, et les builds nightly ont activé le solveur de traits de nouvelle génération.
Ce que cela signifie pour les développeurs
Supprimez vos shims printf. Si vous avez écrit du code C, ou utilisé une fonctionnalité nightly, uniquement pour accepter des arguments variadiques d'un appelant C, vous pouvez désormais le faire en Rust stable. Les hôtes de plugins, les allocateurs personnalisés et les passerelles de journalisation sont les premiers endroits à examiner.
Vérifiez la présence de #[no_mangle] dans le code générique avant de mettre à jour. Un avertissement existe depuis Rust 1.56, donc un crate qui compile encore avec cet avertissement échouera désormais. Recherchez l'attribut sur toute fonction générique dans votre base de code et dans vos dépendances vendorisées.
Surveillez les temps de build de votre CI. Cargo désactive désormais la compilation incrémentale quand CI est définie. C'est généralement le bon choix pour des builds propres, mais une configuration de CI qui met en cache le répertoire target entre les exécutions peut ralentir. Définissez CARGO_INCREMENTAL=1 si vos propres mesures le justifient.
Lancez vos tests de documentation. Des attributs obsolètes dans les blocs de code des commentaires de documentation font désormais échouer la génération de la documentation. Lancez cargo test --doc tôt pour qu'un exemple cassé ne bloque pas une version.
Testez le code qui réutilise des intervalles terminés. Le changement de RangeInclusive ne concerne que les intervalles déjà parcourus jusqu'au bout. Le code qui continue d'utiliser un tel intervalle après la boucle doit être vérifié au regard du nouveau comportement.
Sources
- Announcing Rust 1.99.0 - Rust Blog
- Rust 1.99.0 Ships with Stable C-Variadic Functions - Linux Compatible
- Rust 1.99 Is Out: C-Variadics and What Breaks - ByteIOTA
- 1.99.0 - releases.rs
Articles liés

La réécriture de mold en Rust vise l'éditeur de liens par défaut de Linux
Mold établit les liens 4,9 fois plus vite que LLVM lld. Son auteur le réécrit en Rust et veut que les distributions l'installent comme /usr/bin/ld.

Zig 0.17.0 apporte un système de build scindé et des recompilations rapides
Zig 0.17.0 est sorti le 2 octobre avec 925 commits de 206 contributeurs : un système de build retravaillé, des builds incrémentaux sur Linux x86_64 et LLVM 22.1.8.

Rust 1.100 retire les outils hôtes des cibles Windows 32 bits
Rust 1.100 cesse de livrer le compilateur pour Windows 32 bits. Les cibles i686 gardent la bibliothèque standard, donc la compilation croisée depuis Windows 64 bits continue de fonctionner.