本日10/6(金)にリリースされたRust 1.73の変更点を詳しく紹介します。 この記事が参考になったらTwitterシェアやはてブ、記事末尾からの活動支援などしてくれると嬉しいです。
ピックアップ
個人的に注目する変更点を「ピックアップ」としてまとめました。 全ての変更点を網羅したリストは変更点リストをご覧ください。
符号無し整数を安全に割って切り上げられるようになった
符号無し整数を割って切り上げる事ができるuX::div_ceil
が使えるようになりました。
この手の演算は一般的には(a + b - 1) / b
といった式が使われるものの、この式ではオーバーフローする可能性があります。
しかしuX::div_ceil
ではオーバーフローすることなくこの演算をすることができます。
なお符号付き整数については(-a).div_euclid(-b)
などで同等の結果を得られることから必要不可欠とは言えず、安定化は見送られています。
#![allow(arithmetic_overflow)] fn main() { let a: u8 = 255; let b: u8 = 2; // 常に128 println!("div_ceil:{}", a.div_ceil(b)); // デバッグモード時はパニック、リリースモード時は0(オーバーフロー) println!("一般的な演算:{}", (a + b - 1) / b); // 符号付き整数ではdiv_euclidが使える let a: i8 = 127; let b: i8 = 2; // 常に64 println!("{}", (-a).div_euclid(-b)); }
パニック時の文言が読みやすくなった
Rust 1.73からパニック時の出力が変更され、パニック位置と文言の行が分かれるようになりました。 これまではパニック文言のあとにパニック位置が表示されていたため少し読みにくい状態でした。
同時にassert_eq!
やassert_ne!
が失敗したときの文言も変更され、こちらも読みやすくなっています。
fn main() { let _ = std::thread::spawn(|| { panic!("'hogeeeeeeeeeeee'"); }).join(); // Rust 1.72 // thread '<unnamed>' panicked at ''hogeeeeeeeeeeee'', src/main.rs:3:9 // Rust 1.73 // thread '<unnamed>' panicked at src/main.rs:3:9: // 'hogeeeeeeeeeeee' // ------------------------------ let _ = std::thread::spawn(|| { assert_eq!(0, 1); }).join(); // Rust 1.72 // thread '<unnamed>' panicked at 'assertion failed: `(left == right)` // left: `0`, // right: `1`', src/main.rs:6:9 // Rust 1.73 // thread '<unnamed>' panicked at src/main.rs:6:9: // assertion `left == right` failed // left: 0 // right: 1 // ------------------------------ let _ = std::thread::spawn(|| { assert_eq!(1 + 1, 20, "オレたちは1+1で200だ!10倍だぞ10倍"); }).join(); // Rust 1.72 // thread '<unnamed>' panicked at 'assertion failed: `(left == right)` // left: `2`, // right: `20`: オレたちは1+1で200だ!10倍だぞ10倍', src/main.rs:41:9 // Rust 1.73 // thread '<unnamed>' panicked at src/main.rs:41:9: // assertion `left == right` failed: オレたちは1+1で200だ!10倍だぞ10倍 // left: 2 // right: 20 }
最近のrust-analyzer
最近rust-analyzerに入った変更の中から個人的に気になったものをピックアップしました。
rust-analyzer専用のコードを書けるようになった
2023-09-11 (v0.3.1657)での変更です。
#[cfg(rust_analyzer)]
によりrust-analyzer専用コードを書けるようになりました。
これによりrust-analyzerで上手く解析出来ないコードやパフォーマンス上不利なコードを無視させられるでしょう。
補完候補に完全な関数定義を表示できるようになった
2023-09-25 (v0.3.1673)での変更です。
補完候補で表示される関数のドキュメントにおいて、これまでは引数名やジェネリクス等が省略された関数定義(シグネチャ)が表示されていましたが、 それらを含めた完全な関数定義を表示できるようになりました。
これは設定rust-analyzer.completion.fullFunctionSignatures.enable
にtrue
を指定することで利用できます。
安定化されたAPIのドキュメント
安定化されたAPIのドキュメントを独自に訳して紹介します。リストだけ見たい方は安定化されたAPIをご覧ください。
uX::div_ceil
#[stable(feature = "int_roundings1", since = "1.73.0")] #[rustc_const_stable(feature = "int_roundings1", since = "1.73.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] pub const fn div_ceil(self, rhs: Self) -> Self { /* 実装は省略 */ } }
self
とrhs
の商を計算し、結果を正の無限大方向に丸める。
パニック
この関数はrhs
がゼロの場合にパニックする。
オーバーフローの挙動
オーバーフロー時、この関数はオーバーフロー検査が有効の場合(デバッグモード時の既定)はパニックし、 オーバーフロー検査が無効の場合(リリースモード時の既定)には折り返す。
サンプル
基本的な使い方
assert_eq!(7_u8.div_ceil(4), 2);
uX::next_multiple_of
#[stable(feature = "int_roundings1", since = "1.73.0")] #[rustc_const_stable(feature = "int_roundings1", since = "1.73.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] pub const fn next_multiple_of(self, rhs: Self) -> Self { /* 実装は省略 */ } }
self
以上の値でrhs
の倍数である最小の値を計算する。
パニック
この関数はrhs
がゼロの場合にパニックする。
オーバーフローの挙動
オーバーフロー時、この関数はオーバーフロー検査が有効の場合(デバッグモード時の既定)はパニックし、 オーバーフロー検査が無効の場合(リリースモード時の既定)には折り返す。
サンプル
基本的な使い方
assert_eq!(16_u8.next_multiple_of(8), 16); assert_eq!(23_u8.next_multiple_of(8), 24);
uX::checked_next_multiple_of
#[stable(feature = "int_roundings1", since = "1.73.0")] #[rustc_const_stable(feature = "int_roundings1", since = "1.73.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] pub const fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> { /* 実装は省略 */ } }
self
以上の値でrhs
の倍数である最小の値を計算する。
rhs
がゼロまたは演算がオーバーフローする場合はNone
を返す。
サンプル
assert_eq!(16_u8.checked_next_multiple_of(8), Some(16)); assert_eq!(23_u8.checked_next_multiple_of(8), Some(24)); assert_eq!(1_u8.checked_next_multiple_of(0), None); assert_eq!(u8::MAX.checked_next_multiple_of(2), None);
変更点リスト
言語
- リント
clippy::fn_null_check
をuseless_ptr_null_checks
へと昇格 noop_method_call
を既定で警告するようにした- マクロで
try
とasync
を補間するブロックに対応 - リント
unconditional_recursion
で再帰的なドロップを検出するようにした - いくつかの実装が誤って重複していないとみなされる場合における将来の互換性に関する警告
- リント
invalid_reference_casting
を(既定許可ではなく)既定拒否にした
コンパイラ
- GCCやClangのように
.comment
セクションにバージョン情報を書き込み - v0シンボルのマングリングに関する文書を追加
extern "thiscall"
と"thiscall-unwind"
ABIを安定化- 実装とトレイトの比較において長生きする条件のみを検証
- 固定長な配列での反駁不能(irrefutable)なスライスパターンで型を推論
- 自動トレイトへの明示的な実装が存在する場合は既定の実装を破棄
- いくつかの新しいTier 3ターゲットを追加
wasm32-wasi-preview1-threads
をTier 2ターゲットとして追加
Rustのティア付けされたプラットフォーム対応の詳細はPlatform Supportのページ(※訳注:英語)を参照
ライブラリ
Arc<File>
にRead
、Write
そしてSeek
の実装を追加io::Sink
の機能をio::Empty
に統合Backtrace
がRefUnwindSafe
を実装するようになったExitStatus
がDefault
を実装するようにしたimpl SliceIndex<str> for (Bound<usize>, Bound<usize>)
- 既定のパニック処理における文言形式を変更
assert_eq!
及びassert_ne!
のパニック文言を綺麗に- (非推奨な)Androidの
stat
構造体定義を修正
安定化されたAPI
- 符号無しの
{integer}::div_ceil
- 符号無しの
{integer}::next_multiple_of
- 符号無しの
{integer}::checked_next_multiple_of
std::ffi::FromBytesUntilNulError
std::os::unix::fs::chown
std::os::unix::fs::fchown
std::os::unix::fs::lchown
LocalKey::<Cell<T>>::get
LocalKey::<Cell<T>>::set
LocalKey::<Cell<T>>::take
LocalKey::<Cell<T>>::replace
LocalKey::<RefCell<T>>::with_borrow
LocalKey::<RefCell<T>>::with_borrow_mut
LocalKey::<RefCell<T>>::set
LocalKey::<RefCell<T>>::take
LocalKey::<RefCell<T>>::replace
以下のAPIが定数文脈で使えるようになった。
Cargo
その他
互換性メモ
内部の変更
これらの変更がユーザーに直接利益をもたらすわけではないものの、コンパイラ及び周辺ツール内部では重要なパフォーマンス改善をもたらす。
- LLVMのpointee型を削除し、不透明(opaque)型のみに対応
- PGO・LTO・BOLTの最適化ビルドパイプラインをRustに移植
- ツリー内の
rustc_apfloat
を新しいバージョンのクレートに置き換え - LLVMを17に更新
- 内部の不安定な機能向けにリント
internal_features
を追加 - tracking issueのテンプレートで新しい構文のスタイルに言及
関連リンク
さいごに
次のリリースのRust 1.74は11/17(金)にリリースされる予定です。 Rust 1.74ではrustdocに警告を表示できるようになったり、Apple端末での最低対応OSバージョンが引き上げられたりするようです。