The release of the general-purpose programming language Rust 1.86 has been published, initially developed by Mozilla and now maintained under the auspices of the independent non-profit organization Rust Foundation. The language focuses on safe memory management and provides tools for achieving high parallelism in task execution, all while avoiding garbage collection and runtime (which is limited to basic initialization and maintenance of the standard library).
The memory management methods in Rust relieve developers from errors when manipulating pointers and protect against issues arising from low-level memory operations, such as accessing memory after it has been freed, dereferencing null pointers, buffer overflows, and so on. For distributing libraries, ensuring builds, and managing project dependencies, the package manager Cargo is being developed. A repository at crates.io supports library hosting.
Safe memory handling in Rust is ensured at compile time through reference checking, ownership tracking of objects, lifetime consideration (scope) of objects, and assessment of memory access correctness during code execution. Rust also provides means to protect against integer overflows, mandates the initialization of variable values before use, improved error handling in the standard library, employs the concept of immutability for references and variables by default, and offers strong static typing to minimize logical errors.
Key innovations:
- Support for upcasting traits to a base supertrait has been added, meaning that it is now possible to directly convert a reference to a trait object into a reference to a supertrait object without having to create a special method in the trait that returns a reference to the supertrait. A similar operation can also be performed with other types of smart pointers, for example, "Arc -> Arc" and "*const dyn Trait -> *const dyn Supertrait". trait Trait: Supertrait {} trait Supertrait {} fn upcast(x: &dyn Trait) -> &dyn Supertrait { x }
- In HashMap and slices, the method get_disjoint_mut() has been added for simultaneously obtaining multiple mutable references to elements. Previously, the borrow checker did not allow simultaneous use of references obtained using the get_mut() method. let v = &mut [1, 2, 3]; if let Ok([a, b]) = v.get_disjoint_mut([0, 2]) { *a = 413; *b = 612; } assert_eq!(v, &[413, 2, 612]); if let Ok([a, b]) = v.get_disjoint_mut([0..1, 1..3]) { a[0] = 8; b[0] = 88; b[1] = 888; } assert_eq!(v, &[8, 88, 888]);
- It is now allowed to mark safe functions with the attribute "#[target_feature]", indicating that the function uses specified CPU capabilities. A safe function marked with the "#[target_feature]" attribute can only be safely called by another safe function if it is also marked with "#[target_feature]" (otherwise, such functions must be called within an unsafe block). They cannot be passed to functions that take generic parameters constrained by Fn* traits. Previously, the "#[target_feature]" attribute could only be applied to functions marked as "unsafe". #[target_feature(enable = "avx2")] fn requires_avx2() { // … } #[target_feature(enable = "avx2")] fn safe_callsite() { requires_avx2(); } fn unsafe_callsite() { if is_x86_feature_detected!("avx2") { unsafe { requires_avx2() }; } }
- The Rust compiler includes debug assertions (debug-assert) to ensure that the pointer does not contain a NULL value when reading and writing non-null sizes, as well as during reborrowing of the pointer into a reference. For example, with debug assertions enabled, the following code will now lead to a "panic" state: let _x = *std::ptr::null::(); let _x = &*std::ptr::null::();
- By default, the lint check "missing_abi" is enabled, which triggers a warning if the ABI is not specified after the extern keyword. Previously, if the ABI was not specified after extern, it was assumed to use the "C" ABI. It is now recommended to explicitly specify the ABI as "C", for example, ‘extern "C" {}’ and ‘extern "C" fn’
- A new batch of APIs has been promoted to stable, including stabilized methods and trait implementations:
- {float}::next_down
- {float}::next_up
- ::get_disjoint_mut
- ::get_disjoint_unchecked_mut
- slice::GetDisjointMutError
- HashMap::get_disjoint_mut
- HashMap::get_disjoint_unchecked_mut
- NonZero::count_ones
- Vec::pop_if
- sync::Once::wait
- sync::Once::wait_force
- sync::OnceLock::wait
- The ‘const’ attribute has been applied in the functions:
- hint::black_box
- io::Cursor::get_mut
- io::Cursor::set_position
- str::is_char_boundary
- str::split_at
- str::split_at_checked
- str::split_at_mut
- str::split_at_mut_checked
- A third level of support has been implemented for platforms {aarch64-unknown,x86_64-pc}-nto-qnx710_iosock, {aarch64-unknown,x86_64-pc}-nto-qnx800, {x86_64,i686}-win7-windows-gnu, amdgcn-amd-amdhsa, x86_64-pc-cygwin, {mips,mipsel}-mti-none-elf, m68k-unknown-none-elf, armv7a-nuttx-{eabi,eabihf}, aarch64-unknown-nuttx and thumbv7a-nuttx-{eabi,eabihf}. The third level implies basic support, but without automated testing, publishing official builds, and verifying the possibility of code compilation.
- A warning has been added regarding the discontinuation of the second level of support for the target platform i586-pc-windows-msvc in the next release (1.87). It is recommended to use the i686-pc-windows-msvc platform, which supports SSE2 instructions. The i586-pc-windows-msvc platform has become obsolete, as Windows 10 requires SSE2 support, and earlier Rust releases for Windows are no longer supported.
Additionally, it can be noted that Ferrocene has provided the community with the Ferrocene Language Specification (FLS) for the Rust language, created during the development of its Rust compiler for critical systems and periodically synchronized with the current state of the main Rust compiler. The FLS specification includes a structured and detailed guide on the syntax, semantics, and behavior of Rust, suitable for verification, compatibility assessment, and standardization.
The materials provided will be used to create a reference specification for the Rust language, which can be utilized in the development of alternative compilers and for verifying the compiler in areas critically important from a safety perspective.
Source: opennet.ru
