LoginSignup
6
3

More than 1 year has passed since last update.

Rustのconst関係の更新2022

Posted at

この記事はRust Advent Calendar 2022の18日目の記事です。
昨日は @MaaSaHero さんのRustでAmazon商品URLの不要部分削除するCLI作ったでした。


去年に続き2022年のconst関係の更新をまとめました。
英語がそれほど得意ではないので抜け漏れ間違いがあれば指摘いただけると助かります。

内容はリリースノートを参考にしており確認しているバージョンは 1.58.0 (2022-01-13)から1.66.0 (2022-12-15)までです。


Language

1.58.0

*const T pointers can now be dereferenced in const contexts.

定数文脈で*const Tを逆参照できるようになった。
ただし*mut Tのようなミュータブルな参照は逆参照できない。

1.59.0

Stabilize default arguments for const parameters and remove the ordering restriction for type and const parameters

  • const genericsのデフォルト値を設定できるようなった
  • genericsパラメーターの順番がライフタイム→型→定数と固定だったのをライフタイム→型or定数とできるようになった

1.61.0

const fn signatures can now include generic trait bounds

const fnの中で関数ポインタの作成、返却、キャストを可能にした。
関数ポインタから整数型へ変換や関数ポインタの呼び出しは不可。

作成と返却
const fn get_function() -> fn() {
    fn foo() {
        println!("Hello, World!");
    }
    
    foo
}
キャスト
const fn get_function() -> fn() {
    unsafe {
        std::mem::transmute(0x1234usize)
    }
}

ただし以下のような関数ポインタから整数への変換はできない

const fn fn_to_usize(f: fn()) -> usize {
    f as usize  //~ pointers cannot be cast to integers during const eval
}

以下のような関数ポインタの呼び出しもできない

const fn call_fn_ptr(f: fn()) {
    f() //~ function pointers are not allowed in const fn 
}

const fn signatures can now use impl Trait in argument and return position

const fnの中でtrait bounds(ジェネリクス境界)を使用できるようになりdyn Traitオブジェクトの受け渡しが可能になった。

const fn do_thing<T: Foo>(_x: &T) {
    // ...
}

ただしTraitの関数をconst fnとして定義できないためTraitの関数呼び出しはできない。

Function pointers can now be created, cast, and passed around in a const fn

const fnの引数と戻り値でimpl Traitが使用可能になった。

const fn do_thing(x: impl Foo) -> impl Foo {
    x
}

ただし関連型や関連定数にアクセスする以上のことはできない。

1.62.0

Fix constants not getting dropped if part of a diverging expression

特定の条件でdropが呼ばれないことがあったが修正された。
以下のコードはcbaと出力されるが修正前はcaと出力されていた。

struct Print(&'static str);

impl Drop for Print {
    fn drop(&mut self) {
        println!("{}", self.0);
    }
}

const A: Print = Print("a");
const B: Print = Print("b");

fn main() {
    loop {
        std::mem::forget(({A}, B, Print("c"), break));
    }
}

const functions may now specify extern "C" or extern "Rust"

以下のようにconst fnextern, extern "C", extern "Rust"をつけた定義ができるようになった。

const extern fn foo1() {}
const extern "C" fn foo2() {}
const extern "Rust" fn foo3() {}
const unsafe extern fn bar1() {}
const unsafe extern "C" fn bar2() {}
const unsafe extern "Rust" fn bar3() {}

1.66.0

Change constant evaluation errors from a deny-by-default lint to a hard error

定数文脈の評価時のエラーをリントのdenyからコンパイルエラーに変更した。

Stabilized APIs

以下のAPIが安定化した。

1.65.0

These APIs are now usable in const contexts:

以下のAPIが定数文脈で使用可能になった。

1.58.0

1.61.0

1.63.0

1.64.0

1.65.0

Const-stable:

以下のAPIが定数文脈でも使用可能になった。

1.59.0

Compatibility Notes

1.64.0

Errors at const-eval time are now in future incompatibility reports

将来的に定数文脈の評価時のエラーをリントのdenyからコンパイルエラーに変更するのでその前に将来エラーになるということを表示する。
補足: これは1.66.0の更新内容のChange constant evaluation errors from a deny-by-default lint to a hard errorの前段階の更新です。

所感

かなりできることが増えましたね。
Stabilized APIsとして追加されたAPIが最初からconst fnだったものなどはここに書いていないので実際はこれより多くのことが定数文脈でできるようになっています。すごいですね。
個人的にはStabilize default arguments for const parameters and remove the ordering restriction for type and const parametersでジェネリクスパラメーターの順番の自由度が上がったのが嬉しいです。
Traitの関数をconst fnにできる(const_trait_impl)更新は今年は来ませんでしたね。来年こそ来てくれると嬉しいです。


明日は@serinuntiusさんです。

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3