以下の内容はhttps://aznhe21.hatenablog.com/entry/2025/10/31/rust-1.91より取得しました。


Rust 1.91を早めに深掘り

本日10/31(金)にリリースされたRust 1.91の変更点を詳しく紹介します。 もしこの記事が参考になれば記事末尾から活動を支援頂けると嬉しいです。

この記事は原文の理解や和訳のために一部生成AIを使用していますが、すべて筆者の考えに基づく文章で構成しており、 漫然と生成AIを使用しているものではありません。

Trick or Trait

ピックアップ

個人的に注目する変更点を「ピックアップ」としてまとめました。 全ての変更点を網羅したリストは変更点リストをご覧ください。

Iterator::chainがフリー関数になった

Iterator::chainがフリー関数化され、std::iter::chainとして使えるようになりました。 これは2つのイテレータ化可能な値を受け取り、それらを連結したイテレータを返します。

Iterator::chainだと値を先にイテレータ化しておく必要があり、 2つの値を等価に扱いたいのに書き方が異なってしまうという非対称性が美しくありませんでした。 std::iter::chainでは2つの値で扱い方を統一できて読みやすくなります。

std::iter::zipIterator::zipのような関係ですね。

fn main() {
    // Rust 1.90までは値をイテレータ化してからchainを呼び出す必要があった
    let vec1 = vec![1, 2, 3];
    let vec2 = vec![4, 5, 6];
    for v in vec1.into_iter().chain(vec2) {
        println!("{v}");
    }
    // あるいはemptyにchainするという手法も使えた
    let vec1 = vec![1, 2, 3];
    let vec2 = vec![4, 5, 6];
    for v in std::iter::empty().chain(vec1).chain(vec2) {
        println!("{v}");
    }

    // Rust 1.91からは明示的なイテレータ化が不要になり少し読みやすくなる
    let vec1 = vec![1, 2, 3];
    let vec2 = vec![4, 5, 6];
    for v in std::iter::chain(vec1, vec2) {
        println!("{v}");
    }
}

ARM64版Windowsでの動作が保証されるようになった

ARM64版Windowsのターゲットであるaarch64-pc-windows-msvcがティア1に昇格しました。 これまではティア2であり、コンパイラ等がビルドされることは保証されていましたが、その動作までは保証されていませんでした。 ティア1に昇格したことで動作が保証されるようになり、安心して使えるようになりました。

ローカル変数からのdanglingポインタが警告されるようになった

関数の戻り型がポインタであるとき、その関数から返すポインタがローカル変数を指している場合に警告が出るようになりました。

// warning: a dangling pointer will be produced because the local variable `x` will be dropped
fn hoge() -> *const i32 {
//           ---------- return type of the function is `*const i32`
    let x = 42;
//      - `x` is part the function and will be dropped at the end of the function
    &x
}

安定化されたAPIのドキュメント

安定化されたAPIのドキュメントを独自に訳して紹介します。リストだけ見たい方は安定化されたAPIをご覧ください。

Path::file_prefix

原典

impl Path {
    #[stable(feature = "path_file_prefix", since = "1.91.0")]
    #[must_use]
    pub fn file_prefix(&self) -> Option<&OsStr>
    { /* 実装は省略 */ }
}

ファイル名の接頭部分を取り出す。

接頭部分とは次の通り。

  • ファイル名が存在しない場合はNone
  • ファイル名に.が含まれていない場合はファイル名全体
  • ファイル名の2文字目以降で最初に現れる.より前の部分
  • ファイル名が.で始まり、かつ他に.が含まれていない場合はファイル名全体
  • ファイル名が.で始まる場合、2つ目の.より前の部分

サンプル

use std::path::Path;

assert_eq!("hoge", Path::new("hoge.rs").file_prefix().unwrap());
assert_eq!("hoge", Path::new("hoge.tar.gz").file_prefix().unwrap());
assert_eq!(".config", Path::new(".config").file_prefix().unwrap());
assert_eq!(".config", Path::new(".config.toml").file_prefix().unwrap());

参考

このメソッドはPath::file_stemと似ているが、そちらはファイル名の最後の.より前の部分を取り出す。

AtomicPtr::fetch_ptr_add

原典

#[cfg(target_has_atomic_load_store = "ptr")]
impl<T> AtomicPtr<T> {
    #[inline]
    #[cfg(target_has_atomic = "ptr")]
    #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T
    { /* 実装は省略 */ }
}

ポインタの値をvalだけ(Tの単位で)加算し、加算前のポインタを返す。

これはwrapping_addによりptr = ptr.wrapping_add(val);を原子的に行うのと同じである。

このメソッドはTの単位で動作するため、size_of::<T>()の倍数でない量でポインタをずらすことはできない。 場合によってはこれは不便であるため、故意にずれたポインタを扱いたい場合はfetch_byte_addを使うと良い。

fetch_ptr_addは操作のメモリ順序を指定するOrdering引数を取る。すべての順序指定が可能である。 なお、Acquireを使うとこの操作の格納部分はRelaxedになり、Releaseを使うと読み出し部分がRelaxedになる。

注意:このメソッドはAtomicPtrでの原子操作ができるプラットフォームでのみ利用できる。

サンプル

use core::sync::atomic::{AtomicPtr, Ordering};

let atom = AtomicPtr::<i64>::new(core::ptr::null_mut());
assert_eq!(atom.fetch_ptr_add(1, Ordering::Relaxed).addr(), 0);
// 注意:`size_of::<i64>()`の単位
assert_eq!(atom.load(Ordering::Relaxed).addr(), 8);

AtomicPtr::fetch_ptr_sub

原典

#[cfg(target_has_atomic_load_store = "ptr")]
impl<T> AtomicPtr<T> {
    #[inline]
    #[cfg(target_has_atomic = "ptr")]
    #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T
    { /* 実装は省略 */ }
}

ポインタのアドレスをvalだけ(Tの単位で)減算し、減算前のポインタを返す。

これはwrapping_subによりptr = ptr.wrapping_sub(val);を原子的に実行するのと同じである。

このメソッドはTの単位で動作するため、size_of::<T>()の倍数でない量でポインタをずらすことはできない。 場合によってはこれは不便であるため、故意にずれたポインタを扱いたい場合はfetch_byte_subを使うと良い。

