Programmiersprache Rust 1.65 führt Generic Associated Types ein

Neben der seit langer Zeit in Entwicklung befindlichen Umsetzung von Generics für Associated Types bringt das Release let-else-Anweisungen.

In Pocket speichern vorlesen Druckansicht 50 Kommentare lesen

(Bild: Callum Bainbridge / Shutterstock.com)

Lesezeit: 4 Min.
Inhaltsverzeichnis

Das planmäßig im Sechswochentakt veröffentlichte Rust 1.65 stabilisiert mit Generic Associated Types ein von vielen gewünschtes Feature, das sich seit langem in Entwicklung befindet. Außerdem führt es let-else-Anweisungen ein und ermöglicht das frühzeitige Verlassen gelabelter Codeblöcke über break.

Associated Types verpacken Typen innerhalb einer Trait-Deklaration. Traits in Rust sind vergleichbar mit Interfaces in anderen Sprachen, erlauben aber auch Standardimplementierung von Funktionen. Auch wenn Associated Types als Platzhalter für konkrete Implementierungen dienen, waren bisher für die definierten Typen keine Generics erlaubt. Das ändert sich mit dem aktuellen Release, in dem sich Type, Lifetime und Const Generics ebenso für Associated Types verwenden lassen wie bisher unter anderem für reguläre Typ-Aliase.

Die Neuerung ermöglicht zusätzliche Konstrukte unter anderem für Ownership oder für die Polymorphie. Der Blogbeitrag zum Release zeigt Codebeispiele für einen an den Iterator-Trait aus der Standard-Library angelehnten LendingIterator, der von Self ausleiht, eine Implementierung eines generischen Smart Pointer und das Borrowing eines Arrays:

/// An `Iterator`-like trait that can borrow from `Self`
trait LendingIterator {
    type Item<'a> where Self: 'a;

    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
}

/// Can be implemented over smart pointers, like `Rc` or `Arc`,
/// in order to allow being generic over the pointer type
trait PointerFamily {
    type Pointer<T>: Deref<Target = T>;

    fn new<T>(value: T) -> Self::Pointer<T>;
}

/// Allows borrowing an array of items. Useful for
/// `NdArray`-like types that don't necessarily store
/// data contiguously.
trait BorrowArray<T> {
    type Array<'x, const N: usize> where Self: 'x;

    fn borrow_array<'a, const N: usize>(&'a self) 
      -> Self::Array<'a, N>;
}

Der RFC (Request for Comments) zu Generic Associated Types (GATs) stammt aus dem Jahr 2016 und somit noch vor dem Vorschlag, Const Generics einzuführen, die letztlich mit Rust 1.51 kamen. Im August 2021 hat die Traits-Arbeitsgruppe von Rust mit der Implementierung begonnen und die Hoffnung geäußert, die Stabilisierung in einigen Monaten abschließen zu können. Die Einführung der GATs war seinerzeit laut der Arbeitsgruppe der am höchsten votierte Issue im Rust-Repository.

Der Beitrag zur Stabilisierung erklärt einige der Hürden bei der Umsetzung, darunter das Parsen von GATs im Abstract Syntax Tree und das Auflösen der Lifetimes. Nach wie vor ist die Implementierung nicht frei von Bugs, wie ein Blogbeitrag von Ende Oktober ausführlich erklärt. Insbesondere die Lifetime der ausgeborgten Werten führen noch zu einigen Beschränkungen. Das Team hat sich trotzdem für die Stabilisierung entschlossen, weil es zum einen die Generic Associated Types für sehr nützlich hält und andererseits alle noch bestehenden Probleme für lösbar hält.

Vor allem mehr Lesbarkeit soll die neue let ... else-Anweisung bringen. Bisher waren für die Variablenzuweisung über let nur statisch als passend überprüfbare beziehungsweise unbestreitbare (irrefutable) Patterns erlaubt. Das neue Konstrukt hebt diese Einschränkung auf und ersetzt damit umständlichere Konstrukte mit if let odermatch: Wenn das Pattern passt, erfolgt die Zuweisung und ansonsten wird der else-Block ausgeführt.

Die Heise-Konferenz zu Rust

(Bild: Callum Bainbridge / Shutterstock.com)

Am 9. November findet die zweite Auflage der betterCode() Rust statt. Die Online-Konferenz fokussiert sich dieses Jahr auf einen praxisnahen Einstieg in die Programmiersprache Rust. Die von heise Developer und dpunkt.verlag ausgerichtete Veranstaltung vermittelt in sechs Vorträgen die Grundlagen, um Desktop- und WebAssembly-Anwendungen oder Web-APIs zu erstellen, ohne sich in der Komplexität der Tiefen von Rust zu verlieren.

Ebenfalls neu sind Codeblöcke, die ein Label tragen, und aus denen jederzeit ein Abbruch mit einem Rückgabewert über break erfolgen kann. Folgender Code aus dem Rust-Blog zeigt eine einfache Umsetzung, die eine let-Zuweisung in einen Codeblock packt, der zum einen den Rückgabewert als 1, 2 oder 3 bestimmt und zum anderen je nach Voraussetzung eine, zwei oder drei zusätzliche Funktionen ausführt:

let result = 'block: {
    do_thing();
    if condition_not_met() {
        break 'block 1;
    }
    do_next_thing();
    if condition_not_met() {
        break 'block 2;
    }
    do_last_thing();
    3
};

Weitere Neuerungen wie das Aufsplitten von Debug-Informationen unter Linux und einige stabilisierte APIs lassen sich dem Rust-Blog entnehmen, der jenseits der technischen Inhalte auf den Tod von Mahsa Amini und die Protestbewegung im Iran hinweist und Solidarität zu den Menschen im Iran bekundet.

Wie üblich können Entwicklerinnen und Entwickler, die Rust bereits installiert haben, das aktuelle Release über rustup update stable herunterladen. Für diejenigen, die noch kein Rust verwenden, ist das rustup-Tool auf der Download-Seite separat verfügbar.

(rme)