Rust 团队很高兴地宣布最新版本的 Rust 1.17.0。Rust 是一种专注于安全性、速度和并发性的系统编程语言。
如果您安装了之前版本的 Rust,则获取 Rust 1.17 非常简单,只需运行:
$ rustup update stable
如果您还没有安装,可以从我们网站上的相应页面获取 rustup
,并查看 GitHub 上1.17.0 的详细发行说明。
1.17.0 稳定版的新特性
Rust 1.17.0 的主要内容是一些小的、生活质量上的改进。例如,静态变量和常量现在默认假定为 'static
生命周期。当编写像这样的常量或静态变量时:
const NAME: &'static str = "Ferris";
static NAME: &'static str = "Ferris";
Rust 1.17 将允许您省略 'static
,因为这是唯一合理的生命周期:
const NAME: &str = "Ferris";
static NAME: &str = "Ferris";
在某些情况下,这可以删除大量的样板代码:
// old
const NAMES: &'static [&'static str; 2] = &["Ferris", "Bors"];
// new
const NAMES: &[&str; 2] = &["Ferris", "Bors"];
另一个类似的改进是“字段初始化简写”。类似于 ECMAScript 6 中所谓的“对象字面量属性值简写”,在声明结构体时可以删除重复的代码,如下所示:
// definitions
struct Point {
x: i32,
y: i32,
}
let x = 5;
let y = 6;
// old
let p = Point {
x: x,
y: y,
};
// new
let p = Point {
x,
y,
};
也就是说,x, y
形式将假定其值设置为作用域中具有相同名称的变量。
另一个小的生活质量改进是,新的 Rustacean 常常尝试使用 +
将两个 &str
连接在一起。这行不通,您只能使用 String + &str
。因此,添加了一条新的错误消息,以帮助用户避免犯此错误:
// code
"foo" + "bar"
// old
error[E0369]: binary operation `+` cannot be applied to type `&'static str`
--> <anon>:2:5
|
2 | "foo" + "bar"
| ^^^^^
|
note: an implementation of `std::ops::Add` might be missing for `&'static str`
--> <anon>:2:5
|
2 | "foo" + "bar"
| ^^^^^
// new
error[E0369]: binary operation `+` cannot be applied to type `&'static str`
--> <anon>:2:5
|
2 | "foo" + "bar"
| ^^^^^
|
= note: `+` can't be used to concatenate two `&str` strings
help: to_owned() can be used to create an owned `String` from a string
reference. String concatenation appends the string on the right to the string on
the left and may require reallocation. This requires ownership of the string on
the left.
| "foo".to_owned() + "bar"
当使用 Cargo 的构建脚本时,您必须在 Cargo.toml
中设置脚本的位置。但是,绝大多数人编写的是 build = "build.rs"
,在项目的根目录中使用 build.rs
文件。此约定现在已编码到 Cargo 中,如果 build.rs
存在,则默认使用。我们在过去的几个版本中已经警告过这一更改,您可以使用 build = false
来选择退出。
此版本标志着旧的基于 Makefile
的构建系统的移除。新的系统在 Rust 1.15 中宣布,是用 Rust 编写的,主要使用 Cargo 来驱动构建。现在它已经足够成熟,可以作为唯一的构建系统。
作为该更改的一部分,来自 crates.io 的包现在可以在 Rust 的构建系统中使用。第一个添加的是 mdBook,并且 现在它被用来渲染我们的各种类似书籍的文档。
- The book (repo)
- The reference (repo)
- The nomicon (repo)
此外,请查看指向其各自仓库的链接;它们已移出树外。此外,我们还添加了第四本书,仍然在树内:The Unstable Book。这提供了按名称排列的不稳定功能的概述,包含指向其跟踪问题的链接,并且可能包含初始文档。如果您希望看到某个功能稳定下来,请参与其跟踪问题!
在几个版本之前,rustup
停止了默认安装文档。我们进行此更改是为了节省一些带宽,并且因为并非所有用户都需要本地文档副本。但是,这造成了一个陷阱:一些用户没有意识到这一点发生了变化,并且只有在他们不再连接到互联网时才会注意到。此外,一些用户确实希望拥有本地文档副本,无论他们的连接状态如何。因此,我们撤消了此更改,文档再次默认安装。
最后,虽然此版本充满了改进,但我们想遗憾地通知您一个小的倒退。在 Windows 上,Visual Studio 2017 已经发布,并且 Microsoft 更改了软件的安装结构。Rust 无法自动检测此位置,虽然我们正在进行必要的更改,但它们没有及时完成此版本的发布。在此之前,Visual Studio 2015 仍然可以正常工作,或者您可以在命令行上运行 vcvars.bat
。我们希望尽快使其无缝工作。
有关更多信息,请参阅详细的发行说明。
库的稳定化
此版本稳定了 19 个新的 API。
Arc::into_raw
和Rc::into_raw
允许您使用Arc
或Rc
并获取原始指针。Arc::from_raw
和Rc::from_raw
允许您获取该原始指针并获取Arc
或Rc
。Arc::ptr_eq
和Rc::ptr_eq
如果两个Arc
或两个Rc
指向相同的值(而不仅仅是比较结果相等的值),则返回 true。Ordering::then
允许您将两个Ordering
链接在一起,而Ordering::then_with
允许您使用函数执行此操作。BTreeMap::range
允许您迭代BTreeMap
的一部分,而BTreeMap::range_mut
允许您以可变的方式执行此操作。collections::Bound
可以为您提供更多控制。process::abort
将以异常方式完全终止进程。ptr::read_unaligned
和ptr::write_unaligned
类似于ptr::read
和ptr::write
,但没有对齐要求。Result::expect_err
镜像Result::expect
,但用于Err
情况而不是Ok
情况。Cell::swap
类似于std::mem::swap
,但允许您使用&Cell
而不是&mut T
。Cell::replace
类似于std::mem::replace
,但允许您使用&Cell
而不是&mut T
。Cell::into_inner
允许您使用Cell
并提取其值。Cell::take
允许您从Cell
中取出值,并留下其Default::default
。
在其他更改中,Cell<T>
过去要求 T: Copy
用于其许多方法,但是 此要求已大大放宽。
Box<T>
现在使用 From
实现了十多个新的转换。
SocketAddr
和 IpAddr
也有一些新的转换。以前,您可能编写过类似这样的代码:
"127.0.0.1:3000".parse().unwrap()
现在,您可以编写:
SocketAddr::from(([127, 0, 0, 1], 3000))
// or even
([127, 0, 0, 1], 3000).into()
这会删除一些不必要的运行时解析,并且在一定程度上具有可读性,具体取决于您的偏好。
回溯现在具有更好的格式,默认情况下会省略某些内容。例如,完整的回溯:
thread 'main' panicked at 'explicit panic', foo.rs:2
stack backtrace:
1: 0x55c39a23372c - std::sys::imp::backtrace::tracing::imp::write::hf33ae72d0baa11ed
at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:42
2: 0x55c39a23571e - std::panicking::default_hook::{{closure}}::h59672b733cc6a455
at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:351
3: 0x55c39a235324 - std::panicking::default_hook::h1670459d2f3f8843
at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:367
4: 0x55c39a235afb - std::panicking::rust_panic_with_hook::hcf0ddb069e7beee7
at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:555
5: 0x55c39a22e866 - std::panicking::begin_panic::heb433e9aa28a7408
6: 0x55c39a22e9bf - foo::main::hd216d4a160fcce19
7: 0x55c39a23d44a - __rust_maybe_catch_panic
at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libpanic_unwind/lib.rs:98
8: 0x55c39a236006 - std::rt::lang_start::hd7c880a37a646e81
at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:436
at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panic.rs:361
at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/rt.rs:57
9: 0x55c39a22e9e9 - main
10: 0x7f5e5ed3382f - __libc_start_main
11: 0x55c39a22e6b8 - _start
12: 0x0 - <unknown>
现在变为:
thread 'main' panicked at 'explicit panic', foo.rs:2
stack backtrace:
0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: std::sys_common::backtrace::_print
at /checkout/src/libstd/sys_common/backtrace.rs:71
2: std::panicking::default_hook::{{closure}}
at /checkout/src/libstd/sys_common/backtrace.rs:60
at /checkout/src/libstd/panicking.rs:355
3: std::panicking::default_hook
at /checkout/src/libstd/panicking.rs:371
4: std::panicking::rust_panic_with_hook
at /checkout/src/libstd/panicking.rs:549
5: std::panicking::begin_panic
6: foo::main
7: __rust_maybe_catch_panic
at /checkout/src/libpanic_unwind/lib.rs:98
8: std::rt::lang_start
at /checkout/src/libstd/panicking.rs:433
at /checkout/src/libstd/panic.rs:361
at /checkout/src/libstd/rt.rs:57
9: main
10: __libc_start_main
11: _start
默认情况下。您可以设置环境变量 RUST_BACKTRACE=full
以获取完整的回溯。将来我们可能会做更多的清理;请参阅 此错误 以了解更多信息。
有关更多信息,请参阅详细的发行说明。
Cargo 特性
除了前面提到的 build.rs
更改之外,Cargo 还有一些新的改进。cargo check --all
和 cargo run --package
是两个缺失的标志,现在已受支持。
您现在可以选择忽略 SSL 吊销检查。默认值仍然是检查,当然。
Cargo.toml
中的一个新字段 required-features
允许您指定必须设置哪些特定功能才能构建目标。这是一个示例:假设我们正在编写一个与数据库交互的 crate,并且我们支持多个数据库。我们可以在 Cargo.toml
中添加以下内容:
[features]
# ...
postgres = []
sqlite = []
tools = []
tools
功能允许我们包含额外的工具,而 postgres
和 sqlite
功能控制我们要支持哪些数据库。
以前,cargo build
会尝试构建所有目标,这通常是您想要的。但是,如果我们有一个 src/bin/postgres-tool.rs
,只有在启用 postgres
和 tools
功能时才真正相关,该怎么办?以前,我们必须编写如下内容:
#[cfg(not(all(feature = "postgres", feature = "tools")))]
fn main() {
println!("This tool requires the `postgres` and `tools` features to be enabled.");
}
#[cfg(all(feature = "postgres", feature = "tools"))]
fn main() {
// real code
}
这需要大量的样板代码才能绕过 cargo build
的行为。对于 examples/
来说,这更加不幸,因为 examples/
应该展示如何使用您的库,但是这种恶作剧只在包中相关,如果您尝试自己使用该示例,则不相关。
使用新的 required-features
键,我们可以添加:
[[bin]]
# ...
required-features = ["postgres", "tools"]
现在,只有在我们设置了这两个功能时,cargo build
才会构建我们的 postgres-tool
,因此我们可以编写一个正常的 fn main
,而无需所有 cfg
废话。
有关更多信息,请参阅详细的发行说明。
1.17.0 的贡献者
许多人齐心协力创建了 Rust 1.17。没有你们大家,我们就无法做到这一点。谢谢!