fetch_ptr_subは操作のメモリ順序を指定するOrdering引数を取る。すべての順序指定が可能である。 なお、Acquireを使うとこの操作の格納部分はRelaxedになり、Releaseを使うと読み出し部分がRelaxedになる。

注意:このメソッドはAtomicPtrでの原子操作ができるプラットフォームでのみ利用できる。

サンプル

use core::sync::atomic::{AtomicPtr, Ordering};

let array = [1i32, 2i32];
let atom = AtomicPtr::new(array.as_ptr().wrapping_add(1) as *mut _);

assert!(core::ptr::eq(
    atom.fetch_ptr_sub(1, Ordering::Relaxed),
    &array[1],
));
assert!(core::ptr::eq(atom.load(Ordering::Relaxed), &array[0]));

AtomicPtr::fetch_byte_add

原典

#[cfg(target_has_atomic_load_store = "ptr")]
impl<T> AtomicPtr<T> {
    #[inline]
    #[cfg(target_has_atomic = "ptr")]
    #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T
    { /* 実装は省略 */ }
}

ポインタのアドレスをvalバイト分だけ加算し、加算前のポインタを返す。

これはwrapping_byte_addによりptr = ptr.wrapping_byte_add(val)を原子的に実行するのと同じである。

fetch_byte_addは操作のメモリ順序を指定するOrdering引数を取る。すべての順序指定が可能である。 なお、Acquireを使うとこの操作の格納部分はRelaxedになり、Releaseを使うと読み出し部分がRelaxedになる。

注意:このメソッドはAtomicPtrでの原子操作ができるプラットフォームでのみ利用できる。

サンプル

use core::sync::atomic::{AtomicPtr, Ordering};

let atom = AtomicPtr::<i64>::new(core::ptr::null_mut());
assert_eq!(atom.fetch_byte_add(1, Ordering::Relaxed).addr(), 0);
// 注意:`size_of::<i64>()`単位ではなくバイト単位
assert_eq!(atom.load(Ordering::Relaxed).addr(), 1);

AtomicPtr::fetch_byte_sub

原典

#[cfg(target_has_atomic_load_store = "ptr")]
impl<T> AtomicPtr<T> {
    #[inline]
    #[cfg(target_has_atomic = "ptr")]
    #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T
    { /* 実装は省略 */ }
}

ポインタのアドレスからvalバイト分だけ減算し、減算前のポインタを返す。

これはwrapping_byte_subによりptr = ptr.wrapping_byte_sub(val)を原子的に実行するのと同じである。

fetch_byte_subは操作のメモリ順序を指定するOrdering引数を取る。すべての順序指定が可能である。 なお、Acquireを使うとこの操作の格納部分はRelaxedになり、Releaseを使うと読み出し部分がRelaxedになる。

注意:このメソッドはAtomicPtrでの原子操作ができるプラットフォームでのみ利用できる。

サンプル

use core::sync::atomic::{AtomicPtr, Ordering};

let mut arr = [0i64, 1];
let atom = AtomicPtr::<i64>::new(&raw mut arr[1]);
assert_eq!(atom.fetch_byte_sub(8, Ordering::Relaxed).addr(), (&raw const arr[1]).addr());
assert_eq!(atom.load(Ordering::Relaxed).addr(), (&raw const arr[0]).addr());

AtomicPtr::fetch_or

原典

#[cfg(target_has_atomic_load_store = "ptr")]
impl<T> AtomicPtr<T> {
    #[inline]
    #[cfg(target_has_atomic = "ptr")]
    #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T
    { /* 実装は省略 */ }
}

アドレス部分に対して現在のポインタと引数valでビット単位の「論理和」演算を行い、 現ポインタと結果アドレスの由来を持つポインタを格納する。

これはmap_addrによりptr = ptr.map_addr(|a| a | val)を原子的に実行するのと同じである。 この操作はタグ付きポインタの仕組みでタグビットを原子的に設定することに使える。

警告:この操作は以前の値を返す。由来を失わずに格納された値を計算したい場合はmap_addrを使うと良い。 例:a.fetch_or(val).map_addr(|a| a | val)

fetch_orは操作のメモリ順序を指定するOrdering引数を取る。すべての順序指定が可能である。 なお、Acquireを使うとこの操作の格納部分はRelaxedになり、Releaseを使うと読み出し部分がRelaxedになる。

注意:このメソッドはAtomicPtrでの原子操作ができるプラットフォームでのみ利用できる。

このAPIとその仕様は厳密な由来Strict Provenance実験の一部である。詳細はptrモジュールのドキュメントを参照。

サンプル

use core::sync::atomic::{AtomicPtr, Ordering};

let pointer = &mut 3i64 as *mut i64;

let atom = AtomicPtr::<i64>::new(pointer);
// ポインタの最下位ビットをタグ付け
assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 0);
// 抽出してタグ解除
let tagged = atom.load(Ordering::Relaxed);
assert_eq!(tagged.addr() & 1, 1);
assert_eq!(tagged.map_addr(|p| p & !1), pointer);

AtomicPtr::fetch_and

原典

#[cfg(target_has_atomic_load_store = "ptr")]
impl<T> AtomicPtr<T> {
    #[inline]
    #[cfg(target_has_atomic = "ptr")]
    #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T
    { /* 実装は省略 */ }
}

アドレス部分に対して現在のポインタと引数valでビット単位の「論理積」演算を行い、 現ポインタと結果アドレスの由来を持つポインタを格納する。

これはmap_addrによりptr = ptr.map_addr(|a| a & val)を原子的に実行するのと同じである。 この操作はタグ付きポインタの仕組みでタグビットを原子的に解除することに使える。

警告:この操作は以前の値を返す。由来を失わずに格納された値を計算したい場合はmap_addrを使うと良い。 例:a.fetch_and(val).map_addr(|a| a & val)

fetch_andは操作のメモリ順序を指定するOrdering引数を取る。すべての順序指定が可能である。 なお、Acquireを使うとこの操作の格納部分はRelaxedになり、Releaseを使うと読み出し部分がRelaxedになる。

