Rust is een programmeertaal bedacht door Graydon Hoare en oorspronkelijk ontwikkeld door Mozilla. Het is deels geïnspireerd op de programmeertaal C, maar kent syntactische en semantische verschillen. Het focust op veiligheid en moet moderne computersystemen efficiënter benutten. Het wordt ingezet door onder andere Cloudflare, OVH, Mozilla, Deliveroo, Coursera, AppSignal en Threema. Versie 1.86 is uitgebracht en de releasenotes voor die uitgave kunnen hieronder worden gevonden.
Trait upcastingThis release includes a long awaited feature — the ability to upcast trait objects. If a trait has a supertrait you can coerce a reference to said trait object to a reference to a trait object of the supertrait:
trait Trait: Supertrait {} trait Supertrait {} fn upcast(x: &dyn Trait) -> &dyn Supertrait { x }The same would work with any other kind of (smart-)pointer, like
Arc<dyn Trait> -> Arc<dyn Supertrait>or*const dyn Trait -> *const dyn Supertrait.Previously this would have required a workaround in the form of an
upcastmethod in theTraititself, for examplefn as_supertrait(&self) -> &dyn Supertrait, and this would work only for one kind of reference/pointer. Such workarounds are not necessary anymore.Note that this means that raw pointers to trait objects carry a non-trivial invariant: "leaking" a raw pointer to a trait object with an invalid vtable into safe code may lead to undefined behavior. It is not decided yet whether creating such a raw pointer temporarily in well-controlled circumstances causes immediate undefined behavior, so code should refrain from creating such pointers under any conditions (and Miri enforces that).
Trait upcasting may be especially useful with the
Anytrait, as it allows upcasting your trait object todyn Anyto callAny's downcast methods, without adding any trait methods or using external crates.use std::any::Any; trait MyAny: Any {} impl dyn MyAny { fn downcast_ref<T>(&self) -> Option<&T> { (self as &dyn Any).downcast_ref() } }You can learn more about trait upcasting in the Rust reference.
HashMaps and slices now support indexing multiple elements mutablyThe borrow checker prevents simultaneous usage of references obtained from repeated calls to
get_mutmethods. To safely support this pattern the standard library now provides aget_disjoint_muthelper on slices andHashMapto retrieve mutable references to multiple elements simultaneously. See the following example taken from the API docs ofslice::get_disjoint_mut:Allow safe functions to be marked with thelet 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]); if let Ok([a, b]) = v.get_disjoint_mut([1..=2, 0..=0]) { a[0] = 11; a[1] = 111; b[0] = 1; } assert_eq!(v, &[1, 11, 111]);#[target_feature]attribute.Previously only
unsafefunctions could be marked with the#[target_feature]attribute as it is unsound to call such functions without the target feature being enabled. This release stabilizes thetarget_feature_11feature, allowing safe functions to be marked with the#[target_feature]attribute.Safe functions marked with the target feature attribute can only be safely called from other functions marked with the target feature attribute. However, they cannot be passed to functions accepting generics bounded by the
Fn*traits and only support being coerced to function pointers inside of functions marked with thetarget_featureattribute.Inside of functions not marked with the target feature attribute they can be called inside of an
unsafeblock, however it is the caller's responsibility to ensure that the target feature is available.#[target_feature(enable = "avx2")] fn requires_avx2() { // ... snip } #[target_feature(enable = "avx2")] fn safe_callsite() { // Calling `requires_avx2` here is safe as `safe_callsite` // requires the `avx2` feature itself. requires_avx2(); } fn unsafe_callsite() { // Calling `requires_avx2` here is unsafe, as we must // ensure that the `avx2` feature is available first. if is_x86_feature_detected!("avx2") { unsafe { requires_avx2() }; } }You can check the
Debug assertions that pointers are non-null when required for soundnesstarget_features_11RFC for more information.The compiler will now insert debug assertions that a pointer is not null upon non-zero-sized reads and writes, and also when the pointer is reborrowed into a reference. For example, the following code will now produce a non-unwinding panic when debug assertions are enabled:
let _x = *std::ptr::null::<u8>(); let _x = &*std::ptr::null::<u8>();Trivial examples like this have produced a warning since Rust 1.53.0, the new runtime check will detect these scenarios regardless of complexity.
These assertions only take place when debug assertions are enabled which means that they must not be relied upon for soundness. This also means that dependencies which have been compiled with debug assertions disabled (e.g. the standard library) will not trigger the assertions even when called by code with debug assertions enabled.
Makemissing_abilint warn by defaultOmitting the ABI in extern blocks and functions (e.g.
extern {}andextern fn) will now result in a warning (via themissing_abilint). Omitting the ABI after theexternkeyword has always implicitly resulted in the"C"ABI. It is now recommended to explicitly specify the"C"ABI (e.g.extern "C" {}andextern "C" fn).You can check the Explicit Extern ABIs RFC for more information.
Target deprecation warning for 1.87.0The tier-2 target
i586-pc-windows-msvcwill be removed in the next version of Rust, 1.87.0. Its difference to the much more populari686-pc-windows-msvcis that it does not require SSE2 instruction support, but Windows 10, the minimum required OS version of allwindowstargets (except thewin7targets), requires SSE2 instructions itself.All users currently targeting
i586-pc-windows-msvcshould migrate toi686-pc-windows-msvcbefore the1.87.0release.You can check the Major Change Proposal for more information.
Stabilized APIs
{float}::next_down{float}::next_up<[_]>::get_disjoint_mut<[_]>::get_disjoint_unchecked_mutslice::GetDisjointMutErrorHashMap::get_disjoint_mutHashMap::get_disjoint_unchecked_mutNonZero::count_onesVec::pop_ifsync::Once::waitsync::Once::wait_forcesync::OnceLock::waitThese APIs are now stable in const contexts:
