eyecatch

Rust 1.80.0 を簡単に見ていく

Posted on 2024/07/28
# Technology

初めに

Rust 1.80.0 がリリースされたのでメモ程度に中身を簡単にみていきます。
公式: https://blog.rust-lang.org/2024/07/25/Rust-1.80.0.html

LazyCell と LazyLock

Rust 1.70.0 で stabilizedされた OnceCellOnceLock と同じような処理。ただ違う点は LazyLock::new(f: F) で入れた f: F の initialization が 一番初めにアクセスされたタイミングでされること。

use std::sync::LazyLock;
use std::time::Instant;

// ここでは Instant::now はまだ実行されてない
static LAZY_TIME: LazyLock<Instant> = LazyLock::new(Instant::now);

fn main() {
    let start = Instant::now();
    std::thread::scope(|s| {
        s.spawn(|| {
            // ここで Initialize
            println!("Thread lazy time is {:?}", LAZY_TIME.duration_since(start));
        });

        // またはここで Initialize
        println!("Main lazy time is {:?}", LAZY_TIME.duration_since(start));
    });
}
# Output
Main lazy time is 33.416µs
Thread lazy time is 33.416µs

LazyCellLazyLock の違いは、thread_safe かどうか。
今までは lazy_staticonce_cell などの crates が対応してたが std に入った形。

OnceLock::get_or_init と異なると言っているのがどう異なるのかまだよくわかっていません。

Checked cfg names and values

--check-cfg をつけることで #[cfg(feature = "hoge")]の名前と値をチェックするようにしていたが、1.80.0からはデフォルトでチェックするようになりました。

例えば rayonという crate があるが間違って crayon としてしまったときは下記のようなエラーを表示してくれるようになりました。

fn main() {
    println!("Hello, world!");

    #[cfg(feature = "crayon")]
    rayon::join(
        || println!("Hello, Thing One!"),
        || println!("Hello, Thing Two!"),
    );
}

warning: unexpected `cfg` condition value: `crayon`
 --> src/main.rs:4:11
  |
4 |     #[cfg(feature = "crayon")]
  |           ^^^^^^^^^^--------
  |                     |
  |                     help: there is a expected value with a similar name: `"rayon"`
  |
  = note: expected values for `feature` are: `rayon`
  = help: consider adding `crayon` as a feature in `Cargo.toml`
  = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
  = note: `#[warn(unexpected_cfgs)]` on by default

Exclusive ranges in patterns

今までは下記のコードがあったとき n未満、n超 という表現ができなく a..=b というような表現をしていました。

const MAX: u32 = 100;
const MAX_MINUS_ONE: u32 = MAX - 1;

let n: u32 = 99;
match n {
    0..=MAX_MINUS_ONE => true,
    MAX.. => false,
};

このように MAX より 1 を引いた変数を用意してあげて判定する必要があったが、 a..b というように表現することが可能になりました。

const MAX: u32 = 100;

let n: u32 = 99;
match n {
    0..MAX => true,
    MAX.. => false,
};

おわり

他にもいろんな APIs が更新されていたのでゆっくり見ていきたいと思います。

Vec::into_flattened とか便利そう。