以下の内容はhttps://aznhe21.hatenablog.com/entry/2024/07/26/rust-1.80より取得しました。


Rust 1.80を早めに深掘り

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

ピックアップ

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

遅延初期化されるグローバル変数を書けるようになった

once_cellクレートにあったunsync::Lazysync::Lazyが標準ライブラリに取り込まれ、 それぞれstd::cell::LazyCellstd::sync::LazyLockとして使えるようになりました。 これはonce_cellクレートに加えlazy_staticクレートも置き換えることができます。

これらは一度だけ初期化される変数のための型でOnceCellはスレッド安全ではないもの、OnceLockはスレッド安全なものであり、 とりわけ後者はグローバル変数として使えるため、定数文脈で扱えない値をグローバル化するのに便利です。 OnceCellOnceLockとは異なり、変数定義と共に初期化処理を書くことができ、とても便利です。

use std::sync::LazyLock;

static OS_NAME: LazyLock<String> = LazyLock::new(|| {
    use std::io::BufRead;

    for line in std::io::BufReader::new(std::fs::File::open("/etc/os-release").unwrap()).lines() {
        let line = line.unwrap();
        if line.starts_with("NAME=\"") && line.ends_with('"') {
            return line[6..][..line.len() - 6 - 1].to_string();
        }
    }

    "unknown".to_string()
});

fn main() {
    // `OS_NAME`はどちらかのスレッドで一度だけ初期化され、上書きされることはない
    let t1 = std::thread::spawn(|| println!("{}", *OS_NAME));
    let t2 = std::thread::spawn(|| some_process(&OS_NAME));
    t1.join().unwrap();
    t2.join().unwrap();
}

fn some_process(_os_name: &str) {
    // ...
}

ちなみにOnceCellOnceLockが安定化されたのはRust 1.70なので、実に60週も間が空いたことになります。

Optionの値を条件を満たしたときだけ取り出せるようになった

Option::take_ifが使えるようになり、述語関数を渡すことで、その条件を満たしたときだけ内部の値を取り出すことができるようになりました。

Someでありかつ条件を満たす」というのは中々書きづらく、unwrapも伴いがちだったので地味に便利です。

// Rust 1.79まではunwrapを使うか・・・
fn hoge(v: &mut Option<u32>) {
    if v.as_ref().is_some_and(|x| *x % 2 == 0) {
        println!("{}", v.take().unwrap());
    }
}

// 先にtakeして、条件が満たされなければ元に戻す、とするなど地味に面倒だった
fn fuga(v: &mut Option<u32>) {
    match v.take() {
        Some(x) if x % 2 == 0 => {
            println!("{}", x);
        }
        // 条件を満たさないので元に戻す
        x => *v = x,
    }
}

// take_ifでより直感的になった
fn piyo(v: &mut Option<u32>) {
    if let Some(x) = v.take_if(|x| *x % 2 == 0) {
        println!("{}", x);
    }
}

fn main() {
    hoge(&mut Some(42));
    fuga(&mut Some(42));
    piyo(&mut Some(42));
}

スライスをパニックなしに分割できるようになった

slice::split_at_checkedなどのメソッドが使えるようになり、 インデックスが範囲内であるかを気にせずにスライスを分割できるようになりました。

これまであったslice::split_atでは引数midがスライスの範囲外を示す場合にパニックしてしまうため、 事前に長さチェックを行う必要があり面倒でした。 split_at_checkedでは内部で長さチェックを行ってくれるため安全です。

split_atは気にせず使うと簡単にパニックしてしまうため、Clippyのdisallowed-methods"slice::split_at"を追加しておくと良いかもしれません。

配列を含むスライスを一次元化できるようになった

&[[T; N]]のスライスを&[T]にする、またはVec<[T; N]>Vec<T>にすることができるようになりました。 これらはメモリを再確保することなく、元のメモリ領域を再利用できます。

二次元配列を一次元にするのは画像処理などでよく出てくるパターンですが、メモリの再確保なく行えるのは便利です。

パターンとして終端の含まれない範囲を使えるようになった

パターンマッチではこれまで、N..=MN....=Mのようなパターンを使うことができました。 Rust 1.80からはN..M..Mといったパターンも使えるようになります。

fn hoge(n: u8) {
    // 終端と始端に同じ数字を書きたい日もある
    match n {
        0..=9 => println!("一桁"),
        10..=99 => println!("二桁"),
        100.. => println!("三桁"),
    }
}

fn fuga(n: u8) {
    // Rust 1.80からは書けるようになる
    match n {
        0..10 => println!("一桁"),
        // ここで間違えて10..99と書くと99が抜けてることを教えてくれる
        10..100 => println!("二桁"),
        100.. => println!("三桁"),
    }
}

useなしにsize_of等が使えるようになった

CやC++からライブラリを移植するとき、sizeofmem::size_ofと書き換えたりuseしたりする必要があるなど少し面倒でした。 Rust 1.80からはpreludeにsize_ofsize_of_valalign_ofalign_of_valが含まれるようになり、少し簡単に書けるようになりました。

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

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

LazyCell

原典

#[stable(feature = "lazy_cell", since = "1.80.0")]
pub struct LazyCell<T, F = fn() -> T>
{ /* フィールドは省略 */ }

初めてアクセスされたときに初期化される値。

この構造体のスレッド安全版についてはstd::sync::LazyLockを参照。

サンプル

use std::cell::LazyCell;

let lazy: LazyCell<i32> = LazyCell::new(|| {
    println!("初期化中");
    92
});
println!("準備完了");
println!("{}", *lazy);
println!("{}", *lazy);

// 結果:
//   準備完了
//   初期化中
//   92
//   92

