Graydon Hoare im Interview zur Programmiersprache Rust

Sprachen  –  59 Kommentare

Mozillas Rust steht in Version 0.7 zur Verfügung. Doch was ist der Sinn hinter einen weiteren Programmiersprache? Wann kann man mit ihrer Stabilität rechnen? Und wohin geht die Reise für das optisch an C erinnernde Konstrukt? Frank Müller hat für heise Developer mit Sprachentwickler Graydon Hoare gesprochen.

heise Developer: Graydon, was war beziehungsweise ist deine Motivation hinter der Entwicklung von Rust?

Graydon Hoare: Die Unzufriedenheit mit den Kompromissen, die man beim Schreiben in C++ eingehen muss. Wie viele andere Leute, die im Umfeld von System- und Desktop-Programmen arbeiten, musste ich aus Gründen der Performance, des Speicher- und Laufzeitmodells sowie entwicklungstechnischer Einschränkungen mit dieser Sprache arbeiten. Aber ich finde C++ ziemlich fehlerträchtig.

Es ist schwierig, damit Code zu schreiben, von dessen Fehlerfreiheit und Speichersicherheit ich überzeugt bin. Das gilt doppelt, wenn ich Dinge schreibe, die hochgradig nebenläufig sind oder mit vielen Threads arbeiten.

heise Developer: Was sind die besonderen Stärken von Rust?

Hoare: Meiner Meinung nach ist es die Speichersicherheit. Wenn du dich an die sichere Sprache hältst, also keine unsafe { ... } Blöcke, wird sich dein Programm auch speichersicher verhalten – auch bei Problemen, die sich aus dem parallelen und nebenläufigen Verschachteln ergeben. Das betrifft Dinge wie das Falschverstehen der Lebensdauer von Zeigern, Nullzeigern, Schreiben wilder Zeiger, Scheitern beim Freimachen des Speichers, Data Racing, etwas verändern, was eigentlich unveränderlich sein sollte, und so weiter.

Diese grundlegenden Sachen lassen sich mit "einfacheren" und mehr an der Brute-Force-Methode ausgerichteten Sprachtechniken wie ubiquitärem Verpacken und Garbage Collection erreichen, allerdings wollten wir die volle Bandbreite der C++-Idiome zur Nutzung des Speichers bei voller Geschwindigkeit und geringen Kosten unterstützen (RAII, Stack Allocation, Structure Nesting, interne Zeiger, Zero-Cost References). Statt also den einfachen Weg der GC-zentrischen Sprachen zu gehen, haben wir eine mächtige (und hoffentlich mundende) Kombination aus Speicherabstraktionen gewählt, die auf affinen und regionalen Typensystemen aufbaut. Diese sind in Sprachen aus der Forschung sehr verbreitet, in industriellen allerdings weniger. Aber sie sind großartig. Durch sie können wir die gewünschten Idiome und darüber hinaus viele weitere faszinierende Dinge unterstützen, bei denen wir nicht sicher waren, ob wir sie umsetzen würden können:

  • RAII-Objekte, die statisch nur auf Dinge mit höherer Lebensdauer verweisen können.
  • Objekte, die statisch ihre Mutator-Methoden verlieren, wenn sie von einer veränderlichen zu einer unveränderlichen Variable verschoben werden.
  • Iteratoren, die nicht während der Iteration ungültig gemacht werden können.
  • eine geprüft sichere Weitergabe der Eigentumsrechte, Read-only- und Read-Write-Ordnungen zwischen Koroutinen und Threads.

Auch ist das System der Traits gelungen: Bei ihm verhält es sich ein bisschen wie mit der Arbeit mit Templates in C++, aber mit überprüften Schnittstelleneinschränkungen bei den Parametern der Typen. Dahinter steckt eine sehr bequeme Methode, um zwischen statischem und dynamischen Dispatching in Abhängigkeit vom Nutzungskontext zu wählen, statt das in der Definition zu tun.

Schließlich noch eine Anmerkung zur Ausdrucksmächtigkeit: Ich habe viel Zeit in Nebenprojekten und gelegentlich in bezahlter Arbeit damit verbracht, mit funktionalen Sprachen zu programmieren, und wir haben viele schöne Teile dieser Sprachen eingebunden: leichtgewichtige algebraische Datentypen mit Typinterferenz, Pattern Matching, Lambdas und leichtgewichtige Koroutinen sorgen für eine sehr ausdrucksstarke Erfahrung, sobald man sich an den Stil gewöhnt hat.

heise Developer: Für welche Einsatzszenarien ist Rust gedacht?

Hoare: Für alles, was die Leute heutzutage mit C++ schreiben. Server- und Desktop-Programme. Seltsamerweise haben wir herausgefunden, dass sich viele Spieleentwickler dafür interessieren, was aber letztlich Sinn ergibt. Sie waren eigentlich nicht unsere ursprüngliche Zielgruppe, aber viele von ihnen sind ja C++-Nutzer.

heise Developer: Welche Art von Projekten gibt es momentan und wie groß sind sie?

Hoare: Der Rust-Compiler ist selbst in Rust geschrieben, allerdings hängt sein Stil etwas hinter der Entwicklung der Sprache her, da er ein eigenständiges Projekt ist: Der Compiler ist in einem älteren Dialekt geschrieben, und viele Idiome müssen noch entfernt werden. Das Projekt umfasst etwa 100.000 Codezeilen, plus etwa 100.000 Zeilen in den Standardbibliotheken.

Die wichtigste Zielanwendung ist eine Browser Engine namens Servo, deren Entwicklung der Grund für die Mozilla Foundation ist, in Rust zu investieren. Sie umfasst etwa 35.000 Zeilen. Servo ist noch ein junges Projekt.

Auf unserer Website sind noch einige andere Projekte gelistet, an der die breitere Community arbeitet: einige Spiele, ein paar Demos, verschiedene Bindings und Bibliotheken. Noch nichts wahnsinnig Großes. Die Sprache befindet sich immer noch im Alpha-Stadium. Wir hoffen, dass die Größe der Projekte wächst, wenn sich die Sprache und die Bibliotheken stabilisieren.

Community, Sprachvergleich und Zukunft

heise Developer: Wie groß ist die Community, die die Entwicklung der Rust-Sprache unterstützt und eigene Projekte damit umsetzt?

Hoare: Mozilla beschäftigt ein Team von etwa sechs Leuten, die Vollzeit an Rust arbeiten, plus oder minus verschiedene Besucher, Praktikanten, Helfer aus anderen Teilen des Unternehmens und so weiter. Aber die Community an Rust-Entwicklern ist so sehr gewachsen, dass Leute außerhalb von Mozilla genauso viel oder mehr Arbeiten an der Sprache verrichten wie innerhalb. Wir versuchen sehr offen gegenüber Neuankömmlingen und der Mitarbeit anderer zu sein: Die Entwicklung ist auf GitHub transparent, und jeder ist dazu eingeladen mitzuhelfen. Für das derzeit aktuelle Release (0.7) gab es etwa 100 Mitwirkende, und an dem meisten Tagen sind etwa 250 Leute in unserem IRC-Channel.

heise Developer: Ist ein Port von Firefox zu Rust geplant?

Hoare: Wie ich schon gesagt habe, ist Servo die Zielanwendung für die Rust-Entwicklung. Es ist eine Browser-Engine, also kein vollwertiges Browser-Produkt, aber sie könnte in der Zukunft eventuell in einem Browser genutzt werden. Wir sind nicht sicher, welche Produkte, wenn überhaupt, letztlich auf Servo laufen werden. Zu diesem Zeitpunkt ist es ein Experiment, eine Wette auf die Zukunft.

heise Developer: Wie unterscheidet sich Rust vom ähnlich aussehenden Go oder Sprachen wie Erlang, Scala oder Clojure?

Hoare: Das sind alles großartige Sprachen, und ich bin wahrlich kein Freund eines "Kriegs der Sprachen". Verschiedene Sprachen passen zu verschiedenen Communities und Nischen, und was das angeht, bin ich grundsätzlich ein Pluralist. Wir haben bei weitem mehr gemeinsam mit anderen Sprachen (die auf deiner Liste eingeschlossen), als es Unterschiede gibt, und Gemeinsamkeit ist oft die ehrlichste Form der Verehrung: Wir kopieren die Funktionen, die wir mögen!

Abgesehen davon fragt jeder diese Fragen, deshalb liefere ich mal ein paar Unterschiede: Im Vergleich zu Go ist der Hauptunterschied Speichersicherheit und die damit verbundene kognitive Last, sie zu erreichen. Go geht mehr in Richtung Anwenderfreundlichkeit als in Richtung Sicherheit, und so sitzt man am Ende mit Code da, der einfach zu schreiben und zum Laufen zu bringen ist, bei dem es aber Data Races, Nullzeiger, Veränderlichkeitsfehler und Ähnliches gibt.

