13 points par GN⁺ 2025-10-17 | 2 commentaires | Partager sur WhatsApp
  • Le projet Rust for Linux fait avancer des fonctionnalités clés du langage nécessaires au développement du noyau et contribue ainsi à l’évolution de Rust lui-même
  • Trois éléments sont au cœur du sujet : la projection de champs (Field Projection), l’initialisation en place (In-place Initialization) et les types Self arbitraires (Arbitrary Self Types)
  • Ces fonctionnalités permettent d’exprimer plus naturellement en Rust des structures propres au noyau, comme les smart pointers, la mémoire épinglée (Pin) et le RCU
  • L’équipe Rust avance lentement parce qu’elle privilégie la solidité de la conception, mais l’objectif clair du noyau Linux permet de mieux concentrer les efforts de développement
  • Ces évolutions devraient aussi avoir un impact sur l’écosystème Rust hors du noyau, en aidant fortement à la gestion des smart pointers et à la simplification du code

Amélioration du langage Rust et rôle du noyau Linux

  • Si le développement de nouvelles fonctionnalités dans Rust est lent, c’est à cause de la prudence nécessaire pour éviter de figer de mauvais choix de conception dans le langage et d’un problème d’« alignment in attention »
    • Le projet Rust reposant sur des bénévoles, le développement prend du retard lorsqu’aucune personne ne se consacre à une fonctionnalité précise
  • Comme Rust for Linux est un sujet qui suscite beaucoup d’enthousiasme, il aide à concentrer les efforts sur quelques fonctionnalités essentielles au noyau
  • Le co-responsable de l’équipe langage Rust, Tyler Mandry, a présenté à Kangrejos 2025 les prochaines fonctionnalités du langage Rust et a indiqué que le projet Linux kernel avait joué un rôle de catalyseur dans l’évolution de Rust
    • Principales fonctionnalités : projection de champs, initialisation en place, types Self arbitraires
    • Le développement du noyau a clarifié les cas d’usage réels et les exigences techniques, ce qui a aidé à préciser l’orientation de la conception du langage Rust
    • La priorité absolue est la standardisation des fonctionnalités instables (unstable) déjà utilisées dans les bindings du noyau

Field Projection (projection de champs)

  • Il s’agit d’une fonctionnalité permettant d’extraire un pointeur vers un champ précis à partir d’un pointeur sur une structure, avec l’objectif de généraliser en Rust l’expression C &(r->field)
  • Jusqu’à présent, cela n’était possible qu’avec des références (&) et des pointeurs (*mut), avec des limitations pour les smart pointers définis par l’utilisateur
  • Rust for Linux cherche à étendre cela afin de permettre l’accès aux champs avec une syntaxe identique pour tous les types de pointeurs
  • En particulier, pour le type Pin (structure non déplaçable), la conception prévoit qu’une projection de champ se convertisse automatiquement en Pin<&mut Field> ou en &mut Field
  • Une fois cette fonctionnalité implémentée, il deviendra possible de prendre en charge en toute sécurité les patterns RCU (Read-Copy-Update) en Rust, permettant un accès aux données haute performance sans verrou
  • Le sujet est actuellement discuté dans cette tracking issue, avec un objectif de stabilisation avant Debian 14 (2027)

Arbitrary Self Types (types Self arbitraires)

  • Cette fonctionnalité permet de définir des méthodes qui acceptent des smart pointers
  • Alors qu’auparavant seule une forme comme fn method(&self) était possible, on pourra désormais écrire aussi fn method(self: Pin<&mut MyStruct>)
  • C’est une fonctionnalité indispensable dans le noyau, où l’on utilise divers wrappers de pointeurs comme Arc, Pin et Mutex
  • Lors de l’implémentation, un problème de conflit avec le trait Deref est apparu, mais il est en cours de résolution grâce à l’introduction d’un nouveau trait Receiver
  • Receiver sert à indiquer explicitement qu’un pointeur peut être utilisé comme type Self arbitraire
  • Dans le développement du noyau, cela permet de conserver des appels de chaînes de pointeurs plus concis
  • Ding vérifie actuellement la compatibilité avec les paquets Rust existants à l’aide de l’outil Crater, et a évoqué une possible stabilisation d’ici un an

