Opublikowana została wersja języka programowania ogólnego przeznaczenia Rust 1.81, który początkowo był rozwijany przez projekt Mozilla, a obecnie rozwijany jest pod auspicjami niezależnej organizacji non-profit Rust Foundation. Język koncentruje się na bezpiecznym zarządzaniu pamięcią i oferuje narzędzia do osiągania wysokiego poziomu równoległości w wykonywaniu zadań, przy czym nie korzysta z garbage collectora ani runtime (runtime ogranicza się do podstawowej inicjalizacji i zarządzania standardową biblioteką).
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:
- Stabilizowany jest trait core::error::Error, który definiuje opisy błędów. Zmiana ta pozwala na używanie jednego traitu Error w różnych bibliotekach, niezależnie od środowiska, w tym w bibliotekach niepowiązanych ze standardową biblioteką, korzystających z atrybutu „#![no_std]”.
- Stabilne i niestabilne funkcje sortowania w standardowej bibliotece zostały przetłumaczone na nowe algorytmy, które wykazują większą szybkość działania oraz krótszy czas kompilacji. W implementacji nowych algorytmów sortowania zapewniono identyfikację niepoprawnie zdefiniowanych traitów Ord i zwrócenie błędu (panic) w takich przypadkach zamiast przypadkowo pogrupowanych danych.
- W linterze wprowadzono nowy poziom kontroli „expect” („#[expect(lint)]”), który pozwala upewnić się, że kontrola jest wykonywana i wyświetla ostrzeżenie, jeśli kontrola nie została przeprowadzona (z powodu błędu w implementacji lub wyłączenia kontroli). Na przykład, przy migracji kodu bazy na użycie sprawdzania undocumented_unsafe_blocks przez Clippy można wskazać „#[expect(clippy::undocumented_unsafe_blocks)]”, aby upewnić się, że w trakcie przejścia wszystkie unsafe-bloki będą udokumentowane. W Clippy wprowadzono również kontrole clippy::allow_attributes i clippy::allow_attributes_without_reason, które ułatwiają zamianę atrybutów „#[allow]” na „#[expect(lint)]”.
- Udostępniono możliwość dokumentowania przyczyny zamiany poziomów kontroli (lint), co dostarcza nowym deweloperom informacji o powodach dodania danej kontroli, wyświetlanej w postaci komunikatu kompilatora. Na przykład: #![deny(clippy::float_arithmetic, reason = „no hardware float support”)]
- Nowa porcja API została wprowadzona do stabilnej wersji, w tym ustabilizowane metody i implementacje traitów:
- core::error
- hint::assert_unchecked
- fs::exists
- AtomicBool::fetch_not
- Duration::abs_diff
- IoSlice::advance
- IoSlice::advance_slices
- IoSliceMut::advance
- IoSliceMut::advance_slices
- PanicHookInfo
- PanicInfo::message
- PanicMessage
A feature 'const' that defines the ability to be used in any context instead of constants is applied in functions:
- char::from_u32_unchecked (function)
- char::from_u32_unchecked (method)
- CStr::count_bytes
- CStr::from_ptr
The type std::panic::PanicInfo has been renamed to std::panic::PanicHookInfo (the old name will still work, but from the next version its use will generate a warning). Meanwhile, core::panic::PanicInfo will remain as is, but will evolve as a separate type. This separation of types will allow for the implementation of different methods specific to execution in the context of snd and no_std.
- The transition to the C-unwind ABI (‘extern ‘C-unwind’‘) has been completed, which differs from the ABI without the ‘-unwind’ suffix (‘extern ‘C’‘) by preserving safe behavior (safe) if the unwinding process, initiated during a program crash or exception generation in C++ style, crosses the ABI boundary (for example, when an exception arising from code in one programming language unwinds affecting the stack associated with code in another programming language). Starting with Rust release 1.81, the ‘extern ‘C’‘ ABI involves panic during uncaught unwinding.
- The third level of support has been implemented for platforms i686-unknown-redox, xtensa-esp32-none-elf, xtensa-esp32s2-none-elf, xtensa-esp32s3-none-elf, xtensa-esp32-espidf, xtensa-esp32s2-espidf, xtensa-esp32s3-espidf. The third level implies basic support but without automated testing, publication of official builds, and verification of code build capability.
- The second level of support has been implemented for target platforms loongarch64-unknown-linux-musl and arm64ec-pc-windows-msvc. The second level of support guarantees build success.
- A complete toolkit and profiler has been provided for Linux systems on the LoongArch platform.
- Usunięto lukę (CVE-2024-43402) w std::process::Command, która występuje tylko na platformie Windows i zapobiega obejściu wcześniej naprawionej luki BatBadBut związanej z przetwarzaniem znaków specjalnych podczas używania wywołań Command::arg i Command::args, które są zaprojektowane do bezpośredniego przekazywania argumentów do procesu, bez ich przetwarzania przez powłokę. W praktyce, podczas uruchamiania skryptów bat i cmd, uruchamiano proces cmd.exe, który ma własną logikę podziału argumentów. Obejście zabezpieczeń opiera się na tym, że Windows usuwa wiodące spacje i kropki w ścieżkach, tj. plik z rozszerzeniem „.bat. .” jest traktowany jako „.bat”.
Dodatkowo warto wspomnieć o odejściu Wedsona Almeidy Filho z pozycji opiekuna projektu Rust for Linux, który zajmował się wprowadzaniem do jądra Linux narzędzi dla programistów korzystających z języka Rust. Po odejściu Wedsona w projekcie pozostało jeszcze dwóch opiekunów — Miguel Ojeda, autor i główny deweloper projektu Rust-for-Linux, oraz Alex Gaynor, były dyrektor Python Software Foundation, który przeszedł na promocję Rust. Odszedł opiekun, który dołączył do projektu 4 lata temu, jest pracownikiem firmy Microsoft i autorem eksperymentalnego sterownika dla systemu plików EXT2, napisanego w języku Rust. Ostatnio prace Almeidy były skoncentrowane na tworzeniu narzędzi do programowania systemów plików w języku Rust. W tym roku Almeida dodał 17 commitów do repozytorium Rust-for-Linux (dla porównania Miguel Ojeda dodał 53 commity).
Jako powód odejścia wymienia się brak sił i entuzjazmu, które kiedyś były potrzebne do reagowania na pewne bełkoty o charakterze nie technicznym (nontechnical nonsense). Zdaniem Almeidy, programiści są zmuszeni poświęcać dużo energii na spory dotyczące nieistotnych kwestii, które unieważniają ważniejszy cel globalny. Almeida wciąż wierzy, że przyszłość jąder związana jest z używaniem języków, które zapewniają bezpieczną obsługę pamięci, i jeśli społeczność deweloperów Linuxa tego nie zrozumie, to Linux zostanie wyparty przez jakieś inne jądro, tak jak to miało miejsce z Unixem.
Zwolennicy projektu Rust-for-Linux napotkali konieczność pokonania oporu ze strony doświadczonych, starych programistów jądra, którzy nie widzą potrzeby uczenia się nowego języka. W swoim liście rezygnacyjnym Almeida jako przykład podaje odnośnik do dyskusji, która miała miejsce podczas wystąpienia Almeidy i Kenta Overstreeta na konferencji „Linux Storage, Filesystem, Memory-Management, and BPF Summit”, a która dotyczyła wykorzystania Rust do tworzenia systemów plików. Działalność na rzecz wdrożenia Rust została skrytykowana przez Teda Ts’o, autora systemów plików ext2/ext3/ext4, który porównał inicjatywę Rust-for-Linux do próby zmuszenia wszystkich do przyjęcia religii Rust.
W odpowiedzi na zamiar Almeidy stworzenia wiązania nad interfejsami systemów plików napisanymi w języku C do ich wykorzystania w kodzie napisanym w języku Rust, Ted Ts’o zauważył, że takie wiązanie nieuchronnie prowadzi do problemów, ponieważ jakiekolwiek zmiany w interfejsach C i refaktoryzacja będą wymagały zmiany wiązania dla Rust, a on nie chce brać na siebie dodatkowej odpowiedzialności za naprawianie powstających problemów w kodzie Rust i śledzenie stanu wiązania Rust. Kod w C stale się rozwija, a jeśli jego zmiana zakłóci działanie wiązania dla Rust, doprowadzi to do problemów w wszystkich powiązanych z nim systemach plików.
Ted uważa również, że w przewidywalnej przyszłości wiązanie dla Rust pozostanie drugorzędne, a pojawienie się problemów w powiązaniach będzie jedynie zmartwieniem programistów Rust-for-Linux, a nie społeczności programistycznej systemów plików w jądrze. Zaznaczono, że nie wszyscy programiści planują uczyć się Rust i dlatego po wprowadzeniu zmian wpływających na inny kod będą w stanie zaktualizować tylko zależny kod w C, ale nie będą mogli naprawić wiązań Rust, ponieważ nie znają Rust. Do dyskusji dołączył także James Bottomley, opiekun podsystemu SCSI, który powiedział, że im więcej semantyki jest kodowane w wiązaniach, tym stają się one bardziej kruche z punktu widzenia zapewnienia synchronizacji.
Tymczasem firma Google, która w zeszłym roku przepisała na język Rust oprogramowanie pvmfm, używane w maszynach wirtualnych, uruchamianych na platformie Android, podzielono się doświadczeniem stopniowego wprowadzania kodu w języku Rust do istniejących firmware'ów, pierwotnie napisanych w C lub C++. Pokazano, jak można znacznie zwiększyć bezpieczeństwo firmware'ów, tworząc identyczne pod względem funkcjonalności komponenty zamienne, napisane w języku Rust. Główna uwaga podczas wdrażania Rust skupia się na wykorzystaniu Rust do nowego kodu oraz kodu pełniącego funkcje krytyczne z punktu widzenia bezpieczeństwa (np. kod do przetwarzania danych z zewnętrznych, nieznanych źródeł). Dla integracji kodu w Rust i C proponuje się użycie warstw (shim), tłumaczących wywołania między API w Rust i C (API C jest eksportowane do użycia w kodzie w Rust i odwrotnie), co pozwala na stopniowe przepisywanie elementów API w Rust.
Źródło: opennet.ru
