Dieser Artikel wurde von Lin Clarke in Zusammenarbeit mit dem Rust-Entwicklungsteam („wir“ im Text) verfasst. Sie können den
Beitrag auch im offiziellen Rust-Blog lesen.
Die erste Version von Rust 2018 wurde am 6. Dezember 2018 veröffentlicht. In dieser Version haben wir uns auf die Produktivität konzentriert, damit die Rust-Entwickler so effizient wie möglich arbeiten können.
Die Zeitleiste zeigt den Übergang von Beta zu Rust 2018 und Rust 2015. Sie ist von Symbolen für Tools und vier Bereichen umgeben: WebAssembly, Embedded, Networking und CLI. Der rote Kreis - Entwicklerproduktivität - umgibt alles außer Rust 2015Im Allgemeinen ist es jedoch nicht einfach zu erklären, was Rust 2018 ist.
Einige präsentieren es als eine neue Version der Sprache ... so etwas, aber nicht wirklich. Ich sage "nicht wirklich", weil hier die "neue Version" nicht die neuen Versionen anderer Sprachen bedeutet.
In den meisten anderen Sprachen fügen alle neuen Funktionen eine neue Version hinzu. Die vorherige Version wird nicht aktualisiert.
Das Rust-System arbeitet anders. Dies liegt daran, wie sich die Sprache entwickelt. Fast alle neuen Funktionen sind zu 100% mit Rust kompatibel. Sie erfordern keine Änderungen. Dies bedeutet, dass es keinen Grund gibt, sie auf Rust 2018-Code zu beschränken. Neuere Versionen des Compilers unterstützen weiterhin standardmäßig den „Rust 2015-Modus“.
Aber manchmal erfordert die Entwicklung einer Sprache Innovation, zum Beispiel eine neue Syntax. Und diese neue Syntax kann vorhandene Codebasen beschädigen.
Zum Beispiel die Funktion
async/await
. Anfangs gab es in Rust keine derartigen Konzepte. Es stellte sich jedoch heraus, dass diese Grundelemente wirklich nützlich sind und das Schreiben von asynchronem Code vereinfachen.
Für diese Funktion müssen die Schlüsselwörter
async
und
await
hinzugefügt werden. Sie sollten jedoch darauf achten, den alten Code nicht zu
async
bei dem
async
oder
await
als Variablennamen verwendet werden können.
Daher fügen wir in Rust 2018 Schlüsselwörter hinzu. Obwohl die Funktion noch nicht freigegeben wurde, sind die Schlüsselwörter jetzt reserviert. Alle inkompatiblen Änderungen für die nächsten drei Entwicklungsjahre (z. B. Hinzufügen neuer Schlüsselwörter) werden jeweils in Rust 1.31 vorgenommen.

Obwohl es in Rust 2018 inkompatible Änderungen gibt, bedeutet dies nicht, dass Ihr Code beschädigt wird. Selbst bei
async
und
await
Variablen wird der Code kompiliert. Standardmäßig arbeitet der Compiler wie zuvor.
Wenn Sie jedoch eine der neuen Funktionen verwenden möchten, können Sie den neuen Kompilierungsmodus von Rust 2018 auswählen. Der Befehl für die
cargo fix
zeigt an, ob Sie den Code aktualisieren müssen, um die neuen Funktionen zu verwenden und den Änderungsprozess zu automatisieren. Dann können Sie Ihrem Cargo.toml die
edition=2018
hinzufügen, wenn Sie der Verwendung neuer Funktionen zustimmen.
Dieser Versionsbezeichner in Cargo.toml gilt nicht für das gesamte Projekt und nicht für Ihre Abhängigkeiten. Es ist auf ein bestimmtes Rack beschränkt. Das heißt, Sie können die Kisten Rust 2015 und Rust 2018 gleichzeitig verwenden.

Daher sieht auch bei Verwendung von Rust 2018 alles ungefähr so aus wie bei Rust 2015. Die meisten Änderungen werden gleichzeitig in Rust 2018 und Rust 2015 implementiert. Nur wenige Funktionen erfordern inkompatible Änderungen.

