Merge pull request #1419 from EluvK/eluvk/translation/appendix/rust-versions

translation(appendix/rust-versions) : 1.78
pull/1420/head
Sunface 7 months ago committed by GitHub
commit 4ec4239a5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -384,3 +384,4 @@
- [1.75](appendix/rust-versions/1.75.md) - [1.75](appendix/rust-versions/1.75.md)
- [1.76](appendix/rust-versions/1.76.md) - [1.76](appendix/rust-versions/1.76.md)
- [1.77](appendix/rust-versions/1.77.md) - [1.77](appendix/rust-versions/1.77.md)
- [1.78](appendix/rust-versions/1.78.md)

@ -0,0 +1,114 @@
# Rust 新版解读 | 1.78 | 诊断属性宏
> Rust 1.78 官方 release doc: [Announcing Rust 1.78.0 | Rust Blog](https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html)
通过 [rustup](https://www.rust-lang.org/tools/install) 安装的同学可以使用以下命令升级到 1.78 版本:
```shell
$ rustup update stable
```
## 诊断属性宏
Rust 现在支持 `#[diagnostic]` 属性命名空间,用于影响编译器错误消息。这些被视为提示,编译器不需要使用它们,也不会因为提供了编译器不认识的诊断而报错。这种灵活性允许源代码提供诊断,即使不是所有编译器都支持,无论是不同版本还是完全不同的实现。
随着这个命名空间的出现,第一个支持的属性 `#[diagnostic::on_unimplemented]` 也随之而来,可以放在一个 trait 上,用于自定义当需要但未在类型上实现该 trait 时的消息。考虑下面来自[稳定 PR](https://github.com/rust-lang/rust/pull/119888/) 里的示例:
```rust
#[diagnostic::on_unimplemented(
message = "My Message for `ImportantTrait<{A}>` is not implemented for `{Self}`",
label = "My Label",
note = "Note 1",
note = "Note 2"
)]
trait ImportantTrait<A> {}
fn use_my_trait(_: impl ImportantTrait<i32>) {}
fn main() {
use_my_trait(String::new());
}
```
此前,编译器会给出一个内置错误,如下:
```shell
error[E0277]: the trait bound `String: ImportantTrait<i32>` is not satisfied
--> src/main.rs:12:18
|
12 | use_my_trait(String::new());
| ------------ ^^^^^^^^^^^^^ the trait `ImportantTrait<i32>` is not implemented for `String`
| |
| required by a bound introduced by this call
|
```
现在,使用 `#[diagnostic::on_unimplemented]`,自定义消息填充主要错误行,自定义标签放在源输出上。原始标签仍然写在帮助输出中,任何自定义注释也会被写入。 (这些细节未来可能会发生变化。)
```shell
error[E0277]: My Message for `ImportantTrait<i32>` is not implemented for `String`
--> src/main.rs:12:18
|
12 | use_my_trait(String::new());
| ------------ ^^^^^^^^^^^^^ My Label
| |
| required by a bound introduced by this call
|
= help: the trait `ImportantTrait<i32>` is not implemented for `String`
= note: Note 1
= note: Note 2
```
对于 trait 作者来说,如果你能提供更好的提示,而不是仅仅给出缺失部分,这种诊断就更有用。例如,这是标准库中的一个示例:
```rust
#[diagnostic::on_unimplemented(
message = "the size for values of type `{Self}` cannot be known at compilation time",
label = "doesn't have a size known at compile-time"
)]
pub trait Sized {}
```
更多信息,请参考[诊断工具属性命名空间](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-diagnostic-tool-attribute-namespace)的参考部分。
## 不安全前提断言
Rust 标准库有许多用于不安全函数前提的断言,但历史上它们只在标准库的 `#[cfg(debug_assertions)]` 构建中启用,以避免影响发布性能。然而,由于标准库通常以发布模式编译和分发,大多数 Rust 开发者根本没有执行这些检查。
现在,这些断言的条件被延迟到代码生成,因此它们将根据用户自己对调试断言的设置进行检查(在调试和测试构建中默认启用)。这个变化有助于用户捕获他们代码中的未定义行为。
例如,`slice::from_raw_parts` 需要一个对齐的非空指针。下面故意错位指针的使用有未定义行为,虽然如果你运气不好,它可能在过去看起来“工作”,但调试断言现在可以捕获它:
```rust
fn main() {
let slice: &[u8] = &[1, 2, 3, 4, 5];
let ptr = slice.as_ptr();
// 创建一个 `ptr` 的偏移量,它总是比 `u16` 的正确对齐少一个
let i = usize::from(ptr as usize & 1 == 0);
let slice16: &[u16] = unsafe { std::slice::from_raw_parts(ptr.add(i).cast::<u16>(), 2) };
dbg!(slice16);
}
```
在调试构建中,这将导致一个 panic
```shell
thread 'main' panicked at library/core/src/panicking.rs:220:5:
unsafe precondition(s) violated: slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread caused non-unwinding panic. aborting.
```
## 确定性重新对齐
标准库有一些函数可以改变指针和切片的对齐方式,但以前它们有一些注意事项,使它们在实践中难以依赖,如果你严格遵循它们的文档。这些注意事项主要是为了保护对 `const` 的判断,但它们只对非 `const` 使用稳定。现在它们承诺根据实际输入具有一致的运行时行为。
* [`pointer::align_offset`](https://doc.rust-lang.org/std/primitive.pointer.html#method.align_offset) 计算改变指针到给定对齐方式所需的偏移量。如果不可能,它将返回 `usize::MAX`,但以前允许它始终返回 `usize::MAX`,现在这种行为被移除。
* [`slice::align_to`](https://doc.rust-lang.org/std/primitive.slice.html#method.align_to) 和 [`slice::align_to_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.align_to_mut) 都将切片转换为对齐的中间切片和剩余的不对齐头和尾切片。这些方法现在承诺返回最大可能的中间部分,而不允许实现返回不那么优化的东西,比如将所有东西作为头切片返回。
## Others
其它更新细节和稳定的API列表参考[原Blog](https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#stabilized-apis)
Loading…
Cancel
Save