注意:このメソッドはAtomicPtrでの原子操作ができるプラットフォームでのみ利用できる。

このAPIとその仕様は厳密な由来Strict Provenance実験の一部である。詳細はptrモジュールのドキュメントを参照。

サンプル

use core::sync::atomic::{AtomicPtr, Ordering};

let pointer = &mut 3i64 as *mut i64;
// タグ付きポインタ
let atom = AtomicPtr::<i64>::new(pointer.map_addr(|a| a | 1));
assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 1);
// タグ解除し、以前タグ付けされていたポインタを抽出
let untagged = atom.fetch_and(!1, Ordering::Relaxed)
    .map_addr(|a| a & !1);
assert_eq!(untagged, pointer);

AtomicPtr::fetch_xor

原典

#[cfg(target_has_atomic_load_store = "ptr")]
impl<T> AtomicPtr<T> {
    #[inline]
    #[cfg(target_has_atomic = "ptr")]
    #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T
    { /* 実装は省略 */ }
}

アドレス部分に対して現在のポインタと引数valでビット単位の「排他的論理和」演算を行い、 現ポインタと結果アドレスの由来を持つポインタを格納する。

これはmap_addrによりptr = ptr.map_addr(|a| a ^ val)を原子的に実行するのと同じである。 この操作はタグ付きポインタの仕組みでタグビットを原子的に反転することに使える。

警告:この操作は以前の値を返す。由来を失わずに格納された値を計算したい場合はmap_addrを使うと良い。 例:a.fetch_xor(val).map_addr(|a| a ^ val)

fetch_xorは操作のメモリ順序を指定するOrdering引数を取る。すべての順序指定が可能である。 なお、Acquireを使うとこの操作の格納部分はRelaxedになり、Releaseを使うと読み出し部分がRelaxedになる。

注意:このメソッドはAtomicPtrでの原子操作ができるプラットフォームでのみ利用できる。

このAPIとその仕様は厳密な由来Strict Provenance実験の一部である。詳細はptrモジュールのドキュメントを参照。

サンプル

use core::sync::atomic::{AtomicPtr, Ordering};

let pointer = &mut 3i64 as *mut i64;
let atom = AtomicPtr::<i64>::new(pointer);

// ポインタ上のタグビットを反転
atom.fetch_xor(1, Ordering::Relaxed);
assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1);

{integer}::strict_add

原典

impl u32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_add(self, rhs: Self) -> Self
    { /* 実装は省略 */ }
}

厳格な整数加算。self + rhsを計算するが、オーバーフローが発生した場合はパニックする。

パニック

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

サンプル

assert_eq!((u32::MAX - 2).strict_add(1), u32::MAX - 1);

次の例はオーバーフローによりパニックする。

let _ = (u32::MAX - 2).strict_add(3);

{integer}::strict_sub

原典

impl u32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_sub(self, rhs: Self) -> Self
    { /* 実装は省略 */ }
}

厳格な整数減算。self - rhsを計算するが、オーバーフローが発生した場合はパニックする。

パニック

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

サンプル

assert_eq!(1u32.strict_sub(1), 0);

次の例はオーバーフローによりパニックする。

let _ = 0u32.strict_sub(1);

{integer}::strict_mul

原典

impl u32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_mul(self, rhs: Self) -> Self
    { /* 実装は省略 */ }
}

厳格な整数乗算。self * rhsを計算するが、オーバーフローが発生した場合はパニックする。

パニック

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

サンプル

assert_eq!(5u32.strict_mul(1), 5);

次の例はオーバーフローによりパニックする。

let _ = u32::MAX.strict_mul(2);

{integer}::strict_div

原典

impl i32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_div(self, rhs: Self) -> Self
    { /* 実装は省略 */ }
}

厳格な整数除算。self / rhsを計算するが、オーバーフローが発生した場合はパニックする。

パニック

この関数はrhsがゼロの場合にパニックする。

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

オーバーフローが発生するのは符号付き型でMIN / -1を計算した場合のみである(MINはその型の最小値)。 これは-MINと同じで、その型で表現できないほど大きな正の値になる。

サンプル

assert_eq!((i32::MIN + 1).strict_div(-1), 2147483647);

次の例はオーバーフローによりパニックする。

let _ = i32::MIN.strict_div(-1);

次の例はゼロ除算によりパニックする。

let _ = (1i32).strict_div(0);

{integer}::strict_div_euclid

原典

impl i32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_div_euclid(self, rhs: Self) -> Self
    { /* 実装は省略 */ }
}

厳格なユークリッド除算。self.div_euclid(rhs)を計算するが、オーバーフローが発生した場合は必ずパニックする。

パニック

この関数はrhsがゼロの場合にパニックする。

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

オーバーフローが発生するのは符号付き型でMIN / -1を計算した場合のみである(MINはその型の最小値)。 これは-MINと同じで、その型で表現できないほど大きな正の値になる。

サンプル

assert_eq!((i32::MIN + 1).strict_div_euclid(-1), 2147483647);

次の例はオーバーフローによりパニックする。

let _ = i32::MIN.strict_div_euclid(-1);

次の例はゼロ除算によりパニックする。

let _ = (1i32).strict_div_euclid(0);

{integer}::strict_rem

原典

impl i32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_rem(self, rhs: Self) -> Self
    { /* 実装は省略 */ }
}

厳格な剰余演算。self % rhsを計算するが、除算でオーバーフローが発生した場合はパニックする。

パニック

この関数はrhsがゼロの場合にパニックする。

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

オーバーフローが発生するのは、符号付き型でMIN / -1となるx % yを計算した場合のみである(MINはその型の最小値)。 これは実装上の制約により無効な値となる。

サンプル

assert_eq!(5i32.strict_rem(2), 1);

次の例はゼロ除算によりパニックする。

let _ = 5i32.strict_rem(0);

次の例はオーバーフローによりパニックする。

let _ = i32::MIN.strict_rem(-1);

{integer}::strict_rem_euclid

原典

impl i32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_rem_euclid(self, rhs: Self) -> Self
    { /* 実装は省略 */ }
}

