本文将汇总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
DurationAPI and enhancements toErrorandHash/Hasher. -
'staticvariables may now be recursive.
2015-10-29 Rust 1.4
- When reading ‘lines’ to treat both
\nand\r\nas a valid line-ending.
2015-12-10 Rust 1.5
-
Arc<T>andRc<T>are covariant with respect toTinstead of invariant. -
Defaultis implemented for mutable slices. - There are now
Fromconversions between floating point types where the conversions are lossless. - Thera are now
Fromconversions between integer types where the conversions are lossless. - The
parsemethod 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.libcoreis completely platform agnostic, and requires only a handful of external symbols to be defined. Rust’slibstdbuilds on top oflibcore, adding support for memory allocation, I/O, and concurrency. Applications using Rust in the embedded space, as well as those writing operating systems, often eschewlibstd, using onlylibcore. - 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.-
structwith 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::panicmodule.
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=abortflag. - Add a new crate type, 'cdylib'. cdylibs are dynamic libraries suitable for loading by non-Rust hosts.
2016-08-18 Rust 1.11
-
support for cdylibs has landed in Cargo! By adding this to your
Cargo.toml:crate-type = ["cdylib"]
2016-09-29 Rust 1.12
-
rustctranslates code to LLVM IR via its own "middle" IR (MIR). -
rustcpresents 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 OptionimplementsFromfor its contained type
2016-11-10 Rust 1.13
- new operator,
?, for error handling, a solid ergonomic improvement to the oldtry!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
experimental support for WebAssembly, via the
wasm32-unknown-emscriptentarget.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.
-
?Sizedcan be used inwhereclauses. - 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 likeprintln!, writing a newline. -
Selfmay appear inimplheaders 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}; Documentation is rendered with mdbook instead of the obsolete, in-tree
rustbook
2017-06-08 Rust 1.18
-
pubhas gained a new form:pub(crate) bar; pub(in a::b::c) foo; -
`#[图片上传失败...(image-32849c-1516015456023)].
#![windows_subsystem = "console"] #![windows_subsystem = "windows"]
2017-07-20 Rust 1.19
-
C compatible
unions are now available. RFC 1444union 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 nowbreakwith 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!andeprintln!macros. These work exactly the same asprint!andprintln!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")
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_eachhas been stabilized.
(0..10).for_each(|i| println!("{}", i));
2017-11-22 Rust 1.22
Types that implement
Dropare now allowed inconstandstaticitems.-
T op= &Tnow 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;
2018-01-04 Rust 1.23
-
AsciiExtmethods are now defined directly onu8,char,[u8], andstrtypes, so you no longer need to import the trait. - The various
std::sync::atomic typesnow implementFromtheir 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, andUnsafeCell’snewfunctions - The
newfunctions of the variousAtomicinteger types -
{integer}::min_valueandmax_value -
mem’ssize_ofandalign_of -
ptr::nullandnull_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 yourstructs.-
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
matchbindingsfn 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 => (), } } -
maincan return aResultuse 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_stringuse std::fs; use std::net::SocketAddr; let foo: SocketAddr = fs::read_to_string("address.txt")?.parse()?; Closures now implement
Copyand/orCloneif all captured variables implement either or both traitsStablise
'_. 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_64modules 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
-
NonZeronumber types. - Unit test functions marked with the
#[test]attribute can now returnResult<(), 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 likea::b::csomeplace other than a use statement, you can ask:- Is
athe name of a crate? Then we're looking forb::cinside of it. - Is
athe keyword crate? Then we're looking forb::cfrom the root of our crate. - Otherwise, we're looking for
a::b::cfrom the current spot in the module hierarchy.
// old let json = ::serde_json::from_str("..."); // new let json = serde_json::from_str("..."); - Is
-
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();