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
upcast
method in theTrait
itself, 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
Any
trait, as it allows upcasting your trait object todyn Any
to 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.
HashMap
s and slices now support indexing multiple elements mutablyThe borrow checker prevents simultaneous usage of references obtained from repeated calls to
get_mut
methods. To safely support this pattern the standard library now provides aget_disjoint_mut
helper on slices andHashMap
to 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
unsafe
functions 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_11
feature, 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_feature
attribute.Inside of functions not marked with the target feature attribute they can be called inside of an
unsafe
block, 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_11
RFC 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_abi
lint warn by defaultOmitting the ABI in extern blocks and functions (e.g.
extern {}
andextern fn
) will now result in a warning (via themissing_abi
lint). Omitting the ABI after theextern
keyword 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-msvc
will be removed in the next version of Rust, 1.87.0. Its difference to the much more populari686-pc-windows-msvc
is that it does not require SSE2 instruction support, but Windows 10, the minimum required OS version of allwindows
targets (except thewin7
targets), requires SSE2 instructions itself.All users currently targeting
i586-pc-windows-msvc
should migrate toi686-pc-windows-msvc
before the1.87.0
release.You can check the Major Change Proposal for more information.
Stabilized APIs
{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
These APIs are now stable in const contexts: