- La logique de résolution de types (type resolution) du compilateur Zig a été entièrement repensée, ce qui simplifie sa structure interne et apporte aussi des améliorations visibles pour les utilisateurs
- La nouvelle conception traite de façon paresseuse (lazy) l’analyse des champs de type, évitant d’examiner inutilement la structure détaillée de types non initialisés
- Les messages d’erreur de boucle de dépendances (dependency loop) ont été rendus plus précis, ce qui permet d’identifier clairement la cause de la boucle
- Le problème de suranalyse de la compilation incrémentale (incremental compilation) ainsi que de nombreux bugs ont été corrigés, ce qui améliore nettement la vitesse de build
- Ces changements incluent des dizaines de corrections de bugs et de petites améliorations du langage, renforçant globalement les performances et l’expérience de développement du compilateur Zig
Refonte de la logique de résolution de types
- Une PR d’environ 30�a0000 lignes a été fusionnée, réécrivant la logique de résolution de types du compilateur Zig dans une structure plus logique et plus intuitive
- Au cours de ce processus, l’architecture interne du compilateur a été réorganisée, avec des effets d’amélioration directs aussi pour les utilisateurs
- Le compilateur a été modifié pour effectuer une évaluation paresseuse de l’analyse des champs de type, afin de ne pas explorer inutilement la structure détaillée de types non initialisés
- Dans l’exemple de code, lorsqu’une structure contenant un champ
@compileError est utilisée uniquement comme espace de noms, une erreur de compilation se produisait auparavant, mais le code compile désormais normalement
- Cela évite des dépendances de code inutiles lors de l’utilisation de types servant d’espace de noms comme
std.Io.Writer
Amélioration des messages d’erreur de boucle de dépendances
- Auparavant, les messages d’erreur de boucle de dépendances étaient ambigus, mais ils indiquent désormais clairement la cause et l’emplacement de la boucle
- Dans l’exemple de code où les structures
Foo et Bar se référencent mutuellement, le message d’erreur désigne précisément la position de dépendance de chaque type
- Le message inclut la longueur de la boucle, l’emplacement de déclaration de chaque champ et l’emplacement des requêtes d’alignement
- Même dans des boucles complexes, suffisamment d’informations sont fournies pour identifier facilement l’origine du problème
Amélioration des performances de la compilation incrémentale
- Cette évolution corrige de nombreux bugs de la compilation incrémentale
- En particulier, le problème de « suranalyse (over-analysis) » a été résolu, avec une optimisation pour ne recompiler que les parties modifiées
- En conséquence, la vitesse de compilation s’améliore fortement dans de nombreux cas
- Les développeurs peuvent activer la compilation incrémentale à partir de Zig 0.15.1 pour profiter d’une meilleure expérience de développement
Autres améliorations
- Cette PR comprend des dizaines de corrections de bugs, de petites évolutions du langage et des améliorations de performances du compilateur
- La plupart concernent des cas détaillés ou spécifiques
- L’ensemble des changements est consultable dans la PR #31403 sur Codeberg
- En cas de découverte de nouveaux bugs, il est recommandé de signaler un ticket
Portée de ces changements
- Grâce à la simplification de la logique de résolution de types et à l’optimisation de la compilation incrémentale, la stabilité et l’efficacité du compilateur Zig sont renforcées
- Les développeurs bénéficient d’un retour plus rapide et plus clair, et peuvent espérer un gain de productivité même sur de grandes bases de code
1 commentaires
Commentaires sur Hacker News
Je suis l’auteur de ce devlog
Je comprends les inquiétudes concernant les ruptures de compatibilité dues aux changements du langage, mais je tiens à préciser que cette évolution du compilateur n’a pas eu un impact majeur
Par exemple, lors de la compilation de ZLS avec la nouvelle branche, il n’a fallu que remplacer
.{}par.emptyCela vient de la suppression de la valeur par défaut de
std.ArrayList, qui était déjà deprecated depuis un anEt pour le projet Awebo, il n’y avait que trois points à corriger dans tout l’arbre de dépendances — changement en
.empty, ajout decomptime, ajout deorelse @alignOf(T)Ce sont en majorité des modifications suffisamment simples pour que la plupart des développeurs Zig les appliquent quasi automatiquement
L’essentiel de cette PR concerne moins les cassures que les corrections de bugs et l’amélioration de la compilation incrémentale
Je pense que la qualité et la planification de la PR sont excellentes, et je n’avais absolument pas l’intention de minimiser les efforts de son auteur
J’en ai surtout retenu qu’à l’avenir je devrais mettre davantage de nuances dans mes commentaires et formuler mon avis avec plus de prudence
lib/std/multi_array_list.zig, une question m’est venueJe ne comprends pas pourquoi utiliser
@alignOf(T)dans la définition deMultiArrayList(T)crée une dépendance circulaireMême si
TestMultiArrayListlui-même, n’est-ce pas quand même un type monomorphe totalement distinct ? J’ai sans doute raté quelque choseCode concerné : lien
Je suis curieux d’avoir des retours de personnes qui utilisent Zig en production
Le langage change souvent ; j’aimerais savoir à quel rythme vous mettez à jour ou réécrivez, et si des dépendances se retrouvent parfois en retard sur les versions du langage
Je sais que Bun utilise bien Zig, mais j’aimerais entendre d’autres exemples
Au cours des 1 à 2 dernières années, les changements du langage et de la bibliothèque standard se sont faits sans gros problème
Avant, les montées de version étaient pénibles, mais maintenant cela ressemble plutôt à un léger désagrément
Si on me demande mon retour d’expérience sur Zig, c’est un point que je mentionne à peine tellement cela me paraît stable
Ces grands projets font leurs mises à jour à partir des releases taguées, et terminent généralement la migration en quelques jours à quelques semaines
Il y a aussi très peu de dépendances, donc la charge de mise à niveau reste limitée
En revanche, une simple faute de frappe peut parfois provoquer un plantage du compilateur en SIGBUS, ce qui rend le débogage pénible
.zig-cachea grossi jusqu’à 173 GB, ce qui peut poser problème sur un VPS ARMLa migration de
lightpandade 0.14 vers 0.15 s’est bien passée. 0.16 ne devrait probablement pas poser de gros souci non plusMais en tant qu’auteur de bibliothèque, il est difficile de suivre le rythme des changements rapides de la 0.16
Pour l’instant, je ne fais des essais de compatibilité que sur la branche “dev”
J’ai réécrit un module Node.js/TypeScript en Zig, et c’est 2 fois plus rapide avec 70 % de mémoire en moins
Le support Zig pour
sqliteet la sérialisationJSONa été un gros avantageLe point faible, c’est l’absence de syntaxe pour les closures ou les vtables, ce qui rend la séparation des couches de code plus difficile
J’utilise
Arcset un allocateur bump pour garantir la sûreté mémoire, et je compte continuer à exploiter le mode DebugSafe en productionPasser en ReleaseFast donnait un gain de 25 % en performances, mais pas suffisant pour compenser la perte de sûreté
Même s’il faut modifier le code, c’est à long terme la bonne approche
Je suis impressionné par ce que fait l’équipe Zig
J’utilise souvent le terminal ghostty écrit en Zig, et il est très stable
Cela dit, personnellement je préfère Rust
Rust adopte un modèle de « monde fermé », alors que Zig choisit un modèle de « monde ouvert »
En Rust, il faut implémenter explicitement un trait, tandis qu’en Zig cela fonctionne si la forme (shape) du type correspond
Cela permet à Zig un métaprogrammation puissante, mais l’inférence de types devient moins claire, ce qui complique l’autocomplétion, la documentation et le support LSP
À t’entendre, cela ressemble aux interfaces de Go, mais il me semblait que Zig n’avait pas d’équivalent direct
Le passage de
kernel32àNtdllétait intéressantC’est une idée qu’on pourrait aussi appliquer à l’API espace utilisateur de Linux
En particulier, la gestion des erreurs à la frontière noyau-utilisateur y est similaire
Cela dit, sous Linux, libc et le noyau sont étroitement liés, donc l’usage de
errnoest indispensableJe me demande pourquoi ce schéma est aussi apparu sous Windows
errnoouGetLastError()sont des héritages de l’époque d’avant les threadsÀ l’époque, avec l’ordonnancement coopératif, les variables globales étaient sans danger, mais avec l’arrivée du multicœur et des threads, c’est devenu risqué
C’est pour cela que le thread local est apparu comme alternative
Je me demande s’il ne vaudrait pas mieux ajouter au langage des namespaces explicites plutôt que d’utiliser les types comme espaces de noms
L’idée est d’ajouter une fonctionnalité lorsqu’elle permet réellement des optimisations à plusieurs endroits
En Zig,
@importtransforme un fichier en structure, et les namespaces sont simplement représentés comme des struct imbriquéesAutrement dit, un namespace n’est rien d’autre qu’un autre import
(Je n’ai pas encore assez de café, donc je ne garantis pas la précision.)
Dans les discussions sur les changements de langage, un point est souvent négligé : l’impact sur l’écosystème
Si le langage casse souvent, ce ne sont pas seulement les applis mais aussi les bibliothèques, outils et tutoriels qui doivent suivre en permanence
Au final, cela pousse l’écosystème vers des projets activement maintenus, plutôt que vers des bibliothèques “écrites une fois puis abandonnées”
C’est un compromis valable dans les premières phases de conception d’un langage, mais à long terme cela influence la croissance de l’écosystème
D’autres langages émergents investissent beaucoup d’efforts pour réduire cette fatigue du changement
Il sera intéressant d’observer ce que l’approche de Zig produira
Blender casse souvent son API, mais la plupart des corrections sont mineures
Le problème, c’est qu’il faut bien que quelqu’un les fasse, et si la maintenance s’arrête, les utilisateurs doivent patcher eux-mêmes
Les addons payants ont plus de chances d’être maintenus, mais ce n’est en rien garanti
Une bibliothèque non maintenue est de toute façon du mauvais code
J’aimerais qu’on arrête de critiquer Zig pour faire la promo d’autres langages (comme C3)
Dans la PR de Zig, l’affirmation selon laquelle « Chromium, boringssl, Firefox et Rust appellent SystemFunction036 de advapi32.dll » est fausse
Ils utilisent déjà ProcessPrng, qui n’échoue pas à partir de Windows 10
La source est ce livre blanc Microsoft
Les requêtes RNG sont conçues pour ne jamais échouer, et si un échec survient, c’est le processus lui-même qui est arrêté
Autrement dit, pour garantir des nombres aléatoires de haute qualité, aucune erreur n’est renvoyée
La sémantique du langage de Zig paraît simple en surface, mais les interactions sont subtiles
J’ai l’impression que cela pourrait, avec le temps, produire des cas limites complexes, un peu comme les règles des templates en C++
Une PR de 30 000 lignes, c’est une réalisation impressionnante
Mais changer la sémantique d’un langage est une chose extrêmement importante, donc cela m’a surpris
Je comprends que Zig n’est pas encore en 1.0 et que les changements vont vite, mais la formulation assez décontractée du type « j’ai changé la sémantique dans cette branche » m’a un peu interpellé
Je me demande si ce genre de changement massif fait partie de la culture propre à Zig, ou si c’est moi qui suis en décalage avec l’époque
L’expression « modern Zig » m’a aussi fait sourire vu la vitesse à laquelle le langage évolue
Le devlog n’est pas un texte marketing mais plutôt une trace destinée aux initiés, et Zig n’est pas encore en 1.0
La PR contient largement assez de contexte et de justification
En choisissant Zig, on accepte déjà un certain niveau de risque lié à l’évolution du langage
Au contraire, faire le ménage proprement maintenant est plus avantageux sur le long terme
(Il suffit de penser à des héritages impossibles à corriger, comme la priorité des opérateurs bit à bit en C.)
mluggest un contributeur majeur de Zig et membre de la Zig FoundationCe changement vise à résoudre les dépendances circulaires et à remettre de l’ordre dans le système de types
Les propositions associées sont publiques dans #3257 et #15909
Grâce à ce changement, la résolution des types dans Zig est réorganisée en structure DAG (graphe orienté acyclique), ce qui améliore fortement la stabilité du compilateur
Zig fonctionne selon un modèle BDFN (Benevolent Dictator For Now), où Andrew Kelley a le dernier mot
Mais l’équipe est une organisation à but non lucratif et place en priorité la confiance des utilisateurs et la qualité du langage
Personnellement, c’est un grand honneur de travailler avec Matthew
Un langage formellement correct, mais en pratique profondément désordonné