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],它可以放在特徵上,用於自定義當該特徵被要求但尚未在類型上實現時的訊息。考慮穩定化拉取請求中給出的示例:
#[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
\ 對於特徵作者來說,如果您能提供比僅僅談論缺失實現本身更好的提示,這種診斷會更有用。例如,這是標準庫中的一個簡化示例:
#[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 上提供