厳格なユークリッド剰余演算。self.rem_euclid(rhs)を計算するが、 除算でオーバーフローが発生した場合はパニックする。

パニック

この関数はrhsがゼロの場合にパニックする。

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

オーバーフローが発生するのは、符号付き型でMIN / -1となるx % yを計算した場合のみである(MINはその型の最小値)。 これは実装上の制約により無効な値となる。

サンプル

assert_eq!(5i32.strict_rem_euclid(2), 1);

次の例はゼロ除算によりパニックする。

let _ = 5i32.strict_rem_euclid(0);

次の例はオーバーフローによりパニックする。

let _ = i32::MIN.strict_rem_euclid(-1);

{integer}::strict_neg

原典

impl u32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_neg(self) -> Self
    { /* 実装は省略 */ }
}

厳格な否定演算。-selfを計算するが、self == 0でない場合はパニックする。

正の整数を否定するとオーバーフローすることに注意。

パニック

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

サンプル

assert_eq!(0u32.strict_neg(), 0);

次の例はオーバーフローによりパニックする。

let _ = 1u32.strict_neg();

{integer}::strict_shl

原典

impl u32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_shl(self, rhs: u32) -> Self
    { /* 実装は省略 */ }
}

厳格な左シフト演算。self << rhsを計算するが、rhsselfのビット数以上の場合はパニックする。

パニック

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

サンプル

assert_eq!(0x1u32.strict_shl(4), 0x10);

次の例はオーバーフローによりパニックする。

let _ = 0x10u32.strict_shl(129);")]

{integer}::strict_shr

原典

impl u32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_shr(self, rhs: u32) -> Self
    { /* 実装は省略 */ }
}

厳格な右シフト演算。self >> rhsを計算するが、rhsselfのビット数以上の場合はパニックする。

パニック

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

サンプル

assert_eq!(0x10u32.strict_shr(4), 0x1);

次の例はオーバーフローによりパニックする。

let _ = 0x10u32.strict_shr(129);

{integer}::strict_pow

原典

impl u32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_pow(self, mut exp: u32) -> Self
    { /* 実装は省略 */ }
}

厳格なべき乗。self.pow(exp)を計算するが、オーバーフローが発生した場合はパニックする。

パニック

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

サンプル

assert_eq!(2u32.strict_pow(5), 32);

次の例はオーバーフローによりパニックする。

let _ = u32::MAX.strict_pow(2);

i{N}::strict_add_unsigned

原典

impl i32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_add_unsigned(self, rhs: u32) -> Self
    { /* 実装は省略 */ }
}

厳格な符号なし整数との加算。self + rhsを計算するが、オーバーフローが発生した場合はパニックする。

パニック

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

サンプル

assert_eq!(1i32.strict_add_unsigned(2), 3);

次の例はオーバーフローによりパニックする。

let _ = (i32::MAX - 2).strict_add_unsigned(3);

i{N}::strict_sub_unsigned

原典

impl i32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_sub_unsigned(self, rhs: u32) -> Self
    { /* 実装は省略 */ }
}

厳格な符号なし整数との減算。self - rhsを計算するが、オーバーフローが発生した場合はパニックする。

パニック

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

サンプル

assert_eq!(1i32.strict_sub_unsigned(2), -1);

次の例はオーバーフローによりパニックする。

let _ = (i32::MIN + 2).strict_sub_unsigned(3);

i{N}::strict_abs

原典

impl i32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_abs(self) -> Self
    { /* 実装は省略 */ }
}

厳格な絶対値演算。self.abs()を計算するが、self == MINの場合はパニックする。

パニック

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

サンプル

assert_eq!((-5i32).strict_abs(), 5);

次の例はオーバーフローによりパニックする。

let _ = i32::MIN.strict_abs();

u{N}::strict_add_signed

原典

impl u32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_add_signed(self, rhs: $SignedT) -> Self
    { /* 実装は省略 */ }
}

厳格な符号付き整数との加算。self + rhsを計算するが、オーバーフローが発生した場合はパニックする。

パニック

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

サンプル

assert_eq!(1u32.strict_add_signed(2), 3);

次の例はオーバーフローによりパニックする。

let _ = 1u32.strict_add_signed(-2);
let _ = (u32::MAX - 2).strict_add_signed(3);

u{N}::strict_sub_signed

原典

impl u32 {
    #[stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[track_caller]
    pub const fn strict_sub_signed(self, rhs: $SignedT) -> Self
    { /* 実装は省略 */ }
}

厳格な符号付き整数との減算。self - rhsを計算するが、オーバーフローが発生した場合はパニックする。

パニック

オーバーフローの挙動

この関数はオーバーフロー検査の有無に関わらず、オーバーフローが発生した場合は必ずパニックする。

サンプル

assert_eq!(3u32.strict_sub_signed(2), 1);

次の例はオーバーフローによりパニックする。l

let _ = 1u32.strict_sub_signed(2);
let _ = (u32::MAX).strict_sub_signed(-1);

PanicHookInfo::payload_as_str

原典

impl<'a> PanicHookInfo<'a> {
    #[must_use]
    #[inline]
    #[stable(feature = "panic_payload_as_str", since = "1.91.0")]
    pub fn payload_as_str(&self) -> Option<&str>
    { /* 実装は省略 */ }
}

パニックに関連付けられたペイロードが文字列である場合、それを返す。

ペイロード&'static str型またはString型の場合に値を返す。

Rust 2021以降でpanic!()マクロを呼び出した場合、常にpayload_as_strSomeを返すペイロードになる。

[panic_any]の呼び出し(またはRust 2018以前でpanic!(x)のxが文字列以外の場合)だけが、 payload_as_strNoneを返すペイロードになるだろう。

サンプル

std::panic::set_hook(Box::new(|panic_info| {
    if let Some(s) = panic_info.payload_as_str() {
        println!("パニック発生:{s:?}");
    } else {
        println!("パニック発生");
    }
}));

panic!("普通のパニック");

core::iter::chain

原典

#[stable(feature = "iter_chain", since = "1.91.0")]
pub fn chain<A, B>(a: A, b: B) -> Chain<A::IntoIter, B::IntoIter>
where
    A: IntoIterator,
    B: IntoIterator<Item = A::Item>,
{ /* 実装は省略 */ }