LazyLock

原典

#[stable(feature = "lazy_cell", since = "1.80.0")]
pub struct LazyLock<T, F = fn() -> T>
{ /* フィールドは省略 */ }

初めてアクセスされたときに初期化される値。

この型はスレッド安全なLazyCellであり、静的変数として使用できる。 初期化が複数のスレッドから呼び出される可能性があることから、別の初期化処理が実行中の場合、 逆参照の呼び出しは呼び出し元のスレッドをブロックする。

サンプル

静的変数をLazyLockで初期化する。

use std::sync::LazyLock;

// 注意:静的項目はプログラム終了時に[`Drop`]を呼び出さないため、これは解放されない。
// これは、OSによるメモリの解放が、終了するプログラムが解放するよりも速いため問題ない。
// しかし意図的であることが明確ではないため、valgrindなどのツールはこれを「メモリリーク」として報告する可能性がある。
// ※訳注:Deep Thoughtは小説「銀河ヒッチハイクガイド」に登場するスーパーコンピューター
static DEEP_THOUGHT: LazyLock<String> = LazyLock::new(|| {
    // M3 Ultraでは--release設定でも1600万年掛かる
    another_crate::great_question()
});

// `String`が構築され、`LazyLock`内に保存され、`&String`として返される
let _ = &*DEEP_THOUGHT;
// `LazyLock`から`String`が取得され、`&String`が返される
let _ = &*DEEP_THOUGHT;
use std::sync::LazyLock;

// 注意:静的項目はプログラム終了時に[`Drop`]を呼び出さないため、これは解放されない。
// これは、OSによるメモリの解放が、終了するプログラムが解放するよりも速いため問題ない。
// しかし意図的であることが明確ではないため、valgrindなどのツールはこれを「メモリリーク」として報告する可能性がある。
// ※訳注:Deep Thoughtは小説「銀河ヒッチハイクガイド」に登場するスーパーコンピューター
static DEEP_THOUGHT: LazyLock<String> = LazyLock::new(|| {
mod another_crate {
    pub fn great_question() -> String { "42".to_string() }
}
    // M3 Ultraでは--release設定でも1600万年掛かる
    another_crate::great_question()
});

// `String`が構築され、`LazyLock`内に保存され、`&String`として返される
let _ = &*DEEP_THOUGHT;
// `LazyLock`から`String`が取得され、`&String`が返される
let _ = &*DEEP_THOUGHT;

LazyLockでフィールドを初期化する。

use std::sync::LazyLock;

#[derive(Debug)]
struct UseCellLock {
    number: LazyLock<u32>,
}
fn main() {
    let lock: LazyLock<u32> = LazyLock::new(|| 0u32);

    let data = UseCellLock { number: lock };
    println!("{}", *data.number);
}

Duration::div_duration_f32

原典

impl Duration {
    #[stable(feature = "div_duration", since = "1.80.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
    pub const fn div_duration_f32(self, rhs: Duration) -> f32
    { /* 実装は省略 */ }
}

DurationDurationで割り、f32を返す。

サンプル

use std::time::Duration;

let dur1 = Duration::new(2, 700_000_000);
let dur2 = Duration::new(5, 400_000_000);
assert_eq!(dur1.div_duration_f32(dur2), 0.5);

Duration::div_duration_f64

原典

impl Duration {
    #[stable(feature = "div_duration", since = "1.80.0")]
    #[must_use = "this returns the result of the operation, \
                  without modifying the original"]
    #[inline]
    #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
    pub const fn div_duration_f64(self, rhs: Duration) -> f64
    { /* 実装は省略 */ }
}

DurationDurationで割り、f64を返す。

サンプル

use std::time::Duration;

let dur1 = Duration::new(2, 700_000_000);
let dur2 = Duration::new(5, 400_000_000);
assert_eq!(dur1.div_duration_f64(dur2), 0.5);

Option::take_if

原典

impl<T> Option<T> {
    #[inline]
    #[stable(feature = "option_take_if", since = "1.80.0")]
    pub fn take_if<P>(&mut self, predicate: P) -> Option<T>
    where
        P: FnOnce(&mut T) -> bool,
    { /* 実装は省略 */ }
}

値への可変参照に対して述語がtrueと評価された場合にのみ、Optionから値を取り出す。

言い換えると、述語がtrueを返す場合にselfNoneに置き換える。 このメソッドはOption::takeと似た動作をするが、条件付きである。

サンプル

let mut x = Some(42);

let prev = x.take_if(|v| if *v == 42 {
    *v += 1;
    false
} else {
    false
});
assert_eq!(x, Some(43));
assert_eq!(prev, None);

let prev = x.take_if(|v| *v == 43);
assert_eq!(x, None);
assert_eq!(prev, Some(43));

Seek::seek_relative

原典

pub trait Seek {
    #[stable(feature = "seek_seek_relative", since = "1.80.0")]
    fn seek_relative(&mut self, offset: i64) -> Result<()>
    { /* 実装は省略 */ }
}

現在位置を基準としてシークする。

これはself.seek(SeekFrom::Current(offset))と同等だが新しい位置を返さないため、 BufReaderのような一部実装ではより効率的にシークすることが出来る。

サンプル

use std::{
    io::{self, Seek},
    fs::File,
};

fn main() -> io::Result<()> {
    let mut f = File::open("hoge.txt")?;
    f.seek_relative(10)?;
    assert_eq!(f.stream_position()?, 10);
    Ok(())
}

BinaryHeap::as_slice

原典