Rust 2018 ist nicht nur Änderungen in der Hauptsprache. Weit nicht nur sie.
Rust 2018 ist in erster Linie ein Impuls zur Verbesserung der Produktivität von Rust-Entwicklern, vor allem dank Tools, die außerhalb der Sprache liegen, sowie durch die Entwicklung spezifischer Anwendungen und das Verständnis, wie Rust in diesen Fällen zur effektivsten Programmiersprache gemacht werden kann.
Somit können Sie Rust 2018 als Bezeichner in Cargo.toml darstellen, das verwendet wird, um mehrere Funktionen einzuschließen, die inkompatible Änderungen erfordern ...

Oder Sie können es sich zu einem Zeitpunkt vorstellen, zu dem Rust zu einer der effizientesten Sprachen für viele Anwendungen wird - wenn Sie Leistung, effizienten Ressourceneinsatz oder hohe Zuverlässigkeit benötigen.

Wir bevorzugen die zweite Version der Definition. Schauen wir uns also alle Verbesserungen an, die außerhalb der Sprache vorgenommen wurden, und tauchen wir dann in die Sprache selbst ein.
Rost für bestimmte Anwendungen
Eine Programmiersprache kann an sich abstrakt nicht effektiv sein. Es ist in einer bestimmten Anwendung wirksam. Daher haben wir verstanden, dass es nicht nur notwendig ist, Rust als Sprache oder Werkzeug zu verbessern. Es ist auch notwendig, die Verwendung von Rost in bestimmten Bereichen zu vereinfachen.

In einigen Fällen bedeutete dies die Schaffung eines völlig neuen Werkzeugsatzes für ein völlig neues Ökosystem. In anderen Fällen sollten vorhandene Funktionen und eine gute Dokumentation verbessert werden, um das Aufrufen und Ausführen eines funktionierenden Systems zu vereinfachen.
Das Rust-Entwicklungsteam hat Arbeitsgruppen in vier Bereichen gebildet:
- Webassembly
- Eingebettete Anwendungen
- Netzwerkaufgaben
- Befehlszeilen-Tools
Webassembly
WebAssembly musste einen völlig neuen Satz von Tools erstellen.
Erst im letzten Jahr war es mit WebAssembly möglich, Sprachen wie Rust für die Ausführung im Internet zu kompilieren. Seitdem hat sich Rust schnell zur besten Sprache für die Integration in vorhandene Webanwendungen entwickelt.

Rust eignet sich aus zwei Gründen gut für die Webentwicklung:
- Das Cargo Crash Ecosystem funktioniert so, wie es die meisten Entwickler von Webanwendungen gewohnt sind. Kombinieren Sie eine Reihe kleiner Module, um eine größere Anwendung zu bilden. Dies bedeutet, dass Rust genau dort einfach zu verwenden ist, wo Sie es benötigen.
- Rost ist ressourcenarm und erfordert keine Laufzeit. Sie benötigen nicht viel Code. Wenn Sie ein winziges Modul haben, das viel Hard-Computing-Arbeit leistet, implementieren Sie ein paar Rust-Linien, um es zu beschleunigen.
Mit
web-sys und js-sys aus Rust-Code können Web-APIs wie
fetch
oder
appendChild
einfach
appendChild
. Und
wasm-bindgen
macht es einfach, übergeordnete Datentypen zu unterstützen, die WebAssembly nicht nativ unterstützt.
Nach dem Schreiben des Rust WebAssembly-Moduls gibt es Tools, mit denen Sie es einfach mit dem Rest der Webanwendung verbinden können. Sie können
wasm-pack verwenden , um diese Tools automatisch zu starten und das Modul in npm auszuführen, wenn Sie möchten.
Weitere Informationen finden Sie im
Buch Rust and WebAssembly .
Was weiter?
Nach der Veröffentlichung von Rust 2018 planen die Entwickler, mit der Community zu diskutieren, in welche Richtungen weiter gearbeitet werden soll.
Eingebettete Anwendungen
Für die eingebettete Entwicklung war es notwendig, die Stabilität der vorhandenen Funktionalität zu erhöhen.
Theoretisch war Rust immer eine gute Sprache für eingebettete Anwendungen. Dies ist ein modernes Toolkit, das Entwicklern sehr fehlte, und sehr praktische Sprachfunktionen auf hoher Ebene. All dies ohne unnötige Belastung der CPU und des Speichers. Somit eignet sich Rust hervorragend für Embedded.
In der Praxis stellte sich dies jedoch anders heraus. Dem
stabilen Kanal fehlten die notwendigen Funktionen. Darüber hinaus musste für die Verwendung auf eingebetteten Geräten die Standardbibliothek geändert werden. Dies bedeutet, dass die Benutzer ihre eigene Version der Rust-Kernkiste kompilieren mussten (die Kiste, die in jeder Rust-Anwendung verwendet wird, um die grundlegenden Rust-Bausteine bereitzustellen - integrierte Funktionen und Grundelemente).