引数をイテレータに変換し、連鎖したイテレータにする。

Iterator::chainも参照されたい。

サンプル

use std::iter::chain;

let a = [1, 2, 3];
let b = [4, 5, 6];

let mut iter = chain(a, b);

assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.next(), Some(4));
assert_eq!(iter.next(), Some(5));
assert_eq!(iter.next(), Some(6));
assert_eq!(iter.next(), None);

u{N}::checked_signed_diff

原典

impl u16 {
    #[stable(feature = "unsigned_signed_diff", since = "1.91.0")]
    #[rustc_const_stable(feature = "unsigned_signed_diff", since = "1.91.0")]
    #[inline]
    pub const fn checked_signed_diff(self, rhs: Self) -> Option<$SignedT>
    { /* 実装は省略 */ }
}

検査付き整数減算。self - rhsを計算した結果がi16に収まる場合はその値を返し、オーバーフローした場合はNoneを返す。

サンプル

assert_eq!(10u16.checked_signed_diff(2), Some(8));
assert_eq!(2u16.checked_signed_diff(10), Some(-8));
assert_eq!(u16::MAX.checked_signed_diff(i16::MAX as u16), None);
assert_eq!((i16::MAX as u16).checked_signed_diff(u16::MAX), Some(i16::MIN));
assert_eq!((i16::MAX as u16 + 1).checked_signed_diff(0), None);
assert_eq!(u16::MAX.checked_signed_diff(u16::MAX), Some(0));

core::array::repeat

原典

#[inline]
#[must_use = "cloning is often expensive and is not expected to have side effects"]
#[stable(feature = "array_repeat", since = "1.91.0")]
pub fn repeat<T: Clone, const N: usize>(val: T) -> [T; N]
{ /* 実装は省略 */ }

値を繰り返し複製して型[T; N]の配列を作成する。

これは[val; N]と同じだが、Copyを実装していない型でも使える。

与えた値は結果の配列の要素として使われ、残りのN-1個は複製して埋める。Nがゼロの場合は値が破棄される。

サンプル

Stringを複数作成する。

use std::array;

let string = "おいすー".to_string();
let strings = array::repeat(string);
assert_eq!(strings, ["おいすー", "おいすー"]);

PathBuf::add_extension

原典

impl PathBuf {
    #[stable(feature = "path_add_extension", since = "1.91.0")]
    pub fn add_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool
    { /* 実装は省略 */ }
}

拡張子self.extensionextensionを追加する。

self.file_nameNoneの場合はfalseを返して何もしない。 そうでなければ拡張子を更新してtrueを返す。

パニック

渡した拡張子にパス区切り文字が含まれている場合はパニックする(is_separator参照)。

警告

追加するextensionはドットを含んでもよく、その場合も全体が使われるが、 self.extensionに反映されるのは最後のドット以降の部分だけである。

下記の例を参照。

サンプル

use std::path::{Path, PathBuf};

let mut p = PathBuf::from("/feel/the");

p.add_extension("formatted");
assert_eq!(Path::new("/feel/the.formatted"), p.as_path());

p.add_extension("dark.side");
assert_eq!(Path::new("/feel/the.formatted.dark.side"), p.as_path());

p.set_extension("cookie");
assert_eq!(Path::new("/feel/the.formatted.dark.cookie"), p.as_path());

p.set_extension("");
assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path());

p.add_extension("");
assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path());

Path::with_added_extension

原典

impl Path {
    #[stable(feature = "path_add_extension", since = "1.91.0")]
    pub fn with_added_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf
    { /* 実装は省略 */ }
}

selfに拡張子を追加し、所有版PathBufを作成する。

PathBuf::add_extensionも参照されたい。

サンプル

use std::path::{Path, PathBuf};

let path = Path::new("foo.rs");
assert_eq!(path.with_added_extension("txt"), PathBuf::from("foo.rs.txt"));

let path = Path::new("foo.tar.gz");
assert_eq!(path.with_added_extension(""), PathBuf::from("foo.tar.gz"));
assert_eq!(path.with_added_extension("xz"), PathBuf::from("foo.tar.gz.xz"));
assert_eq!(path.with_added_extension("").with_added_extension("txt"), PathBuf::from("foo.tar.gz.txt"));

Duration::from_mins

原典

impl Duration {
    #[stable(feature = "duration_constructors_lite", since = "1.91.0")]
    #[rustc_const_stable(feature = "duration_constructors_lite", since = "1.91.0")]
    #[must_use]
    #[inline]
    pub const fn from_mins(mins: u64) -> Duration
    { /* 実装は省略 */ }
}

分を指定して新しいDurationを作成する。

パニック

分数がDurationのサイズを超える場合はパニックする。

サンプル

use std::time::Duration;

let duration = Duration::from_mins(10);

assert_eq!(10 * 60, duration.as_secs());
assert_eq!(0, duration.subsec_nanos());

Duration::from_hours

原典

impl Duration {
    #[stable(feature = "duration_constructors_lite", since = "1.91.0")]
    #[rustc_const_stable(feature = "duration_constructors_lite", since = "1.91.0")]
    #[must_use]
    #[inline]
    pub const fn from_hours(hours: u64) -> Duration
    { /* 実装は省略 */ }
}

時を指定して新しいDurationを作成する。

パニック

時がDurationのサイズを超える場合はパニックする。

サンプル

use std::time::Duration;

let duration = Duration::from_hours(6);

assert_eq!(6 * 60 * 60, duration.as_secs());
assert_eq!(0, duration.subsec_nanos());

Ipv4Addr::from_octets

原典

impl Ipv4Addr {
    #[stable(feature = "ip_from", since = "1.91.0")]
    #[rustc_const_stable(feature = "ip_from", since = "1.91.0")]
    #[must_use]
    #[inline]
    pub const fn from_octets(octets: [u8; 4]) -> Ipv4Addr
    { /* 実装は省略 */ }
}

4要素のバイト配列からIpv4Addrを作成する。

サンプル

use std::net::Ipv4Addr;

let addr = Ipv4Addr::from_octets([13u8, 12u8, 11u8, 10u8]);
assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);

Ipv6Addr::from_octets

原典

impl Ipv6Addr {
    #[stable(feature = "ip_from", since = "1.91.0")]
    #[rustc_const_stable(feature = "ip_from", since = "1.91.0")]
    #[must_use]
    #[inline]
    pub const fn from_octets(octets: [u8; 16]) -> Ipv6Addr
    { /* 実装は省略 */ }
}

16要素のバイト配列からIpv6Addrを作成する。

サンプル

use std::net::Ipv6Addr;

let addr = Ipv6Addr::from_octets([
    0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8,
    0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8,
]);
assert_eq!(
    Ipv6Addr::new(
        0x1918, 0x1716, 0x1514, 0x1312,
        0x1110, 0x0f0e, 0x0d0c, 0x0b0a,
    ),
    addr
);

Ipv6Addr::from_segments

原典

impl Ipv6Addr {
    #[stable(feature = "ip_from", since = "1.91.0")]
    #[rustc_const_stable(feature = "ip_from", since = "1.91.0")]
    #[must_use]
    #[inline]
    pub const fn from_segments(segments: [u16; 8]) -> Ipv6Addr
    { /* 実装は省略 */ }
}

8要素の16ビット配列からIpv6Addrを作成する。

サンプル

use std::net::Ipv6Addr;

let addr = Ipv6Addr::from_segments([
    0x20du16, 0x20cu16, 0x20bu16, 0x20au16,
    0x209u16, 0x208u16, 0x207u16, 0x206u16,
]);
assert_eq!(
    Ipv6Addr::new(
        0x20d, 0x20c, 0x20b, 0x20a,
        0x209, 0x208, 0x207, 0x206,
    ),
    addr
);

Cell::as_array_of_cells

原典

impl<T, const N: usize> Cell<[T; N]> {
    #[stable(feature = "as_array_of_cells", since = "1.91.0")]
    #[rustc_const_stable(feature = "as_array_of_cells", since = "1.91.0")]
    pub const fn as_array_of_cells(&self) -> &[Cell<T>; N]
    { /* 実装は省略 */ }
}

&Cell<[T; N]>から&[Cell<T>; N]を返す。

サンプル

use std::cell::Cell;

let mut array: [i32; 3] = [1, 2, 3];
let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array);
let array_cell: &[Cell<i32>; 3] = cell_array.as_array_of_cells();

u{N}::carrying_add

原典

impl u64 {
    #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")]
    #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool)
    { /* 実装は省略 */ }
}

selfrhscarryを加算し、和と出力キャリーを含むタプルを(この順序で)返す。

2つの整数オペランドとキャリー・イン・ビットの「三元加算(ternary addition)」を実行し、 結果の整数とキャリー・アウト・ビットを返す。これにより複数の加算を連鎖してより広い加算を行うことができ、 巨大整数の加算にも役立つ。

これは電子回路でいう64ビットの「全加算器」と考えることができる。

入力キャリーが偽の場合、このメソッドはoverflowing_addと同等であり、 出力キャリーはオーバーフローフラグと一致する。なお符号なし整数ではキャリーとオーバーフローは似ているが、 符号付き整数では異なる。

サンプル

//    3  MAX    (a = 3 × 2^64 + 2^64 - 1)
// +  5    7    (b = 5 × 2^64 + 7)
// ---------
//    9    6    (sum = 9 × 2^64 + 6)

let (a1, a0): (u64, u64) = (3, u64::MAX);
let (b1, b0): (u64, u64) = (5, 7);
let carry0 = false;

let (sum0, carry1) = a0.carrying_add(b0, carry0);
assert_eq!(carry1, true);
let (sum1, carry2) = a1.carrying_add(b1, carry1);
assert_eq!(carry2, false);

assert_eq!((sum1, sum0), (9, 6));

u{N}::borrowing_sub

原典

impl u64 {
    #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")]
    #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool)
    { /* 実装は省略 */ }
}

self - rhs - borrowを計算し、差分と出力ボローを含むタプルを返す。

2つの整数オペランドとボロー・イン・ビットを引いて「三元減算(ternary subtraction)」を行い、 結果の整数とボロー・アウト・ビットを返す。 これにより複数の減算を連鎖してより広い減算を行うことができ、巨大整数の減算にも役立つ。

サンプル

//    9    6    (a = 9 × 2^64 + 6)
// -  5    7    (b = 5 × 2^64 + 7)
// ---------
//    3  MAX    (diff = 3 × 2^64 + 2^64 - 1)

let (a1, a0): (u64, u64) = (9, 6);
let (b1, b0): (u64, u64) = (5, 7);
let borrow0 = false;

let (diff0, borrow1) = a0.borrowing_sub(b0, borrow0);
assert_eq!(borrow1, true);
let (diff1, borrow2) = a1.borrowing_sub(b1, borrow1);
assert_eq!(borrow2, false);

assert_eq!((diff1, diff0), (3, u64::MAX));

u{N}::carrying_mul

原典

impl u64 {
    #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")]
    #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    pub const fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self)
    { /* 実装は省略 */ }
}

self * rhs + carryの「完全な乗算」を行う。オーバーフローせずに計算できる。

結果の下位(ラップアラウンド)ビットと上位(オーバーフロー)ビットを2つの値として(この順序で)返す。

余分な値を加算できる「長い乗算」を行い、追加のオーバーフロー値を返すことがある。 これにより複数の乗算を連鎖してより大きな値を表現する「巨大整数」を作ることができる。

もし加算も必要ならSelf::carrying_mul_addを使うと良い。

サンプル

この例は整数型全体で共通なのでu32型を使っていることに注意。

assert_eq!(5u32.carrying_mul(2, 0), (10, 0));
assert_eq!(5u32.carrying_mul(2, 10), (20, 0));
assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2));
assert_eq!(1_000_000_000u32.carrying_mul(10, 10), (1410065418, 2));
assert_eq!(u64::MAX.carrying_mul(u64::MAX, u64::MAX), 0, u64::MAX));

これは、ネイティブ型より広い型でスカラー乗算を実装する際に必要な基本操作である。