impl<T, A: Allocator> BinaryHeap<T, A> {
    #[must_use]
    #[stable(feature = "binary_heap_as_slice", since = "1.80.0")]
    pub fn as_slice(&self) -> &[T]
    { /* 実装は省略 */ }
}

内包するVec内におけるすべての値を任意の順序でスライスとして返す。

サンプル

基本的な使い方。

use std::collections::BinaryHeap;
use std::io::{self, Write};

let heap = BinaryHeap::from([1, 2, 3, 4, 5, 6, 7]);

io::sink().write(heap.as_slice()).unwrap();

NonNull::offset

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[must_use = "returns a new pointer rather than modifying its argument"]
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
    pub const unsafe fn offset(self, count: isize) -> Self
    where
        T: Sized,
    { /* 実装は省略 */ }
}

ポインタにオフセットを足す。

countは型Tの単位である。例えばcountが3の場合、ポインタのオフセットは3 * size_of::<T>()バイトを表す。

安全性

いずれかの条件に違反した場合、結果は未定義動作となる。

  • 計算されたオフセットcount * size_of::<T>()バイトがisizeの範囲を超えてはならない
  • 計算されたオフセットが0でない場合、selfは何らかの割当済みオブジェクトへのポインタから派生しなければならず、 selfと結果間の全メモリ範囲は、その割当済みオブジェクトの範囲内でなければならない。特に、この範囲はアドレス空間の端を 「回り込み」してはいけない

割当済みオブジェクトはisize::MAXバイトより大きくなることはないため、計算されたオフセットが 割当済みオブジェクトの範囲内に収まる場合、1つ目の条件を満たすことが保証される。 これは、例えばvec.as_ptr().add(vec.len())vecVec<T>の場合)は常に安全であることを意味する。

サンプル

use std::ptr::NonNull;

let mut s = [1, 2, 3];
let ptr: NonNull<u32> = NonNull::new(s.as_mut_ptr()).unwrap();

unsafe {
    println!("{}", ptr.offset(1).read());
    println!("{}", ptr.offset(2).read());
}

NonNull::byte_offset

原典

impl<T: ?Sized> NonNull<T> {
    #[must_use]
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
    pub const unsafe fn byte_offset(self, count: isize) -> Self
    { /* 実装は省略 */ }
}

ポインタからのオフセットをバイト単位で計算する。

countバイト単位である

これは、u8ポインタにキャストしてoffsetすることへの近道である。 詳細と安全要件についてはそのメソッドを参照。

ポインタの示す先が非Sizedの場合、この操作はデータポインタのみを変更し、メタデータは変更しない。

NonNull::add

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[must_use = "returns a new pointer rather than modifying its argument"]
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
    pub const unsafe fn add(self, count: usize) -> Self
    where
        T: Sized,
    { /* 実装は省略 */ }
}

ポインタにオフセットを足す(.offset(count as isize)への近道)。

countは型Tの単位である。例えばcountが3の場合、ポインタのオフセットは3 * size_of::<T>()バイトを表す。

安全性

いずれかの条件に違反した場合、結果は未定義動作となる。

  • 計算されたオフセットcount * size_of::<T>()バイトがisizeの範囲を超えてはならない
  • 計算されたオフセットが0でない場合、selfは何らかの割当済みオブジェクトへのポインタから派生しなければならず、 selfと結果間の全メモリ範囲は、その割当済みオブジェクトの範囲内でなければならない。特に、この範囲はアドレス空間の端を 「回り込み」してはいけない

割当済みオブジェクトはisize::MAXバイトより大きくなることはないため、計算されたオフセットが 割当済みオブジェクトの範囲内に収まる場合、1つ目の条件を満たすことが保証される。 これは、例えばvec.as_ptr().add(vec.len())vecVec<T>の場合)は常に安全であることを意味する。

サンプル

use std::ptr::NonNull;

let s: &str = "123";
let ptr: NonNull<u8> = NonNull::new(s.as_ptr().cast_mut()).unwrap();

unsafe {
    println!("{}", ptr.add(1).read() as char);
    println!("{}", ptr.add(2).read() as char);
}

NonNull::byte_add

原典

    #[must_use]
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[rustc_allow_const_fn_unstable(set_ptr_value)]
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
    pub const unsafe fn byte_add(self, count: usize) -> Self

ポインタからのオフセットをバイト単位で計算する(.byte_offset(count as isize)への近道)。

countはバイト単位である。

これは、u8ポインタにキャストしてaddすることへの近道である。 詳細と安全要件についてはそのメソッドを参照。

ポインタの示す先が非Sizedの場合、この操作はデータポインタのみを変更し、メタデータは変更しない。

NonNull::sub

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[must_use = "returns a new pointer rather than modifying its argument"]
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_allow_const_fn_unstable(unchecked_neg)]
    pub const unsafe fn sub(self, count: usize) -> Self
    where
        T: Sized,
    { /* 実装は省略 */ }
}

ポインタからオフセットを引く(.offset((count as isize).wrapping_neg())への近道)。

countは型Tの単位である。例えばcountが3の場合、ポインタのオフセットは3 * size_of::<T>()バイトを表す。

安全性

いずれかの条件に違反した場合、結果は未定義動作となる。

  • 計算されたオフセットcount * size_of::<T>()バイトがisizeの範囲を超えてはならない
  • 計算されたオフセットが0でない場合、selfは何らかの割当済みオブジェクトへのポインタから派生しなければならず、 selfと結果間の全メモリ範囲は、その割当済みオブジェクトの範囲内でなければならない。特に、この範囲はアドレス空間の端を 「回り込み」してはいけない

