Rust 发布团队发布了最新版本 1.80.0,Rust 是一种强大的编程语言,使开发者能够构建可靠、高效的软件,秉承了 Rust 团队一贯的风格,1.80.0 版本在效率、代码安全性和灵活性方面均有大幅升级,使得 Rust 语言更加强大和易用,这次更新带来了哪些新特性和改进?我们一起来看一看:
注:关于 1.80.0 更详细升级信息可查看 Rust blog 原文以及 1.80.0 的详细发行公告 。也可以在 GitHub 上查看 1.80.0 的发行日志 。
如果已经安装了以前版本的 Rust,可以通过以下命令升级到 1.80.0 版本:
$
rustup update stable
如果还没有安装,可以从网站上的相应页面获取 rustup 安装。
(命令:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
)如果想使用测试未来版本,可以考虑使用 beta 版本(
rustup default beta
) 或 nightly 版本 (rustup default nightly
),这两个版本不太稳定,使用过程中可能遇到错误,如果遇到任何错误,可以发送报告。
1.80.0 稳定版主要带来以下变化:
新增 LazyCell
和 LazyLock
两个同步类型
Rust 1.80 中新增加了 LazyCell
和 LazyLock
两个同步原语,这些“懒惰”类型会延迟数据的初始化,直到第一次访问时才进行初始化。它们与 1.70 中稳定的 OnceCell
和 OnceLock
类型类似,但初始化函数包含在 cell 中。这标志着从流行的 lazy_static
和 once_cell
库中引入的功能已经在标准库中稳定化了,所以后续你应该不用使用社区的lazy_static
和 once_cell
库了。
注:
OnceLock
:是 Rust 中的一种类型,其作用是提供一种只能被初始化一次的锁。一旦锁被获取,它就不能再次被初始化。这对于一些需要全局可变状态,但不能重复初始化的情况很有用。
OnceCell
:是 Rust 中的一种类型,这种类型的实例只能被赋值一次。一旦实例被赋值,就不能再改变其值。这种类型通常用于延迟初始化的全局变量。
LazyLock
是线程安全的,它是线程安全时的选项,因此适用于像静态值static
这样的场合。无论哪个线程首次访问静态值,都只会被初始化一次,所有线程都会看到相同的值。
例如,下面例子中spawn线程
和 主线程
都将看到完全相同的持续时间,因为 LAZY_TIME
将由首次访问静态值的任一线程进行一次性初始化。它们都不需要知道如何初始化它,这与 OnceLock::get_or_init()
不同。
代码如下:
use std::sync::LazyLock;
use std::time::Instant;
static LAZY_TIME: LazyLock<Instant> = LazyLock::new(Instant::now);
fn main() {
let start = Instant::now();
std::thread::scope(|s| {
s.spawn(|| {
println!("Thread lazy time is {:?}", LAZY_TIME.duration_since(start));
});
println!("Main lazy time is {:?}", LAZY_TIME.duration_since(start));
});
}
LazyCell
在没有线程同步的情况下执行相同的操作,所以它没有实现 Sync
,这对于静态来说是必要的,但它仍然可以在 thread_local!
静态中使用(每个线程都有不同的初始化)。
注:总的来说,LazyLock
、LazyCell
、OnceLock
和OnceCell
都是用于延迟初始化数据的工具,LazyLock
和LazyCell
内置了的初始化,所以使用者不需要手动初始化它,而OnceLock
和OnceCell
则需要手动初始化。
检查 cfg 名称和值
在Rust 1.79 中,rustc
稳定了一个--check-cfg
标志,现在 Rust1.80 的 Cargo 对其cfg
知道的所有名称和值启用这些检查,包括对Cargo.toml
以及cargo::rustc-check-cfg
构建脚本的输出。
默认警告unexpected_cfgs
lint 会报告意外的 cfg,用于捕获拼写错误或其他错误配置。例如,在具有可选rayon
依赖项的项目中,代码配置了错误的feature
值,会被检测出来发出警告,如下所示:
fn main() {
println!("Hello, world!");
#[cfg(feature = "crayon")]
rayon::join(
|| println!("Hello, Thing One!"),
|| println!("Hello, Thing Two!"),
);
}
warning: unexpected `cfg` condition value: `crayon`
--> src/main.rs:4:11
|
4 | #[cfg(feature = "crayon")]
| ^^^^^^^^^^--------
| |
| help: there is a expected value with a similar name: `"rayon"`
|
= note: expected values for `feature` are: `rayon`
= help: consider adding `crayon` as a feature in `Cargo.toml`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default
无论实际rayon
功能是否启用,都会报告相同的警告。
[lints]
清单中的表格还可Cargo.toml
用于扩展自定义的已知名称和值的列表cfg
。rustc
自动提供警告中使用的语法。
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(foo, values("bar"))'] }
可以在之前的博客文章中阅读有关此功能的更多信息。
模式中的排他范围(Exclusive ranges in patterns)
Rust 的范围现在可以使用独占端点,写成a..b
或..b
类似于Range
和RangeTo
表达式类型。例如,以下模式现在可以在一个模式的终点和下一个模式的起点使用相同的常量:
pub fn size_prefix(n: u32) -> &'static str {
const K: u32 = 10u32.pow(3);
const M: u32 = 10u32.pow(6);
const G: u32 = 10u32.pow(9);
match n {
..K => "",
K..M => "k",
M..G => "M",
G.. => "G",
}
}
以前,模式中只允许包含(a..=b
或..=b
)或开放(a..
)范围,因此像这样的代码需要为包含端点设置单独的常量(如K-1)。
一直以来,Exclusive ranges 是一个不稳定的功能。Rust 团队表示,该功能稳定下来的阻碍因素在于它们可能会增加混乱并增加模式中出现 off-by-one errors
的可能性。在 Rust 1.80 中,exhaustiveness checking 得到了增强,可以更好地检测模式匹配中的差距,新的 lintnon_contiguous_range_endpoints
和 overlapping_range_endpoints
将有助于检测在哪些情况下需要将 exclusive 模式和 inclusive 模式相互切换。
稳定的 API
impl Default for Rc<CStr>
impl Default for Rc<str>
impl Default for Rc<[T]>
impl Default for Arc<str>
impl Default for Arc<CStr>
impl Default for Arc<[T]>
impl IntoIterator for Box<[T]>
impl FromIterator<String> for Box<str>
impl FromIterator<char> for Box<str>
LazyCell
LazyLock
Duration::div_duration_f32
Duration::div_duration_f64
Option::take_if
Seek::seek_relative
BinaryHeap::as_slice
NonNull::offset
NonNull::byte_offset
NonNull::add
NonNull::byte_add
NonNull::sub
NonNull::byte_sub
NonNull::offset_from
NonNull::byte_offset_from
NonNull::read
NonNull::read_volatile
NonNull::read_unaligned
NonNull::write
NonNull::write_volatile
NonNull::write_unaligned
NonNull::write_bytes
NonNull::copy_to
NonNull::copy_to_nonoverlapping
NonNull::copy_from
NonNull::copy_from_nonoverlapping
NonNull::replace
NonNull::swap
NonNull::drop_in_place
NonNull::align_offset
<[T]>::split_at_checked
<[T]>::split_at_mut_checked
str::split_at_checked
str::split_at_mut_checked
str::trim_ascii
str::trim_ascii_start
str::trim_ascii_end
<[u8]>::trim_ascii
<[u8]>::trim_ascii_start
<[u8]>::trim_ascii_end
Ipv4Addr::BITS
Ipv4Addr::to_bits
Ipv4Addr::from_bits
Ipv6Addr::BITS
Ipv6Addr::to_bits
Ipv6Addr::from_bits
Vec::<[T; N]>::into_flattened
<[[T; N]]>::as_flattened
<[[T; N]]>::as_flattened_mut
这些 API 现在在 const 上下文中是稳定的:
其他变化(Others)
了解更多有关 Rust、Cargo和 Clippy中所有变化的详细信息,请参阅完整的发布说明 ,其它更新细节,和稳定的API列表,以及贡献者列表。
官方资料
关于1.80.0 升级的更多信息,可以查阅:
- 1.80.0 官方博客:blog.rust-lang.org/2024/07/25/…
- 1.80.0 版本标记:github.com/rust-lang/r…
- 1.80.0 变更日志:releases.rs/docs/1.80.0
- 1.80.0 感谢列表:thanks.rust-lang.org/rust/1.80.0
- 1.80.0 Cargo 更新:github.com/rust-lang/c…
- 1.80.0 Clippy 更新:github.com/rust-lang/r…