Merge pull request #1448 from EluvK/main

translation(appendix/rust-versions) : 1.80
pull/1465/head
Sunface 3 months ago committed by GitHub
commit aa4e805cf8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -386,3 +386,4 @@
- [1.77](appendix/rust-versions/1.77.md) - [1.77](appendix/rust-versions/1.77.md)
- [1.78](appendix/rust-versions/1.78.md) - [1.78](appendix/rust-versions/1.78.md)
- [1.79](appendix/rust-versions/1.79.md) - [1.79](appendix/rust-versions/1.79.md)
- [1.80](appendix/rust-versions/1.80.md)

@ -0,0 +1,104 @@
# Rust 新版解读 | 1.80 | “懒”类型、开区间范围模式
> Rust 1.80 官方 release doc: [Announcing Rust 1.80.0 | Rust Blog](https://blog.rust-lang.org/2024/07/25/Rust-1.80.0.html)
通过 [rustup](https://www.rust-lang.org/tools/install) 安装的同学可以使用以下命令升级到 1.80 版本:
```shell
$ rustup update stable
```
## `LazyCell``LazyLock`
这两个 "lazy" 类型会延迟数据的初始化直到第一次访问。它们类似于 1.70 版本中稳定的 `OnceCell``OnceLock` 类型,但是初始化函数包含在 cell 中。这完成了吸纳流行的 [`lazy_static`](https://crates.io/crates/lazy-static) 和 [`once_cell`](https://crates.io/crates/once_cell) crates 中的功能到标准库中。
`LazyLock` 是线程安全的选项,适用于静态值的场景。例如,下面的例子中,无论是 spawn 线程还是主线程,都会看到相同的时间,因为 `LAZY_TIME` 只会被初始化一次,由哪个访问静态值的端点先访问。与 `OnceLock::get_or_init()` 不同,使用方都不需要知道如何初始化它。
```rust
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!` 静态值中使用(每个线程初始化一次)。取决于线程安全的需求如何,这两种类型都可以在其他数据结构中使用,来达到懒初始化的目的。
## `cfg` 名称和值检查
在 1.79 版本中rustc 稳定了一个 [`--check-cfg` 标志](https://doc.rust-lang.org/rustc/check-cfg.html),现在 Cargo 1.80 为所有的 `cfg` 名称和值启用了这些检查(除了 rustc 中[已知的名称和值](https://doc.rust-lang.org/rustc/check-cfg.html#well-known-names-and-values))。这包括来自 Cargo.toml 的特性名称以及来自构建脚本的新 `cargo::rustc-check-cfg` 输出。
出现期望外的 cfgs 会默认生成 `unexpected_cfgs` lint用于捕获拼写错误或其他配置错误。例如在一个有可选的 `rayon` 特性依赖项的项目中,这段代码配置了错误的特性值:
```rust
fn main() {
println!("Hello, world!");
#[cfg(feature = "crayon")]
rayon::join(
|| println!("Hello, Thing One!"),
|| println!("Hello, Thing Two!"),
);
}
```
```bash
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 特性,都会报告该警告。
`Cargo.toml` 文件中的 `[lints]` 部分可以用于扩展自定义 `cfg` 的已知名称和值列表。`rustc` 自动提供了警告中使用的[语法](https://doc.rust-lang.org/rustc/check-cfg.html#specifying-expected-names-and-values)。
```toml
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(foo, values("bar"))'] }
```
你可以在之前的发布 nightly 时的[博客文章](https://blog.rust-lang.org/2024/05/06/check-cfg.html)中阅读更多关于这个特性的内容。
## 开区间的范围模式
Rust 的范围模式现在可以使用右开区间,写作 `a..b``..b`,类似于 `Range``RangeTo` 表达式类型。例如,以下模式现在可以使用相同的常量作为一个模式的结束和下一个模式的开始:
```rust
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`)。
该特性作为一个不稳定的特性已经实现了很长时间,阻碍其稳定的考虑主要是它可能会增加模式匹配中的混乱程度,增加出现差一错误的机会。为此,穷尽性检查已经得到了增强,以更好地检测模式匹配中的空缺,新的 lint `non_contiguous_range_endpoints``overlapping_range_endpoints` 将有助于检测是否正确使用了开区间和闭区间。
## Others
其它更新细节,和稳定的 API 列表,参考[原Blog](https://blog.rust-lang.org/2024/07/25/Rust-1.80.0.html#stabilized-apis)
Loading…
Cancel
Save