割当済みオブジェクトはisize::MAXバイトより大きくなることはないため、計算されたオフセットが 割当済みオブジェクトの範囲内に収まる場合、1つ目の条件を満たすことが保証される。 これは、例えばvec.as_ptr().add(vec.len())vecVec<T>の場合)は常に安全であることを意味する。

サンプル

use std::ptr::NonNull;

let s: &str = "123";

unsafe {
    let end: NonNull<u8> = NonNull::new(s.as_ptr().cast_mut()).unwrap().add(3);
    println!("{}", end.sub(1).read() as char);
    println!("{}", end.sub(2).read() as char);
}

NonNull::byte_sub

原典

impl<T: ?Sized> NonNull<T> {
    #[must_use]
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[rustc_allow_const_fn_unstable(set_ptr_value)]
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
    pub const unsafe fn byte_sub(self, count: usize) -> Self
    { /* 実装は省略 */ }
}

ポインタからのオフセットをバイト単位で計算する(.byte_offset((count as isize).wrapping_neg())への近道)。

countはバイト単位である。

これは、u8ポインタにキャストしてsubすることへの近道である。 詳細と安全要件についてはそのメソッドを参照。

ポインタの示す先が非Sizedの場合、この操作はデータポインタのみを変更し、メタデータは変更しない。

NonNull::offset_from

原典

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

2つのポインタ間の距離を計算する。戻り値はTの単位であり、バイト単位での距離をmem::size_of::<T>()で割った値。

これは(self as isize - origin as isize) / (mem::size_of::<T>() as isize)と同等だが、 コンパイラが何をしているのかを理解しやすい代わりに未定義動作を引き起こす可能性に満ちている。

このメソッドの主な動機は、現在「開始」と「終了」ポインタ(「終了」は配列の「終端の次」の位置)として表している Tの配列・スライスのlenを計算することにある。その場合、end.offset_from(start)は配列の長さを得る。

この用例では次の安全要件すべてが当然に満たされる。

安全性

いずれかの条件に違反した場合、結果は未定義動作となる。

  • selforiginはいずれかを満たさなければならない
  • 同じアドレスを指している
  • 両方が同じ割当済みオブジェクトへのポインタから派生しており、その2ポインタ間のメモリ範囲が そのオブジェクトの範囲内である(例は下記を参照)

  • ポインタ間の距離(バイト単位)はTの大きさの正確な倍数である必要がある

その結果、ポインタ間の絶対距離(バイト単位)は、数学的に整数で計算した場合(「回り込み」なしに) isizeをオーバーフローすることはない。これは範囲内の要件と、割当済みオブジェクトがisize::MAXより 大きくなることはないという事実による。

ポインタが同じ割当済みオブジェクトから派生するという要件は、主にconst互換性のためである。 異なる割当済みオブジェクトへのポインタ間の距離はコンパイル時には不明である。 ただしこの要件は実行時にも存在し、最適化によって悪用される可能性がある。 同じ割当由来であることが保証されないポインタ間の距離を計算する場合は、(self as isize - origin as isize) / mem::size_of::<T>()を使用すること。

パニック

この関数は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(ptr1), 2);
    assert_eq!(ptr1.offset_from(ptr2), -2);
    assert_eq!(ptr1.offset(2), ptr2);
    assert_eq!(ptr2.offset(-2), ptr1);
}

間違った使い方。

#![feature(strict_provenance)]
use std::ptr::NonNull;

let ptr1 = NonNull::new(Box::into_raw(Box::new(0u8))).unwrap();
let ptr2 = NonNull::new(Box::into_raw(Box::new(1u8))).unwrap();
let diff = (ptr2.addr().get() as isize).wrapping_sub(ptr1.addr().get() as isize);
// Make ptr2_other an "alias" of ptr2.add(1), but derived from ptr1.
let diff_plus_1 = diff.wrapping_add(1);
let ptr2_other = NonNull::new(ptr1.as_ptr().wrapping_byte_offset(diff_plus_1)).unwrap();
assert_eq!(ptr2.addr(), ptr2_other.addr());
// Since ptr2_other and ptr2 are derived from pointers to different objects,
// computing their offset is undefined behavior, even though
// they point to addresses that are in-bounds of the same object!

let one = unsafe { ptr2_other.offset_from(ptr2) }; // Undefined Behavior! ⚠️

NonNull::byte_offset_from

原典

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

2つのポインタ間の距離を計算する。戻り値はバイト単位である。

これは、u8ポインタにキャストしてoffset_fromすることへの近道である。 詳細と安全要件についてはそのメソッドを参照。

ポインタの示す先が非Sizedの場合、この操作はデータポインタのみを考慮し、メタデータは無視する。

NonNull::read

原典

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

selfからムーブすることなく値を読み取る。これはselfのメモリを変更しない。

安全性に関する懸念や例についてはptr::readを参照。

NonNull::read_volatile

原典

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

selfからムーブすることなく、揮発的に値を読み取る。これはselfのメモリを変更しない。

揮発操作はI/Oメモリに対して行われることが意図されており、他の揮発操作との間で 除外されたり並べ替えられたりしないことが保証される。

安全性に関する懸念や例についてはptr::read_volatileを参照。

NonNull::read_unaligned

原典

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

selfからムーブすることなく値を読み取る。これはselfのメモリを変更しない。

readと異なり、ポインタはアライメントされていなくても良い。

安全性に関する懸念や例についてはptr::read_unalignedを参照。

NonNull::write

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
    pub const unsafe fn write(self, val: T)
    where
        T: Sized,
    { /* 実装は省略 */ }
}

指定された値でメモリ位置を上書きするが、古い値を読み取ったり破棄したりはしない。

安全性に関する懸念や例についてはptr::writeを参照。

NonNull::write_volatile

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    pub unsafe fn write_volatile(self, val: T)
    where
        T: Sized,
    { /* 実装は省略 */ }
}

指定された値でメモリ位置を揮発的に上書きするが、古い値を読み取ったり破棄したりはしない。

揮発操作はI/Oメモリに対して行われることが意図されており、他の揮発操作との間で 除外されたり並べ替えられたりしないことが保証される。

安全性に関する懸念や例についてはptr::write_volatileを参照。

NonNull::write_unaligned

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
    pub const unsafe fn write_unaligned(self, val: T)
    where
        T: Sized,
    { /* 実装は省略 */ }
}

指定された値でメモリ位置を上書きするが、古い値を読み取ったり破棄したりはしない。

writeと異なり、ポインタはアライメントされていなくても良い。

安全性に関する懸念や例についてはptr::write_unalignedを参照。

NonNull::write_bytes

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[doc(alias = "memset")]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
    pub const unsafe fn write_bytes(self, val: u8, count: usize)
    where
        T: Sized,
    { /* 実装は省略 */ }
}

指定されたポインタに対してmemsetを呼び出し、startからcount * size_of::<T>()バイト分のメモリをvalに設定する。

安全性に関する懸念や例についてはptr::write_bytesを参照。

NonNull::copy_to

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
    pub const unsafe fn copy_to(self, dest: NonNull<T>, count: usize)
    where
        T: Sized,
    { /* 実装は省略 */ }
}

selfからdestcount * size_of<T>バイトをコピーする。入力と出力は重複しても構わない。

注意:この関数の引数はptr::copy同じ順序である。

安全性に関する懸念や例についてはptr::copyを参照。

NonNull::copy_to_nonoverlapping

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
    pub const unsafe fn copy_to_nonoverlapping(self, dest: NonNull<T>, count: usize)
    where
        T: Sized,
    { /* 実装は省略 */ }
}

selfからdestcount * size_of<T>バイトをコピーする。入力と出力は重複してはならない

注意:この関数の引数はptr::copy_nonoverlapping同じ順序である。

安全性に関する懸念や例についてはptr::copy_nonoverlappingを参照。

NonNull::copy_from

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
    pub const unsafe fn copy_from(self, src: NonNull<T>, count: usize)
    where
        T: Sized,
    { /* 実装は省略 */ }
}

srcからselfcount * size_of<T>バイトをコピーする。入力と出力は重複しても構わない。

注意:この関数の引数はptr::copy逆の順序である。

安全性に関する懸念や例についてはptr::copyを参照。

NonNull::copy_from_nonoverlapping

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
    pub const unsafe fn copy_from_nonoverlapping(self, src: NonNull<T>, count: usize)
    where
        T: Sized,
    { /* 実装は省略 */ }
}

srcからselfcount * size_of<T>バイトをコピーする。入力と出力は重複してはならない

注意:この関数の引数はptr::copy_nonoverlapping逆の順序である。

安全性に関する懸念や例についてはptr::copy_nonoverlappingを参照。

NonNull::replace

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    pub unsafe fn replace(self, src: T) -> T
    where
        T: Sized,
    { /* 実装は省略 */ }
}

selfにある値をsrcで置き換える。古い値を返すが、いずれも破棄はしない。

安全性に関する懸念や例についてはptr::replaceを参照。

NonNull::swap

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_unstable(feature = "const_swap", issue = "83163")]
    pub const unsafe fn swap(self, with: NonNull<T>)
    where
        T: Sized,
    { /* 実装は省略 */ }
}

2つの異なる位置にある同じ型の値を交換するが、どちらも非初期化しない。 mem::swapとほとんど機能が同等であるが、重複しても構わない。

安全性に関する懸念や例についてはptr::swapを参照。

NonNull::drop_in_place

原典

impl<T: ?Sized> NonNull<T> {
    #[inline(always)]
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    pub unsafe fn drop_in_place(self)
    { /* 実装は省略 */ }
}

ポインタが指す値にデストラクタがあればそれ実行する。

安全性に関する懸念や例についてはptr::drop_in_placeを参照。

NonNull::align_offset

原典

impl<T: ?Sized> NonNull<T> {
    #[inline]
    #[must_use]
    #[stable(feature = "non_null_convenience", since = "1.80.0")]
    #[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
    pub const fn align_offset(self, align: usize) -> usize
    where
        T: Sized,
    { /* 実装は省略 */ }
}

ポインタのアライメントをalignに揃えるために適用する必要のあるオフセットを計算する。

ポインタのアライメントを揃えることが不可能な場合、実装はusize::MAXを返すことがある。 また実装が常にusize::MAXを返すことも許容される。 ここで使用可能なオフセットを得られるかどうかはアルゴリズムの性能にのみ依存し、 その正確さには依存しない。

オフセットはバイト単位ではなく、T要素の数で表される。

ポインタをオフセットした結果がオーバーフローしない、またはポインタが指す割当を超えないという保証は一切ない。 返されるオフセットがアライメント以外のすべての点で正しいことを確認するのは呼び出し元の責任である。

パニック

alignが2のべき乗でない場合、この関数はパニックする。

サンプル

隣接するu8u16としてアクセスする

use std::mem::align_of;
use std::ptr::NonNull;

let x = [5_u8, 6, 7, 8, 9];
let ptr = NonNull::new(x.as_ptr() as *mut u8).unwrap();
let offset = ptr.align_offset(align_of::<u16>());

if offset < x.len() - 1 {
    let u16_ptr = ptr.add(offset).cast::<u16>();
    assert!(u16_ptr.read() == u16::from_ne_bytes([5, 6]) || u16_ptr.read() == u16::from_ne_bytes([6, 7]));
} else {
    // ポインタは`offset`でアライメントを揃えることができるが、
    // 割当範囲外を指すことになる
}
use std::mem::align_of;
use std::ptr::NonNull;

