1 Punkte von GN⁺ 2026-03-12 | 1 Kommentare | Auf WhatsApp teilen
  • Die Logik der Typauflösung (type resolution) im Zig-Compiler wurde grundlegend neu gestaltet, wodurch die interne Struktur vereinfacht und auch für Nutzer sichtbare Verbesserungen erzielt wurden
  • Das neue Design verarbeitet die Analyse von Typfeldern verzögert (lazy), sodass Detailstrukturen nicht initialisierter Typen nicht unnötig geprüft werden
  • Die Fehlermeldungen für Abhängigkeitsschleifen (dependency loops) wurden konkret verbessert, sodass sich die Ursache der Schleife klarer erkennen lässt
  • Probleme mit übermäßiger Analyse bei der inkrementellen Kompilierung (incremental compilation) sowie zahlreiche Bugs wurden behoben, was die Build-Geschwindigkeit deutlich erhöht
  • Diese Änderung umfasst Dutzende Bugfixes und kleinere Sprachverbesserungen und stärkt insgesamt die Performance und Developer Experience des Zig-Compilers

Neugestaltung der Logik zur Typauflösung

  • Ein PR mit rund 30.000 Zeilen wurde gemergt, in dem die Logik zur Typauflösung des Zig-Compilers in eine logischere und intuitivere Struktur umgeschrieben wurde
    • Dabei wurde die interne Struktur des Compilers aufgeräumt, was auch für Nutzer direkte Verbesserungen bringt
  • Der Compiler wurde so geändert, dass er die Analyse von Typfeldern lazy auswertet, sodass er die Detailstruktur nicht initialisierter Typen nicht unnötig durchsucht
    • Wenn in einem Beispielcode eine Struktur mit einem @compileError-Feld nur als Namespace verwendet wird, führte das früher zu einem Compilerfehler, kompiliert jetzt aber korrekt
    • Dadurch werden unnötige Code-Abhängigkeiten bei der Verwendung von Namespace-artigen Typen wie std.Io.Writer vermieden

Verbesserte Fehlermeldungen für Abhängigkeitsschleifen

  • Früher waren die Fehlermeldungen für Abhängigkeitsschleifen unklar, jetzt zeigen sie Ursache und Position der Schleife eindeutig an
    • Wenn sich im Beispielcode die Strukturen Foo und Bar gegenseitig referenzieren, weist die Fehlermeldung jetzt konkret auf die Abhängigkeitsstellen der jeweiligen Typen hin
    • Die Meldung enthält die Länge der Schleife, die Deklarationsposition jedes Felds und die Position der Alignment-Abfrage
  • Auch bei komplexen Schleifen werden genügend Informationen bereitgestellt, sodass sich die Ursache leicht nachvollziehen lässt

Performance-Verbesserungen bei der inkrementellen Kompilierung

  • Mit dieser Änderung wurden zahlreiche Bugs in der inkrementellen Kompilierung behoben
    • Insbesondere wurde das Problem der „übermäßigen Analyse (over-analysis)“ gelöst, sodass nur geänderte Teile neu kompiliert werden
    • Dadurch steigt in vielen Fällen die Kompilierungsgeschwindigkeit deutlich
  • Entwickler können die inkrementelle Kompilierung ab Zig 0.15.1 aktivieren und die verbesserte Developer Experience nutzen

Weitere Verbesserungen

  • Dieser PR enthält Dutzende Bugfixes, kleinere Sprachänderungen und Performance-Verbesserungen des Compilers
    • Die meisten betreffen Detailfragen oder spezielle Sonderfälle
  • Die vollständigen Änderungen sind auf Codeberg in PR #31403 einsehbar
  • Beim Auffinden neuer Bugs wird empfohlen, Issues zu melden

Bedeutung der Änderungen

  • Durch die Vereinfachung der Typauflösungslogik und die Optimierung der inkrementellen Kompilierung wurden Stabilität und Effizienz des Zig-Compilers verbessert
  • Entwickler erhalten schnelleres und klareres Feedback und können auch in großen Codebasen mit höherer Produktivität rechnen