In-place Initialization (initialisation en place)

  • Il s’agit d’une fonctionnalité qui fournit au niveau du langage ce que la macro pin_init!() utilisée dans le noyau permet déjà
  • Elle permet d’initialiser un objet directement en mémoire sans le déplacer après sa création, ce qui est utile pour les structures Pin, les Future et les traits dyn
  • Trois propositions sont discutées en parallèle
    • Approche par mot-clé init : ajout syntaxique minimal en réutilisant le trait existant PinInit
    • Approche par référence &out : ajout d’une référence en écriture seule, comme les pointeurs out en C, avec prise en charge de l’initialisation champ par champ
    • Approche d’optimisation de style C++ : création directe sur le tas dès le départ pour les objets destinés à y être déplacés immédiatement
  • L’objectif final est d’expérimenter à la fois PinInit et l’approche par out-reference afin d’en valider l’utilisabilité en conditions réelles
  • Si cette fonctionnalité est adoptée, elle devrait contribuer à simplifier la structure non seulement du noyau, mais aussi du code Rust asynchrone dans son ensemble

L’influence de Rust for Linux sur Rust

  • Le noyau Linux joue le rôle de banc d’essai réaliste pour l’évolution du langage Rust
  • Les trois fonctionnalités partent toutes de besoins propres au noyau, comme les smart pointers, la mémoire épinglée et les structures de concurrence,
    mais elles finiront par bénéficier aussi aux développeurs Rust en général
  • Ces évolutions sont considérées comme un exemple de boucle vertueuse entre le développement du noyau et celui du langage