#![feature(bigint_helper_methods)]
fn scalar_mul_eq(little_endian_digits: &mut Vec<u16>, multiplicand: u16) {
    let mut carry = 0;
    for d in little_endian_digits.iter_mut() {
        (*d, carry) = d.carrying_mul(multiplicand, carry);
    }
    if carry != 0 {
        little_endian_digits.push(carry);
    }
}

let mut v = vec![10, 20];
scalar_mul_eq(&mut v, 3);
assert_eq!(v, [30, 60]);

assert_eq!(0x87654321_u64 * 0xFEED, 0x86D3D159E38D);
let mut v = vec![0x4321, 0x8765];
scalar_mul_eq(&mut v, 0xFEED);
assert_eq!(v, [0xE38D, 0xD159, 0x86D3]);

carryがゼロの際はoverflowing_mulと似ているが、 オーバーフローが起きたかどうかだけでなくオーバーフローの値そのものを返す点が異なる。

#![feature(bigint_helper_methods)]
let r = u8::carrying_mul(7, 13, 0);
assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(7, 13));
let r = u8::carrying_mul(13, 42, 0);
assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(13, 42));

返されたタプルの第一要素は、 wrapping_mulwrapping_addを組み合わせた値と一致する。

#![feature(bigint_helper_methods)]
assert_eq!(
    789_u16.carrying_mul(456, 123).0,
    789_u16.wrapping_mul(456).wrapping_add(123),
);

u{N}::carrying_mul_add

原典

impl u64 {
    #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")]
    #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    pub const fn carrying_mul_add(self, rhs: Self, carry: Self, add: Self) -> (Self, Self)
    { /* 実装は省略 */ }
}

self * rhs + carry1 + carry2の「完全な乗算」を行う。

結果の下位(ラップアラウンド)ビットと上位(オーバーフロー)ビットを2つの値として(この順序で)返す。

この計算はオーバーフローしない。二倍幅の結果は最大値でもちょうど収まる。 これは十進法で「9 × 9 + 9 + 9 = 81 + 18 = 99 = 9×10⁰ + 9×10¹ = 10² - 1」と同じである。

余分な値を加算できる「長い乗算」を行い、追加のオーバーフロー値を返すことがある。 これにより複数の乗算を連鎖してより大きな値を表現する「巨大整数」を作ることができる。

加算が不要ならSelf::carrying_mulを使うと良い。

サンプル

この例は整数型全体で共通なのでu32型を使っていることに注意。

assert_eq!(5u32.carrying_mul_add(2, 0, 0), (10, 0));
assert_eq!(5u32.carrying_mul_add(2, 10, 10), (30, 0));
assert_eq!(1_000_000_000u32.carrying_mul_add(10, 0, 0), (1410065408, 2));
assert_eq!(1_000_000_000u32.carrying_mul_add(10, 10, 10), (1410065428, 2));
assert_eq!(u64::MAX.carrying_mul_add(u64::MAX, u64::MAX, u64::MAX), (u64::MAX, u64::MAX));

これは「筆算式」のO(n²)乗算における、桁ごとの基本操作である。

この例は整数型全体で共通なので、説明のためu8型を使っていることに注意。

fn quadratic_mul<const N: usize>(a: [u8; N], b: [u8; N]) -> [u8; N] {
    let mut out = [0; N];
    for j in 0..N {
        let mut carry = 0;
        for i in 0..(N - j) {
            (out[j + i], carry) = u8::carrying_mul_add(a[i], b[j], out[j + i], carry);
        }
    }
    out
}

// -1 * -1 == 1
assert_eq!(quadratic_mul([0xFF; 3], [0xFF; 3]), [1, 0, 0]);

assert_eq!(u32::wrapping_mul(0x9e3779b9, 0x7f4a7c15), 0xcffc982d);
assert_eq!(
    quadratic_mul(u32::to_le_bytes(0x9e3779b9), u32::to_le_bytes(0x7f4a7c15)),
    u32::to_le_bytes(0xcffc982d)
);

BTreeMap::extract_if

原典

impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
    #[stable(feature = "btree_extract_if", since = "1.91.0")]
    pub fn extract_if<F, R>(&mut self, range: R, pred: F) -> ExtractIf<'_, K, V, R, F, A>
    where
        K: Ord,
        R: RangeBounds<K>,
        F: FnMut(&K, &mut V) -> bool,
    { /* 実装は省略 */ }
}

指定した範囲の要素(キーと値の組)をキーの昇順で訪問しつつ、 クロージャで要素を削除するかどうか判定するイテレータを作成する。

クロージャtrueを返すとその要素は連想配列から削除されて返される。 クロージャfalseを返した場合やパニックした場合は要素は連想配列に残り、イテレーターから返されない。

このイテレータでは、削除するかどうかに関わらずクロージャ内で各要素の値を変更できる。

返されたExtractIfについて、使い切らなかったり途中でループを止めるなどして破棄した場合、残った要素は保持される。 イテレータが不要ならば述語関数を否定した形でretainを使うと良い。

サンプル

use std::collections::BTreeMap;

// 元の連想配列を再利用しながら偶数キーと奇数キーに分割する
let mut map: BTreeMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
let evens: BTreeMap<_, _> = map.extract_if(.., |k, _v| k % 2 == 0).collect();
let odds = map;
assert_eq!(evens.keys().copied().collect::<Vec<_>>(), [0, 2, 4, 6]);
assert_eq!(odds.keys().copied().collect::<Vec<_>>(), [1, 3, 5, 7]);

// 元の連想配列を再利用しながら下半分と上半分に分割する
let mut map: BTreeMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
let low: BTreeMap<_, _> = map.extract_if(0..4, |_k, _v| true).collect();
let high = map;
assert_eq!(low.keys().copied().collect::<Vec<_>>(), [0, 1, 2, 3]);
assert_eq!(high.keys().copied().collect::<Vec<_>>(), [4, 5, 6, 7]);

BTreeSet::extract_if

原典

impl<T, A: Allocator + Clone> BTreeSet<T, A> {
    #[stable(feature = "btree_extract_if", since = "1.91.0")]
    pub fn extract_if<F, R>(&mut self, range: R, pred: F) -> ExtractIf<'_, T, R, F, A>
    where
        T: Ord,
        R: RangeBounds<T>,
        F: FnMut(&T) -> bool,
    { /* 実装は省略 */ }
}

