Series: The Rust Annals

Vol. I Issue 48 nlopes.dev

Announcing Rust 1.47.0

Rust 1.47 makes arrays of any length implement standard-library traits, restores concise panic backtraces, and moves the default compiler toolchain to LLVM 11. It also adds Windows Control Flow Guard support, nine stable library APIs, and a broad set of newly const integer and ASCII operations.

Standard-library traits now work on arrays of any length

This release contains no new language features, but delivers its long-awaited standard-library change: standard-library traits are now implemented for arrays of any length.

Rust could not be generic over the integer N in the array type [T; N], so each trait implementation had to be written for every supported length. The standard library stopped at N of 32. The compiler now contains enough of the still-unstable const-generics implementation for the standard library to use it internally and remove that limit.

On Rust 1.46, this program:

fn main() {
    let xs = [0; 34];

    println!("{:?}", xs);
}

produced:

error[E0277]: arrays only have std trait implementations for lengths 0..=32
 --> src/main.rs:4:22
  |
4 |     println!("{:?}", xs);
  |                      ^^ the trait `std::array::LengthAtMost32` is not implemented for `[{integer}; 34]`
  |
  = note: required because of the requirements on the impl of `std::fmt::Debug` for `[{integer}; 34]`
  = note: required by `std::fmt::Debug::fmt`
  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

With Rust 1.47, it prints the array. Libraries cannot yet use this technique for their own traits; that must wait for const generics to stabilize, for which the source gave no estimated date.

Panic backtraces are concise again

Rust 1.47 fixes a regression in the backtrace filtering first introduced in Rust 1.18. For this input:

fn main() {
    panic!();
}

the regressed output included mostly internal frames:

thread 'main' panicked at 'explicit panic', src/main.rs:2:5
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.46/src/backtrace/libunwind.rs:86
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.46/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print_fmt
             at src/libstd/sys_common/backtrace.rs:78
   3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
             at src/libstd/sys_common/backtrace.rs:59
   4: core::fmt::write
             at src/libcore/fmt/mod.rs:1076
   5: std::io::Write::write_fmt
             at src/libstd/io/mod.rs:1537
   6: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:62
   7: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:49
   8: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:198
   9: std::panicking::default_hook
             at src/libstd/panicking.rs:217
  10: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:526
  11: std::panicking::begin_panic
             at /rustc/04488afe34512aa4c33566eb16d8c912a3ae04f9/src/libstd/panicking.rs:456
  12: playground::main
             at src/main.rs:2
  13: std::rt::lang_start::{{closure}}
             at /rustc/04488afe34512aa4c33566eb16d8c912a3ae04f9/src/libstd/rt.rs:67
  14: std::rt::lang_start_internal::{{closure}}
             at src/libstd/rt.rs:52
  15: std::panicking::try::do_call
             at src/libstd/panicking.rs:348
  16: std::panicking::try
             at src/libstd/panicking.rs:325
  17: std::panic::catch_unwind
             at src/libstd/panic.rs:394
  18: std::rt::lang_start_internal
             at src/libstd/rt.rs:51
  19: std::rt::lang_start
             at /rustc/04488afe34512aa4c33566eb16d8c912a3ae04f9/src/libstd/rt.rs:67
  20: main
  21: __libc_start_main
  22: _start

Rust 1.47 instead shows the frames most useful for locating the panic:

thread 'main' panicked at 'explicit panic', src/main.rs:2:5
stack backtrace:
   0: std::panicking::begin_panic
             at /rustc/d6646f64790018719caebeafd352a92adfa1d75a/library/std/src/panicking.rs:497
   1: playground::main
             at ./src/main.rs:2
   2: core::ops::function::FnOnce::call_once
             at /rustc/d6646f64790018719caebeafd352a92adfa1d75a/library/core/src/ops/function.rs:227

This makes the panic’s origin easier to see. Set RUST_BACKTRACE=full to retain the complete backtrace.

The compiler adopts LLVM 11 and adds Windows Control Flow Guard

Rust’s bundled compiler backend has been upgraded to LLVM 11, which is now the default. The compiler can still be built with LLVM versions as old as 8.

rustc now supports -C control-flow-guard, which turns on Control Flow Guard on Windows. Other platforms ignore the flag.

Rustdoc also gains support for the Ayu theme.

Nine APIs stabilize and more operations become const

Nine new APIs are stable:

The following previously stable APIs can now be used in const contexts:

  • The new method for all NonZero integers.
  • The checked_add, checked_sub, checked_mul, checked_neg, checked_shl, checked_shr, saturating_add, saturating_sub, and saturating_mul methods for all integers.
  • The checked_abs, saturating_abs, saturating_neg, and signum methods for all signed integers.
  • The is_ascii_alphabetic, is_ascii_uppercase, is_ascii_lowercase, is_ascii_alphanumeric, is_ascii_digit, is_ascii_hexdigit, is_ascii_punctuation, is_ascii_graphic, is_ascii_whitespace, and is_ascii_control methods for char and u8.

Reproduced from the Rust blog under its publication licence. Typeset in Literata.