unsafe {
let x = [5_u8, 6, 7, 8, 9];
let ptr = NonNull::new(x.as_ptr() as *mut u8).unwrap();
let offset = ptr.align_offset(align_of::<u16>());

if offset < x.len() - 1 {
    let u16_ptr = ptr.add(offset).cast::<u16>();
    assert!(u16_ptr.read() == u16::from_ne_bytes([5, 6]) || u16_ptr.read() == u16::from_ne_bytes([6, 7]));
} else {
    // ポインタは`offset`でアライメントを揃えることができるが、
    // 割当範囲外を指すことになる
}
}

<[T]>::split_at_checked

原典

impl<T> [T] {
    #[stable(feature = "split_at_checked", since = "1.80.0")]
    #[rustc_const_stable(feature = "split_at_checked", since = "1.80.0")]
    #[inline]
    #[must_use]
    pub const fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])>
    { /* 実装は省略 */ }
}

スライスをインデックスで2つに分割する。スライスが小さすぎる場合はNoneを返す。

mid ≤ lenの場合はスライスを2つの組で返す。 1つ目は[0, mid)mid自体を含まない)の範囲をすべて含み、 2つ目は[mid, len)len自体を含まない)の範囲をすべて含む。

それ以外の場合、つまりmid > lenの場合はNoneを返す。

サンプル

let v = [1, -2, 3, -4, 5, -6];

{
   let (left, right) = v.split_at_checked(0).unwrap();
   assert_eq!(left, []);
   assert_eq!(right, [1, -2, 3, -4, 5, -6]);
}

{
    let (left, right) = v.split_at_checked(2).unwrap();
    assert_eq!(left, [1, -2]);
    assert_eq!(right, [3, -4, 5, -6]);
}

{
    let (left, right) = v.split_at_checked(6).unwrap();
    assert_eq!(left, [1, -2, 3, -4, 5, -6]);
    assert_eq!(right, []);
}

assert_eq!(None, v.split_at_checked(7));

<[T]>::split_at_mut_checked

原典

impl<T> [T] {
    #[stable(feature = "split_at_checked", since = "1.80.0")]
    #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")]
    #[inline]
    #[must_use]
    pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut [T], &mut [T])>
    { /* 実装は省略 */ }
}

可変スライスをインデックスで2つに分割する。スライスが小さすぎる場合はNoneを返す。

mid ≤ lenの場合はスライスを2つの組で返す。 1つ目は[0, mid)mid自体を含まない)の範囲をすべて含み、 2つ目は[mid, len)len自体を含まない)の範囲をすべて含む。

それ以外の場合、つまりmid > lenの場合はNoneを返す。

サンプル

let mut v = [1, 0, 3, 0, 5, 6];

if let Some((left, right)) = v.split_at_mut_checked(2) {
    assert_eq!(left, [1, 0]);
    assert_eq!(right, [3, 0, 5, 6]);
    left[1] = 2;
    right[1] = 4;
}
assert_eq!(v, [1, 2, 3, 4, 5, 6]);

assert_eq!(None, v.split_at_mut_checked(7));

str::split_at_checked

原典

impl str {
    #[inline]
    #[must_use]
    #[stable(feature = "split_at_checked", since = "1.80.0")]
    pub fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)>
    { /* 実装は省略 */ }
}

文字列をインデックスで2つに分割する。

引数midは文字列の開始位置からの有効なバイトオフセットでなければならず、 またUTF-8コードポイントの境界上にある必要がある。そうでない場合、このメソッドはNoneを返す。

返される2つのスライスは、文字列スライスの開始からmidまでと、midから文字列スライスの終わりまでを含む。

可変な文字列スライスが必要な場合はsplit_at_mut_checkedを参照。

サンプル

let s = "Per Martin-Löf";

let (first, last) = s.split_at_checked(3).unwrap();
assert_eq!("Per", first);
assert_eq!(" Martin-Löf", last);

assert_eq!(None, s.split_at_checked(13));  // Inside “ö”
assert_eq!(None, s.split_at_checked(16));  // Beyond the string length

str::split_at_mut_checked

原典

impl str {
    #[inline]
    #[must_use]
    #[stable(feature = "split_at_checked", since = "1.80.0")]
    pub fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut str, &mut str)>
    { /* 実装は省略 */ }
}

可変文字列をインデックスで2つに分割する。

引数midは文字列の開始位置からの有効なバイトオフセットでなければならず、 またUTF-8コードポイントの境界上にある必要がある。そうでない場合、このメソッドはNoneを返す。

返される2つのスライスは、文字列スライスの開始からmidまでと、midから文字列スライスの終わりまでを含む。

不変な文字列スライスが必要な場合はsplit_at_checkedを参照。

サンプル

let mut s = "Per Martin-Löf".to_string();
if let Some((first, last)) = s.split_at_mut_checked(3) {
    first.make_ascii_uppercase();
    assert_eq!("PER", first);
    assert_eq!(" Martin-Löf", last);
}
assert_eq!("PER Martin-Löf", s);

assert_eq!(None, s.split_at_mut_checked(13));  // Inside “ö”
assert_eq!(None, s.split_at_mut_checked(16));  // Beyond the string length

str::trim_ascii

原典

impl str {
    #[must_use = "this returns the trimmed string as a new slice, \
                  without modifying the original"]
    #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
    #[inline]
    pub const fn trim_ascii(&self) -> &str
    { /* 実装は省略 */ }
}

