Rust团队很高兴宣布Rust的新版本1.78.0。Rust是一种编程语言,使每个人都能构建可靠高效的软件。
\ 如果您通过rustup安装了之前版本的Rust,您可以通过以下方式获取1.78.0:
$ rustup update stable
\ 如果您还没有安装,可以从我们网站上的相应页面获取rustup,并查看1.78.0的详细发布说明。
\ 如果您想通过测试未来版本来帮助我们,可以考虑在本地更新使用beta通道(rustup default beta)或nightly通道(rustup default nightly)。请报告您可能遇到的任何错误!
Rust现在支持#[diagnostic]属性命名空间来影响编译器错误消息。这些被视为编译器不必须使用的提示,提供编译器不识别的诊断信息也不会被视为错误。这种灵活性允许源代码提供诊断信息,即使它们不被所有编译器支持,无论是不同版本还是完全不同的实现。
\ 随着这个命名空间的引入,第一个支持的属性是#[diagnostic::on_unimplemented],它可以放在trait上,用于自定义当该trait被要求但尚未在类型上实现时的消息。考虑稳定化拉取请求中给出的示例:
#[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()); }
\ 之前,编译器会给出这样的内置错误:
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]后,其自定义消息填充主要错误行,其自定义标签放置在源输出上。原始标签仍作为帮助输出写入,任何自定义注释也会被写入。(这些确切细节可能会发生变化。)
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作者来说,如果您能提供比仅仅谈论缺失实现本身更好的提示,这种诊断会更有用。例如,这是标准库中的一个简化示例:
#[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 {}
\ 有关更多信息,请参阅关于diagnostic工具属性命名空间的参考部分。
unsafe前提条件Rust标准库对unsafe函数的前提条件有许多断言,但历史上它们只在标准库的#[cfg(debug_assertions)]构建中启用,以避免影响发布版本的性能。然而,由于标准库通常以发布模式编译和分发,大多数Rust开发者根本没有执行这些检查。
\ 现在,这些断言的条件延迟到代码生成时,因此它们将根据用户自己的调试断言设置进行检查——在调试和测试构建中默认启用。这一变化帮助用户捕获代码中的未定义行为,尽管检查多少的细节通常不稳定。
\ 例如,slice::from_raw_parts需要一个对齐的非空指针。以下故意错位指针的使用具有未定义行为,虽然如果您不幸的话,它在过去可能看起来"有效",但现在调试断言可以捕获它:
fn main() { let slice: &[u8] = &[1, 2, 3, 4, 5]; let ptr = slice.as_ptr(); // Create an offset from `ptr` that will always be one off from `u16`'s correct alignment 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); } 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计算将指针更改为给定对齐所需的偏移量。如果不可能,它返回usize::MAX,但之前允许始终返回usize::MAX,现在该行为已被移除。slice::align_to和slice::align_to_mut都将切片转换为对齐的中间切片和剩余的未对齐头尾切片。这些方法现在承诺返回最大可能的中间部分,而不是允许实现返回不那么理想的结果,比如将所有内容作为头切片返回。impl Read for &Stdin'static生命周期用于几个std::error::Error相关实现impl<Fd: AsFd>实现接受?Sizedimpl From<TryReserveError> for io::Error\ 这些API现在在const上下文中稳定:
Barrier::new()x86_64-pc-windows-msvci686-pc-windows-msvcx86_64-pc-windows-gnui686-pc-windows-gnux86_64-pc-windows-gnullvmi686-pc-windows-gnullvmu128/i128 ABI更改。使用自己的LLVM且版本低于18的发行版可能仍会面临该帖子中提到的调用约定错误。查看Rust、Cargo和Clippy中的所有变更。
许多人共同创建了Rust 1.78.0。没有你们所有人,我们无法做到这一点。谢谢!
Rust发布团队
\ 也发布于此处
\ 照片由Ubaid E. Alyafizi在Unsplash上提供


