Zig vs. Rust im Jahr 2026
(zackoverflow.dev)- Als ich vor etwa drei Jahren eine Bytecode-VM und einen Garbage Collector direkt in Zig und unsafe Rust geschrieben habe, war die menschenfreundliche Ergonomie von Zig im Vorteil, aber mit dem Beginn des Zeitalters der Coding-Agenten ist dieser Vorteil faktisch bedeutungslos geworden
- Der Produktivitätsgewinn von 1,5- bis 5-fach für Entwicklerinnen und Entwickler durch die wichtigsten Features von Zig wird vom 100-fachen Produktivitätsgewinn durch Rust-basierte Coding-Agenten überrollt
- Die Kernfunktionen von Zig wie die Allocator-Schnittstelle, Integer mit beliebiger Bitbreite,
packed structund comptime entfalten ihren Wert vor allem dann, wenn Menschen den Code direkt schreiben - Das Typsystem von Rust ist wirksamer dabei, Fehler von Agenten dank bounded polymorphism und der Erzwingung von Invarianten bereits zur Compile-Zeit zu verhindern
- In einer Situation, in der die von Agenten erzeugte Code-Menge um das Hundertfache steigt, ist die Garantie auf Speichersicherheit von Rust ein entscheidender Vorteil gegenüber Zig
Zentrale Veränderungen
- Zig hatte große Vorteile bei der Ergonomie von unsafe Code, aber da Menschen immer weniger Code direkt schreiben, sinkt auch der praktische Wert dieses Vorteils
- Die 1,5- bis 5-fache Produktivitätssteigerung für menschliche Entwickler durch Zig-Features wird vom 100-fachen Gewinn durch Coding-Agenten in Rust überschattet
- Ein großer Teil der bekanntesten Zig-Features verbessert die Bequemlichkeit beim händischen Schreiben von Code, doch für Coding-Agenten ist dieser Unterschied weit weniger wichtig
- Vor etwa drei Jahren habe ich beim Schreiben einer Bytecode-VM und eines Garbage Collectors in Zig und unsafe Rust den Eindruck gewonnen, dass die Erfahrung beim Schreiben von unsafe Code auf der Zig-Seite besser ist
- Auch nach dem Stand von 2026 ist Zig eine gute Sprache, aber Rust ist zur bevorzugteren Sprache geworden und passt auch besser zu Coding-Agenten
Zigs Allocator-Schnittstelle
- Die Allocator-Schnittstelle von Zig macht es leicht, spezialisierte Allocators wie arena oder stack fallback einzusetzen, um bestimmte Codepfade zu optimieren
- Wenn man eine Zeile Nutzereingabe liest, ist die Eingabelänge theoretisch unbegrenzt und erfordert daher einen Heap-Allocator, aber in der Praxis sind Eingaben meist kurze Suchbegriffe oder Pfade und damit deutlich kleiner als 1 KB
std.heap.stackFallback(256, heap_allocator)legt einen Puffer fester Größe auf dem Stack ab und wechselt nur dann auf den Heap, wenn die Eingabe darüber hinausgeht; im Normalfall kann also ohne Heap-Allokation gearbeitet werden- Früher gab es in Rust nichts, das der
Allocator-Schnittstelle von Zig entsprach; wenn man also einVec<T>mit Custom Allocator brauchte, musste man die Implementierung der Standardbibliothek kopieren und anpassen - Der Collections-Source von Bumpalo war in dieser Form ein Fork der Standard-Collections, verbunden mit einem bump allocator
- In Rust nightly gab es eine Zeit lang das
Allocator-Trait, und inzwischen scheint es auf einem ausreichend guten Stand zu sein - Ein Unterschied ist, dass Rusts
Allocatorauf Traits basiert und daher statischen Dispatch nutzt, während Zigs Allocator auf einer vtable basiert - Eine communityweite Konvention, Datenstrukturen wie in Zig auf Basis von Allocator-Parametern zu entwerfen, gibt es in Rust nicht, aber da KI Code leicht kopieren und anpassen kann, ist diese Einschränkung weniger wichtig geworden
Integer mit beliebiger Bitbreite und packed struct
- Zigs Integer mit beliebiger Bitbreite und
packed structmachen Dinge wie CPU-Cache-Optimierung im Stil datenorientierten Designs, tagged pointer, NaN boxing und bitflags deutlich einfacher - Wenn man eine Obj-C-API zusammen mit Metal über die Objective-C runtime C API verwendet, kann
idein tagged pointer sein und nicht einfach ein ausgerichteter Heap-Objektzeiger - Übergibt man einem Code, der von Ausrichtung ausgeht, ein getaggtes
NSNumber, kann UB entstehen; man muss also günstig prüfen können, ob es sich um einen Heap-Zeiger oder einen tagged immediate handelt - In einem vereinfachten Layout für Objective-C tagged pointer zeigt das niederwertigste Bit an, dass es sich nicht um einen Heap-Zeiger handelt, die nächsten 3 Bit identifizieren den Klassen-Slot, und die restlichen 60 Bit bilden die Payload
- Zig kann mit
enum(u3)undpacked structein Bit-Layout wieclass: TaggedClass,payload: u60direkt als Typ ausdrücken - In Zig kann man mit
@bitCastzwischen rohemu64undObjcTaggedPointerwechseln und inis_ns_numberis_taggedsowie die Klasse.ns_numberprüfen - Im entsprechenden Rust-Code liegen Konstanten wie
TAG_MASK,CLASS_MASK,CLASS_SHIFTundPAYLOAD_SHIFTinnerhalb vonObjcTaggedPointer(u64); bei der Erzeugung wird per OR verknüpft, beim Zugriff werden Masken angewendet - In Rust ist der Klassen-Slot keine echte Typinformation, sondern eine
u64-Konstante, und diese handgeschriebene Vorgehensweise ist weniger ergonomisch als in Zig - In Rust ist es besser, Crates wie bitfield oder bitflags zu verwenden, aber beide hängen von proc macros ab und fühlen sich nicht so gut an wie Zigs
packed struct - Mit Coding-Agenten fällt das Problem, dass solcher Code mühsam von Hand zu schreiben ist, deutlich weniger ins Gewicht
Der veränderte Wert von comptime
- Zigs comptime ist das spektakulärste Feature, und abgesehen von einigen schwer zugänglichen Sprachen mit abhängigen Typen gibt es kaum eine Sprache, die Compile-Time-Evaluation so gut bietet wie Zig
- In der Praxis vermisse ich comptime inzwischen nicht mehr oft; etwa 95 % der Nutzung entfielen darauf, generische Datenstrukturen mit parametrisierten Typen zu erzeugen
- Ein typisches Muster ist
fn ArrayList(comptime T: type) type, das einen Typ entgegennimmt und einen Struct-Typ mititems: []T,capacity: usizeundallocator: Allocatorzurückgibt - Das Typsystem von Rust ersetzt einen erheblichen Teil dieser Zig-artigen comptime-Generics und kann noch mehr Invarianten erzwingen
- In den verbleibenden etwa 5 % der Fälle ist das Fehlen von comptime unangenehm, und eine verlässliche Alternative ist nur Codegen
- Wenn man während der Spieleentwicklung hitbox geometry aus einem Tool hartkodiert in eine Datenstruktur übernehmen will, muss man in Rust Claude ein Skript schreiben lassen, das eine Rust-Datei erzeugt
- Trotzdem braucht man Compile-Time-Evaluation in der Praxis nicht besonders oft
Die Vorteile von Rusts Typsystem
- Das Typsystem von Rust wird als wertvollerer Tausch gegenüber Zigs comptime eingeschätzt und ist besonders stark im Bereich von Traits/Typeclasses für bounded polymorphism
- In Zig denselben Grad an bounded polymorphism umzusetzen, ist sehr schwierig
- Das Typsystem von Rust kann mehr Invarianten erzwingen und hilft dadurch, typische Fehler von Coding-Agenten zu verhindern
- Im Spielecode wird das Crate euclid verwendet, um ein in der Grafikprogrammierung häufiges Problem zu vermeiden: die Verwechslung von Koordinatenräumen
- Wenn man für jeden Koordinatenraum spezialisierte Typen wie
Point<Screen>oderPoint<World>erstellt, wird das versehentliche Vermischen von Welt- und Bildschirmkoordinaten bereits beim Kompilieren verhindert - Mit separaten Typen wie
WorldPoint,WorldVectorundScreenPointist die Addition von point und vector innerhalb desselben Raums erlaubt - Über
Translation2D::<f32, WorldSpace, ScreenSpace>kann man explizit vom Weltraum in den Bildschirmraum umwandeln - Umgekehrt ist Code wie
let bad: ScreenPoint = player;, derWorldPointdirektScreenPointzuweist, nicht erlaubt
Der Effekt, sich weniger mit Speicherproblemen befassen zu müssen
- Wenn Coding-Agenten das Schreiben von 100-mal mehr Code ermöglichen, steigt auch die Menge an Speicherproblemen, die man in Zig-Code prüfen muss, um das Hundertfache
- Ohne formale Verifikation wird die Oberfläche des Suchraums, den man zur Fehlersuche untersuchen muss, viel größer
- In einer Situation wie heute, in der die erzeugte Code-Menge stark wächst, ist Rust attraktiver
- Der klassische Trade-off bei Rust war, dass der borrow checker die Produktivität von Entwicklerinnen und Entwicklern senkt, wenn sie noch nicht damit vertraut sind; mit Coding-Agenten verliert dieser Nachteil aber stark an Bedeutung
- Selbst wenn man in Rust
unsafeverwendet, kann man Coding-Agenten Werkzeuge wie miri ausführen lassen, um zu prüfen, ob keine UB entsteht und ob die aliasing-Regeln von Rust eingehalten werden
Fazit
- Zig ist weiterhin eine Sprache, die ich vermisse, und eine gute Sprache
- In der Arbeitsweise des Jahres 2026 ist Rust die bevorzugtere Wahl und harmoniert auch besser mit Coding-Agenten
1 Kommentare
Lobste.rs-Meinungen
Mein früherer Teamleiter war ziemlich stark der Meinung, dass Copy-paste-Code nicht immer schlecht ist
Wegen des DRY-Prinzips klang das instinktiv falsch oder zumindest kontrovers, aber er war ein sehr pragmatischer Mensch und wandte dieses Prinzip vor allem auf große Test-Codebasen an
Seine Logik war, dass eine einfache, aber größere und redundantere Codebasis wartbarer sein kann, als krampfhaft eine clevere gemeinsame Schnittstelle zu bauen
Seit ich LLMs nutze, komme ich auf denselben Gedanken zurück, und inzwischen wende ich ihn auch auf wichtigere Teile von Software an
Codegenerierung ist schnell, und LLMs scheinen bei einfachen, aber redundanten Codebasen eher richtig zu liegen
Wenn man zu viel Abstraktion in Tests einbaut, nur um Redundanz zu reduzieren, werden sie schwerer verständlich und es besteht das Risiko, dass sie auf subtile Weise falsch sind
Noch schlimmer ist, dass Tests, wenn sie die Abstraktionen des zu testenden Codes wiederverwenden, auf dieselbe Weise falsch sein können wie dieser Code
Außerdem sind Tests im Gegensatz zu Anwendungscode praktisch kostenlos „komponierbar“
Wenn man das Test-Harness nicht ernsthaft ruiniert hat, kann man Tests beliebig hinzufügen oder löschen, ohne andere Tests zu beeinflussen; da es keine Integrationsreibung gibt, entfällt damit auch ein Grund, Redundanz zu vermeiden
Bei Tests habe ich das schon als DAMP ausgedrückt gesehen: „Descriptive and Meaningful Phrases“, ein Prinzip, das Lesbarkeit über Einzigartigkeit stellt
Dieses Prinzip kann Redundanz in Form ähnlicher wiederholter Codeabschnitte erzeugen, lässt Tests aber offensichtlicher korrekt erscheinen
https://testing.googleblog.com/2019/12/…
In der Go-Community gibt es ein ähnliches Sprichwort: „A little copying is better than a little dependency“ https://go-proverbs.github.io/
Ich bin dankbar, dass er Live-Coding geteilt hat
Wenn ich mich richtig erinnere, hat er beim Starten von etwas oft den ähnlichsten existierenden Code gesucht, ihn komplett kopiert und dann von dort aus angepasst
Ich dachte dann: „Du setzt dich nicht erst lange hin und überlegst dir, welche Abstraktion beide gemeinsam haben?“ – aber er hat einfach mit Copy-paste weitergemacht und war deutlich produktiver als ich
Interessant, wenn man das Timing von Buns Zig → Rust AI-Rewrite bedenkt https://xcancel.com/jarredsumner/status/2053063524826620129#m
Davon wären 75 in einer Sprache mit Destruktoren, Move-Semantik und Borrow Checker gar nicht erst kompilierbar gewesen
Das heißt, ungefähr jeder dritte ausgelieferte PR ist vom Typ „auf dem Fehlerpfad Freigabe vergessen“
Etwa 88 der 108 Fälle liegen in Zig, während die rund 14 auf der C++-Seite größtenteils Restkategorien wie Referenzzyklen und GC-Concurrency-Races sind, die in jeder Sprache übrig bleiben
Der Unterschied zwischen Zig und Rust ist also real, und die Zig-Bugs sind genau von der Art, die sich mit Destruktoren und Ownership beheben lässt, während C++ bereits nahe am Boden angekommen ist
Ohne stärkere Compile-Time-Garantien bleibt das ein Katz-und-Maus-Spiel
Der Vorschlag ist, nicht immer wieder die größte Bug-Kategorie einzeln zu reparieren, sondern sie strukturell zu eliminieren
– bun/docs/rust-rewrite-plan.md at claude/phase-a-port · oven-sh/bun · GitHub
Bei der Stelle „in den restlichen 5 % der Fälle ist es ohne comptime unerquicklich, und die einzige Möglichkeit, zuverlässig zu gleichwertigen Ergebnissen zu kommen, ist Codegenerierung“ ist nicht klar, was der Autor meint
Denn über prozedurale Makros sagt er nichts
Es ist zwar etwas umständlich, es sauber aufzubauen, aber man kann damit eine Menge machen
Ich finde auch, dass Codegenerierung teilweise einen unnötig schlechten Ruf hat
Mit
build.rs-Skripten habe ich schon einige ziemlich lästige Probleme per Codegenerierung gelöst, und es funktioniert gutVielleicht werde ich das später natürlich bereuen
Die Kernaussage des Artikels scheint ungefähr diese zu sein
Rust ist zwar eine gute Sprache, aber das ist trotzdem etwas überzogen
Wirkt wie Werbung für Coding-Agents
Aus einem verlinkten Artikel desselben Autors: Ein sehr häufiger Fehler in der Grafikprogrammierung ist es, Koordinatenräume zu verwechseln, und das Typsystem ist stark genug, per Typen auszudrücken, welche Koordinatenräume und Transformationen gültig sind
Dasselbe gilt für Währungen, Distanzen und Gewichte in SI- und imperialen Einheiten, validierte Strings versus benutzerbereitgestellte Strings und Geheimwerte
Außerdem kann man mit gut gepflegten Zustandstypen unmögliche oder unsounde Zustände verhindern
Aber persönlich ist das Feature, das ich mir in Rust am meisten wünsche, die vollständige Eliminierung von Data Races
Data Races gibt es auch in verwalteten Sprachen
Das „nimm doch einfach Go“ scheitert daran, dass in Go alles zwischen Threads referenzbasiert mutierbar ist, inklusive Slice-Akrobatik
Sogar JavaScript, früher eine komplette Spielzeugsprache und doch eine der reinsten und sichersten Varianten, hat bei jedem
awaitpotenziell ein RaceGanz zu schweigen von der Bösartigkeit des everything-is-an-EventEmitter-Musters
Also ja. Wenn es nur GC gäbe … 🤫
Es fühlt sich an, als würde der eigentliche Punkt etwas versteckt
Coding-Agents können Python und JavaScript ebenfalls sehr gut
Ob sie darin besser sind als in Rust, ist subjektives Herumwedeln, aber ich würde diese Sprachen trotzdem nicht für viele Aufgaben wählen
Ich frage mich, ob das Problem darin liegt, dass sich Zigs Features oft ändern, oder ob die AI-Trainingsdaten einfach wegen der noch jüngeren Sprache unsauber sind
Für mich ist Zig schwerer zu schreiben als Rust, aber leichter zu lesen
Im AI-Zeitalter liest man mehr Code, als man selbst schreibt, deshalb bevorzuge ich eher Zig
Angesichts der aktuellen Menge an generiertem Code ist die Aussage, Rust sei attraktiver, nur der erste Schritt
Je mehr Computer Code schreiben, desto vorteilhafter werden formalere Sprachen sein
Das wirkt wie eine weitere Phase der Debatte um dynamische Typisierung
So nach dem Motto: „Dynamische Typisierung ist für Menschen einfacher, aber warum sollte man für die Maschine dieselbe Sache dreimal explizit angeben?“
Typen, Lifetimes … was gibt es sonst noch, das für Maschinen leichter zu schreiben und zu konsumieren ist
Ich frage mich, wie schwer es für Menschen werden wird, direkt in den Sprachen zu programmieren, in denen Computer künftig Code schreiben