Rust 2015 各版本更新要点

本文将汇总Rust 1.0之后各版本在语法和部分库函数方面的更新,略过编译器和标准库的性能优化、工具链和文档的改进等内容。

2015-05-15 Rust 1.0

2015-06-25 Rust 1.1

  • New std::fs APIs.

2015-08-06 Rust 1.2

  • Rc<[T]> is fully usable.

2015-09-17 Rust 1.3

  • new Duration API and enhancements to Error and Hash/Hasher.
  • 'static variables may now be recursive.

2015-10-29 Rust 1.4

  • When reading ‘lines’ to treat both \n and \r\n as a valid line-ending.

2015-12-10 Rust 1.5

  • Arc<T> and Rc<T> are covariant with respect to T instead of invariant.
  • Default is implemented for mutable slices.
  • There are now From conversions between floating point types where the conversions are lossless.
  • Thera are now From conversions between integer types where the conversions are lossless.
  • The parse method accepts a leading "+" when parsing integers.

2016-01-21 Rust 1.6

  • The core library is stable, as are most of its APIs. Rust’s standard library is two-tiered: there’s a small core library, libcore, and the full standard library, libstd, that builds on top of it. libcore is completely platform agnostic, and requires only a handful of external symbols to be defined. Rust’s libstd builds on top of libcore, adding support for memory allocation, I/O, and concurrency. Applications using Rust in the embedded space, as well as those writing operating systems, often eschew libstd, using only libcore.
  • The `#[图片上传失败...(image-f4d162-1516015456023)].

2016-03-02 Rust 1.7

  • support for custom hash algorithms in the standard library’s HashMap<K, V> type.

2016-04-14 Rust 1.8

  • “operator equals” operators, such as += and -=, are now overloadable via coresponding traits.

  • struct with no fields can have curly braces:

    struct Foo; // works
    struct Bar { } // also works
    

2016-05-26 Rust 1.9

  • The #[deprecated] attribute when applied to an API will generate warnings when used. The warnings may be suppressed with#[allow(deprecated)].
  • stabilization of the std::panic module.

2016-07-07 Rust 1.10

  • Single-variant enums support the #[repr(..)\] attribute.
  • panic! can be converted to a runtime abort with the -C panic=abort flag.
  • Add a new crate type, 'cdylib'. cdylibs are dynamic libraries suitable for loading by non-Rust hosts.

2016-08-18 Rust 1.11

  • Macros can be expanded inside of trait definitions

  • support for cdylibs has landed in Cargo! By adding this to your Cargo.toml:

    crate-type = ["cdylib"]
    

2016-09-29 Rust 1.12

  • rustc translates code to LLVM IR via its own "middle" IR (MIR).
  • rustc presents a new, more readable error format, along with machine-readable JSON error output for use by IDEs.
  • The format! macro and friends now allow a single argument to be formatted in multiple styles
  • Option implements From for its contained type

2016-11-10 Rust 1.13

  • new operator, ?, for error handling, a solid ergonomic improvement to the old try! macro.
fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = File::open("username.txt")?;
    let mut s = String::new();

    f.read_to_string(&mut s)?;

    Ok(s)
}
  • Macros can now be used in type position (RFC 873).

  • Attributes can be applied to statements (RFC 16).

2016-12-22 Rust 1.14

  • rustup is the recommended Rust installation method

  • experimental support for WebAssembly, via the wasm32-unknown-emscripten target.

  • println!(), with no arguments, prints newline. Previously, an empty string was required to achieve the same.

  • .. matches multiple tuple fields in enum variants, structs and tuples. RFC 1492.

    struct Point(i32, i32, i32);
    let p = Point(0, 1, 2);
    // Previously you could ignore all three elements:
    match p {
        Point(..) => println!("found a point"),
    }
    // Now you could only ignore parts of the tuple:
    match p {
        Point(x, ..) => println!("x is {}", x),
    }
    

2017-02-02 Rust 1.15

  • The Rust build system is now re-written in Rust, using Cargo.
  • ?Sized can be used in where clauses.
  • Basic procedural macros allowing custom #[derive], aka "macros 1.1". This allows popular code-generating crates like Serde and Diesel to work ergonomically. RFC 1681.
  • Tuple structs may be empty. Unary and empty tuple structs may be instantiated with curly braces. Part of RFC 1506.

2017-03-16 Rust 1.16

  • All public types in std implement Debug
  • writeln! now has a single-argument form, just like println!, writing a newline.
  • Self may appear in impl headers and in struct expressions

2017-04-27 Rust 1.17

  • The 'staticlifetime is now assumed in statics and consts.

    // old
    const NAME: &'static str = "Ferris";
    static NAME: &'static str = "Ferris";
    const NAMES: &'static [&'static str; 2] = &["Ferris", "Bors"];
    
    // new
    const NAME: &str = "Ferris";
    static NAME: &str = "Ferris";
    const NAMES: &[&str; 2] = &["Ferris", "Bors"];
    
  • Fields of structs may be initialized without duplicating the field/variable names. RFC 1682

    let x = 5;
    let y = 6;
    let p = Point {x, y};
    
  • Self may be included in the where clause of impls. RFC 1647

  • Static variables may contain references to other statics

  • Documentation is rendered with mdbook instead of the obsolete, in-tree rustbook

  • rustup installs documentation by default

2017-06-08 Rust 1.18

  • pub has gained a new form:

    pub(crate) bar;
    pub(in a::b::c) foo;
    
  • `#[图片上传失败...(image-32849c-1516015456023)].

    #![windows_subsystem = "console"]
    #![windows_subsystem = "windows"]
    
  • 0e+10 is now a valid floating point literal