先頭と末尾のASCII空白文字が削除された文字列スライスを返す。

「空白文字」とはu8::is_ascii_whitespaceで定義されているものを示す。

サンプル

assert_eq!("\r hello world\n ".trim_ascii(), "hello world");
assert_eq!("  ".trim_ascii(), "");
assert_eq!("".trim_ascii(), "");

str::trim_ascii_start

原典

impl str {
    #[must_use = "this returns the trimmed string as a new slice, \
                  without modifying the original"]
    #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
    #[inline]
    pub const fn trim_ascii_start(&self) -> &str
    { /* 実装は省略 */ }
}

先頭のASCII空白文字が削除された文字列スライスを返す。

「空白文字」とはu8::is_ascii_whitespaceで定義されているものを示す。

サンプル

assert_eq!(" \t \u{3000}hello world\n".trim_ascii_start(), "\u{3000}hello world\n");
assert_eq!("  ".trim_ascii_start(), "");
assert_eq!("".trim_ascii_start(), "");

str::trim_ascii_end

原典

impl str {
    #[must_use = "this returns the trimmed string as a new slice, \
                  without modifying the original"]
    #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
    #[inline]
    pub const fn trim_ascii_end(&self) -> &str
    { /* 実装は省略 */ }
}

末尾のASCII空白文字が削除された文字列スライスを返す。

「空白文字」とはu8::is_ascii_whitespaceで定義されているものを示す。

サンプル

assert_eq!("\r hello world\u{3000}\n ".trim_ascii_end(), "\r hello world\u{3000}");
assert_eq!("  ".trim_ascii_end(), "");
assert_eq!("".trim_ascii_end(), "");

<[u8]>::trim_ascii

原典

impl [u8] {
    #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
    #[inline]
    pub const fn trim_ascii(&self) -> &[u8]
    { /* 実装は省略 */ }
}

先頭と末尾のASCII空白バイトが削除されたバイトスライスを返す。

「空白文字」とはu8::is_ascii_whitespaceで定義されているものを示す。

サンプル

assert_eq!(b"\r hello world\n ".trim_ascii(), b"hello world");
assert_eq!(b"  ".trim_ascii(), b"");
assert_eq!(b"".trim_ascii(), b"");

<[u8]>::trim_ascii_start

原典

impl [u8] {
    #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
    #[inline]
    pub const fn trim_ascii_start(&self) -> &[u8]
    { /* 実装は省略 */ }
}

先頭のASCII空白バイトが削除されたバイトスライスを返す。

「空白文字」とはu8::is_ascii_whitespaceで定義されているものを示す。

サンプル

assert_eq!(b" \t hello world\n".trim_ascii_start(), b"hello world\n");
assert_eq!(b"  ".trim_ascii_start(), b"");
assert_eq!(b"".trim_ascii_start(), b"");

<[u8]>::trim_ascii_end

原典

impl [u8] {
    #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
    #[inline]
    pub const fn trim_ascii_end(&self) -> &[u8]
    { /* 実装は省略 */ }
}

末尾のASCII空白バイトが削除されたバイトスライスを返す。

「空白文字」とはu8::is_ascii_whitespaceで定義されているものを示す。

サンプル

assert_eq!(b"\r hello world\n ".trim_ascii_end(), b"\r hello world");
assert_eq!(b"  ".trim_ascii_end(), b"");
assert_eq!(b"".trim_ascii_end(), b"");

Ipv4Addr::BITS

原典

impl Ipv4Addr {
    #[stable(feature = "ip_bits", since = "1.80.0")]
    pub const BITS: u32 = 32;
}

IPv4アドレスの、ビット単位の大きさ。

サンプル

use std::net::Ipv4Addr;

assert_eq!(Ipv4Addr::BITS, 32);

Ipv4Addr::to_bits

原典

impl Ipv4Addr {
    #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
    #[stable(feature = "ip_bits", since = "1.80.0")]
    #[must_use]
    #[inline]
    pub const fn to_bits(self) -> u32
    { /* 実装は省略 */ }
}

IPv4アドレスを、ネイティブなバイト順序でu32表現に変換する。

IPv4アドレスはビッグエンディアンであるが、u32の値は対象プラットフォームのネイティブなバイト順序で使用される。 つまり、u32の値はIPv4アドレスの整数表現であり、IPv4アドレスのビッグエンディアンにおけるビット列の整数解釈ではない。 これにより、u32の値に0xffffff00をマスクすると、対象プラットフォームのエンディアンに関係なく アドレスの最後のオクテットが0に設定される。

サンプル

use std::net::Ipv4Addr;

let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78);
assert_eq!(0x12345678, addr.to_bits());
use std::net::Ipv4Addr;

let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78);
let addr_bits = addr.to_bits() & 0xffffff00;
assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x00), Ipv4Addr::from_bits(addr_bits));

Ipv4Addr::from_bits

原典

impl Ipv4Addr {
    #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
    #[stable(feature = "ip_bits", since = "1.80.0")]
    #[must_use]
    #[inline]
    pub const fn from_bits(bits: u32) -> Ipv4Addr
    { /* 実装は省略 */ }
}

ネイティブなバイト順序のu32IPv4アドレスに変換する。

エンディアンについての説明はIpv4Addr::to_bitsを参照。

サンプル

use std::net::Ipv4Addr;

let addr = Ipv4Addr::from(0x12345678);
assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr);

Ipv6Addr::BITS

原典

impl Ipv6Addr {
    #[stable(feature = "ip_bits", since = "1.80.0")]
    pub const BITS: u32 = 128;
}

IPv6アドレスの、ビット単位の大きさ。

サンプル

use std::net::Ipv6Addr;