Infolgedessen waren die Entwickler auf die experimentelle Version von Rust angewiesen. In Ermangelung automatischer Tests funktionierte die Versuchsanordnung häufig nicht mit Mikrocontrollern.
Um dies zu beheben, versuchten die Entwickler, alle erforderlichen Funktionen auf einen stabilen Kanal zu übertragen und dem CI-System Tests für Mikrocontroller hinzuzufügen. Dies bedeutet, dass durch das Ändern einer Desktop-Komponente die integrierte Version nicht beschädigt wird.
Mit solchen Änderungen verlagert sich die Entwicklung eingebetteter Systeme auf Rust vom Bereich fortgeschrittener Experimente zum Bereich normaler Effizienz.
Weitere Informationen finden Sie im
Buch Rust for Embedded Systems .
Was weiter?
In diesem Jahr erhielt Rust wirklich gute Unterstützung für die beliebte ARM Cortex-M-Familie. Viele Architekturen werden jedoch noch nicht gut unterstützt. Rust muss erweitert werden, um andere Architekturen ähnlich zu unterstützen.
Netzwerkaufgaben
Um im Netzwerk arbeiten zu können, musste eine Schlüsselabstraktion in die Sprache eingebettet werden:
async/await
. Daher können Entwickler Standard-Rust-Redewendungen auch in asynchronem Code verwenden.
Bei Netzwerkaufgaben müssen Sie häufig warten. Zum Beispiel eine Antwort auf eine Anfrage. Wenn der Code synchron ist, wird die Arbeit gestoppt: Der Kern des Prozessors, auf dem der Code ausgeführt wird, kann nichts tun, bis eine Anforderung eintrifft. Im asynchronen Code kann eine solche Funktion jedoch in den Standby-Modus versetzt werden, während der CPU-Kern den Rest erledigt.
Asynchrone Programmierung ist auch in Rust 2015 möglich, und dies hat viele Vorteile. In Hochleistungsanwendungen verarbeitet die Serveranwendung viel mehr Verbindungen zu jedem Server. Eingebettete Anwendungen auf winzigen Single-Thread-CPUs optimieren die Verwendung eines einzelnen Threads.
Diese Vorteile sind jedoch mit einem großen Nachteil verbunden: Für einen solchen Code funktioniert die Kreditüberprüfung nicht und Sie müssen nicht standardmäßige (und leicht verwirrte) Rust-Redewendungen verwenden. Dies ist der Vorteil von
async/await
. Dies gibt dem Compiler die notwendigen Informationen, um das Ausleihen von asynchronen Funktionsaufrufen zu testen.
Schlüsselwörter für
async/await
in Version 1.31 implementiert, obwohl sie derzeit von der Implementierung nicht unterstützt werden. Der größte Teil der Arbeit ist erledigt und die Funktion sollte in der nächsten Version verfügbar sein.
Was weiter?
Zusätzlich zu einer effektiven Entwicklung auf niedriger Ebene kann Rust eine effizientere Entwicklung von Netzwerkanwendungen auf einer höheren Ebene ermöglichen.
Viele Server führen Routineaufgaben aus: URLs analysieren oder mit HTTP arbeiten. Wenn Sie sie in Komponenten umwandeln - allgemeine Abstraktionen, die als Kisten geteilt werden -, ist es einfach, sie miteinander zu verbinden und alle Arten von Server- und Framework-Konfigurationen zu bilden.
Ein experimentelles
Tide-Framework wurde erstellt, um Komponenten zu entwickeln und zu testen.
Befehlszeilen-Tools
Für Befehlszeilentools war es erforderlich, kleine Bibliotheken auf niedriger Ebene zu Abstraktionen auf höherer Ebene zu kombinieren und einige vorhandene Tools zu verbessern.
Für einige Skripte ist bash ideal. Zum Beispiel, um einfach andere Shell-Tools aufzurufen und Daten zwischen ihnen zu übertragen.
Aber Rust ist eine großartige Option für viele andere Werkzeuge. Wenn Sie beispielsweise ein komplexes Tool wie
ripgrep oder ein CLI-Tool zusätzlich zur Funktionalität einer vorhandenen Bibliothek erstellen.
Rust benötigt keine Laufzeit und wird in eine einzelne statische Binärdatei kompiliert, was die Verteilung des Programms vereinfacht. Und Sie erhalten Abstraktionen auf hoher Ebene, die nicht in anderen Sprachen wie C und C ++ vorliegen.
Was kann Rust noch verbessern? Natürlich Abstraktionen auf noch höherem Niveau.
Mit übergeordneten Abstraktionen kann eine vorgefertigte CLI schnell und einfach zusammengestellt werden.
Ein Beispiel für eine solche Abstraktion ist die Bibliothek für
menschliche Panik . Wenn keine solche Bibliothek vorhanden ist, gibt der CLI-Code im Falle eines Fehlers wahrscheinlich das gesamte Backtracking zurück. Aber es ist nicht sehr interessant für Benutzer. Sie können eine benutzerdefinierte Fehlerbehandlung hinzufügen, dies ist jedoch schwierig.
Bei der Human Panic Library wird die Ausgabe automatisch in die Fehler-Dump-Datei verschoben. Dem Benutzer wird eine informative Meldung angezeigt, in der er ein Problem melden und die Speicherauszugsdatei herunterladen kann.