指定した範囲の要素を昇順で訪問し、クロージャで要素を削除するかどうか判定するイテレータを作成する。

クロージャtrueを返すとその要素は集合から削除されて返される。 クロージャfalseを返した場合やパニックした場合は要素は集合に残り、イテレータから返されない。

返されたExtractIfについて、使い切らなかったり途中でループを止めるなどして破棄した場合、残った要素は保持される。 イテレータが不要ならば述語関数を否定した形でretainを使うと良い。

サンプル

use std::collections::BTreeSet;

// 元の集合を再利用しながら偶数と奇数に分割する
let mut set: BTreeSet<i32> = (0..8).collect();
let evens: BTreeSet<_> = set.extract_if(.., |v| v % 2 == 0).collect();
let odds = set;
assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![0, 2, 4, 6]);
assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7]);

// 元の集合を再利用しながら下半分と上半分に分割する
let mut set: BTreeSet<i32> = (0..8).collect();
let low: BTreeSet<_> = set.extract_if(0..4, |_v| true).collect();
let high = set;
assert_eq!(low.into_iter().collect::<Vec<_>>(), [0, 1, 2, 3]);
assert_eq!(high.into_iter().collect::<Vec<_>>(), [4, 5, 6, 7]);

str::ceil_char_boundary

原典

impl str {
    #[stable(feature = "round_char_boundary", since = "1.91.0")]
    #[rustc_const_stable(feature = "round_char_boundary", since = "1.91.0")]
    #[inline]
    pub const fn ceil_char_boundary(&self, index: usize) -> usize
    { /* 実装は省略 */ }
}

is_char_boundary(x)trueとなる、index以上の最も近いxを見つける。

indexが文字列の長さを超えている場合は、文字列の長さを返す。

このメソッドはfloor_char_boundaryの補完的な役割を持つ。詳細はそちらを参照。

サンプル

let s = "❤️🧡💛💚💙💜";
assert_eq!(s.len(), 26);
assert!(!s.is_char_boundary(13));

let closest = s.ceil_char_boundary(13);
assert_eq!(closest, 14);
assert_eq!(&s[..closest], "❤️🧡💛");

str::floor_char_boundary

原典

impl str {
    #[stable(feature = "round_char_boundary", since = "1.91.0")]
    #[rustc_const_stable(feature = "round_char_boundary", since = "1.91.0")]
    #[inline]
    pub const fn floor_char_boundary(&self, index: usize) -> usize
    { /* 実装は省略 */ }
}

is_char_boundary(x)trueとなる、index以下の最も近いxを見つける。

このメソッドは指定されたバイト数を超えないように文字列を切り詰めつつ、UTF-8として正しい文字列に保つのに役立つ。 ただしこれは文字単位で行われるため、基になる文字が分割されていなくても、書記素(grapheme)を見た目上分断することがある。 例えば、絵文字🧑‍🔬(科学者)を分割した結果🧑(人)だけが残る場合がある。

サンプル

let s = "❤️🧡💛💚💙💜";
assert_eq!(s.len(), 26);
assert!(!s.is_char_boundary(13));

let closest = s.floor_char_boundary(13);
assert_eq!(closest, 10);
assert_eq!(&s[..closest], "❤️🧡");

変更点リスト

言語

コンパイラ

プラットフォーム対応

Rustのティア付けされたプラットフォーム対応の詳細はPlatform Supportのページ(※訳注:英語)を参照

ライブラリ

安定化されたAPI

以下のAPIが定数文脈で使えるようになった。

Cargo

  • 🎉 build.build-dirを安定化。 この設定で中間生成物の保存先ディレクトリを指定できる。 これらの生成物はCargoやrustcがビルド時に作るものである。通常は利用者が直接触る必要はなく、 build-dir内のレイアウトは実装依存であり予告なく変更される可能性がある。 (設定ドキュメント) (ビルドキャッシュドキュメント#15833 #15840

  • --targetフラグとbuild.target設定で"host-tuple"という文字列を指定できるようになり、 ホストマシンのtarget tripleに自動で置き換えられるようになった。 #15838 #16003 #16032

Rustdoc

互換性メモ

Cargoの互換性メモ

  • build.build-dirが設定されている場合、cargo publish.crateのtarballを最終ビルド生成物として保持しなくなった。 これらのtarballは以前は誤って含まれていたが、今後は中間生成物扱いとなる。 .crateのtarballを最終生成物として得たい場合はcargo packageを使うこと。 将来のバージョンではbuild.build-dirの有無に関係なくこの変更が適用される予定。 #15910
  • Cargoの文言表示をrustcの診断スタイルに合わせるよう調整。 これによりCargoの一部の文言において端末色が変更される。 #15928
  • Cargoのbuild-dirの内部仕様に依存するツールやプロジェクトは、 build-dirのレイアウトを変更するユーザーでは動作しない可能性がある。 該当する場合、特に将来build-dirの既定の場所を変更する可能性(cargo#16147)を考慮し、 これらのケースを事前に十分テストすることを推奨する。 Cargoの内部仕様から移行できない場合、build-dirのレイアウト変更を準備しているため、具体的なユースケースについて知らせて欲しい。 (cargo#15010

内部の変更

これらの変更がユーザーに直接利益をもたらすわけではないものの、コンパイラ及び周辺ツール内部では重要なパフォーマンス改善をもたらす。

関連リンク

さいごに

次のリリースのRust 1.92は12/12(金)にリリースされる予定です。 Rust 1.92ではBTreeMapEntryinsert_entryが使えるようになるようです。

ライセンス表記

  • この記事はApache 2/MITのデュアルライセンスで公開されている公式リリースノート及びドキュメントから翻訳・追記をしています
  • 冒頭の画像中にはRust公式サイトで配布されているロゴを使用しており、 このロゴはRust財団によってCC-BYの下で配布されています
  • 冒頭の画像はいらすとやさんの画像を使っています。いつもありがとうございます



以上の内容はhttps://aznhe21.hatenablog.com/entry/2025/10/31/rust-1.91より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14