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


Rust 1.87を早めに深掘り

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

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

ピックアップ

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

Rustは今日で10周年

Rust 1.0は2015年5月16日にリリースされ、今日でなんと10周年です。 当時の言語機能を思い出してみると、基礎は変わらないものの、まるで別言語のように機能が足りていませんね。

匿名パイプが使えるようになった

外部プロセスとの通信に使える匿名パイプが使えるようになりました。

主には外部プロセスを起動するCommandと組み合わせて使うことが想定されているようで、 stdoutstderrに同じパイプを指定することで、標準入力と標準エラーを一緒に処理することができるようです。

その他にもチャネルの代わりに匿名パイプを使うことで、スレッド間の通信をReadWriteトレイトを通して行うという使い方もできそうです。

Vecなどから値を抜き取ってイテレーターとして取り出せるようになった

VecLinkedListextract_ifメソッドが追加され、Rangeとクロージャを渡すことで、動的配列から条件に一致した値を削除しつつ、 その値をイテレーター経由で受け取れるようになりました。

イテレーターを途中で止めることで削除も途中で止めることができます。 動的配列の分割などに便利です。

fn main() {
    let mut langs: Vec<String> = ["rust", "c", "javascript", "scala"]
        .into_iter()
        .map(ToString::to_string)
        .collect();

    // 長さが偶数の文字列だけ抜き取り
    let even_langs: Vec<String> = langs.extract_if(.., |s| s.len() % 2 == 0).collect();
    assert_eq!(even_langs, vec!["rust", "javascript"]);
    // langsから抜き取られた文字列は削除される
    assert_eq!(langs, vec!["c", "scala"]);
}

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

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

Vec::extract_if

原典

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

範囲内の要素を削除すべきかについて、クロージャを使って判断するイテレータを生成する。

クロージャがtrueを返すと要素は削除されてイテレータから返される。クロージャがfalseを 返すと要素はVecに残ってイテレータからは返されない。

抽出対象は指定された範囲内にある要素のみだが、 いずれかの要素が抽出された場合には範囲より後の要素も移動が必要になることがある。

そのままドロップしたり途中で繰り返しをやめたりした時など、戻り値のExtractIfを処理しきらなかった場合 残った要素は保持される。イテレータを使う必要がない場合は述語関数を反転させてretain_mutを使うと良い。

このメソッドを使うのは次のコードと同等である。

let mut i = range.start;
let end_items = vec.len() - range.end;

while i < vec.len() - end_items {
    if some_predicate(&mut vec[i]) {
        let val = vec.remove(i);
        // コードを書く
    } else {
        i += 1;
    }
}
let some_predicate = |x: &mut i32| { *x % 2 == 1 };
let mut vec = vec![0, 1, 2, 3, 4, 5, 6];
let mut vec2 = vec.clone();
let range = 1..5;
let mut i = range.start;
let end_items = vec.len() - range.end;
let mut extracted = vec![];

while i < vec.len() - end_items {
    if some_predicate(&mut vec[i]) {
        let val = vec.remove(i);
        extracted.push(val);
        // コードを書く
    } else {
        i += 1;
    }
}

let extracted2: Vec<_> = vec2.extract_if(range, some_predicate).collect();
assert_eq!(vec, vec2);
assert_eq!(extracted, extracted2);

しかしextract_ifの方が使いやすい。extract_ifは要素を一括で後ろにずらすことができるためより効率的でもある。

またextract_ifは要素を保持するか削除するかに関わらず、 フィルター用クロージャに渡される要素を変更することもできる。

パニック

rangeが範囲外の場合にパニックする。

サンプル

元の記憶領域を再利用しつつ配列を偶数と奇数に分ける。

let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15];

let evens = numbers.extract_if(.., |x| *x % 2 == 0).collect::<Vec<_>>();
let odds = numbers;

assert_eq!(evens, vec![2, 4, 6, 8, 14]);
assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]);

Range引数を使いVecの一部だけを処理することもできる。

let mut items = vec![0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2];
let ones = items.extract_if(7.., |x| *x == 1).collect::<Vec<_>>();
assert_eq!(items, vec![0, 0, 0, 0, 0, 0, 0, 2, 2, 2]);
assert_eq!(ones.len(), 3);

vec::ExtractIf

原典

#[stable(feature = "extract_if", since = "1.87.0")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ExtractIf<
    'a,
    T,
    F,
    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
>
{ /* フィールドは省略 */ }

要素を削除すべきかについてクロージャを使って判断するイテレータ

この構造体はVec::extract_ifによって生成される。詳細はそちらの文書を参照されたい。

サンプル

let mut v = vec![0, 1, 2];
let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(.., |x| *x % 2 == 0);

LinkedList::extract_if

原典

impl<T, A: Allocator> LinkedList<T, A> {
    #[stable(feature = "extract_if", since = "1.87.0")]
    pub fn extract_if<F>(&mut self, filter: F) -> ExtractIf<'_, T, F, A>
    where
        F: FnMut(&mut T) -> bool,
    { /* 実装は省略 */ }
}

要素を削除すべきかについて、クロージャを使って判断するイテレータを生成する。

クロージャがtrueを返すと要素は削除されてイテレータから返される。クロージャがfalseを 返すと要素はリストに残ってイテレータからは返されない。

そのままドロップしたり途中で繰り返しをやめたりした時など、戻り値のExtractIfを処理しきらなかった場合 残った要素は保持される。イテレータを使う必要がない場合はextract_if().for_each(drop)を使うと良い。

またextract_ifは要素を残すか削除するかに関わらず、 フィルター用クロージャに渡される要素を変更することもできる。

サンプル