Der Beginn der Entwicklung von CLI-Tools ist ebenfalls einfacher geworden. Beispielsweise automatisiert die
Confy- Bibliothek ihre Konfiguration. Er fragt nur zwei Dinge:
- Wie heißt die Anwendung?
- Welche Konfigurationsparameter möchten Sie bereitstellen (die Sie als eine Struktur definieren, die serialisiert und deserialisiert werden kann)?
Confy bestimmt alles andere selbst.
Was weiter?
Wir haben viele Aufgaben für die CLI abstrahiert. Aber es gibt noch etwas zu abstrahieren. Wir werden weitere solche Bibliotheken auf hoher Ebene veröffentlichen.
Rostwerkzeuge

Wenn Sie in einer beliebigen Sprache schreiben, arbeiten Sie mit den Tools: Beginnen Sie mit dem Editor und fahren Sie mit anderen Tools in allen Phasen der Entwicklung und des Supports fort.
Dies bedeutet, dass eine effektive Sprache von effektiven Werkzeugen abhängt.
Hier sind einige neue Tools (und Verbesserungen an bestehenden) in Rust 2018.
IDE-Unterstützung
Die Leistung hängt natürlich von der schnellen und reibungslosen Übertragung von Code vom Kopf des Entwicklers auf den Computerbildschirm ab. Hier ist die IDE-Unterstützung von entscheidender Bedeutung. Dazu benötigen wir Tools, die der IDE die Bedeutung von Rust-Code "erklären" können: Schlagen Sie beispielsweise sinnvolle Optionen für die automatische Vervollständigung von Zeichenfolgen vor.
In Rust 2018 konzentrierte sich die Community auf die von der IDE geforderten Funktionen. Mit dem Aufkommen von Rust Language Server und IntelliJ Rust unterstützen viele IDEs Rust jetzt vollständig.
Schnellere Zusammenstellung
Um die Compilerleistung zu verbessern, muss sie beschleunigt werden. Das haben wir getan.
Zuvor hat der Compiler beim Kompilieren der Rust-Kiste jede einzelne Datei in der Kiste neu kompiliert. Die inkrementelle Kompilierung ist jetzt implementiert: Sie kompiliert nur die Teile, die sich geändert haben. Zusammen mit anderen Optimierungen machte dies den Rust-Compiler viel schneller.
rustfmt
Effizienz erfordert auch, dass wir niemals über Code-Formatierungsregeln streiten oder die Stile anderer Leute manuell korrigieren.
Das rustfmt-Tool hilft dabei: Es formatiert den Code automatisch gemäß dem Standardstil neu (durch den die
Community einen Konsens erreicht hat ). Rustfmt stellt sicher, dass der gesamte Rust-Code dem gleichen Stil entspricht, wie das Clang-Format für C ++ oder Prettier für JavaScript.
Clippy
Manchmal ist es schön, einen erfahrenen Berater in der Nähe zu haben, der Ratschläge zu Best Practices für das Schreiben von Code gibt. Dies ist, was Clippy tut: Es überprüft den Code während der Anzeige und schlägt Standard-Idiome vor.
Rustfix
Wenn Sie jedoch eine alte Codebasis mit veralteten Redewendungen haben, kann es anstrengend sein, den Code unabhängig zu überprüfen und zu korrigieren. Sie möchten nur, dass jemand Korrekturen an der gesamten Codebasis vornimmt.
In diesen Fällen automatisiert rustfix den Prozess. Gleichzeitig werden Regeln von Tools wie Clippy angewendet und der alte Code gemäß den Redewendungen von Rust 2018 aktualisiert.
Änderungen an Rust selbst
Änderungen im Ökosystem haben die Effizienz der Programmierung erheblich gesteigert. Einige Probleme können jedoch nur durch Änderungen in der Sprache selbst gelöst werden.

