こんにちは、あずんひ(@aznhe21)です。最近は標準ライブラリを持続的に翻訳する仕組みを考えてますが難航中です。
さて、本日7/1(金)にRust 1.62がリリースされました。 この記事ではRust 1.62での変更点を詳しく紹介します。
ピックアップ
個人的に注目する変更点を「ピックアップ」としてまとめました。 全ての変更点を網羅したリストは変更点リストをご覧ください。
列挙型で#[derive(Default)]できるようになった
列挙型でDefault
トレイトを#[derive]
できるようになりました。
ただし、#[default]
属性は非unitな(=フィールドを持つ)バリアントやnon-exhaustiveなバリアントでは使えません。
#[derive(Debug, Default)] enum Language { C, Cpp, D, Delphi, #[default] Rust, } fn main() { println!("{:?}", Language::default()); }
浮動小数点数で全順序による比較ができるようになった
Rust 1.61以前において、浮動小数点数をソートする場合はordered-floatクレートなどを使っていました。
Rust 1.62ではf32::total_cmp
やf64::total_cmp
が導入され、IEEE 754の全順序に従った比較ができるようになりました。
Ord
が実装されるわけではない上、partial_cmp
とは結果が異なる場合があることに注意が必要です。
これらのメソッドを使うと以下のように値が並びます。
- 負のシグナルを発生させないNaN(quiet NaN)
- 負のシグナルを発生させるNaN(signaling NaN)
- 負の無限大
- 負の数値
- 負の非正規数
- 負のゼロ
- 正のゼロ
- 正の非正規数
- 正の無限大
- 正のシグナルを発生させるNaN(signaling NaN)
- 正のシグナルを発生させないNaN(quiet NaN)
fn main() { let mut values = [ -1.0, 1.0, -0.0, 0.0, f32::NAN, -f32::NAN, f32::INFINITY, f32::NEG_INFINITY, ]; values.sort_by(f32::total_cmp); // [NaN, -inf, -1.0, -0.0, 0.0, 1.0, inf, NaN] println!("{:?}", values); }
LinuxにおいてMutexなどの実装がfutexに切り替わった
Linux※におけるstd::sync::Mutex
・std::sync::Condvar
・std::sync::RwLock
の内部実装がpthreadからfutexに切り替わりました。
これにはメモリ消費量の削減やロック・ロック解除操作の軽量化といったメリットがあります。
※:厳密にはLinux以外にもAndroid・Emscripten・FreeBSD・OpenBSD・DragonFly BSDを含みます(#[cfg(target_os)]
指定より)
この変更を受け、Rust 1.63ではこれらオブジェクトのコンストラクタが定数化されるようです。
なお、Rust 1.61以前でもparking_lot
クレートによって近い恩恵を受けることができます。
cargo addコマンドが追加された
Cargo.toml
に新たな依存クレートを追加するcargo add
コマンドが追加されました。
Rust 1.61依然もcargo-editをインストールすることでこのコマンドが使えましたが、Rust 1.62で標準コマンドとして採用されました。
なおcargo rm
などのコマンドは依然cargo-editにしかない上、cargo add
自体もcargo-editのものとはいくつか仕様が異なる点があるため注意が必要です。
cargo add package
としたとき、packageクレートの最新版がCargo.toml
の[dependencies]
などのセクションに追加されます。
フラグも色々あるので、詳細はcargo add
のヘルプをご覧ください。
cargo add serde # serde = "X.Y.Z" cargo add serde -F derive cargo add serde --features derive # serde = { version = "X.Y.Z", features = ["derive"] } cargo add serde@1 # serde = "1" cargo add serde@1 --rename serde_v1 # serde_v1 = { version = "1", package = "serde" }
安定化されたAPIのドキュメント
安定化されたAPIのドキュメントを独自に訳して紹介します。リストだけ見たい方は安定化されたAPIをご覧ください。
bool::then_some
impl bool { #[stable(feature = "bool_to_option", since = "1.62.0")] #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] pub const fn then_some<T>(self, t: T) -> Option<T> where T: ~const Destruct, { /* 実装は省略 */ } }
bool
がtrue
であればSome(t)
を、それ以外であればNone
を返す。
サンプル
assert_eq!(false.then_some(0), None); assert_eq!(true.then_some(0), Some(0));
f32::total_cmp
impl f32 { #[stable(feature = "total_cmp", since = "1.62.0")] #[must_use] #[inline] pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { /* 実装は省略 */ } }
self
とother
の順序を返す。
浮動小数点数間の標準的な半順序とは異なり、この比較では
IEEE 754(2008版)浮動小数点標準で定義される述語totalOrder
に従って常に順序が生成される。
値は以下の順に並ぶ。
- 負のシグナルを発生させないNaN(quiet NaN)
- 負のシグナルを発生させるNaN(signaling NaN)
- 負の無限大
- 負の数値
- 負の非正規数
- 負のゼロ
- 正のゼロ
- 正の非正規数
- 正の無限大
- 正のシグナルを発生させるNaN(signaling NaN)
- 正のシグナルを発生させないNaN(quiet NaN)
この関数によってもたらされた順序はf32
のPartialOrd
やPartialEq
の実装と常に一致するとは限らない。
例えばそれらの実装では負のゼロと正のゼロは等しいと見做されるが、total_cmp
では等しくはない。
シグナルを発生させるNaNのビットの解釈はIEEE 754標準に従うが、 一部の古い非準拠(例:MIPS)ハードウェア実装の解釈とは一致しない場合がある。
サンプル
struct GoodBoy { name: String, weight: f32, } let mut bois = vec![ GoodBoy { name: "ちび".to_owned(), weight: 0.1 }, GoodBoy { name: "ポチ".to_owned(), weight: 99.0 }, GoodBoy { name: "むぎ".to_owned(), weight: 10.0 }, GoodBoy { name: "マル".to_owned(), weight: f32::INFINITY }, GoodBoy { name: "Abs. Unit".to_owned(), weight: f32::NAN }, GoodBoy { name: "ふわり".to_owned(), weight: -5.0 }, ]; bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
f64::total_cmp
impl f64 { #[stable(feature = "total_cmp", since = "1.62.0")] #[must_use] #[inline] pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { /* 実装は省略 */ } }
self
とother
の順序を返す。
浮動小数点数間の標準的な半順序とは異なり、この比較では
IEEE 754(2008版)浮動小数点標準で定義される述語totalOrder
に従って常に順序が生成される。
値は以下の順に並ぶ。
- 負のシグナルを発生させないNaN(quiet NaN)
- 負のシグナルを発生させるNaN(signaling NaN)
- 負の無限大
- 負の数値
- 負の非正規数
- 負のゼロ
- 正のゼロ
- 正の非正規数
- 正の無限大
- 正のシグナルを発生させるNaN(signaling NaN)
- 正のシグナルを発生させないNaN(quiet NaN)
この関数によってもたらされた順序はf64
のPartialOrd
やPartialEq
の実装と常に一致するとは限らない。
例えばそれらの実装では負のゼロと正のゼロは等しいと見做されるが、total_cmp
では等しくはない。
シグナルを発生させるNaNのビットの解釈はIEEE 754標準に従うが、 一部の古い非準拠(例:MIPS)ハードウェア実装の解釈とは一致しない場合がある。
サンプル
struct GoodBoy { name: String, weight: f64, } let mut bois = vec![ GoodBoy { name: "ちび".to_owned(), weight: 0.1 }, GoodBoy { name: "ポチ".to_owned(), weight: 99.0 }, GoodBoy { name: "むぎ".to_owned(), weight: 10.0 }, GoodBoy { name: "マル".to_owned(), weight: f64::INFINITY }, GoodBoy { name: "Abs. Unit".to_owned(), weight: f64::NAN }, GoodBoy { name: "ふわり".to_owned(), weight: -5.0 }, ]; bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
Stdin::lines
impl Stdin { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "stdin_forwarders", since = "1.62.0")] pub fn lines(self) -> Lines<StdinLock<'static>> { /* 実装は省略 */ } }
このハンドルを消費して入力の各行に対するイテレータを返す。
このメソッドの意味論に関してはBufRead::lines
の文書を参照。
サンプル
use std::io; let lines = io::stdin().lines(); for line in lines { println!("得た行:{}", line.unwrap()); }
windows::CommandExt::raw_arg
pub trait CommandExt: Sealed { #[stable(feature = "windows_process_extensions_raw_arg", since = "1.62.0")] fn raw_arg<S: AsRef<OsStr>>(&mut self, text_to_append_as_is: S) -> &mut process::Command; }
引用符の追加やエスケープを行わずにそのままの文字列をコマンドラインに追加する。
これはcmd.exe /c
に対してCommandLineToArgvW
のエスケープ規約に従わない引数を渡すときに便利である。
変更点リスト
言語
- 列挙型における、バリアントに
#[default]
を付けた上での#[derive(Default)]
が安定化された
→ピックアップ - 関数の戻り値が空の型(uninhabited types=バリアントのない列挙型)の呼び出し後は いくらかの到達不能コードに関する検証をやめるようになった
- 発散する(diverging)式に定数が含まれる場合に定数がドロップされないのを修正
- ユニット構造体・列挙型の分割代入がサポートされた
- mutable_borrow_reservation_conflictリントを削除し、それらのコードパターンを許容するようになった
コンパイラ
- リンカ:dylibの依存関係におけるwhole-archiveの使用を取りやめ
unaligned_references
リントを初期拒否にした。 このリントは将来の互換性に関するリントでもあるため、最終的にはコンパイルエラーになると予想される- -Zbinary-dep-depinfoが指定されたときだけ依存情報(dep info)にコード生成バックエンドを追加するようになった
- 非静的なアイテムでは
#[thread_local]
属性を弾くようになった - Tier 3に
aarch64-pc-windows-gnullvm
・x86_64-pc-windows-gnullvm
ターゲットを追加した※ - 未使用のマクロルールに関する警告のリントを実装
x86_64-unknown-none
ターゲットをTier 2に格上げ※
※Rustのティア付けされたプラットフォームサポートの詳細はPlatform Supportのページ(※訳注:英語)を参照
ライブラリ
- Windows:パイプを連鎖させるときにパイプリレーを使用するようになった
- Linuxにおいて、MutexとCondvarをfutexによるものに置き換え
→ピックアップ - Linuxにおいて、RwLockをfutexによるものに置き換え
→ピックアップ - std:UNIXにおけるParkerの実装でpthreadを直接使用するようになった
安定化されたAPI
bool::then_some
f32::total_cmp
f64::total_cmp
Stdin::lines
windows::CommandExt::raw_arg
impl<T: Default> Default for AssertUnwindSafe<T>
From<Rc<str>> for Rc<[u8]>
From<Arc<str>> for Arc<[u8]>
FusedIterator for EncodeWide
- aarch64向けのRDM組み込み関数
Clippy
Cargo
Cargo.toml
にコマンドラインから依存関係を追加するcargo add
コマンドを追加。 文書
→ピックアップcargo add
などのツールと挙動を合わせるため、パッケージIDの仕様が、 以前からあるname:version
に加えてname@version
形式をサポートするようになった。cargo install
とcargo yank
もこの形式をサポートするようになり、 バージョンを個別のフラグとして渡す必要が無くなった- Cargoのホームディレクトリ(基本
~/.cargo
)のgit
とregistry
ディレクトリが キャッシュディレクトリとしてマークされるようになり、バックアップや 検索用インデックスに含まれないようになった(Windows) - 自動的な
@
引数ファイルのサポートを追加した。これにより、rustc
へのコマンドラインがOSの制限を超えている場合に 「レスポンスファイル」を使用するようになる
互換性メモ
- 指定されたターゲットがホストターゲットと同じ場合、
cargo test
がrustdoc
に--target
を渡すようになった。 #10594 - rustdoc:.woffフォントファイルを削除
- 要素反復式のライフタイムを考慮してCopy境界を強制
内部の変更
これらの変更がユーザーに直接利益をもたらすわけではないものの、コンパイラ及び周辺ツール内部での重要なパフォーマンス改善をもたらす。
関連リンク
さいごに
次のリリースのRust 1.63は8/12(金)にリリースされる予定です。
1.63ではライフタイムを気にせず使える「スコープ付きスレッド」やMutex
などのコンストラクタの定数化が使えるようになる予定です。