New updates in Rust 1.66.0
Rust is a programming language that can be used for a variety of purposes. It is designed to be fast and efficient, as well as emphasize type safety and concurrency.
Rust is a systems programming language that is designed to be safe, concurrent, and practical. It achieves these goals by using an innovative ownership system and borrowing concepts to enforce memory safety while also preventing data races at compile time. This makes Rust ideal for developing low-level systems software while also providing high-level features that are typically found in functional programming languages.
The Rust programming language team is excited to announce version 1.66.0! Rust is a dependable and efficient programming language that empowers everyone to easily build software.
If you’re using an older version of Rust, you can update to 1.66.0 with the following command:
If you need it, you can get rustup from the right page on their website. You can also find the detailed release notes for 1.66.0 on GitHub.
The new features in 1.66.0 stable
| The explicit discrimination of enums with fields
Even when they have fields, enums with integer representations can now use explicit discriminates.
You can use explicit discriminants on enums with representations, as long as none of their variants have fields. Explicit discriminants are most useful when passing values across language boundaries where the enum’s representation needs to match in both languages.
The Bar enum is guaranteed to have the same layout as u8, which means that the Bar::C variant is guaranteed to have a discriminant of 42. This is because variants without explicitly-specified values will have discriminants that are automatically assigned according to their order in the source code. So, in this case, Bar::A will have a discriminant of 0, Bar::B will have a discriminant of 1, and Bar::D will have a discriminant of 43. Without this feature, the only way to set the explicit value of Bar::C would be to add 41 unnecessary variants before it!
This is a great feature because it allows you to be more concise in your code and eliminates the need for extra variants that take up space and don’t add anything useful to your enum.
Please note that while it is possible to inspect the discriminant of a field-less enum via casting (e.g. Bar::C as u8), Rust currently provides no language-level way to access the raw discriminant of an enum with fields. Instead, unsafe code must be used to inspect the discriminant of an enum with fields. Since this feature is intended for use with cross-language FFI where unsafe code is already necessary, this should hopefully not be too much of an extra burden. In the meantime, if all you need is an opaque handle to the discriminant, please see the std::mem::discriminant function.
| core::hint::black_box
When you’re benchmarking or examining the machine code produced by a compiler, there are times when you’ll want to prevent optimizations from happening in certain places. For example, the function push_cap executes Vec::push 4 times in a loop:
When you inspect the optimized output of the compiler on x86_64, you’ll notice that it’s quite concise:
The entire function push_cap we wanted to benchmark has been optimized away, so there’s no need to worry about it!
We can work around this by using the newly stabilized black_box function. Functionally, black_box doesn’t do much – it takes the value you pass it and passes it right back. However, internally, the compiler treats black_box as a function that could do anything with its input and return any value (as its name implies). This allows us to bypass some restrictions that would otherwise apply.
This is a very useful optimization hint for the compiler. For example, if we know that the vector will be used after every iteration of the for loop, we can tell the compiler to disable optimizations that might otherwise be performed.
In our optimized assembly output, we can now find the unrolled for loop:
You can also see a side effect of calling black_box in this assembly output. The instruction mov qword ptr [rsp + 8], rbx is uselessly repeated after every iteration. This instruction writes the address v.as_ptr() as the first argument of the function, which is never actually called. This can potentially cause problems down the line if the function is ever called with a different first argument.
As you can see, the code that is produced doesn’t take into account the possible allocations that could be caused by the push call. This is because the compiler is still using the fact that we called Vec::with_capacity(4) in the bench_push function. If you want to see how black_box affects compiler optimizations, try playing around with its placement or using it in multiple places.
| cargo remove
Rust 1.62.0 introduced cargo add, a command line utility that allows you to add dependencies to your project. You can now use cargo remove to remove dependencies as well.
| Stabilized APIs
- proc_macro::Span::source_text
- u*::{checked_add_signed, overflowing_add_signed, saturating_add_signed, wrapping_add_signed}
- i*::{checked_add_unsigned, overflowing_add_unsigned, saturating_add_unsigned, wrapping_add_unsigned}
- i*::{checked_sub_unsigned, overflowing_sub_unsigned, saturating_sub_unsigned, wrapping_sub_unsigned}
- BTreeSet::{first, last, pop_first, pop_last}
- BTreeMap::{first_key_value, last_key_value, first_entry, last_entry, pop_first, pop_last}
- Add AsFd implementations for stdio lock types on WASI.
- impl TryFrom<Vec<T>> for Box<[T; N]>
- core::hint::black_box
- Duration::try_from_secs_{f32,f64}
- Option::unzip
- std::os::fd
| Other changes
The Rust 1.66 release also brings a few other changes, including:
- You can use ..=X ranges in patterns.
- Linux builds are now optimized for both the rustc frontend and LLVM backend with LTO and BOLT, respectively. This improves both runtime performance and memory usage.
You may also check out everything that has changed in Rust.
If you like this post then you may also like to share the same with your colleagues. Let us know your thoughts on our blogs and on social media posts on Instagram, Facebook, LinkedIn, and Twitter.