Wie bereits in der Einleitung erwähnt, sind die meisten Sprachänderungen vollständig mit dem vorhandenen Rust-Code kompatibel. Alle diese Änderungen sind Teil von Rust 2018. Da sie jedoch nichts beschädigen, funktionieren sie in jedem Rust-Code ... sogar im alten.
Schauen wir uns die wichtigen Funktionen an, die allen Versionen hinzugefügt wurden. Dann schauen Sie sich eine kurze Liste der Funktionen von Rust 2018 an.
Neue Funktionen für alle Versionen
Hier ist ein kleines Beispiel für die neuen Funktionen, die in allen Versionen der Sprache verfügbar sind (oder sein werden).
Genauere Überprüfung der Kreditaufnahme
Ein großer Vorteil von Rust ist die Überprüfung der Kreditaufnahme. Es stellt sicher, dass der Code speichersicher ist. Dies ist aber auch eine ziemlich komplizierte Funktion für Rust-Neulinge.
Ein Teil der Schwierigkeit liegt darin, neue Konzepte zu lernen. Aber es gibt noch einen anderen Teil ... Das Testen von Ausleihen lehnt manchmal Code ab, der aus der Sicht eines Programmierers zu funktionieren scheint, der das Konzept der Speichersicherheit vollständig versteht.
Sie können eine Variable nicht ausleihen, da sie bereits ausgeliehen istDies liegt daran, dass sich die Lebensdauer der Ausleihe bis zum Ende des Felds erstrecken sollte - beispielsweise bis zum Ende der Funktion, in der sich die Variable befindet.
Dies bedeutete, dass anderen Variablen bis zum Ende der Funktion der Zugriff auf diesen Wert verweigert wird, selbst wenn die Variable nicht mehr mit dem Wert arbeitet und nicht mehr versucht, darauf zuzugreifen.
Um die Situation zu korrigieren, haben wir den Scheck intelligenter gemacht. Jetzt sieht sie, wann die Variable den Wert
tatsächlich verwendet hat. Danach wird die Verwendung von Daten nicht blockiert.

Dies ist zwar nur in Rust 2018 verfügbar, aber in naher Zukunft wird die Funktion allen anderen Versionen hinzugefügt. Bald werden wir mehr zu diesem Thema schreiben.
Verfahrensmakros in stabilem Rost
Rust hatte Makros vor Rust 1.0. In Rust 2018 wurden jedoch ernsthafte Verbesserungen vorgenommen, beispielsweise wurden prozedurale Makros angezeigt. Mit ihnen können Sie Rust Ihre eigene Syntax hinzufügen.
Rust 2018 bietet zwei Arten von prozeduralen Makros:
Funktionsmakros
Mit funktionsähnlichen Makros können Sie Objekte erstellen, die wie normale Funktionsaufrufe aussehen, aber tatsächlich zur Kompilierungszeit ausgeführt werden. Sie nehmen einen Code und geben einen anderen aus, den der Compiler dann in die Binärdatei einfügt.
Sie existierten vorher, aber mit begrenztem. Ein Makro konnte nur die match-Anweisung ausführen. Er hatte keinen Zugriff, um alle Token im eingehenden Code anzuzeigen.
Bei prozeduralen Makros erhalten Sie jedoch dieselbe Eingabe wie beim Parser: denselben Token-Stream. Dies bedeutet, dass Sie viel leistungsfähigere Makros wie Funktionen erstellen können.
Attributähnliche Makros
Wenn Sie mit Dekorateuren in Sprachen wie JavaScript vertraut sind, sind Attributmakros sehr ähnlich. Mit ihnen können Sie Fragmente von Rust-Code mit Anmerkungen versehen, die vorverarbeitet und in etwas anderes umgewandelt werden sollen.
Das
derive
macht genau das. Wenn Sie es über eine Struktur legen, nimmt der Compiler diese Struktur (nachdem sie als Liste von Token analysiert wurde) und verarbeitet sie. Insbesondere wird eine grundlegende Implementierung von Funktionen aus dem Merkmal hinzugefügt.
Ergonomischere Anleihen im Vergleich
Es gibt eine einfache Änderung.
Wenn Sie zuvor etwas ausleihen wollten und versuchten, eine Übereinstimmung zu finden, mussten Sie eine seltsame Syntax hinzufügen:

Anstelle von
&Some(ref s)
schreiben wir jetzt einfach
Some(s)
.
Neue Rust 2018 Funktionen
Der kleinste Teil von Rust 2018 enthält spezifische Funktionen für diese Version. Hier ist eine kleine Reihe von Änderungen in Rust 2018.
Stichworte
Rust 2018 hat einige Schlüsselwörter hinzugefügt:
Diese Funktionen sind noch nicht vollständig implementiert, aber Schlüsselwörter werden in Rust 1.31 hinzugefügt.
Daher müssen wir in Zukunft keine neuen Schlüsselwörter einführen (was zu einer inkompatiblen Änderung führen würde), wenn wir diese Funktionen implementieren.Modulares System
Ein großer Schmerz für Rust-Neulinge ist das modulare System. Und es ist klar warum. Es war schwer zu verstehen, warum Rust ein bestimmtes Modul auswählt. Um dies zu beheben, haben wir einige Änderungen am Pfadmechanismus vorgenommen.Wenn Sie beispielsweise ein Rack importiert haben, können Sie es im Pfad auf der obersten Ebene verwenden. Wenn Sie jedoch Code in ein Submodul verschieben, funktioniert dies nicht mehr.
Ein weiteres Beispiel ist das Präfix ::
, das sowohl für die Wurzel der Kiste als auch für die externe Kiste verwendet wird. Es ist schwer zu verstehen, was vor uns liegt.Wir haben es expliziter gemacht. Wenn Sie sich nun auf die Wurzelkiste beziehen möchten, verwenden Sie das Präfix crate::
. Dies ist nur eine der Verbesserungen zur Klarheit.Wenn der aktuelle Code die Funktionen von Rust 2018 nutzen soll, müssen Sie den Code höchstwahrscheinlich aktualisieren, um die neuen Pfade widerzuspiegeln. Dies muss jedoch nicht manuell erfolgen. Bevor Sie den Versionsbezeichner zu Cargo.toml hinzufügen, führen Sie ihn einfach aus cargo fix
und nehmen Sie rustfix
die erforderlichen Änderungen vor.Weitere Informationen
Alle Informationen zur neuen Version der Sprache sind im Rust 2018-Handbuch enthalten .