本文将汇总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 toError
andHash
/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>
andRc<T>
are covariant with respect toT
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’slibstd
builds 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.-
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
-
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
implementsFrom
for 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-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 inwhere
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 likeprintln!
, writing a newline. -
Self
may appear inimpl
headers and in struct expressions
2017-04-27 Rust 1.17
-
The
'static
lifetime 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
-
pub
has 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
union
s 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.
-
loop
s can nowbreak
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!
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_each
has been stabilized.
(0..10).for_each(|i| println!("{}", i));
2017-11-22 Rust 1.22
Types that implement
Drop
are now allowed inconst
andstatic
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;
2018-01-04 Rust 1.23
-
AsciiExt
methods are now defined directly onu8
,char
,[u8]
, andstr
types, so you no longer need to import the trait. - The various
std::sync::atomic types
now implementFrom
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
, andUnsafeCell
’snew
functions - The
new
functions of the variousAtomic
integer types -
{integer}::min_value
andmax_value
-
mem
’ssize_of
andalign_of
-
ptr::null
andnull_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 yourstruct
s.-
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
bindingsfn 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 aResult
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/orClone
if 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_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 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::c
someplace other than a use statement, you can ask:- Is
a
the name of a crate? Then we're looking forb::c
inside of it. - Is
a
the keyword crate? Then we're looking forb::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("...");
- 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();