2 commentaires

 
GN⁺ 2025-10-17
Avis Hacker News
  • Il m’a fallu un peu de temps pour lire et comprendre le document RFC sur la fonctionnalité lightweight clones de Rust. Au début, je trouvais cette fonctionnalité assez intéressante, mais au final cela m’a rappelé une fois de plus que Rust est un langage complexe à apprendre. Du point de vue de quelqu’un comme moi, qui n’a jamais vraiment appris Rust ni C++, cela donne l’impression que tous les concepts et fonctionnalités du C++ moderne sont combinés avec des éléments de Haskell. Malgré tout, quand je vois les gens construire beaucoup de choses utiles avec Rust, je me dis qu’il y a forcément quelque chose de solide derrière. Donc je compte m’y remettre sérieusement bientôt. Lien vers la RFC associée

    • D’après mon expérience, C++ est bien plus complexe que Rust. Rien que pour l’initialisation, il y a huit façons de faire ; pour les catégories de valeurs, il y en a cinq, dont les xvalues ; les conventions de formatage et de nommage ne sont pas cohérentes ; il faut gérer la rule of 5, les exceptions, vérifier systématiquement this != other lors d’un move assignment, sans parler du perfect forwarding, de la SFINAE, des ersatz de traits, etc. Il y a énormément de points complexes. Pour bien utiliser C++, il faut aussi apprendre toutes les conventions construites au-dessus du standard pour coder de manière sûre et rapide, et il arrive souvent que les approches, comme la gestion des exceptions, entrent toutes en conflit ou obligent à choisir une solution peu idéale

    • Dans la communauté Rust, l’ambiance autour de cette proposition de lightweight clones devient de plus en plus négative. La raison est sa complexité. Même dans le document officiel de Rust sur l’orientation du design, la complexité apparaît comme le principal obstacle. Une proposition Rust n’a pas forcément besoin d’être simple à tout prix, mais lightweight clone ne fait qu’alléger un peu quelque chose qui est déjà possible ; si les gens n’arrivent pas à le comprendre facilement, alors c’est un vrai problème

    • Vu de loin, Rust paraît énorme, mais dès qu’on code avec, on s’y habitue assez vite. Par exemple, au début je ne comprenais pas du tout le concept de lifetime, donc je codais uniquement avec Rc<>. Une fois les bases acquises, j’ai réétudié les lifetimes et c’était beaucoup plus simple. En réalité, la plupart des utilisateurs n’auront jamais à se soucier de fonctionnalités comme lightweight clones

    • Par rapport au C, c’est très complexe, mais par rapport au C++, c’est bien plus simple. On est presque à un point où il n’est quasiment jamais nécessaire d’aller fouiller dans la documentation ou les références juste pour comprendre du code. Rust occupe une position très équilibrée : « pas assez complexe pour s’en arracher les cheveux, pas assez simple pour que le code devienne complexe à cause des limites du langage ». Et en plus, le code est correct par défaut

    • La complexité de Rust mène moins facilement à un mauvais usage accidentel que celle du C++. Et avec clippy, on peut faire convertir automatiquement le code vers des formes plus idiomatic, donc même si on ne connaît pas directement une nouvelle fonctionnalité comme lightweight clones, on peut se la voir proposer. Dans la plupart des cas, on peut l’appliquer facilement juste avec l’option --fix de clippy. C’est là une différence décisive avec C++ : en C++, les fonctionnalités inutilisées s’accumulent ou servent uniquement à écrire du code inutilement compliqué, ce qui ajoute continuellement de la complexité

  • J’ai lu que le projet Rust for Linux avait beaucoup aidé Rust, alors par curiosité je suis allé chercher les fichiers *.rs dans l’arbre du kernel. J’ai vu un dossier rust contenant une couche de compatibilité d’API, et dans l’arbre du kernel seulement quelques pilotes de proof of concept qui réécrivent simplement des pilotes existants (à l’exception du pilote Nvidia inachevé). Il ne semble donc y avoir pratiquement rien de réellement utilisé en production. La réécriture en Rust d’Android Binder donne aussi l’impression d’être à peine encore présente. Mon impression générale est celle d’un petit projet expérimental, et je me demande s’il est vraiment nécessaire de mener ce genre d’expérience de co-développement de langage dans l’arbre source du logiciel le plus important au monde. Je me dis qu’il vaudrait peut-être mieux faire cela sur un OS plus expérimental comme Redox

    • Le pilote GPU pour Apple Silicon a été écrit en Rust, et son auteur a dit que cela aurait été bien plus difficile en C. Il n’est pas encore upstream, mais il a expliqué en substance : « quand on écrit un nouveau pilote kernel complexe, on finit inévitablement par rencontrer toutes sortes de problèmes, comme des race conditions, des memory leaks ou des use-after-free ; en le faisant en Rust, ces problèmes ont pratiquement disparu et le pilote fonctionne de manière stable. Grâce aux fonctionnalités de sûreté, j’ai la certitude que le pilote est thread-safe et memory-safe, et la conception elle-même évolue naturellement dans la bonne direction. Pour moi, c’est la magie de Rust. » Lien vers le retour d’expérience de l’auteur Et sur la question de savoir s’il est acceptable de faire ce genre d’expérimentation dans l’arbre du kernel, il est mentionné que Torvalds n’est pas d’accord avec cette critique

    • L’avis selon lequel « la réécriture en Rust d’Android Binder ne fait que subsister » est faux. Ce projet vise actuellement à remplacer complètement l’implémentation en C. Article associé Les principaux pilotes pour le matériel Apple des séries M ont également été écrits en Rust, et il ne s’agit ni de simples réécritures ni de proof of concept

    • Pour créer des pilotes complexes, il faut d’abord une couche d’interface. Le projet RfL travaille à ajouter cette infrastructure upstream, et c’est seulement une fois cette base en place qu’on peut écrire des pilotes complexes. Red Hat travaille sur nova, Asahi sur l’Apple GPU, et Collabora sur ARM Mali. Si même trois pilotes GPU ne comptent pas comme des pilotes complexes, alors on peut se demander ce qui en est un

    • Concernant l’affirmation selon laquelle la réécriture en Rust de Binder ne ferait que subsister, les messages de commit dans l’arbre de Linus montrent qu’elle est dans un état très abouti. Rust Binder passe tous les tests Binder de l’Android Open Source Project, et diverses applications et fonctionnalités fonctionnent sans problème notable. Le boot et l’exécution d’applications se passent aussi sans souci sur l’émulateur cuttlefish et sur le Pixel 6 Pro. Les fonctionnalités actuelles sont équivalentes à celles du Binder en C ; il ne manque que certaines fonctions de débogage, qui devraient être ajoutées prochainement. Et le projet Rust for Linux a certes démarré hors de l’arbre du kernel, mais pour expérimenter une véritable intégration, il faut au final faire les essais dans l’arbre lui-même

    • Le but de ce projet n’est pas une expérience conjointe de développement de langage, mais bien d’utiliser Rust pour le développement du kernel Linux. C’est un projet lancé directement par des développeurs clés qui voulaient utiliser Rust. Comme il s’agit d’un logiciel extrêmement important, l’avancement est prudent, et poser les bases prend du temps. Que Rust en tire accessoirement des bénéfices est un bonus

  • Dans l’article, j’ai vu le passage en italique suivant : <i>dans le cadre des field projections, il a désormais été décidé que tous les champs de structure seraient structuralement pin, de sorte qu’on obtiendra toujours des types comme Pin<&mut Field></i>. J’avais raté ce point auparavant. C’est techniquement complexe, mais je suis content que cette décision débloque un problème qui freinait plusieurs discussions

  • Les gens discutent du point suivant : <i>le design final s’inspire du C++ et utilise une optimisation attendue consistant, lorsqu’on crée une nouvelle valeur pour l’allouer sur le heap puis la déplacer immédiatement, à la construire directement sur le heap dès le départ</i>. Le terme « optimisation » peut prêter à confusion ici, donc il y a une discussion sur un éventuel changement de nom

    • Il est possible que je ne comprenne pas correctement la complexité du problème, mais j’ai l’impression qu’il ne suffirait pas de définir une calling convention appropriée. Si la taille de la structure dépasse x, ou si un marker type est présent, le caller passerait un buffer via outref et le callee écrirait directement la structure dans ce buffer. De cette façon, même en écrivant du code ordinaire, on pourrait éviter les allocations heap redondantes, et dans d’autres cas aussi, cela réduirait les copies inutiles. Comme c’est un sujet sur lequel beaucoup d’efforts ont déjà été investis, je me demande plutôt pourquoi les solutions proposées sont plus inconfortables

    • Je pense qu’au lieu de traiter cela comme une optimisation interne, il serait plus intuitif pour tout le monde d’en faire explicitement une fonction comme new

    • En C++, ce genre de sémantique s’appelle l’elision

    • Je propose des noms comme « coalesced heap construction » ou « coalesced heap allocation »

  • Chaque fois que j’entends parler des diverses fonctionnalités de Rust, je me surprends à faire la blague : « évitons absolument de mettre tokio dans le kernel ». Si Rust progresse suffisamment et qu’un direct composition renderer apparaît, au point de permettre des applications s’exécutant à l’échelle de tout le kernel, ce serait quand même une situation assez intéressante

    • Implémenter un async runtime dans le kernel est vraiment trivial. En fait, la workqueue du kernel est déjà un runtime

    • Si ce n’est pas une blague, c’est une incompréhension fondamentale de la manière dont on structure le code kernel en Rust (et en C). Quand on code dans le kernel, Rust fonctionne en no_std, comme le ferait l’équivalent de la stdlib C, et on ne peut pas utiliser cargo ni des crates. Pour utiliser tokio, il faudrait en réécrire la moitié et remplacer toutes les interactions avec l’OS, comme les sockets, par des mécanismes adaptés au kernel

  • Je pense que les nouvelles fonctionnalités Rust liées à Linux cette fois-ci sont les premières à être largement utiles au langage Rust au-delà du seul kernel. J’ai l’impression qu’un développement de fonctionnalités centré sur le kernel freinait un peu le développement d’autres fonctionnalités de langage ou de bibliothèque

    • À ma connaissance, la programmation système est le domaine d’application prioritaire de Rust. L’interoperability est essentielle pour les OS, l’embarqué ou les systèmes complexes à base de C. Ces fonctionnalités ne me semblent pas réservées au kernel ; elles ressemblent plutôt à des utilitaires généraux indispensables pour la programmation système réelle

    • Il y a des avancées pour le développement kernel et firmware à plusieurs endroits, mais elles ne font pas toujours la une des préoccupations de tout le monde. Philipp est particulièrement en train de faire avancer fortement ce domaine

    • Le rôle principal de Rust est la programmation système bas niveau. Pour les autres domaines, les langages managés compilés en userspace sont de bien meilleurs choix, et dans des systèmes structurés comme Self, Inferno ou Android, je pense qu’il n’y a aucun problème à se concentrer sur ce type de fonctionnalités bas niveau à la manière du C

  • Ces fonctionnalités sont excellentes, non seulement pour le kernel mais aussi pour d’autres domaines (en particulier generalized projections). Le fait que Linux tire l’évolution du langage Rust me satisfait énormément

  • Je me demande s’il existe des recherches ou des outils utilisant les LLM pour convertir automatiquement du code C en Rust. Je me demande s’il serait possible de demander à un LLM de produire du code Rust pour du chat, de l’USB, de l’i2c, des pilotes GPU, etc., puis de le faire compiler et tester ; ou bien d’essayer d’abord sur des projets « plus petits » comme sqlite, apache ou nginx

    • Côté recherche non fondée sur les LLM, il y a le projet c2rust, avec de vrais cas d’usage. Les LLM restent fondamentalement dans l’approximation, donc ils n’y arrivent pas correctement et produisent trop de bugs subtils. Sans y combiner des formal methods, ce n’est pas vraiment praticable. Il y a aussi beaucoup de problèmes que les seuls tests unitaires ne détectent pas. Et les exemples donnés comme projets « plus petits » ne sont en réalité pas si petits. Voir des cas d’usage réels

    • La Darpa s’intéresse aussi à ce type de recherche et a commencé à la financer, mais on n’en est pas encore à un stade où il y a des résultats concrets disponibles

 
ahwjdekf 2025-10-17

L’alignement du fanatisme (alignment in dogmatism)