元のリストを再利用しつつリストを偶数と奇数に分ける。

use std::collections::LinkedList;

let mut numbers: LinkedList<u32> = LinkedList::new();
numbers.extend(&[1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]);

let evens = numbers.extract_if(|x| *x % 2 == 0).collect::<LinkedList<_>>();
let odds = numbers;

assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![2, 4, 6, 8, 14]);
assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 9, 11, 13, 15]);

linked_list::ExtractIf

原典

#[stable(feature = "extract_if", since = "1.87.0")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ExtractIf<
    'a,
    T: 'a,
    F: 'a,
    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
>
{ /* フィールドは省略 */ }

LinkedListのextract_ifを呼び出すことによって生成されるイテレータ

<[T]>::split_off

原典

impl<T> [T] {
    #[inline]
    #[must_use = "method does not modify the slice if the range is out of bounds"]
    #[stable(feature = "slice_take", since = "1.87.0")]
    pub fn split_off<'a, R: OneSidedRange<usize>>(
        self: &mut &'a Self,
        range: R,
    ) -> Option<&'a Self>
    { /* 実装は省略 */ }
}

指定された範囲に対応する部分スライスを削除し、その参照を返す。

指定された範囲がスライスの範囲外の場合、Noneを返してスライスは変更しない。

またこのメソッドは2....6のような一方指定の範囲しか受け付けず、2..6のような両指定の範囲は受け付けない。

サンプル

スライスから最初の3要素を分離する。

let mut slice: &[_] = &['a', 'b', 'c', 'd'];
let mut first_three = slice.split_off(..3).unwrap();

assert_eq!(slice, &['d']);
assert_eq!(first_three, &['a', 'b', 'c']);

スライスから最後の2要素を分離する。

let mut slice: &[_] = &['a', 'b', 'c', 'd'];
let mut tail = slice.split_off(2..).unwrap();

assert_eq!(slice, &['a', 'b']);
assert_eq!(tail, &['c', 'd']);

rangeが範囲外の場合はNoneを得る。

let mut slice: &[_] = &['a', 'b', 'c', 'd'];

assert_eq!(None, slice.split_off(5..));
assert_eq!(None, slice.split_off(..5));
assert_eq!(None, slice.split_off(..=4));
let expected: &[char] = &['a', 'b', 'c', 'd'];
assert_eq!(Some(expected), slice.split_off(..4));

<[T]>::split_off_mut

原典

impl<T> [T] {
    #[inline]
    #[must_use = "method does not modify the slice if the range is out of bounds"]
    #[stable(feature = "slice_take", since = "1.87.0")]
    pub fn split_off_mut<'a, R: OneSidedRange<usize>>(
        self: &mut &'a mut Self,
        range: R,
    ) -> Option<&'a mut Self>
    { /* 実装は省略 */ }
}

指定された範囲に対応する部分スライスを削除し、その可変参照を返す。

指定された範囲がスライスの範囲外の場合、Noneを返してスライスは変更しない。

またこのメソッドは2....6のような一方指定の範囲しか受け付けず、2..6のような両指定の範囲は受け付けない。

サンプル

スライスから最初の3要素を分離する。

let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
let mut first_three = slice.split_off_mut(..3).unwrap();

assert_eq!(slice, &mut ['d']);
assert_eq!(first_three, &mut ['a', 'b', 'c']);

スライスから最後の2要素を取り出す。

let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
let mut tail = slice.split_off_mut(2..).unwrap();

assert_eq!(slice, &mut ['a', 'b']);
assert_eq!(tail, &mut ['c', 'd']);

rangeが範囲外の場合はNoneを得る。

let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];

assert_eq!(None, slice.split_off_mut(5..));
assert_eq!(None, slice.split_off_mut(..5));
assert_eq!(None, slice.split_off_mut(..=4));
let expected: &mut [_] = &mut ['a', 'b', 'c', 'd'];
assert_eq!(Some(expected), slice.split_off_mut(..4));

<[T]>::split_off_first

原典

impl<T> [T] {
    #[inline]
    #[stable(feature = "slice_take", since = "1.87.0")]
    #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")]
    pub const fn split_off_first<'a>(self: &mut &'a Self) -> Option<&'a T>
    { /* 実装は省略 */ }
}

スライスから最初の要素を削除し、その参照を返す。

スライスが空の場合はNoneを返す。

サンプル

let mut slice: &[_] = &['a', 'b', 'c'];
let first = slice.split_off_first().unwrap();

assert_eq!(slice, &['b', 'c']);
assert_eq!(first, &'a');

<[T]>::split_off_first_mut

原典

impl<T> [T] {
    #[inline]
    #[stable(feature = "slice_take", since = "1.87.0")]
    #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")]
    pub const fn split_off_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T>
    { /* 実装は省略 */ }
}

スライスから最初の要素を削除し、その可変参照を返す。

スライスが空の場合はNoneを返す。

サンプル

let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
let first = slice.split_off_first_mut().unwrap();
*first = 'd';

assert_eq!(slice, &['b', 'c']);
assert_eq!(first, &'d');

<[T]>::split_off_last

原典

impl<T> [T] {
    #[inline]
    #[stable(feature = "slice_take", since = "1.87.0")]
    #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")]
    pub const fn split_off_last<'a>(self: &mut &'a Self) -> Option<&'a T>
    { /* 実装は省略 */ }
}

スライスから最後の要素を削除し、その参照を返す。

スライスが空の場合はNoneを返す。

サンプル

let mut slice: &[_] = &['a', 'b', 'c'];
let last = slice.split_off_last().unwrap();

assert_eq!(slice, &['a', 'b']);
assert_eq!(last, &'c');

