Author: Zhang Handong/Post editor: Zhang Handong


Rust 1.50 stable release is released on February 11, 2021. Updates to version 1.50 include:

  • Language-level features
  • The compiler
  • The standard library
  • Stability of the API
  • Cargo related
  • other
  • Compatibility Tips

Here are some highlights.

Language-level features

Constant generic[CONST; N]Further improved:

  • Constant generic arrays are implementedops::Indexops::IndexMut.
  • An array of constants with duplicate values[x; N]Constant values are now supported as x, whether or not x is implementedCopy.

Rust has a built-in array type [T; LEN], but LEN has never supported generics, so such arrays become second-class citizens. For example, [0,0,0] and [0,0,0] are not of the same type. First-class citizens should be at least represented by the same type, regardless of the length of the array. To enhance this array type, constant generics support was introduced. [CONST; N] from version 1.38 to plan, within the Rust 1.38 ~ 1.46, introduced a STD: : array: : LengthAtMost32 to limit the length of the default [T; LEN] no more than 32. With Rust 1.47, support for [CONST; N] was introduced internally for the first time.

The [CONST; N] functionality was further improved by Rust 1.50.

Ops ::Index and OPS ::IndexMut:

fn second<C>(container: &C) -> &C::Output
where
    C: std::ops::Index<usize> +?Sized,
{
    &container[1]}fn main() {
    let array: [i32; 3] = [1.2.3];
    assert_eq!(second(&array[..] ), &2); // It must be sliced
    assert_eq!(second(&array), &2); // Now you can pass the reference directly
}
Copy the code

Constant arrays with duplicate values [x; N] now support constant values as x:

fn main() {
    // This line of code is not allowed because 'Option
      
       >' does not implement 'Copy'.
      
    let array: [Option<Vec<i32> >;10] = [None; 10];

  	// However, the 'const' definition is ok now
    const NONE: Option<Vec<i32> > =None;
    const EMPTY: Option<Vec<i32> > =Some(Vec::new());

    // Although 'Copy' is not implemented, the value of 'const' can now be repeated.
    let nones = [NONE; 10];
    let empties = [EMPTY; 10];
}
Copy the code

This can be tricky to write, but after RFC 2920: Inline const stabilates, it can be written as follows:

fn main() {
    // This line of code is not allowed because 'Option
      
       >' does not implement 'Copy'.
      
    let array: [Option<Vec<i32> >;10] = [None; 10];

    // Although 'Copy' is not implemented, the value of 'const' can now be repeated.
    let nones : [Option<Vec<i32> >;10] = [const {None}; 10];
    let empties : [Option<Vec<i32> >;10]  = [const {Some(Vec::new())}; 10];
}
Copy the code

Rust could have done this:

fn main() {
    // This line of code is not allowed because 'Option
      
       >' does not implement 'Copy'.
      
    let array: [Option<Vec<i32> >;10] = [None; 10];

    // Although 'Copy' is not implemented, the value of 'const' can now be repeated.
    let nones : [Option<Vec<i32> >;10] = [None; 10];
    let empties : [Option<Vec<i32> >;10]  = [Some(Vec::new()); 10];
}
Copy the code

None and Some(Vec::new()) above can be automatically promoted to constants by the compiler, but this can be confusing for users. For Some types that cannot be automatically promoted to constants, users need to learn a lot of constant-promotion rules and use const fn to define constants. Rather than explicitly annotating directly with a const block expression.

Also, about #! [Feature (min_CONST_generics)] will be stable in Rust 1.51, estimated 2021-03-25.

Shared body (union)ManualDropAssignment of type fields is considered secure

// A new feature in Rust 1.49 allows ManuallyDrop to be used in unions
use core::mem::ManuallyDrop;

union MyUnion {
    f1: u32,
    f2: ManuallyDrop<String>,}fn main() {
    let mut u = MyUnion { f1: 1 };

    // These do not require `unsafe`.
    u.f1 = 2;
    u.f2 = ManuallyDrop::new(String::from("example"));
}

Copy the code

Destructors are not called for fields of Copy or ManuallyDrop in the Union type, so you don’t need to add an unsafe block.

Furthermore, when dropping a Union type, you need to implement the Drop manually. Because of the nature of the pool, it does not know which fields are safe to drop, so it needs to be Copy or ManuallyDrop.

#! [feature(untagged_unions)]
use std::mem::ManuallyDrop;
use std::cell::RefCell;

union U1 {
    a: u8
}

union U2 {
    a: ManuallyDrop<String>}union U3<T> {
    a: ManuallyDrop<T>
}

union U4<T: Copy> {
    a: T
}

