Die Veröffentlichung von Rust 1.51, der Programmiersprache, die ursprünglich von Mozilla entwickelt wurde, aber nun unter der Schirmherrschaft der unabhängigen gemeinnützigen Organisation Rust Foundation weitergeführt wird, ist erfolgt. Die Sprache konzentriert sich auf eine sichere Arbeit mit Speicher, bietet automatisches Speichermanagement und ermöglicht eine hohe Parallelität bei der Ausführung von Aufgaben, ohne dabei einen Garbage Collector oder eine Runtime zu verwenden (die Runtime beschränkt sich auf die grundlegende Initialisierung und den Support der Standardbibliothek).
Das automatische Speichermanagement in Rust befreit Entwickler von Fehlern beim Umgang mit Zeigern und schützt vor Problemen, die aus der niederen Speicherverwaltung entstehen, wie etwa dem Zugreifen auf Speicherbereiche nach deren Freigabe, dem Dereferenzieren von Nullzeigern, Pufferüberläufen usw. Zur Verbreitung von Bibliotheken, zur Gewährleistung des Builds und zur Verwaltung der Abhängigkeiten wird der Paketmanager Cargo entwickelt. Für die Bereitstellung von Bibliotheken wird das Repository crates.io unterstützt.
Hauptneuheiten:
- Die Funktionalität in Zusammenhang mit konstanten Generics hat den Status eines minimalen marktfähigen Produkts (MVP) erreicht, was eine breite Anwendung ermöglicht. Konstante Generics erlauben es, Typen für feste Werte zu generalisieren, d. h. generische Argumente zu verwenden, die durch einen Bereich konstanter Werte und nicht durch Typen oder Lebensdauern eingeschränkt sind. Diese Möglichkeit ermöglicht die Verwendung von Typen, die mit ganzen Zahlen parametriert sind, und abstrahiert das Erstellen von Typen für Arrays beliebiger Größe, ohne dass ein separater Typ für jeden Bereich erlaubter Werte erstellt werden muss, um sicherzustellen, dass keine Werte außerhalb des zulässigen Bereichs liegen.
Ab der aktuellen Version wurde die Möglichkeit eingeführt, für Arrays vom Typ „[T; N]“ (Typ T und Größe N) sich vom Typ und der Größe zu abstrahieren, indem Werte mit beliebigen ganzzahligen, booleschen und zeichenbasierten Typen verwendet werden (struct- und enum-Typen werden derzeit noch nicht unterstützt). Konstante Generics erleichtern die Entwicklung von Bibliotheken erheblich. Zum Beispiel kann zum Einsatz eines Arrays, das nicht an einen bestimmten Typ und eine bestimmte Größe gebunden ist, folgendes angegeben werden: struct Array { // ^^^^^^^^^^^^^^^^^^^ Definition des konstanten Generics list: [T; LENGTH] // ^^^^^^ seine Verwendung }
Bei der tatsächlichen Verwendung dieser Definition „Array“ generiert der Compiler eine monomorphe Version von Array: struct Array { list: [u8; 32] }
- Die auf konstanten Generics basierende API std::array::IntoIter wurde stabilisiert, mit der es möglich ist, für jedes Array Iteratoren nach Wert zu erstellen: fn main() { let array = [1, 2, 3, 4, 5]; // Früher musste für die Iteration der Wert die Methode .iter() aufgerufen werden for item in array.iter().copied() { println!(„{}“, item); } // Jetzt kann angegeben werden for item in std::array::IntoIter::new(array) { println!(„{}“, item); } }
- Der Paketmanager Cargo unterstützt das neue Feld resolver in Cargo.toml, mit dem die zweite Version des Feature-Resolvers aktiviert werden kann. Diese neue Version des Resolvers vermeidet das Zusammenführen von Abhängigkeitsfunktionen, die im Abschnitt „[features]“ aufgeführt sind, wo dies unangemessen ist, beispielsweise beim Hinzufügen einer Abhängigkeit, die eine Standardfunktion in Build-Skripten und -Makros anfordert, während eine nicht standardisierte Funktion in der endgültigen ausführbaren Datei verwendet wird.
Die Möglichkeiten des in den Abhängigkeiten mehrfach erwähnten Pakets wurden bis jetzt kombiniert. Wenn beispielsweise ein Projekt von der Abhängigkeit foo ausgeht, die die Funktionen A und B definiert, und dieses Paket in anderen Paketen bar und baz verwendet wird, wobei bar von foo mit Funktion A und baz von foo mit Funktion B abhängt, dann wird Cargo diese Funktionen kombinieren und foo mit den Funktionen A und B kompilieren. Diese Methode kann dazu führen, dass eine aufgrund einer Abhängigkeit aktivierte Funktion mit dem Zielsystem inkompatibel ist, für das der endgültige Build erfolgt. Zum Beispiel, wenn eine Version von foo mit "#![no_std]" in einer mit "#![no_std]" gebauten ausführbaren Datei benötigt wird, während gleichzeitig foo mit "std" für den Build in build.rs verwendet wird. Durch die Angabe von resolver="2" in der Cargo.toml wird der Paketmanager nun versuchen, diesen Konflikt korrekt zu behandeln, indem er dev-, host- und target-Abhängigkeiten trennt.
- In cargo wurde die Option split-debuginfo implementiert, die im Abschnitt „[profile]“ festgelegt wird, sowie das entsprechende Flag „-Csplit-debuginfo=unpacked“ in rustc. Dies bietet die Implementierung einer neuen Methode zur Speicherung von Debug-Informationen, die die Notwendigkeit des Aufrufs des Werkzeugs dsymutil überflüssig macht und den Prozess des Aufbaus mit Debug-Informationen in macOS erheblich beschleunigt.
- Die macOS-Funktionen „ptr::addr_of!“ und „ptr::addr_of_mut!“ wurden stabilisiert, die rohe Zeiger für nicht ausgerichtete Felder erstellen. use std::ptr; #[repr(packed)] struct Packed { f1: u8, f2: u16, } let packed = Packed { f1: 1, f2: 2 }; // &packed.f2 erstellt einen nicht ausgerichteten Zeiger, was zu undefiniertem Verhalten führen kann. let raw_f2 = ptr::addr_of!(packed.f2); assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
- Eine neue Reihe von APIs wurde in den stabilen Bereich überführt. Darunter wurden die folgenden Methoden stabilisiert:
- Arc::decrement_strong_count
- Arc::increment_strong_count
- Once::call_once_force
- Peekable::next_if_eq
- Peekable::next_if
- Seek::stream_position
- array::IntoIter
- panic::panic_any
- ptr::addr_of!
- ptr::addr_of_mut!
- slice::fill_with
- slice::split_inclusive_mut
- slice::split_inclusive
- slice::strip_prefix
- slice::strip_suffix
- str::split_inclusive
- sync::OnceState
- task::Wake
- Die dritte Unterstützungsebene wurde für die Plattformen i386-unknown-linux-gnu, i486-unknown-linux-gnu, aarch64_be-unknown-linux-gnu, aarch64-unknown-linux-gnu_ilp32 und aarch64_be-unknown-linux-gnu_ilp32 implementiert. Die dritte Ebene bietet grundlegende Unterstützung, jedoch ohne automatisierte Tests, Veröffentlichung offizieller Builds und Überprüfung der Möglichkeit, den Code zu kompilieren.
Quelle: opennet.ru