<[T]>::split_off_last_mut

原典

impl<T> [T] {
    #[inline]
    #[stable(feature = "slice_take", since = "1.87.0")]
    #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")]
    pub const fn split_off_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T>
    { /* 実装は省略 */ }
}

スライスから最後の要素を削除し、その可変参照を返す。

スライスが空の場合はNoneを返す。

サンプル

let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
let last = slice.split_off_last_mut().unwrap();
*last = 'd';

assert_eq!(slice, &['a', 'b']);
assert_eq!(last, &'d');

String::extend_from_within

原典

impl String {
    #[cfg(not(no_global_oom_handling))]
    #[stable(feature = "string_extend_from_within", since = "1.87.0")]
    pub fn extend_from_within<R>(&mut self, src: R)
    where
        R: RangeBounds<usize>,
    { /* 実装は省略 */ }
}

範囲srcから文字列の末尾に要素をコピーする。

パニック

開始点または終了点がchar境界にない場合、または範囲外の場合にパニックする。

サンプル

let mut string = String::from("abcde");

string.extend_from_within(2..);
assert_eq!(string, "abcdecde");

string.extend_from_within(..2);
assert_eq!(string, "abcdecdeab");

string.extend_from_within(4..8);
assert_eq!(string, "abcdecdeabecde");

os_str::Display

原典

#[stable(feature = "os_str_display", since = "1.87.0")]
pub struct Display<'a>
{ /* フィールドは省略 */ }

OsStrformat!{}で安全に表示するための補助構造体。

OsStrは非Unicodeデータを含む可能性がある。それを抑制できるようこの構造体でDisplayトレイトを実装している。 この構造体はOsStrdisplayメソッドによって生成される。 これはプラットフォームによっては非可逆な変換を行うことがある。

サンプル

use std::ffi::OsStr;

let s = OsStr::new("Hello, world!");
println!("{}", s.display());

OsStr::display

原典

impl OsStr {
    #[stable(feature = "os_str_display", since = "1.87.0")]
    #[must_use = "this does not display the `OsStr`; \
                  it returns an object that can be displayed"]
    #[inline]
    pub fn display(&self) -> Display<'_>
    { /* 実装は省略 */ }
}

Unicodeデータを含む可能性のあるOsStrを安全に表示するためのオブジェクトを返す。 これはプラットフォームによっては非可逆な変換を行うことがある。OsStrを エスケープしたい場合はDebugを使用されたい。

サンプル

use std::ffi::OsStr;

let s = OsStr::new("Hello, world!");
println!("{}", s.display());

io::pipe

原典

#[stable(feature = "anonymous_pipe", since = "1.87.0")]
#[inline]
pub fn pipe() -> io::Result<(PipeReader, PipeWriter)>
{ /* 実装は省略 */ }

匿名パイプを生成する。

挙動

パイプとは、プロセス間で動作する、OSが提供する一方向のデータチャネルである。 単一プロセスの場合はより良く高速な方法があるため、パイプは通常2つ以上のプロセス間で通信するために使用される。

具体的には次のような動作をする。

  • PipeReaderの読み込みはパイプが空でなくなるまで待機される
  • PipeWriterの書き込みはパイプが満杯の場合待機される
  • PipeWriterの全コピーが閉じられた場合、対応するPipeReaderでの読み込みはEOFを返す
  • PipeWriterは共有可能で、複数のプロセスやスレッドが同時に書き込めるが (ターゲット依存な閾値を超えた)書き込みは内容が混ざり合う可能性がある
  • PipeReaderは共有可能で、複数のプロセスやスレッドが同時に読み込める。 任意のデータはバイト単位でいずれか1つの読み手にしか消費されない。データの混ざり合いについては保証されない
  • 移植性のあるアプリケーションでは1バイトより大きいメッセージの原子性を仮定できない

プラットフォーム依存の挙動

この関数は現在Unixpipe関数とWindowsCreatePipe関数に対応している。

なお、これは将来的には変更される可能性がある

容量

パイプの容量はプラットフォーム依存である。以下Linuxman pageから引用(※訳注:と共に和訳)。

実装によってパイプの容量には限界がある。アプリケーションは特定の容量に依存すべきではない。 読み取りプロセス側はデータ来たらすぐに消費するよう、また書き込みプロセス側は待機したままに ならないようにアプリケーションを設計すべきである。

サンプル

use std::process::Command;
use std::io::{pipe, Read, Write};
let (ping_rx, mut ping_tx) = pipe()?;
let (mut pong_rx, pong_tx) = pipe()?;

// 入力をそのまま出力するプロセスを起動
let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;

ping_tx.write_all(b"hello")?;
// echo_server側の読み取り待ちを解除するため閉じる
drop(ping_tx);

let mut buf = String::new();
// echo_server側の書き手が閉じられるまで待機
pong_rx.read_to_string(&mut buf)?;
assert_eq!(&buf, "hello");

echo_server.wait()?;
#[cfg(miri)] fn main() {}
#[cfg(not(miri))]
fn main() -> std::io::Result<()> {
    use std::process::Command;
    use std::io::{pipe, Read, Write};
    let (ping_rx, mut ping_tx) = pipe()?;
    let (mut pong_rx, pong_tx) = pipe()?;

    // 入力をそのまま出力するプロセスを起動
    let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;

    ping_tx.write_all(b"hello")?;
    // echo_server側の読み取り待ちを解除するため閉じる
    drop(ping_tx);

    let mut buf = String::new();
    // echo_server側の書き手が閉じられるまで待機
    pong_rx.read_to_string(&mut buf)?;
    assert_eq!(&buf, "hello");

    echo_server.wait()?;
    Ok(())
}