// For unstable Copy types other than ManuallyDrop, '#! [Feature (untagged_unions)] 'gate is supported.
union URef {
    p: &'static mut i32,}RefCell does not implement Drop, but it is non-copy
union URefCell { // field that does not drop but is not `Copy`, either
    a: (RefCell<i32>, i32),}fn generic_noncopy<T: Default> () {let mut u3 = U3 { a: ManuallyDrop::new(T::default()) };
    u3.a = ManuallyDrop::new(T::default()); // OK (assignment does not drop)
    
}

fn generic_copy<T: Copy + Default> () {let mut u3 = U3 { a: ManuallyDrop::new(T::default()) };
    u3.a = ManuallyDrop::new(T::default()); // OK
    
    let mut u4 = U4 { a: T::default() };
    u4.a = T::default(); // OK
}

fn main() {
    let mut u1 = U1 { a: 10 }; // OK
    
    u1.a = 11; // OK

    let mut u2 = U2 { a: ManuallyDrop::new(String::from("old"))};// OK
    u2.a = ManuallyDrop::new(String::from("new")); // OK (assignment does not drop)

    let mut u3 = U3 { a: ManuallyDrop::new(0)};// OK
    u3.a = ManuallyDrop::new(1); // OK

    let mut u3 = U3 { a: ManuallyDrop::new(String::from("old"))};// OK
    u3.a = ManuallyDrop::new(String::from("new")); // OK (assignment does not drop)
    
}
Copy the code

The compiler

  • Added built-in support for armV5te-unknown-Linux-uclibcgnueabi targets. Based on the ARMv5TE instruction set, you can think of it as an ARM processor, but it actually has a lot of old Intel technology modified in it.
  • Added support for Arm64 Catalyst on ARM Macs. Apple will soon release arm64-based Macs, and macOS applications will use the Darwin ABI running on ARM. The PR adds support for Catalyst applications on ARM Macs: iOS applications compiled for the Darwin ABI.
  • Fixed link issues on FreeBSD. On FreeBSD, sometimes a problem occurs even if it is included in the base systemlldThe link Rust program also fails because Rust does not find the link program. This seems to mainly affect bare/cross compilation, for examplewasmTo build andarm / riscvWorking naked (for example, when trying to compile). inLinuxAnd on other operating systems, the full tooling for building Rust is enabled, so there are no linking issues. If Rust is built correctly with these options, this PR should enable the full functionality on FreeBSD.

In addition to these three, there is additional Target Support, check out the Platform Support page.

The standard library

forproc_macro::PunctincreasePartialEq<char>

Used to identify special punctuation marks in macros more conveniently. Such as:

// ...
else if let TokenTree::Punct(ref tt) = tree {
  if tt.as_char() == '$' {
    after_dollar = true;
    return None;
  }
  // ...
 if p.as_char() == '>' { 
  // ...
if tt.as_char() == '=' { 
Copy the code

Unix platform optimization:Option<File>The magnitude is equivalent toFile

On Unix platforms, Rust’s files consist only of the system’s integer file descriptor, and it is never -1! A system call that returns a file descriptor uses -1 to indicate an error (check errno), so -1 cannot be a real file descriptor. Starting with Rust 1.50, this Niche (specific ecological scenario) has been added to the type definition, so it can also be used for layout optimization. So Option

will now have the same size as File itself!

Compatibility change

Expired compare_and_swap method

Compare_exchange and compare_exchange_weak are recommended. The expired CAS method is used to correspond to compare_exchange_strong and compare_exchange_weak of CPP, and to avoid unnecessary instructions in ARM architecture by using cas. Because when CAS is available, many people may use CAS directly, resulting in unnecessary instructions under ARM.

The ARM architecture implements LL/SC pairs (load-Linked /store-conditional) upon which CAS can be implemented. The load-linked (LL) operation returns only the current variable value of the pointer address. If there is no change in the memory of the pointer address after reading, the store-conditional (SC) operation succeeds and will read the stored new value of the pointer address; otherwise, SC will fail.

The CAS implemented through LL/SC is not an atomic operation, but it does perform an atomic CAS, with the contents of the target memory cell either unchanged or atomically changed. Since the CAS implemented through LL/SC is not an atomic operation, the CAS may be interrupted during execution. So two compare_exchange primitives were added to the C++11 standard: compare_exchange_weak and compare_exchange_strong. This weak version may fail, for example by returning false, even if the current variable value is equal to the expected value. As you can see, any weak CAS breaks the CAS semantics and returns false when it should have returned true. Strong CAS strictly follows the CAS semantics.

When is the Weak CAS used and when is the Strong CAS used? The following principles are usually enforced:

If CAS is in a loop (which is a basic CAS application pattern) and there are not thousands of operations in the loop (the loop body is lightweight and simple), use compare_exchange_weak. Otherwise, use compare_exchange_strong.

Therefore, the Rust library out-of-date CAS method is designed to allow developers to determine whether to use strong or weak CAS semantics based on the scenario. The CAS method in the standard library is just a wrapper around Compare_exchange, whereas compare_exchange in Rust has strong CAS semantics and is therefore open to abuse.

Discontinue support for all CloudABI targets

Include:

  • aarch64-unknown-cloudabi
  • armv7-unknown-cloudabi
  • i686-unknown-cloudabi
  • x86_64-unknown-cloudabi

Since CloudABI is no longer maintained, consider WASI, which was inspired by some of its concepts and is now its successor.

Content: February issue of Rust Chinese (Rust_Magazine)