W dniu obchodów dziesięciolecia wydania języka programowania Rust 1.0 (projekt Rust został założony w 2006 roku, wydanie 0.1 miało miejsce w 2012 roku, a pierwsza stabilna wersja została zaproponowana w 2015 roku) opublikowano wersję Rust 1.87. Język koncentruje się na bezpiecznej pracy z pamięcią i zapewnia narzędzia do osiągania wysokiego poziomu równoległości wykonywania zadań, omijając jednocześnie użycie garbage collectora i runtime (runtime ogranicza się do podstawowej inicjalizacji i wsparcia standardowej biblioteki).
Metody zarządzania pamięcią w Rust eliminują błędy związane z manipulowaniem wskaźnikami oraz chronią przed problemami wynikającymi z niskopoziomowej obsługi pamięci, takimi jak dostęp do pamięci po jej zwolnieniu, dereferencjonowanie wskaźników zerowych, wychodzenie poza granice bufora itp. Dla rozprowadzania bibliotek, zapewnienia budowy i zarządzania zależnościami, rozwijany jest menedżer pakietów Cargo. Dla publikacji bibliotek wspierany jest repozytorium crates.io.
Bezpieczne zarządzanie pamięcią w Rust jest zapewnione podczas kompilacji poprzez kontrolę referencji, śledzenie własności obiektów, uwzględnianie czasu życia obiektów (zakresu widoczności) oraz ocenę prawidłowości dostępu do pamięci w czasie wykonywania kodu. Rust oferuje również narzędzia do ochrony przed przepełnieniami liczbowymi, wymaga obowiązkowej inicjalizacji wartości zmiennych przed użyciem, lepiej obsługuje błędy w standardowej bibliotece, stosuje koncepcję niemutowalności (immutable) referencji i zmiennych domyślnie oraz oferuje silne statyczne typowanie w celu minimalizacji błędów logicznych.
Główne nowości:
- Do standardowej biblioteki dodano wsparcie dla nieznanych kanałów (anonymous pipe). Aby utworzyć nieznane kanały, zaproponowano metodę std::io::pipe(), która może być używana w połączeniu z std::process::Command do obsługi standardowych strumieni wejściowych i wyjściowych, a także do łączenia strumieni stdout i stderr. use std::process::Command; use std::io::Read; let (mut recv, send) = std::io::pipe()?; let mut command = Command::new("path/to/bin") // połączenie stdout i stderr w jeden kanał .stdout(send.try_clone()?) .stderr(send) .spawn()?; let mut output = Vec::new(); recv.read_to_end(&mut output)?; assert!(command.wait()?.success());
- Zezwalają na wywołanie z safe-kodu większości funkcji wbudowanych w kompilatorze (Intrinsics) std::arch. Zmiana dotyczy wbudowanych funkcji std::arch, które oznaczone są jako unsafe tylko z powodu powiązania z określoną funkcjonalnością, jeśli ta funkcjonalność jest włączona. Na przykład, _mm256_add_epi32 można wywołać z safe-kodu, jeśli w aplikacji używana jest ‘#[target_feature(enable = "avx2")]’.
- Z bloków „asm!” z kodem assemblerowym zezwolono na przechodzenie do bloków z kodem w języku Rust, co ułatwia rozwój niskopoziomowego kodu, na przykład implementację optymalizacji w jądrze lub organizację interakcji z sprzętem. Punkt przejścia dla komendy assemblerowej „jmp” określany jest w makrze „asm!” przy użyciu nowego operand „label”, zawierającego wyrażenie blokowe z kodem w języku Rust. unsafe { asm!( "jmp {}", label { println!("Jumped from asm!"); } ); }
- Zezwolenie na precyzyjne określenie przechwyconych typów ogólnych i czasu życia w definicjach typów za pomocą typów zwracanych impl Trait. trait Foo { fn method(&'a self) -> impl Sized; type Implicit1: Sized; fn method_desugared(&'a self) -> Self::Implicit1; fn precise(&'a self) -> impl Sized + use; type Implicit2: Sized; fn precise_desugared(&'a self) -> Self::Implicit2; }
- Nowa porcja API została wprowadzona do stabilnej wersji, w tym ustabilizowane metody i implementacje traitów:
- Vec::extract_if
- vec::ExtractIf
- LinkedList::extract_if
- linked_list::ExtractIf
- ::split_off
- ::split_off_mut
- ::split_off_first
- ::split_off_first_mut
- ::split_off_last
- ::split_off_last_mut
- String::extend_from_within
- os_str::Display
- OsString::display
- OsStr::display
- io::pipe
- io::PipeReader
- io::PipeWriter
- impl From for OwnedHandle
- impl From for OwnedHandle
- impl From for Stdio
- impl From for Stdio
- impl From for OwnedFd
- impl From for OwnedFd
- Box<MaybeUninit>::write
- impl TryFrom<Vec> for String
- ::offset_from_unsigned
- ::byte_offset_from_unsigned
- ::offset_from_unsigned
- ::byte_offset_from_unsigned
- NonNull::offset_from_unsigned
- NonNull::byte_offset_from_unsigned
- ::cast_signed
- NonZero::::cast_signed.
- ::cast_unsigned.
- NonZero::::cast_unsigned.
- ::is_multiple_of
- ::unbounded_shl
- ::unbounded_shr
- ::unbounded_shl
- ::unbounded_shr
- ::midpoint
- ::from_utf8
- ::from_utf8_mut
- ::from_utf8_unchecked
- ::from_utf8_unchecked_mut
- Wskaźnik „const” zastosowany w funkcjach:
- core::str::from_utf8_mut
- ::copy_from_slice
- SocketAddr::set_ip
- SocketAddr::set_port,
- SocketAddrV4::set_ip
- SocketAddrV4::set_port,
- SocketAddrV6::set_ip
- SocketAddrV6::set_port
- SocketAddrV6::set_flowinfo
- SocketAddrV6::set_scope_id
- char::is_digit
- char::is_whitespace
- <N::as_flattened
- <N::as_flattened_mut
- String::into_bytes
- String::as_str
- String::capacity
- String::as_bytes
- String::len
- String::is_empty
- String::as_mut_str
- String::as_mut_vec
- Vec::as_ptr
- Vec::as_slice
- Vec::capacity
- Vec::len
- Vec::is_empty
- Vec::as_mut_slice
- Vec::as_mut_ptr
- Usunięto drugi poziom wsparcia dla docelowej platformy i586-pc-windows-msvc. Zaleca się korzystanie z platformy i686-pc-windows-msvc, która różni się wsparciem dla instrukcji SSE2. Platforma i586-pc-windows-msvc straciła sens, ponieważ dla Windows 10 wymagana jest obsługa SSE2, a wcześniejsze wersje systemu Windows w Rust nie są już wspierane.
Źródło: opennet.ru
