preludeに導入されたFuture/IntoFutureトレイト
Rust 2024では、非同期関数のためのトレイトFuture/IntoFutureがpreludeに含まれることになりました。
Rustのpreludeとは、自動でスコープに取り込まれるアイテムです。Rust 2021では、以下のアイテムがpreludeに含まれていました。preludeに含まれるアイテムは、useキーワードによる取り込みなしに使うことができます。いずれも、ほとんどのプログラムで必要になる基本的なアイテムです。
std::marker::{Copy, Send, Sized, Sync, Unpin}
std::ops::{Drop, Fn, FnMut, FnOnce}
std::mem::drop
std::boxed::Box
std::borrow::ToOwned
std::clone::Clone
std::cmp::{PartialEq, PartialOrd, Eq, Ord}
std::convert::{AsRef, AsMut, Into, TryInto, From, TryFrom}
std::iter::{Iterator, Extend, FromIterator, IntoIterator, DoubleEndedIterator, ExactSizeIterator}
std::option::Option::{self, Some, None}
std::result::Result::{self, Ok, Err}
std::vec::Vec
Rust 2024では、これにstd::future::Futureとstd::future::IntoFutureが加わります。これによってuseなしにFutureとIntoFutureのメソッドを呼び出せるようになるだけと思われがちですが、実際にはメソッドの衝突の発生に留意する必要があります。型名と異なり、トレイトのメソッド呼び出しは曖昧になる可能性があるからです。
例えば、Futureトレイトにあるpollメソッドを考えます。同名のメソッドを独自に定義していても、従来はFutureトレイトを明示的にuseしているはずなので、意識して使い分けできていました。
Rust 2024ではFutureトレイトの利用で明示的なuseが不要なので、単にpollメソッドが呼び出されたとき、どのpollメソッドを呼び出せばよいか、コンパイラは判断できません。これを解決するためには、パス式で完全修飾構文を用いて、どの名前空間に属するpollメソッドなのかを明示する必要があります。
なお、rust_2024_prelude_collisionsリントによって変更が必要な箇所を警告させることができます。
スライス型のBoxに実装されたIntoIteratorトレイト
Rust 2024を含む全エディションにおいて、スライス型のBox(Box<[T]>)にIntoIteratorトレイトが実装されました。
スライスを持つBoxとは、別のコレクションへの参照を持つBoxです。コレクションへの参照なので、into_iterメソッドなどでイテレータ化し、要素を順番に取り出したいということがあります。このためのアプローチが過去バージョンにおいてとられてきましたが、Rust 2024でIntoIteratorトレイトが過去エディションに遡って実装されたことで、同じ記述で期待する効果を得られるようになりました。
Rust 1.80より前のバージョンでは、スライスを持つBoxでinto_iterメソッドを呼び出すと、自動的にスライスへの参照に変換され、for式では、スライスの各要素(参照)を取得するようになっています。
let boxed_slice: Box<[i32]> = vec![1, 2, 3].into_boxed_slice();
for x in boxed_slice.into_iter() { // &[i32]に変換される
println!("{x}"); // &i32となる
}
Rust 1.80ではIntoIteratorトレイトが実装され、into_iterメソッドの呼び出しなしに各要素を取得できます。上記とは異なり、要素の型は参照ではなく値となります。
let boxed_slice: Box<[i32]> = vec![1, 2, 3].into_boxed_slice();
for x in boxed_slice { // into_iterメソッド不要
println!("{x}"); // i32となる
}
しかしながら、この記述法は1.80より前のバージョンではエラーとなるので、Rust 2024では過去エディションに遡ってIntoIteratorトレイトが実装され、into_iterメソッドの呼び出しで同じ振る舞いをするようになります。
let boxed_slice: Box<[i32]> = vec![1, 2, 3].into_boxed_slice();
for x in boxed_slice.into_iterator() {
println!("{x}"); // i32となる
}
まとめ
今回は、Rust 2024で新しく導入されたキーワードgen、プレフィクスのない#"abc"#形式の文字列など新しい構文、never型フォールバックの変更、RPITのライフタイムキャプチャ方法の改善、static mutへの参照の禁止などの構文の変更、preludeに導入されたFuture、IntoFutureトレイトと、スライス型のBoxに実装されたIntoIteratorトレイトなどの、標準ライブラリの変更を中心に紹介しました。
次回は、Unsafe Rustにかかわる変更として、Unsafeとなった関数、Unsafeな関数内におけるUnsafeなコードの扱い、Unsafeとなったexternブロック、Unsafeのマークが必須となった属性などについて、Unsafe Rustのあらましとともに紹介します。