io::PipeReader

原典

#[stable(feature = "anonymous_pipe", since = "1.87.0")]
#[derive(Debug)]
pub struct PipeReader(/* フィールドは省略 */);

匿名パイプの読み取り側。

io::PipeReader::try_clone

原典

impl PipeReader {
    #[stable(feature = "anonymous_pipe", since = "1.87.0")]
    pub fn try_clone(&self) -> io::Result<Self>
    { /* 実装は省略 */ }
}

内包するファイル記述子を共有する、新しいPipeReaderインスタンスを生成する。

サンプル

use std::fs;
use std::io::{pipe, Write};
use std::process::Command;
const NUM_SLOT: u8 = 2;
const NUM_PROC: u8 = 5;
const OUTPUT: &str = "work.txt";

let mut jobs = vec![];
let (reader, mut writer) = pipe()?;

// NUM_SLOT文字をパイプに書き込む
writer.write_all(&[b'|'; NUM_SLOT as usize])?;

// パイプから1文字読み取り、処理を行い、パイプに書き戻すプロセスをいくつか起動する
// パイプが空になるとプロセスは待機するため、常にNUM_SLOT個のプロセスだけが動作できる
for _ in 0..NUM_PROC {
    jobs.push(
        Command::new("bash")
            .args(["-c",
                &format!(
                     "read -n 1\n\
                      echo -n 'x' >> '{OUTPUT}'\n\
                      echo -n '|'",
                ),
            ])
            .stdin(reader.try_clone()?)
            .stdout(writer.try_clone()?)
            .spawn()?,
    );
}

// 全ジョブが終了するまで待機
for mut job in jobs {
    job.wait()?;
}

// 仕事を確認して掃除
let xs = fs::read_to_string(OUTPUT)?;
fs::remove_file(OUTPUT)?;
assert_eq!(xs, "x".repeat(NUM_PROC.into()));
#[cfg(miri)] fn main() {}
#[cfg(not(miri))]
fn main() -> std::io::Result<()> {
    use std::fs;
    use std::io::{pipe, Write};
    use std::process::Command;
    const NUM_SLOT: u8 = 2;
    const NUM_PROC: u8 = 5;
    const OUTPUT: &str = "work.txt";

    let mut jobs = vec![];
    let (reader, mut writer) = pipe()?;

    // NUM_SLOT文字をパイプに書き込む
    writer.write_all(&[b'|'; NUM_SLOT as usize])?;

    // パイプから1文字読み取り、処理を行い、パイプに書き戻すプロセスをいくつか起動する
    // パイプが空になるとプロセスは待機するため、常にNUM_SLOT個のプロセスだけが動作できる
    for _ in 0..NUM_PROC {
        jobs.push(
            Command::new("bash")
                .args(["-c",
                    &format!(
                         "read -n 1\n\
                          echo -n 'x' >> '{OUTPUT}'\n\
                          echo -n '|'",
                    ),
                ])
                .stdin(reader.try_clone()?)
                .stdout(writer.try_clone()?)
                .spawn()?,
        );
    }

    // 全ジョブが終了するまで待機
    for mut job in jobs {
        job.wait()?;
    }

    // 仕事を確認して掃除
    let xs = fs::read_to_string(OUTPUT)?;
    fs::remove_file(OUTPUT)?;
    assert_eq!(xs, "x".repeat(NUM_PROC.into()));
    Ok(())
}

io::PipeWriter

原典

#[stable(feature = "anonymous_pipe", since = "1.87.0")]
#[derive(Debug)]
pub struct PipeWriter(/* フィールドは省略 */);

匿名パイプの書き込み側。

io::PipeWriter::try_clone

原典

impl PipeWriter {
    #[stable(feature = "anonymous_pipe", since = "1.87.0")]
    pub fn try_clone(&self) -> io::Result<Self>
    { /* 実装は省略 */ }
}

内包するファイル記述子を共有する、新しいPipeWriterインスタンスを生成する。

サンプル

use std::process::Command;
use std::io::{pipe, Read};
let (mut reader, writer) = pipe()?;

// stdoutとstderrに書き込むプロセスを起動
let mut peer = Command::new("bash")
    .args([
        "-c",
        "echo -n hoge\n\
         echo -n fuga >&2"
    ])
    .stdout(writer.try_clone()?)
    .stderr(writer)
    .spawn()?;

// 読み取って結果を確認
let mut msg = String::new();
reader.read_to_string(&mut msg)?;
assert_eq!(&msg, "hogefuga");

peer.wait()?;
#[cfg(miri)] fn main() {}
#[cfg(not(miri))]
fn main() -> std::io::Result<()> {
    use std::process::Command;
    use std::io::{pipe, Read};
    let (mut reader, writer) = pipe()?;

    // stdoutとstderrに書き込むプロセスを起動
    let mut peer = Command::new("bash")
        .args([
            "-c",
            "echo -n foo\n\
             echo -n bar >&2"
        ])
        .stdout(writer.try_clone()?)
        .stderr(writer)
        .spawn()?;

    // 読み取って結果を確認
    let mut msg = String::new();
    reader.read_to_string(&mut msg)?;
    assert_eq!(&msg, "foobar");

    peer.wait()?;
    Ok(())
}

Box<MaybeUninit<T>>::write

原典

impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
    #[stable(feature = "box_uninit_write", since = "1.87.0")]
    #[inline]
    pub fn write(mut boxed: Self, value: T) -> Box<T, A>
    { /* 実装は省略 */ }
}

値を書き込んでBox<T, A>に変換する。