2017-07-20 Rust 1.19

  • C compatible unions are now available. RFC 1444

    union MyUnion {
        f1: u32,
        f2: f32,
    }
    
    let u = MyUnion { f1: 1 };
    unsafe { u.f1 = 5 };
    let value = unsafe { u.f1 };
    

    Enums have a “tag” that stores which variant is the correct one at runtime; unions elide this tag. So reading or writing a union’s field is unsafe. One major use-case is interoperability with C.

  • loops can now break with a value:

    let x = loop { break 7; };
    
  • closures that do not capture an environment can now be coerced to a function pointer:

    let f: fn(i32) -> i32 = |x| x + 1;
    
  • Numeric fields can now be used for creating tuple structs. RFC 1506

    struct Point(u32, u32);
    let x = Point { 0: 7, 1: 0 };
    
  • eprint! and eprintln! macros. These work exactly the same as print! and println! but instead write to standard error.

2017-08-31 Rust 1.20

  • Define “associated constants” on traits, structs, and enums.

    struct Struct;
    
    impl Struct {
      // associated constant
      const ID: u32 = 0;
      
      // associated function
        fn foo() {
            println!("foo is called");
        }
    }
    
    fn main() {
        Struct::foo();
        println!("the ID of Struct is: {}", Struct::ID);
    }
    
  • allow messages in the unimplemented!() macro. ie. unimplemented!("Waiting for 1.21 to be stable")

  • Upgrade to Unicode 10.0.0

2017-10-12 Rust 1.21

  • You can now use static references for literals.

    fn main() {
        let x: &'static u32 = &0;
        let y = &5;
        
        thread::spawn(move || {
            println!("{}", y);
        }); 
    }
    
  • Iterator::for_each has been stabilized.

(0..10).for_each(|i| println!("{}", i));
  • Generate builtin impls for Clone for all arrays and tuples that are T: Clone

2017-11-22 Rust 1.22

  • can use ? with Option

  • Types that implement Drop are now allowed in const and static items.

  • T op= &T now works for primitive types, which is a fancy way of saying:

    let mut x = 2;
    let y = &8;
    
    // Previously, you’d have needed to write x += *y
    x += y;
    
  • Now accepts underscores in unicode escapes

2018-01-04 Rust 1.23

  • AsciiExt methods are now defined directly on u8, char, [u8], and str types, so you no longer need to import the trait.
  • The various std::sync::atomic types now implement From their non-atomic types.

2018-02-15 Rust 1.24

The following functions may now be used inside a constant expression, for example, to initialize a static:

  • Cell, RefCell, and UnsafeCell’s new functions
  • The new functions of the various Atomic integer types
  • {integer}::min_value and max_value
  • mem’s size_of and align_of
  • ptr::null and null_mut

2018-03-29 Rust 1.25

  • nested import groups

    use std::fs::File;
    use std::io::Read;
    use std::path::{Path, PathBuf};
    

    can be now be written as:

    use std::{fs::File, io::Read, path::{Path, PathBuf}};
    
  • [repr(align(x))] lets you set the alignment of your structs.

  • Allow | at the start of a match arm.e.g.

    enum Foo { A, B, C }
    match x {
        Foo::A | Foo::B => println!("AB"),
        Foo::C => println!("C"),
    }
    // better code alignment
    match x {
        | Foo::A
        | Foo::B => println!("AB"),
        | Foo::C => println!("C"),
    }
    