1 Kommentare

 
GN⁺ 2026-03-12
Hacker-News-Kommentare
  • Ich bin der Autor dieses Devlogs.
    Ich verstehe die Bedenken wegen Kompatibilitätsbrüchen durch Sprachänderungen, möchte aber klarstellen, dass diese Compiler-Änderung keine große Schockwelle auslöst.
    Als ich zum Beispiel ZLS mit dem neuen Branch gebaut habe, musste ich nur .{} in .empty ändern. Das lag daran, dass der Standardwert von std.ArrayList entfernt wurde, und das war bereits seit einem Jahr deprecated.
    Auch im Projekt Awebo gab es im gesamten Abhängigkeitsbaum nur drei nötige Änderungen — .empty, comptime hinzufügen und orelse @alignOf(T) ergänzen.
    Solche Anpassungen sind meist so simpel, dass Zig-Entwickler sie fast reflexartig erledigen.
    Der Kern dieses PRs ist weniger das Brechen von Code als vielmehr Bugfixes und Verbesserungen beim inkrementellen Kompilieren.

    • Ich war einer der Kommentatoren, die gegenüber der Änderung kritisch wirkten.
      Ich halte die Qualität und Planung des PRs für sehr hoch und hatte überhaupt nicht die Absicht, die Mühe des Autors herabzusetzen.
      Ich habe nur die Lehre daraus gezogen, künftig mehr Nuancen zu markieren und vorsichtiger zu formulieren.
    • Ich bin nicht direkt an Zig beteiligt, aber die hinzugefügten Kommentare in lib/std/multi_array_list.zig haben bei mir eine Frage aufgeworfen.
      Ich verstehe nicht, warum die Verwendung von @alignOf(T) in der Definition von MultiArrayList(T) eine zyklische Abhängigkeit erzeugt.
      Selbst wenn T MultiArrayList selbst wäre, wäre das doch ein vollständig getrennter monomorpher Typ, oder? Vermutlich übersehe ich etwas.
      Relevanter Code: Link
  • Mich würden Erfahrungen von Leuten interessieren, die Zig in Produktionsumgebungen einsetzen.
    Die Sprache ändert sich häufig; mich würde interessieren, wie eure Update- oder Rewrite-Zyklen aussehen und ob Abhängigkeitspakete manchmal hinter Sprachversionen zurückbleiben.
    Ich weiß, dass Bun Zig gut nutzt, aber ich würde gern auch andere Beispiele hören.

    • Ich pflege eine Zig-Compiler-Codebasis mit ungefähr 250.000 LoC (roc-lang/roc).
      In den letzten ein bis zwei Jahren liefen die Änderungen an Sprache und Standardbibliothek ohne größere Probleme ab.
      Früher waren Upgrades mühsam, heute fühlt es sich eher nach einer kleinen Unannehmlichkeit an.
      Wenn mich jemand nach der Erfahrung mit Zig fragt, erwähne ich diesen Punkt kaum noch, so stabil ist das inzwischen.
    • Ich habe an zwei produktiven Zig-Codebasen gearbeitet: tigerbeetle und sig.
      Solche großen Projekte aktualisieren sich anhand getaggter Releases und schließen Migrationen meist innerhalb von Tagen bis wenigen Wochen ab.
      Es gibt außerdem kaum Abhängigkeiten, daher ist die Upgrade-Last nicht besonders hoch.
    • Zig 0.15 ist ziemlich stabil.
      Allerdings können kleine Tippfehler zu SIGBUS-Compiler-Abstürzen führen, was das Debugging schwierig macht.
      .zig-cache ist bei mir bis auf 173 GB angewachsen und hat auf einem ARM-VPS Probleme verursacht.
      Das Upgrade von lightpanda von 0.14 auf 0.15 verlief problemlos. 0.16 dürfte ebenfalls keine großen Probleme machen.
      Als Bibliotheksentwickler ist es aber schwer, mit dem schnellen Änderungstempo von 0.16 mitzuhalten.
      Im Moment unterstütze ich das nur experimentell auf dem „dev“-Branch.
    • Ich betreibe etwa 20.000 LoC Zig-0.16-Code in DebugSafe-Modus in Produktion.
      Ich habe ein Node.js/TypeScript-Modul in Zig neu geschrieben; es ist doppelt so schnell und braucht 70 % weniger Speicher.
      Die Unterstützung von Zig für sqlite und JSON-Serialisierung war ein großer Vorteil.
      Der Nachteil ist das Fehlen von Closures oder einer vtable-Syntax, was die Trennung von Code-Ebenen erschwert.
      Mit Arcs und einem Bump-Allocator habe ich Speichersicherheit sichergestellt und plane, dauerhaft im DebugSafe-Modus zu bleiben.
      Der Wechsel zu ReleaseFast brachte zwar 25 % mehr Geschwindigkeit, aber nicht genug, um dafür die Sicherheit aufzugeben.
    • Ich denke, C++ hat mit seinem ewigen Versprechen von Abwärtskompatibilität eher einen Fehler gemacht, weil das die Sprachentwicklung behindert hat.
      Selbst wenn man Code anpassen muss, ist das langfristig der richtige Ansatz.
  • Ich bin von den Leistungen des Zig-Teams beeindruckt.
    Ich nutze oft das in Zig geschriebene ghostty-Terminal, und es ist sehr stabil.
    Persönlich bevorzuge ich aber Rust.
    Rust verfolgt ein „Closed-World“-Modell, Zig ein „Open-World“-Modell.
    In Rust müssen Traits explizit implementiert werden, während es in Zig funktioniert, wenn die Form (shape) eines Typs passt.
    Dadurch ist in Zig mächtige Metaprogrammierung möglich, aber weil die Typinferenz weniger klar ist, werden Autovervollständigung, Dokumentation und LSP-Unterstützung schwieriger.

    • Mich würde ein konkretes Beispiel interessieren.
      So wie du es beschreibst, klingt es ähnlich wie Interfaces in Go, aber soweit ich weiß, gibt es in Zig kein direkt entsprechendes Konzept.
  • Der Wechsel von kernel32 zu Ntdll war interessant.
    Das ist ein Konzept, das sich auch auf Linux-User-Space-APIs anwenden lässt.
    Besonders die Art der Fehlerbehandlung an der Kernel-User-Grenze wirkt ähnlich.
    Allerdings sind unter Linux libc und Kernel eng verflochten, weshalb die Verwendung von errno unverzichtbar ist.
    Mich würde interessieren, warum sich dieses Muster auch unter Windows entwickelt hat.

    • Muster wie errno oder GetLastError() sind Relikte aus der Zeit vor Threads.
      Früher war bei kooperativem Scheduling eine globale Variable unproblematisch, aber mit Multicore-Systemen und Threads wurde das riskant.
      Deshalb kam Thread-Local Storage als Alternative auf.
  • Statt Typen wie Namespaces zu verwenden, frage ich mich, ob es nicht besser wäre, der Sprache explizite Namespaces hinzuzufügen.

    • Zig verfolgt sprachlichen Minimalismus.
      Wenn sich eine Funktion an vielen Stellen auszahlt, wird sie dann hinzugefügt.
    • Eigentlich ist das kein Workaround, sondern Eleganz im Design.
      In Zig verwandelt @import eine Datei in eine Struktur, und Namespaces werden einfach als verschachtelte Structs dargestellt.
      Ein Namespace ist also nur ein weiterer Import.
      (Ich habe noch nicht genug Kaffee intus, also ohne Gewähr.)
  • In Diskussionen über Sprachänderungen wird ein Punkt oft übersehen — nämlich die Auswirkungen auf das Ökosystem.
    Wenn die Sprache häufig Breaking Changes hat, müssen nicht nur Apps, sondern auch Bibliotheken, Tools und Tutorials ständig nachziehen.
    Dadurch verschiebt sich das Ökosystem tendenziell in Richtung aktiv gepflegter Projekte statt Bibliotheken, die „einmal gebaut und dann liegen gelassen“ werden.
    In frühen Phasen des Sprachdesigns ist das ein vertretbarer Trade-off, langfristig beeinflusst es aber das Wachstum des Ökosystems.
    Andere junge Sprachen investieren viel Arbeit in die Minimierung dieser Änderungsmüdigkeit.
    Es bleibt spannend zu beobachten, zu welchen Ergebnissen Zigs Ansatz führt.

    • Als Beispiel kann man das Blender-Addon-Ökosystem nennen.
      Blender bricht seine API häufig, aber die meisten Anpassungen sind klein.
      Trotzdem muss irgendjemand sie machen, und wenn die Wartung endet, müssen Nutzer selbst patchen.
      Bezahlte Add-ons bleiben eher gepflegt, aber selbst das ist keine Garantie.
    • Ich finde trotzdem, dass Zig es wert ist.
      Nicht gepflegte Bibliotheken sind ohnehin schlechter Code.
      Statt Zig zu kritisieren, sollte man aufhören, andere Sprachen wie C3 zu bewerben.
  • Die in einem Zig-PR erwähnte Aussage, „Chromium, boringssl, Firefox und Rust rufen SystemFunction036 aus advapi32.dll auf“, stimmt nicht.
    Diese Projekte verwenden bereits ProcessPrng, und unter Windows 10 und neuer schlägt das nicht fehl.
    Belege dazu stehen im Microsoft-Whitepaper.
    RNG-Anfragen sind so entworfen, dass sie niemals fehlschlagen; falls doch, wird stattdessen der Prozess beendet.
    Um hochwertige Zufallszahlen zu garantieren, wird also kein Fehlercode zurückgegeben.

    • (Das ist eine Antwort auf ein anderes Devlog auf derselben Seite.)
  • Die Sprachsemantik von Zig wirkt an der Oberfläche einfach, aber ihre Wechselwirkungen sind subtil.
    So etwas könnte mit der Zeit komplexe Randfälle hervorbringen, ähnlich wie bei den Template-Regeln in C++.

  • Ein PR mit 30.000 Zeilen ist eine beeindruckende Leistung.
    Trotzdem hat es mich überrascht, dass dabei Sprachsemantik geändert wurde, denn das ist eine sehr weitreichende Sache.
    Ich verstehe, dass Zig noch vor 1.0 steht und sich daher schnell verändert, aber die lockere Formulierung, man habe „in diesem Branch die Semantik geändert“, fand ich etwas irritierend.
    Ich frage mich, ob solche großen Änderungen Teil der speziellen Zig-Kultur sind oder ob ich einfach nicht mehr auf der Höhe der Zeit bin.
    Die Formulierung „modern Zig“ musste mich wegen des hohen Änderungstempos der Sprache zum Lachen bringen.

    • Nur weil der Stil locker ist, sollte man ihn nicht als leichtfertige Haltung missverstehen.
      Das Devlog ist kein Marketingtext, sondern eher ein internes Protokoll für Eingeweihte, und Zig ist noch nicht 1.0.
      Der PR enthält ausreichend Kontext und Begründungen.
      Wer sich für Zig entschieden hat, hat damit ein gewisses Maß an Risiko durch Sprachänderungen bereits in Kauf genommen.
      Es ist eher ein langfristiger Vorteil, die Dinge jetzt noch sauber glattzuziehen.
      (Man denke nur an Altlasten wie die nicht mehr korrigierbare Priorität der Bitoperatoren in C.)
    • mlugg ist ein zentraler Zig-Mitwirkender und Mitglied der Zig Foundation.
      Diese Änderung dient der Auflösung zyklischer Abhängigkeiten und der Bereinigung des Typsystems.
      Die zugehörigen Vorschläge sind öffentlich in #3257 und #15909 dokumentiert.
      Dadurch wird Zigs Typauflösung in eine DAG-Struktur (gerichteter azyklischer Graph) überführt, was die Stabilität des Compilers deutlich verbessert.
      Zig wird nach dem BDFN-Modell (Benevolent Dictator For Now) geführt, und die letzte Entscheidungsgewalt liegt bei Andrew Kelley.
      Das Team ist jedoch eine Non-Profit-Organisation und stellt Nutzervertrauen und Sprachqualität an erste Stelle.
      Persönlich ist es für mich eine große Ehre, mit Matthew zusammenzuarbeiten.
    • Vielleicht ist diese Haltung auch eine Reaktion auf die chaotische Geschichte der Sprache C.
      Formal wirkte sie perfekt, in der Praxis war sie aber eine Sprache des Chaos.