このメソッドはBox::assume_initと同様にBoxを変換するが、変換前にvalueを書き込むため安全性が保証される。 このメソッドでは場合によってはスタックからのコピーを最適化できることもあるため、性能が向上することがある。

サンプル

let big_box = Box::<[usize; 1024]>::new_uninit();

let mut array = [0; 1024];
for (i, place) in array.iter_mut().enumerate() {
    *place = i;
}

// 前のコードはヒープに直接書き込むため、
// 最適化によりこのコピーは省略されるかもしれない
let big_box = Box::write(big_box, array);

for (i, x) in big_box.iter().enumerate() {
    assert_eq!(*x, i);
}

<*const T>::offset_from_unsigned

原典

impl<T: ?Sized> *const T {
    #[stable(feature = "ptr_sub_ptr", since = "1.87.0")]
    #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")]
    #[inline]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    pub const unsafe fn offset_from_unsigned(self, origin: *const T) -> usize
    where
        T: Sized,
    { /* 実装は省略 */ }
}

selforigin以上であることがわかっている場合に限り同じメモリ領域内にある2つのポインタ間の距離を計算する。 戻り値はTの単位であり、バイト単位の距離はsize_of::<T>()で割られる。

この関数はoffset_fromと同じ値を返すがオフセットが非負であることが保証されているという前提が加わる。 このメソッドはusize::try_from(self.offset_from(origin)).unwrap_unchecked()と同等だが、 最適化用の情報が少し多いため一部処理系ではより良い最適化ができることがある。

このメソッドはaddに渡したcount(または引数を入れ替えてsubに渡したcount)を 逆算するものと考えることができる。次のコードはすべて安全性の前提条件を満たしている前提では等価である。

ptr.offset_from_unsigned(origin) == count
origin.add(count) == ptr
ptr.sub(count) == origin
unsafe fn blah(ptr: *const i32, origin: *const i32, count: usize) -> bool { unsafe {
    ptr.offset_from_unsigned(origin) == count
    &&
    origin.add(count) == ptr
    &&
    ptr.sub(count) == origin
} }