Im Vergleich zu Erlang hat Rust einen statisch typisierten "Ahead of time"-Compiler. Rust kompiliert mehr wie C oder C++, mit Typenüberprüfung im gesamten Programm und optimiertem Maschinencode als Ausgabe. Das Speicher- und Aufgabenüberwachungsmodell ist dem von Erlang sehr ähnlich, da es unveränderliche Daten bevorzugt, keine Nullzeiger hat, die Eigentumsrechte zwischen Tasks isoliert und es beim Ausfall eine einfache Crash-Restart-Philosophie (Stichwort "Let it Crash", Red.) verfolgt.

Der Hauptunterschied zu Scala ist die JVM, ähnlich wie der VM-Unterschied bei Erlang. Die Werkzeuge und die Laufzeit sind alle unterschiedlich. Scala (und zu einem gewissen Anteil auch Clojure) erbt einige Dinge durch die Ausrichtung auf die JVM, die wir nicht haben wollen, einschließlich der Schwierigkeiten beim Einsatz der langsameren Schnittstelle zu C, den Overhead der allgegenwärtigen Garbage Collection und der GC- sowie zeigerlastigen Objektrepräsentationen. Zusätzlich ist Scalas Nebenläufigkeit anfällig für Data Races, ähnlich wie die von Go.

Clojure scheint Nebenläufigkeit wenigstens direkt angegangen zu haben. Vergleicht man Rust mit Clojure, ist der Hauptunterschied wahrscheinlich (über die mit Scala erwähnten Einschränkungen durch die JVM hinaus), dass Rust überhaupt nicht Lisp ist. Lisp-Sprachen scheinen ausgesprochene "Usability Splits" zu verursachen: Einige Leute mögen sie, einige hassen sie. Ich bin ein alter Lisp-Fan und verstehe nicht, was das Problem der Hasser ist. Allerdings hatten wir das Gefühl, dass wir es uns nicht leisten konnten, eine derartige Menge an Nutzern zu verstimmen, die wir verloren hätten, wenn wir uns für eine Lisp-artige Syntax entschieden hätten. Selbiges gilt für beispielsweise die Forth- oder Haskell-Syntax. Schöne Sprachen, aber wir waren der Meinung, dass wir, um das C++-Publikum anzusprechen, etwas brauchten, dass etwas vertrauter aussieht. Wir haben ein sehr schönes Makrosystem im Lisp-Stil ausgewählt – oder wenigstens das beste, was sich mit C-artiger Syntax umsetzen lässt.

heise Developer: Kannst du die Roadmap zur Version 1.0 beschreiben?

Hoare: Unser Bug Tracker hat Bugs auf Grundlage von Reifegraden des Projekts bestimmten Meilensteinen zugeordnet: ob sie klar definiert sind, rückwärtkompatibel, Feature-complete, ausreichend getestet, produktionsbereit. Wir stufen die Bugs in diese Meilensteine ein und hoffen, dass 1.0-Release so zu behandeln, wie es die Nummer andeutet: Als ein Versprechen von wenigstens Rückwärtskompatibilität, vielleicht ein klein wenig mehr als nur das. Wir hoffen so eine Veröffentlichung irgendwann spät in diesem oder früh im nächsten Jahr zu haben, allerdings lässt sich der Zeitpunkt nur schwer zuverlässig voraussagen. Wir veröffentlichen in jedem Quartal, egal auf welchem Reifegrad wir sind: Unser System zur Integration von Änderungen stellt sicher, dass die Produktqualität nicht zurückgeht.

Zu diesem Zeitpunkt befinden wir uns immer noch in der 0.x-Serie der Entwicklung: auf dem Alpha-Level. Rust ist nicht stabil, und Leute die mit dem momentanen Code arbeiten, sollten mit einigen Brüchen rechnen. Wir werden weiterhin 0.x-Releases herausbringen, bis das Produkt den Reifegrad einer Version 1.0 erreicht hat. Abgesehen davon sind wir bei der siebten Veröffentlichungen im Alpha-Zyklus, und die Zahl der Änderungen, die Brüche verursachen, ist dramatisch zurückgegangen. Im Moment versuchen wir hauptsächlich Sachen anzugehen, von denen wir wissen, dass sie falsch, ineffizient oder zu überraschend für die Nutzer sind. Die Hauptarbeit an den Funktionen ist beendet.

heise Developer: Graydon, wir bedanken uns für die Beantwortung der Fragen. (jul)

Frank Müller
arbeitet als Software Engineer bei Canonical.