assert_eq!(Ipv6Addr::BITS, 128);

Ipv6Addr::to_bits

原典

impl Ipv6Addr {
    #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
    #[stable(feature = "ip_bits", since = "1.80.0")]
    #[must_use]
    #[inline]
    pub const fn to_bits(self) -> u128
    { /* 実装は省略 */ }
}

IPv6アドレスを、ネイティブなバイト順序でu128表現に変換する。

IPv6アドレスはビッグエンディアンであるが、u128の値は対象プラットフォームのネイティブなバイト順序で使用される。 つまり、u128の値はIPv6アドレスの整数表現であり、IPv6アドレスのビッグエンディアンにおけるビット列の整数解釈ではない。 これにより、u128の値に0xffffffffffffffffffffffffffff0000_u128をマスクすると、対象プラットフォームのエンディアンに関係なく アドレスの最後のオクテットが0に設定される。

サンプル

use std::net::Ipv6Addr;

let addr = Ipv6Addr::new(
    0x1020, 0x3040, 0x5060, 0x7080,
    0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
);
assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr));
use std::net::Ipv6Addr;

let addr = Ipv6Addr::new(
    0x1020, 0x3040, 0x5060, 0x7080,
    0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
);
let addr_bits = addr.to_bits() & 0xffffffffffffffffffffffffffff0000_u128;
assert_eq!(
    Ipv6Addr::new(
        0x1020, 0x3040, 0x5060, 0x7080,
        0x90A0, 0xB0C0, 0xD0E0, 0x0000,
    ),
    Ipv6Addr::from_bits(addr_bits));

Ipv6Addr::from_bits

原典

impl Ipv6Addr {
    #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
    #[stable(feature = "ip_bits", since = "1.80.0")]
    #[must_use]
    #[inline]
    pub const fn from_bits(bits: u128) -> Ipv6Addr
    { /* 実装は省略 */ }
}

ネイティブなバイト順序のu128IPv6アドレスに変換する。

エンディアンについての説明はIpv6Addr::to_bitsを参照。

サンプル

use std::net::Ipv6Addr;

let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128);
assert_eq!(
    Ipv6Addr::new(
        0x1020, 0x3040, 0x5060, 0x7080,
        0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
    ),
    addr);

Vec::<[T; N]>::into_flattened

原典

impl<T, A: Allocator, const N: usize> Vec<[T; N], A> {
    #[stable(feature = "slice_flatten", since = "1.80.0")]
    pub fn into_flattened(self) -> Vec<T, A>
    { /* 実装は省略 */ }
}

Vec<[T; N]>Vec<T>へと平たくする。

パニック

返されるVecの長さがusizeをオーバーフローする場合はパニックする。

これは大きさのない型の配列のVecを平たくする場合にのみ発生する可能性があり、 実際には意味がないことが多い。size_of::<T>() > 0の場合、これがパニックすることはあり得ない。

サンプル

let mut vec = vec![[1, 2, 3], [4, 5, 6], [7, 8, 9]];
assert_eq!(vec.pop(), Some([7, 8, 9]));

let mut flattened = vec.into_flattened();
assert_eq!(flattened.pop(), Some(6));

<[[T; N]]>::as_flattened

原典

impl<T, const N: usize> [[T; N]] {
    #[stable(feature = "slice_flatten", since = "1.80.0")]
    #[rustc_const_unstable(feature = "const_slice_flatten", issue = "95629")]
    pub const fn as_flattened(&self) -> &[T]
    { /* 実装は省略 */ }
}

&[[T; N]]&[T]へと平たくする。

パニック

返されるスライスの長さがusizeをオーバーフローする場合はパニックする。

これは大きさのない型の配列のスライスを平たくする場合にのみ発生する可能性があり、 実際には意味がないことが多い。size_of::<T>() > 0の場合、これがパニックすることはあり得ない。

サンプル

assert_eq!([[1, 2, 3], [4, 5, 6]].as_flattened(), &[1, 2, 3, 4, 5, 6]);

assert_eq!(
    [[1, 2, 3], [4, 5, 6]].as_flattened(),
    [[1, 2], [3, 4], [5, 6]].as_flattened(),
);

let slice_of_empty_arrays: &[[i32; 0]] = &[[], [], [], [], []];
assert!(slice_of_empty_arrays.as_flattened().is_empty());

let empty_slice_of_arrays: &[[u32; 10]] = &[];
assert!(empty_slice_of_arrays.as_flattened().is_empty());

<[[T; N]]>::as_flattened_mut

原典

    #[stable(feature = "slice_flatten", since = "1.80.0")]
    pub fn as_flattened_mut(&mut self) -> &mut [T]
    { /* 実装は省略 */ }
}

&mut [[T; N]]&[T]へと平たくする。

パニック

返されるスライスの長さがusizeをオーバーフローする場合はパニックする。

これは大きさのない型の配列のスライスを平たくする場合にのみ発生する可能性があり、 実際には意味がないことが多い。size_of::<T>() > 0の場合、これがパニックすることはあり得ない。

サンプル

fn add_5_to_all(slice: &mut [i32]) {
    for i in slice {
        *i += 5;
    }
}

let mut array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
add_5_to_all(array.as_flattened_mut());
assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]);

変更点リスト

言語

コンパイラ

ライブラリ

安定化されたAPI

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

Cargo

Rustdoc

互換性メモ

内部の変更

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

関連リンク

さいごに

次のリリースのRust 1.81は9/6(金)にリリースされる予定です。 Rust 1.81では巻き戻しのできるC ABIが使えるようになったりソートの実装が置き換わったりするようです。

ライセンス表記

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



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

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