安全性

  • ポインタ間の距離は非負でなければならない(self >= origin

  • offset_fromにおけるすべての安全性要件はこのメソッドにも適用される。詳細はそちらを参照

重要なのは、このメソッドの戻り値の型はより大きなオフセットを表すことができるにも 関わらずisize::MAXバイト以上の差があるポインタを渡すことは許可されていないということ。 そのためこのメソッドの戻り値は常にisize::MAX as usize以下となる。

パニック

この関数はTが大きさのない型(ZST)の場合にパニックを起こす。

サンプル

let a = [0; 5];
let ptr1: *const i32 = &a[1];
let ptr2: *const i32 = &a[3];
unsafe {
    assert_eq!(ptr2.offset_from_unsigned(ptr1), 2);
    assert_eq!(ptr1.add(2), ptr2);
    assert_eq!(ptr2.sub(2), ptr1);
    assert_eq!(ptr2.offset_from_unsigned(ptr2), 0);
}

// ポインタの順序が正しくないため間違い
// ptr1.offset_from_unsigned(ptr2)

<*const T>::byte_offset_from_unsigned

原典

impl<T: ?Sized> *const T {
    #[stable(feature = "ptr_sub_ptr", since = "1.87.0")]
    #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")]
    #[inline]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    pub const unsafe fn byte_offset_from_unsigned<U: ?Sized>(self, origin: *const U) -> usize
    { /* 実装は省略 */ }
}

selforigin以上であることがわかっている場合に限り同じメモリ領域内にある2つのポインタ間の距離を計算する。 戻り値はバイト単位である。

これはu8ポインタにキャストしてからoffset_from_unsignedを呼び出すための便利メソッドである。 詳細と安全性要件はそちらのメソッドを参照。

Sizedポインタに対しては、この操作はメタデータを無視してデータポインタのみを考慮する。

<*mut T>::offset_from_unsigned

原典

impl<T: ?Sized> *mut T {
    #[stable(feature = "ptr_sub_ptr", since = "1.87.0")]
    #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")]
    #[inline]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    pub const unsafe fn offset_from_unsigned(self, origin: *const T) -> usize
    where
        T: Sized,
    { /* 実装は省略 */ }
}

selforigin以上であることがわかっている場合に限り同じメモリ領域内にある2つのポインタ間の距離を計算する。 戻り値はTの単位であり、バイト単位の距離はsize_of::<T>()で割られる。

この関数はoffset_fromと同じ値を返すがオフセットが非負であることが保証されているという前提が加わる。 このメソッドはusize::try_from(self.offset_from(origin)).unwrap_unchecked()と同等だが、 最適化用の情報が少し多いため一部処理系ではより良い最適化ができることがある。

このメソッドはaddに渡したcount(または引数を入れ替えてsubに渡したcount)を 逆算するものと考えることができる。次のコードはすべて、安全性の前提条件を満たしている前提では等価である。

ptr.offset_from_unsigned(origin) == count
origin.add(count) == ptr
ptr.sub(count) == origin
unsafe fn blah(ptr: *mut i32, origin: *mut i32, count: usize) -> bool { unsafe {
    ptr.offset_from_unsigned(origin) == count
    &&
    origin.add(count) == ptr
    &&
    ptr.sub(count) == origin
} }

安全性

  • ポインタ間の距離は非負でなければならない(self >= origin

  • offset_fromにおけるすべての安全性要件はこのメソッドにも適用される。詳細はそちらを参照

重要なのは、このメソッドの戻り値の型はより大きなオフセットを表すことができるにも 関わらずisize::MAXバイト以上の差があるポインタを渡すことは許可されていないということ。 そのためこのメソッドの戻り値は常にisize::MAX as usize以下となる。

パニック

この関数はTが大きさのない型(ZST)の場合にパニックを起こす。

サンプル

let mut a = [0; 5];
let p: *mut i32 = a.as_mut_ptr();
unsafe {
    let ptr1: *mut i32 = p.add(1);
    let ptr2: *mut i32 = p.add(3);

    assert_eq!(ptr2.offset_from_unsigned(ptr1), 2);
    assert_eq!(ptr1.add(2), ptr2);
    assert_eq!(ptr2.sub(2), ptr1);
    assert_eq!(ptr2.offset_from_unsigned(ptr2), 0);
}

// ポインタの順序が正しくないため間違い
// ptr1.offset_from(ptr2)

<*mut T>::byte_offset_from_unsigned

原典

impl<T: ?Sized> *mut T {
    #[stable(feature = "ptr_sub_ptr", since = "1.87.0")]
    #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")]
    #[inline]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    pub const unsafe fn byte_offset_from_unsigned<U: ?Sized>(self, origin: *mut U) -> usize
    { /* 実装は省略 */ }
}

selforigin以上であることがわかっている場合に限り同じメモリ領域内にある2つのポインタ間の距離を計算する。 戻り値はバイト単位である。

これはu8ポインタにキャストしてからoffset_from_unsignedを呼び出すための便利メソッドである。 詳細と安全性要件はそちらのメソッドを参照。

Sizedポインタに対しては、この操作はメタデータを無視してデータポインタのみを考慮する。

NonNull::offset_from_unsigned

原典

impl<T: ?Sized> NonNull<T> {
    #[inline]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[stable(feature = "ptr_sub_ptr", since = "1.87.0")]
    #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")]
    pub const unsafe fn offset_from_unsigned(self, subtracted: NonNull<T>) -> usize
    where
        T: Sized,
    { /* 実装は省略 */ }
}

selforigin以上であることがわかっている場合に限り同じメモリ領域内にある2つのポインタ間の距離を計算する。 戻り値はTの単位であり、バイト単位の距離はsize_of::<T>()で割られる。

この関数はoffset_fromと同じ値を返すがオフセットが非負であることが保証されているという前提が加わる。 このメソッドはusize::try_from(self.offset_from(origin)).unwrap_unchecked()と同等だが、 最適化用の情報が少し多いため一部処理系ではより良い最適化ができることがある。

このメソッドはaddに渡したcount(または引数を入れ替えてsubに渡したcount)を 逆算するものと考えることができる。次のコードはすべて安全性の前提条件を満たしている前提では等価である。

ptr.offset_from_unsigned(origin) == count
origin.add(count) == ptr
ptr.sub(count) == origin
unsafe fn blah(ptr: std::ptr::NonNull<u32>, origin: std::ptr::NonNull<u32>, count: usize) -> bool { unsafe {
    ptr.offset_from_unsigned(origin) == count
    &&
    origin.add(count) == ptr
    &&
    ptr.sub(count) == origin
} }

安全性

  • ポインタ間の距離は非負でなければならない(self >= origin

  • offset_fromにおけるすべての安全性要件はこのメソッドにも適用される。詳細はそちらを参照

重要なのは、このメソッドの戻り値の型はより大きなオフセットを表すことができるにも 関わらずisize::MAXバイト以上の差があるポインタを渡すことは許可されていないということ。 そのためこのメソッドの戻り値は常にisize::MAX as usize以下となる。

パニック

この関数はTが大きさのない型(ZST)の場合にパニックを起こす。

サンプル

use std::ptr::NonNull;

let a = [0; 5];
let ptr1: NonNull<u32> = NonNull::from(&a[1]);
let ptr2: NonNull<u32> = NonNull::from(&a[3]);
unsafe {
    assert_eq!(ptr2.offset_from_unsigned(ptr1), 2);
    assert_eq!(ptr1.add(2), ptr2);
    assert_eq!(ptr2.sub(2), ptr1);
    assert_eq!(ptr2.offset_from_unsigned(ptr2), 0);
}

// ポインタの順序が正しくないため間違い
// ptr1.offset_from_unsigned(ptr2)

NonNull::byte_offset_from_unsigned

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[stable(feature = "ptr_sub_ptr", since = "1.87.0")]
    #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")]
    pub const unsafe fn byte_offset_from_unsigned<U: ?Sized>(self, origin: NonNull<U>) -> usize
    { /* 実装は省略 */ }
}

selforigin以上であることがわかっている場合に限り同じメモリ領域内にある2つのポインタ間の距離を計算する。 戻り値はバイト単位である。

これはu8ポインタにキャストしてからoffset_from_unsignedを呼び出すための便利メソッドである。 詳細と安全性要件はそちらのメソッドを参照。

<uN>::cast_signed

原典

impl usize {
    #[stable(feature = "integer_sign_cast", since = "1.87.0")]
    #[rustc_const_stable(feature = "integer_sign_cast", since = "1.87.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline(always)]
    pub const fn cast_signed(self) -> $SignedT
    { /* 実装は省略 */ }
}

selfを同じ大きさの符号付き整数として再解釈したビットパターンを返す。

これはasでのキャストと同じ結果を生成するが、ビット幅が同じであることが保証される。

サンプル

基本的な使い方。

let n = usize::MAX;

assert_eq!(n.cast_signed(), -1isize);

NonZero::<uN>::cast_signed

原典

impl NonZero<$Int> {
    #[stable(feature = "integer_sign_cast", since = "1.87.0")]
    #[rustc_const_stable(feature = "integer_sign_cast", since = "1.87.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline(always)]
    pub const fn cast_signed(self) -> NonZero<$Sint>
    { /* 実装は省略 */ }
}

selfを同じ大きさの符号付き整数として再解釈したビットパターンを返す。

サンプル

基本的な使い方。

let n = NonZero::<usize>::MAX;

assert_eq!(n.cast_signed(), NonZero::new(-1isize).unwrap());
use std::num::NonZero;

<iN>::cast_unsigned

原典

impl isize {
    #[stable(feature = "integer_sign_cast", since = "1.87.0")]
    #[rustc_const_stable(feature = "integer_sign_cast", since = "1.87.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline(always)]
    pub const fn cast_unsigned(self) -> $UnsignedT
    { /* 実装は省略 */ }
}

selfを同じ大きさの符号無し整数として再解釈したビットパターンを返す。

これはasでのキャストと同じ結果を生成するが、ビット幅が同じであることが保証される。

サンプル

基本的な使い方。

let n = -1isize;

assert_eq!(n.cast_unsigned(), usize::MAX);

NonZero::<iN>::cast_unsigned

原典

impl NonZero<isize> {
    #[stable(feature = "integer_sign_cast", since = "1.87.0")]
    #[rustc_const_stable(feature = "integer_sign_cast", since = "1.87.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline(always)]
    pub const fn cast_unsigned(self) -> NonZero<usize>
    { /* 実装は省略 */ }
}

selfを同じ大きさの符号無し整数として再解釈したビットパターンを返す。

サンプル

let n = NonZero::new(-1isize).unwrap();

assert_eq!(n.cast_unsigned(), NonZero::<usize>::MAX);
use std::num::NonZero;

let n = NonZero::new(-1isize).unwrap();

assert_eq!(n.cast_unsigned(), NonZero::<usize>::MAX);

<uN>::is_multiple_of

原典

impl usize {
    #[stable(feature = "unsigned_is_multiple_of", since = "1.87.0")]
    #[rustc_const_stable(feature = "unsigned_is_multiple_of", since = "1.87.0")]
    #[must_use]
    #[inline]
    #[rustc_inherit_overflow_checks]
    pub const fn is_multiple_of(self, rhs: Self) -> bool
    { /* 実装は省略 */ }
}

selfrhsの整数倍である場合にtrueを返し、そうでない場合はfalseを返す。

この関数はself % rhs == 0と同等であるがrhs == 0の場合でもパニックを起こさない。 代わりに0.is_multiple_of(0) == trueとなり、そして任意の非ゼロ値nに 対してはn.is_multiple_of(0) == falseとなる。

サンプル

基本的な使い方。

assert!(6_usize.is_multiple_of(2));
assert!(!5_usize.is_multiple_of(2));

assert!(0_usize.is_multiple_of(0));
assert!(!6_usize.is_multiple_of(0));

<uN>::unbounded_shl

原典

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

無制限の左シフト。self << rhsを計算するがrhsの値は制限されない。

rhsselfのビット数以上の場合は値全体がシフトアウトされて0が返る。

サンプル

基本的な使い方。

assert_eq!(0x1usize.unbounded_shl(4), 0x10);
assert_eq!(0x1usize.unbounded_shl(129), 0);

<uN>::unbounded_shr

原典

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

無制限の右シフト。self >> rhsを計算するがrhsの値は制限されない。

rhsselfのビット数以上の場合は値全体がシフトアウトされて0が返る。

サンプル

基本的な使い方。

assert_eq!(0x10usize.unbounded_shr(4), 0x1);
assert_eq!(0x10usize.unbounded_shr(129), 0);

<iN>::unbounded_shl

原典

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

無制限の左シフト。self << rhsを計算するがrhsの値は制限されない。

rhsselfのビット数以上の場合は値全体がシフトアウトされて0が返る。

サンプル

基本的な使い方。

assert_eq!(0x1isize.unbounded_shl(4), 0x10);
assert_eq!(0x1isize.unbounded_shl(129), 0);

<iN>::unbounded_shr

原典

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

無制限の右シフト。self >> rhsを計算するがrhsの値は制限されない。

rhsselfのビット数以上の場合、正の数の場合は0が、負の数の場合は-1が返る。

サンプル

assert_eq!(0x10isize.unbounded_shr(4), 0x1);
assert_eq!(0x10isize.unbounded_shr(129), 0);
assert_eq!(isize::MIN.unbounded_shr(129), -1);

<iN>::midpoint

原典

impl isize {
    #[stable(feature = "num_midpoint_signed", since = "1.87.0")]
    #[rustc_const_stable(feature = "num_midpoint_signed", since = "1.87.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[doc(alias = "average_floor")]
    #[doc(alias = "average_ceil")]
    #[doc(alias = "average")]
    #[inline]
    pub const fn midpoint(self, rhs: Self) -> Self
    { /* 実装は省略 */ }
}

selfrhsの中間点(平均値)を計算する。

midpoint(a, b)は十分大きな符号付き整数型で計算した場合の(a + b) / 2と同じである。 これにより結果は常にゼロ方向に丸められ、オーバーフローは発生しない。

サンプル

assert_eq!(0isize.midpoint(4), 2);
assert_eq!((-1isize).midpoint(2), 0);
assert_eq!((-7isize).midpoint(0), -3);
assert_eq!(0isize.midpoint(-7), -3);
assert_eq!(0isize.midpoint(7), 3);

<str>::from_utf8

原典

impl str {
    #[stable(feature = "inherent_str_constructors", since = "1.87.0")]
    #[rustc_const_stable(feature = "inherent_str_constructors", since = "1.87.0")]
    #[rustc_diagnostic_item = "str_inherent_from_utf8"]
    pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error>
    { /* 実装は省略 */ }
}

バイトのスライスを文字列スライスに変換する。

文字列スライス(&str)はバイト列(u8)で構成されており、また バイト列スライス(&[u8])もバイト列で構成されていることから、 この関数は両者の変換を行う。ただしすべてのバイト列スライスが有効な 文字列スライスであるわけではない。&strは有効なUTF-8である必要があり、from_utf8()は バイト列が有効なUTF-8であることを検査した上で変換を行う。

バイト列スライスが有効なUTF-8であることが確実で、かつ有効性検査のオーバーヘッドを避けたい場合は 検査を省略する非安全版の関数from_utf8_uncheckedもある。

&strではなくStringが必要な場合はString::from_utf8の使用を検討されたい。

[u8; N]としてスタックに割り当てた上で&[u8]を取得できるため、 この関数でのみスタックに割り当てられた文字列を得られる。 使い方については下記の例を参照されたい。

エラー

スライスがUTF-8でない場合はスライスがUTF-8でない理由を説明とともにErrが返る。

サンプル

基本的な使い方。

// Vecにあるバイト列
let sparkle_heart = vec![240, 159, 146, 150];

// ?(try)演算子を使ってバイト列が有効かどうかを検査
let sparkle_heart = str::from_utf8(&sparkle_heart)?;

assert_eq!("💖", sparkle_heart);
// Vecにあるバイト列
let sparkle_heart = vec![240, 159, 146, 150];

// ?(try)演算子を使ってバイト列が有効かどうかを検査
let sparkle_heart = str::from_utf8(&sparkle_heart)?;

assert_eq!("💖", sparkle_heart);
Ok::<_, std::str::Utf8Error>(())

不正なバイト列

// Vecにある無効なバイト列
let sparkle_heart = vec![0, 159, 146, 150];

assert!(str::from_utf8(&sparkle_heart).is_err());

返されるエラー種別の詳細についてはUtf8Errorのドキュメントを参照されたい。

スタックに割り当てられた文字列

// スタックに割り当てられたバイト列
let sparkle_heart = [240, 159, 146, 150];

// バイト列が正答であることが分かっているので`unwrap()`するだけ
let sparkle_heart: &str = str::from_utf8(&sparkle_heart).unwrap();

assert_eq!("💖", sparkle_heart);

<str>::from_utf8_mut

原典

impl str {
    #[stable(feature = "inherent_str_constructors", since = "1.87.0")]
    #[rustc_const_stable(feature = "const_str_from_utf8", since = "1.87.0")]
    #[rustc_diagnostic_item = "str_inherent_from_utf8_mut"]
    pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error>
    { /* 実装は省略 */ }
}

バイト列の可変スライスを文字列の可変スライスに変換する。

サンプル

基本的な使い方。

// "Hello, Rust!"の可変Vec
let mut hellorust = vec![72, 101, 108, 108, 111, 44, 32, 82, 117, 115, 116, 33];

// このバイト列が有効であることが分かっているので`unwrap()`を使う
let outstr = str::from_utf8_mut(&mut hellorust).unwrap();

assert_eq!("Hello, Rust!", outstr);

不正なバイト列

// 可変Vecにある無効なバイト列
let mut invalid = vec![128, 223];

assert!(str::from_utf8_mut(&mut invalid).is_err());

返されるエラー種別の詳細についてはUtf8Errorのドキュメントを参照されたい。

<str>::from_utf8_unchecked

原典

impl str {
    #[inline]
    #[must_use]
    #[stable(feature = "inherent_str_constructors", since = "1.87.0")]
    #[rustc_const_stable(feature = "inherent_str_constructors", since = "1.87.0")]
    #[rustc_diagnostic_item = "str_inherent_from_utf8_unchecked"]
    pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str
    { /* 実装は省略 */ }
}

文字列が有効なUTF-8であることを検査せずにバイト列のスライスを文字列のスライスに変換する。

安全版についてはfrom_utf8を参照されたい。

安全性

渡されるバイト列は有効なUTF-8である必要がある。

サンプル

基本的な使い方。

// Vecにあるバイト列
let sparkle_heart = vec![240, 159, 146, 150];

let sparkle_heart = unsafe {
    str::from_utf8_unchecked(&sparkle_heart)
};

assert_eq!("💖", sparkle_heart);

<str>::from_utf8_unchecked_mut

原典

impl str {
    #[inline]
    #[must_use]
    #[stable(feature = "inherent_str_constructors", since = "1.87.0")]
    #[rustc_const_stable(feature = "inherent_str_constructors", since = "1.87.0")]
    #[rustc_diagnostic_item = "str_inherent_from_utf8_unchecked_mut"]
    pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str
    { /* 実装は省略 */ }
}

文字列が有効なUTF-8であることを検査せずにバイト列のスライスを文字列のスライスに変換する、可変版。

不変版についてはfrom_utf8_uncheckedを参照されたい。

サンプル

基本的な使い方。

let mut heart = vec![240, 159, 146, 150];
let heart = unsafe { str::from_utf8_unchecked_mut(&mut heart) };

assert_eq!("💖", heart);

変更点リスト

言語

コンパイラ

プラットフォーム対応

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

ライブラリ

安定化されたAPI

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

Cargo

互換性メモ

内部の変更

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

関連リンク

さいごに

次のリリースのRust 1.88は6/27(金)にリリースされる予定です。 Rust 1.88では今度こそlet chains(ifなどでlet他の条件式などを繋げられる機能)が使えるようになったり、 #[cfg(true)]#[cfg(false)]と書けるようになったりする予定です。

ライセンス表記

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



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

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