diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 142b5b8ea..5b14b3dea 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -390,3 +390,5 @@ - [1.81](appendix/rust-versions/1.81.md) - [1.82](appendix/rust-versions/1.82.md) - [1.83](appendix/rust-versions/1.83.md) + - [1.84](appendix/rust-versions/1.84.md) + - [1.85](appendix/rust-versions/1.85.md) diff --git a/src/appendix/rust-versions/1.84.md b/src/appendix/rust-versions/1.84.md new file mode 100644 index 000000000..339749dbb --- /dev/null +++ b/src/appendix/rust-versions/1.84.md @@ -0,0 +1,69 @@ +# Rust 新版解读 | 1.84 | Const 能力拓展 + +> Rust 1.84 官方 release doc: [Announcing Rust 1.84.0 | Rust Blog](https://blog.rust-lang.org/2025/01/09/Rust-1.84.0.html) + +通过 [rustup](https://www.rust-lang.org/tools/install) 安装的同学可以使用以下命令升级到 1.84 版本: + +```shell +$ rustup update stable +``` + +## Cargo 在依赖版本选择中考虑 Rust 版本 + +1.84.0 稳定了支持最低 Rust 版本(MSRV, minimum supported Rust version)的解析器,该解析器优先选择与项目声明的 MSRV (`Cargo.toml` 里的 `package.rust_version`) 兼容的依赖版本。通过支持 MSRV 的版本选择,维护者可以减少支持旧工具链的工作量,因为不再需要为每个依赖手动选择旧版本。 + +你可以通过 `.cargo/config.toml` 启用支持 MSRV 的解析器: + +```toml +[resolver] +incompatible-rust-versions = "fallback" +``` + +然后在添加依赖时: + +```bash +$ cargo add clap + Updating crates.io index +warning: ignoring clap@4.5.23 (which requires rustc 1.74) to maintain demo's rust-version of 1.60 + Adding clap v4.0.32 to dependencies + Updating crates.io index + Locking 33 packages to latest Rust 1.60 compatible versions + Adding clap v4.0.32 (available: v4.5.23, requires Rust 1.74) +``` + +在 CI 中[验证最新依赖](https://doc.rust-lang.org/cargo/guide/continuous-integration.html#verifying-latest-dependencies)时,你可以覆盖此行为: + +```bash +$ CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS=allow cargo update + Updating crates.io index + Locking 12 packages to latest compatible versions + Updating clap v4.0.32 -> v4.5.23 +``` + +你也可以通过在 `Cargo.toml` 清单文件中设置 [`package.resolver = "3"`](https://doc.rust-lang.org/cargo/reference/resolver.html#resolver-versions) 来启用此功能,但这需要将 MSRV 提升到 1.84。对于使用 Rust 2024 的项目(将在 1.85 中稳定),新的解析器将默认启用。 + +这为库作者在决定采用新 Rust 工具链功能的策略时提供了更大的灵活性。以前,库采用新 Rust 工具链的功能会迫使使用旧 Rust 版本的下游用户要么升级工具链,要么手动选择与工具链兼容的旧版本库(并避免运行 `cargo update`)。现在,这些用户将能够自动使用与其旧工具链兼容的旧库版本。 + +有关决定 MSRV 策略时的更多注意事项,请参阅[文档](https://doc.rust-lang.org/cargo/reference/rust-version.html#setting-and-updating-rust-version)。 + +## 新 trait 求解器的迁移开始 + +Rust 编译器正在迁移到新的 trait 求解器实现。下一代 trait 求解器是 Rust 类型系统核心组件的重新实现。它不仅负责检查 trait 边界(例如 `Vec: Clone`)是否成立,还被类型系统的许多其他部分使用,例如规范化(确定 ` as IntoIterator>::Item` 的基础类型)和类型等价(检查 `T` 和 `U` 是否相同)。 + +在 1.84 中,新求解器用于检查 trait 实现的一致性。从高层次来看,一致性负责确保在考虑其他 crate 中尚未编写或不可见的代码时,给定类型的 trait 实现最多只有一个。 + +此稳定化修复了旧实现中的一些主要理论上的正确性问题,导致可能会报告以前未报告的“trait 冲突实现”错误。根据 [Crater](https://github.com/rust-lang/crater/) 对可用代码的评估,我们预计受影响的模式非常罕见。此次稳定版本还提高了我们证明实现不重叠的能力,在某些情况下允许编写更多代码。 + +有关更多详细信息,请参阅之前的[博客文章](https://blog.rust-lang.org/inside-rust/2024/12/04/trait-system-refactor-initiative.html)和[稳定报告](https://github.com/rust-lang/rust/pull/130654)。 + +## 严格来源 API + +在 Rust 中,[指针不仅仅是“整数”或“地址”](https://rust-lang.github.io/rfcs/3559-rust-has-provenance.html)。例如,“释放后使用”是未定义行为,即使你“幸运”并且在读取/写入之前重新分配了释放的内存。另一个例子是,通过从 `&i32` 引用派生的指针写入是未定义行为,即使通过不同指针写入同一地址是合法的。这里的底层模式是,指针的计算方式很重要,而不仅仅是计算结果的地址。因此,我们说指针具有**来源**:要完全描述 Rust 中与指针相关的未定义行为,我们不仅需要知道指针指向的地址,还需要跟踪它是从哪些其他指针“派生”的。 + +大多数情况下,程序员不需要过多担心来源,指针的派生方式非常清晰。然而,当将指针转换为整数并返回时,结果指针的来源是不明确的。在此版本中,Rust 添加了一组 API,可以在许多情况下替代整数指针转换的使用,从而避免此类转换固有的歧义。特别是,现在可以在不将指针转换为整数(或反方向将整数转换成指针)的情况下实现使用对齐指针的最低有效位存储额外信息的模式。这使得代码更易于推理,更易于编译器分析,并且还有益于像 [Miri](https://github.com/rust-lang/miri) 这样的工具和像 [CHERI](https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/) 这样的架构,旨在检测和诊断指针滥用。 + +有关更多详细信息,请参阅标准库中关于[来源](https://doc.rust-lang.org/std/ptr/index.html#provenance)的文档。 + +## Others + +其它更新细节,和稳定的 API 列表,包括上述 `provenance` 相关 API,参考[原Blog](https://blog.rust-lang.org/2025/01/09/Rust-1.84.0.html#stabilized-apis) diff --git a/src/appendix/rust-versions/1.85.md b/src/appendix/rust-versions/1.85.md new file mode 100644 index 000000000..86a785369 --- /dev/null +++ b/src/appendix/rust-versions/1.85.md @@ -0,0 +1,174 @@ +# Rust 新版解读 | 1.85 | Rust 2024 稳定版、`async` 闭包 + +> Rust 1.85 官方 release doc: [Announcing Rust 1.85.0 | Rust Blog](https://blog.rust-lang.org/2025/02/20/Rust-1.85.0.html) + +通过 [rustup](https://www.rust-lang.org/tools/install) 安装的同学可以使用以下命令升级到 1.85 版本: + +```shell +$ rustup update stable +``` + +## Rust 2024 + +我们很高兴地宣布,Rust 2024 版现已稳定! +大的新版本也是一种用于选择可能带来向后兼容性风险的更改的机制。有关如何实现此目标的详细信息以及迁移的详细说明,请参阅[版本指南](https://doc.rust-lang.org/edition-guide/editions/index.html)。 + +[版本指南](https://doc.rust-lang.org/edition-guide/rust-2024/index.html)里包含了每个更改的详细信息,这里有一份简要总结: + +- 语言 + - [RPIT 生命周期捕获规则](https://doc.rust-lang.org/edition-guide/rust-2024/rpit-lifetime-capture.html) — 当 `use<..>` 不存在时,更改 `impl Trait` 类型对参数的默认捕获。 + - [`if let` 临时作用域](https://doc.rust-lang.org/edition-guide/rust-2024/temporary-if-let-scope.html) — 更改 `if let` 表达式的临时作用域。 + - [尾表达式临时作用域](https://doc.rust-lang.org/edition-guide/rust-2024/temporary-tail-expr-scope.html) — 更改块中尾表达式的临时作用域。 + - [预留模式匹配的人性化改进](https://doc.rust-lang.org/edition-guide/rust-2024/match-ergonomics.html) — 禁止某些模式组合以避免混淆并为未来的改进留出空间。 + - [不安全的 `extern` 块](https://doc.rust-lang.org/edition-guide/rust-2024/unsafe-extern.html) — `extern` 块现在需要 `unsafe` 关键字。 + - [不安全属性](https://doc.rust-lang.org/edition-guide/rust-2024/unsafe-attributes.html) — `export_name`、`link_section` 和 `no_mangle` 属性现在必须标记为 `unsafe`。 + - [`unsafe_op_in_unsafe_fn` 警告](https://doc.rust-lang.org/edition-guide/rust-2024/unsafe-op-in-unsafe-fn.html) — [`unsafe_op_in_unsafe_fn`](https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unsafe-op-in-unsafe-fn) lint 现在默认警告,要求在 `unsafe` 函数中显式使用 `unsafe {}` 块。 + - [禁止引用 `static mut`](https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html) — 对 `static mut` 项的引用现在会生成默认拒绝的错误。 + - [Never 类型 fallback 更改](https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html) — 更改了 never 类型 `!` 的强制转换方式,并将 [`never_type_fallback_flowing_into_unsafe`](https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#never-type-fallback-flowing-into-unsafe) lint 级别更改为“拒绝”。 + - [宏片段说明符](https://doc.rust-lang.org/edition-guide/rust-2024/macro-fragment-specifiers.html) — `macro_rules!` 宏中的 `expr` 宏片段说明符现在也匹配 `const` 和 `_` 表达式。 + - [缺失的宏片段说明符](https://doc.rust-lang.org/edition-guide/rust-2024/missing-macro-fragment-specifiers.html) — [`missing_fragment_specifier`](https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#missing-fragment-specifier) lint 现在是一个错误,拒绝没有片段说明符类型的宏元变量。 + - [`gen` 关键字](https://doc.rust-lang.org/edition-guide/rust-2024/gen-keyword.html) — 保留 `gen` 关键字,以便将来添加生成器块。 + - [保留语法](https://doc.rust-lang.org/edition-guide/rust-2024/reserved-syntax.html) — 保留 `#"foo"#` 风格的字符串和 `##` 标记,以便将来更改如何解析受保护的字符串字面量。 +- 标准库 + - [prelude 的更改](https://doc.rust-lang.org/edition-guide/rust-2024/prelude.html) — 将 `Future` 和 `IntoFuture` 添加到 prelude 中。 + - [为 `Box<[T]>` 添加 `IntoIterator`](https://doc.rust-lang.org/edition-guide/rust-2024/intoiterator-box-slice.html) — 更改了迭代器与 `Box<[T]>` 的工作方式。 + - [新不安全的函数](https://doc.rust-lang.org/edition-guide/rust-2024/newly-unsafe-functions.html) — `std::env::set_var`、`std::env::remove_var` 和 `std::os::unix::process::CommandExt::before_exec` 现在是不安全的函数。 +- Cargo + - [Cargo: Rust 版本感知解析器](https://doc.rust-lang.org/edition-guide/rust-2024/cargo-resolver.html) — 更改默认依赖解析器行为以考虑 `rust-version` 字段。 + - [Cargo: 表和键名一致性](https://doc.rust-lang.org/edition-guide/rust-2024/cargo-table-key-names.html) — 删除了一些过时的 `Cargo.toml` 键。 + - [Cargo: 报错错误使用默认特性开关的继承情况](https://doc.rust-lang.org/edition-guide/rust-2024/cargo-inherited-default-features.html) — 更改了 `default-features = false` 与继承的工作区依赖项的工作方式。 +- Rustdoc + - [Rustdoc 组合测试](https://doc.rust-lang.org/edition-guide/rust-2024/rustdoc-doctests.html) — 文档测试现在组合成一个可执行文件,显著提高了性能。 + - [Rustdoc 嵌套 `include!` 更改](https://doc.rust-lang.org/edition-guide/rust-2024/rustdoc-nested-includes.html) — 更改了嵌套 `include!` 文件的相对路径行为。 +- Rustfmt + - [Rustfmt: 样式版本](https://doc.rust-lang.org/edition-guide/rust-2024/rustfmt-style-edition.html) — 引入了“样式版本”的概念,允许你分开控制格式化版本与 Rust 版本。 + - [Rustfmt: 格式化修复](https://doc.rust-lang.org/edition-guide/rust-2024/rustfmt-formatting-fixes.html) — 大量修复了各种情况的格式化问题。 + - [Rustfmt: 原始标识符排序](https://doc.rust-lang.org/edition-guide/rust-2024/rustfmt-raw-identifier-sorting.html) — 更改了诸如 `r#async` 带有 `r#` 标识符的排序方式。 + - [Rustfmt: 带数字的排序](https://doc.rust-lang.org/edition-guide/rust-2024/rustfmt-version-sorting.html) — 更改了包含整数的标识符的排序方式。 + +### 迁移到 2024 + +指南包含了所有新功能的迁移说明,以及[将现有项目迁移到新版本](https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html)的一般说明。 +在许多情况下,`cargo fix` 可以自动完成必要的更改。你甚至可能会发现,2024 版不需要对你的代码进行任何更改! + +请注意,通过 `cargo fix` 进行的自动修复非常保守,以避免更改代码的语义。在许多情况下,你可能希望保持代码不变并使用 Rust 2024 的新语义;例如,继续使用 `expr` 宏匹配器,并忽略条件表达式的转换,因为你希望使用新的 2024 版 drop 顺序语义。`cargo fix` 的结果不应被视为建议,而只是保持行为的保守转换。 + +## `async` 闭包 + +Rust 现在支持异步闭包,如 `async || {}`,它在调用时返回 future。这类似于 `async fn`,它也可以从本地环境中捕获值,就像普通闭包和函数之间的区别一样。标准库 prelude 中还提供了 3 个类似的 trait:`AsyncFn`、`AsyncFnMut` 和 `AsyncFnOnce`。 + +在某些情况下,你可以通过普通闭包和异步块来近似实现这一点,例如 `|| async {}`。然而,这种内部块返回的 future 无法从闭包捕获中借用,但 `async` 闭包可以做到这一点: + +```rust +let mut vec: Vec = vec![]; + +let closure = async || { + vec.push(ready(String::from("")).await); +}; +``` + +此外,使用 `Fn` trait 返回 `Future` 时,无法正确表达函数签名,但你可以使用 `AsyncFn` trait 来编写: + +```rust +use core::future::Future; +async fn f(_: impl for<'a> Fn(&'a u8) -> Fut) +where + Fut: Future, +{ todo!() } + +async fn f2(_: impl for<'a> AsyncFn(&'a u8)) +{ todo!() } + +async fn main() { + async fn g(_: &u8) { todo!() } + f(g).await; + //~^ ERROR 类型不匹配 + //~| ERROR 一个类型比另一个更通用 + + f2(g).await; // 没问题! +} +``` + +因此,`async` 闭包为这两个问题提供了一流的解决方案!有关更多详细信息,请参阅 [RFC 3668](https://rust-lang.github.io/rfcs/3668-async-closures.html) 和[稳定报告](https://github.com/rust-lang/rust/pull/132706)。 + +## 从诊断中隐藏 trait 实现 + +新的 `#[diagnostic::do_not_recommend]` 属性是给编译器的一个提示,不要将注释的 trait 实现显示为诊断消息的一部分。对于库作者来说,这是一种防止编译器提出可能无益或误导的建议的方式。例如: + +```rust +pub trait Foo {} +pub trait Bar {} + +impl Bar for T {} + +struct MyType; + +fn main() { + let _object: &dyn Bar = &MyType; +} +``` + +```text +error[E0277]: 未满足 trait 绑定 `MyType: Bar` + --> src/main.rs:9:29 + | +9 | let _object: &dyn Bar = &MyType; + | ^^^^ trait `Foo` 未为 `MyType` 实现 + | +note: 需要 `MyType` 实现 `Bar` + --> src/main.rs:4:14 + | +4 | impl Bar for T {} + | --- ^^^ ^ + | | + | 在此处引入的未满足的 trait 绑定 + = note: 需要将 `&MyType` 转换为 `&dyn Bar` +``` + +对于某些 API,实现 `Foo` 并通过该泛型实现间接获得 `Bar` 可能是有意义的。对于其他 API,可能期望大多数用户直接实现 `Bar`,因此 `Foo` 建议是一个误导。在这种情况下,添加诊断提示将更改错误消息如下: + +```rust +#[diagnostic::do_not_recommend] +impl Bar for T {} +``` + +```text +error[E0277]: 未满足 trait 绑定 `MyType: Bar` + --> src/main.rs:10:29 + | +10 | let _object: &dyn Bar = &MyType; + | ^^^^ trait `Bar` 未为 `MyType` 实现 + | + = note: 需要将 `&MyType` 转换为 `&dyn Bar` +``` + +有关原始动机,请参阅 [RFC 2397](https://rust-lang.github.io/rfcs/2397-do-not-recommend.html),以及当前的[参考](https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-diagnosticdo_not_recommend-attribute)以获取更多详细信息。 + +## 元组的 `FromIterator` 和 `Extend` + +早期版本的 Rust 为 `(T, U)` 元组对的迭代器实现了便利的 trait,使其行为类似于 `Iterator::unzip`,其中 `Extend` 在 1.56 版中实现,`FromIterator` 在 1.79 版中实现。这些现在已*扩展*到更多的元组长度,从单例 `(T,)` 到 12 个元素长的 `(T1, T2, .., T11, T12)`。例如,你现在可以使用 `collect()` 一次性分发到多个集合中: + +```rust +use std::collections::{LinkedList, VecDeque}; +fn main() { + let (squares, cubes, tesseracts): (Vec<_>, VecDeque<_>, LinkedList<_>) = + (0i32..10).map(|i| (i * i, i.pow(3), i.pow(4))).collect(); + println!("{squares:?}"); + println!("{cubes:?}"); + println!("{tesseracts:?}"); +} +``` + +```text +[0, 1, 4, 9, 16, 25, 36, 49, 64, 81] +[0, 1, 8, 27, 64, 125, 216, 343, 512, 729] +[0, 1, 16, 81, 256, 625, 1296, 2401, 4096, 6561] +``` + +## `std::env::home_dir()` 的更新 + +`std::env::home_dir()` 已被弃用多年,因为如果设置了 `HOME` 环境变量(这不是 Windows 上的标准配置),它可能会在某些 Windows 配置中给出令人惊讶的结果。我们之前避免更改其行为,因为担心与依赖此非标准配置的代码的兼容性。鉴于该函数已被弃用很长时间,我们现在将其行为更新为错误修复,后续版本将取消对该函数的弃用。 + +## Others + +其它更新细节,和稳定的 API 列表,参考[原Blog](https://blog.rust-lang.org/2025/02/20/Rust-1.85.0.html#stabilized-apis)