Programmiersprache Rust 1.61 kann Programme aussagekräftig beenden

Neben einem frei gestaltbaren Rückgabewert der main-Funktion bietet das Release Erweiterungen bei konstanten Funktionen.

In Pocket speichern vorlesen Druckansicht 15 Kommentare lesen

(Bild: Callum Bainbridge / Shutterstock.com)

Lesezeit: 4 Min.
Von
  • Rainald Menge-Sonnentag
Inhaltsverzeichnis

Im planmäßigen Sechswochentakt ist Rust 1.61 erschienen. Nachdem das vorige Release vor allem Ergänzungen in der Toolchain an Bord hatte, bringt das aktuelle einige Ergänzungen für die Sprache selbst. Unter anderem lassen sich für die Funktion main neuerdings flexible Rückgabewerte nutzen, und die konstanten Funktionen werden flexibler im Zusammenspiel mit Traits und Zeigern.

In den Anfangszeiten von Rust endete die Funktion main, die als Einstiegspunkt für typische Programme dient, ohne jede Statusmeldung. Seit Rust 1.26 erlaubt die Programmiersprache die Rückgabe von Result. Im Zusammenspiel mit C entspricht dabei der Rust-Wert Ok dem C-Rückgabewert EXIT_SUCCESS und Err entspricht EXIT_FAILURE.

Zuständig für die Rückgabe ist der Trait Termination. Traits in Rust ähneln Interfaces in anderen Programmiersprachen. Sie definieren eine Reihe von Methoden für einen zunächst unbekannten Typ Self. Termination existierte bisher nur unter der Haube und galt als instabil.

Rust 1.61 stabilisiert den Trait und generalisiert im Zuge dessen den Rückgabewert mit dem Typ ExitCode. Letzterer enthält einerseits die Konstanten SUCCESS and FAILURE und implementiert darüber hinaus From<u8> für beliebige Rückgabewerte. Darüber hinaus lässt sich Termination mit eigenen Typen verwenden, um zusätzliche Arbeitsschritte vor der Ausgabe des ExitCode zu definieren.

Folgendes Beispiel aus dem Rust-Blog zeigt den Einsatz des Traits in einer Umsetzung des Git-Befehls bisect run. Dazu definiert der Code eine Enumeration mit passenden Rückgabewerten:

use std::process::{ExitCode, Termination};

#[repr(u8)]
pub enum GitBisectResult {
    Good = 0,
    Bad = 1,
    Skip = 125,
    Abort = 255,
}

impl Termination for GitBisectResult {
    fn report(self) -> ExitCode {
        // Maybe print a message here
        ExitCode::from(self as u8)
    }
}

fn main() -> GitBisectResult {
    std::panic::catch_unwind(|| {
        todo!("test the commit")
    }).unwrap_or(GitBisectResult::Abort)
}

Die zweite große Neuerung betrifft konstante Funktionen, die Rust seit Version 1.31 kennt. Letztere markierte 2018 gleichzeitig den Start der zweiten Edition der Programmiersprache Rust. Eine const fn lässt sich im Gegensatz zu regulären Funktionen in konstanten Kontexten ausführen, also beispielsweise in einem const or static Element. Da der Compiler sie in diesem Kontext beim Übersetzen evaluieren kann, nimmt er in dem Fall zusätzlich erweiterte Optimierungen vor. Außerhalb der Kontexte verhalten konstante Funktionen sich weitgehend wie reguläre, sind aber einigen Beschränkungen unterbunden.

Seit dem ersten Aufschlag hat Rust einige Ergänzungen für die konstanten Funktionen mitgebracht, unter anderem in der Version 1.33 und in Rust 1.46. Das aktuelle Release beseitigt nun einige Beschränkungen für const fn. Unter anderem lassen sich Funktions-Pointer erstellen, übergeben und casten. Allerdings ist es nach wie vor nicht erlaubt, die fn-Zeiger direkt aufzurufen.

Im Zusammenspiel mit Traits erlaubt Rust 1.61 für konstante Funktionen Trait Bounds mit generischen Parametern wie T: Copy. Außerdem können sie dyn Trait-Typen für Objekte, deren genaues Speicher-Layout erst zur Laufzeit bekannt ist, und generischere impl Trait-Typen verarbeiten. Der Aufruf von Methoden der Traits aus der konstanten Funktion ist jedoch noch nicht erlaubt.

Nennenswert ist noch, dass das Absichern von Daten in Standard-Streams vor Überschreiben bei nebenläufiger Programmierung über lock() neuerdings im statischen Verlaufskontext erfolgt. Bisher war nur ein Lock Guard auf &self für Stdin, Stdout und Stderr möglich, womit das Absichern auf den ursprünglichen Scope beschränkt war. Nun erfolgt der Lock Guard über die gesamte Lebenszeit des Programms, also der Lifetime 'static.

Weitere Details zu Rust 1.61, darunter einige stabilisierte APIs, lassen sich dem Rust-Blog entnehmen. 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.

Siehe auch:

  • Rust: Download schnell und sicher von heise.de

(rme)