2018-05-11 Rust 1.26

  • impl Trait

    // before
    fn foo() -> Box<Fn(i32) -> i32> {
        Box::new(|x| x + 1)
    }
    
    // after
    fn foo() -> impl Fn(i32) -> i32 {
        |x| x + 1
    }
    
    fn foo() -> impl Iterator<Item = i32> {
        vec![1, 2, 3]
            .into_iter()
            .map(|x| x + 1)
            .filter(|x| x % 2 == 0)
    }
    
    // before
    fn foo<T: Trait>(x: T) {
    
    // after
    fn foo(x: impl Trait) {
    
  • Nicer match bindings

    fn hello(arg: &Option<String>) {
        match arg {
            Some(name) => println!("Hello {}!", name),
            None => println!("I don't know who you are."),
        }
    }
    
    fn hello(arg: &mut Option<String>) {
        match arg {
            Some(name) => name.push_str(", world"),
            None => (),
        }
    }
    
  • main can return a Result

    use std::fs::File;
    
    fn main() -> Result<(), std::io::Error> {
        let f = File::open("bar.txt")?;
    
        Ok(())
    }
    
  • Inclusive ranges with ..=

    fn takes_u8(x: u8) {
        // ...
    }
    
    fn main() {
        for i in 0..=255 {
            println!("i: {}", i);
            takes_u8(i);
        }
    }
    
  • Basic slice patterns

    let arr = [1, 2, 3];
    
    match arr {
        [1, _, _] => "starts with one",
        [a, b, c] => "starts with something else",
    }
    
    fn foo(s: &[u8]) {
        match s {
            [a, b] => (),
            [a, b, c] => (),
            _ => (),
        }
    }
    
  • 128 bit integers

    let x: i128 = 0;
    let y: u128 = 0;
    
  • stabilized fs::read_to_string

    use std::fs;
    use std::net::SocketAddr;
    
    let foo: SocketAddr = fs::read_to_string("address.txt")?.parse()?;
    
  • Closures now implement Copy and/or Clone if all captured variables implement either or both traits

  • Stablise '_. The underscore lifetime can be used anywhere where a lifetime can be elided.

  • A lot of operations are now available in a const context. E.g. You can now index into constant arrays, reference and dereference into constants, and use Tuple struct constructors.

  • Added hexadecimal formatting for integers with fmt::Debug e.g. assert!(format!("{:02x?}", b"Foo\0") == "[46, 6f, 6f, 00]")

2018-06-21 Rust 1.27

  • the std::arch, arch::x86 & arch::x86_64 modules which contain SIMD intrinsics, a new macro called `is_x86_feature_detected!

  • dyn Trait

    // old => new
    Box<Foo> => Box<dyn Foo>
    &Foo => &dyn Foo
    &mut Foo => &mut dyn Foo
    
  • The #[must_use] attribute can now also be used on functions as well as types.

    #[must_use]
    fn double(x: i32) -> i32 {
        2 * x
    }
    
    fn main() {
        double(4); // warning: unused return value of `double` which must be used
    
        let _ = double(4); // (no warning)
    }
    

2018-08-02 Rust 1.28

  • NonZero number types.
  • Unit test functions marked with the #[test] attribute can now return Result<(), E: Debug> in addition to ().

2018-09-18 Rust 1.29

Three APIs were stabilized:

  • Arc<T>::downcast
  • Rc<T>::downcast
  • Iterator::flatten

2018-10-25 Rust 1.30

  • Procedural Macros

    #[route(GET, "/")]
    fn index() {}
    
    #[proc_macro_attribute]
    pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream { }
    
  • Module system improvements
    Wherever you see a path like a::b::c someplace other than a use statement, you can ask:

    • Is a the name of a crate? Then we're looking for b::c inside of it.
    • Is a the keyword crate? Then we're looking for b::c from the root of our crate.
    • Otherwise, we're looking for a::b::c from the current spot in the module hierarchy.
    // old
    let json = ::serde_json::from_str("...");
    
    // new
    let json = serde_json::from_str("...");
    
  • Raw Identifiers

    // define a local variable named `for`
    let r#for = true;
    
    // define a function named `for`
    fn r#for() {
        // ...
    }
    
    // call that function
    r#for();
    

推荐阅读更多精彩内容