低レイヤー開発者が注目すべきRustのアップデート 2025年版
この記事はRust Advent Calendar 2025の8日目の記事です。
Rustの言語機能は6週間ごとに新バージョンがリリースされています。
私はアップデートのたびに勝手にリリースパーティというイベントでアップデートの内容を解説しています。
今年は1.84.0から1.91.0までリリースされています。それぞれ様々な変更が入っていてリリースノートを見ると日々改善されているのがわかります。
今回は今年あったアップデートから特に低レイヤー開発に関する内容をピックアップして紹介します。
naked functions
1.88.0でnaked functionsの安定化がされました。Rustの普通の関数は呼び出し時と呼び出し元に戻るときにそれぞれ特殊な処理が入ります。しかし、インラインアセンブラで自前で呼び出し元に戻る場合、呼び出し元に戻る際の処理が入らず不整合が発生してしまいます。例えば、呼び出し時にレジスタをスタックに追加して戻るときにそのスタックから値を戻すという処理だった場合、スタックがずれてしまうという問題が発生します。nakedというアトリビュートを付与された関数はこれらの特殊処理が省略されるようになり、インラインアセンブラで呼び出し元に戻ってもこのような問題が起こらないようになります。
関数に#[unsafe(naked)]というアトリビュートをつけます。アトリビュートにunsafeをつけているのに見慣れていない人もいるかもしれませんが、これはRust 2024 Editionで追加された機能です。
raw pointer関連の改善
低レイヤーで避けて通れないのが生ポインタの扱いです。生ポインタを使うとRustの特性である所有権やライフタイムの性質が効かないunsafe処理が絡むことになり扱いが難しいです。
大きな変更としては1.84.0で入ったstrict provenance APIsがあります。
生ポインタの値がどのように生成されたかを追うことができるようにできるAPIが使えることにより、MiriやCHERIなどの静的解析ツールで恩恵が得られるようです。
1.84.0では他にもポインタの参照外しへの生ポインタの生成がsafeになったり(addr_of!((*ptr).field)のようなコード。これは単にアドレスをつくっているだけで、ptrが不正な値でもアドレス値の計算自体はできるので安全)、即座にdropされる値へのポインタをつくるとlintで警告が出る変更も追加されています。
1.86.0では生ポインタアクセスでnon-nullかどうかを判定するdebug assertionsが入るようになりました。これによりdebug assertionが有効なビルドの場合、ランタイムで不正なポインタアクセスをしようとするとpanicを発生させてくれるようになります。
このようにRustの生ポインタは単にアドレス値を取り扱うだけでなく、扱いやすいように様々な工夫がされているのがわかります。
Edition 2024
今年のRust全体での大きな変更としてEdition 2024が安定化されたことが挙げられます。
Edition 2024は1.85.0から使えるようになり、詳しい変更はEdition Guideから見ることができます。
低レイヤー関連で関係がありそうなのは
-
unsafe extern
- 外部のC言語関数を呼び出すときなどに用いられる
externブロックにunsafeキーワードつけることができ、危険性をより明示的にできる
- 外部のC言語関数を呼び出すときなどに用いられる
-
unsafe attribute
-
no_mangleやextern_nameのような書き手側で安全性を証明しなければいけないアトリビュートにunsafeをつけることが必要になった
-
-
unsafe_op_in_unsafe_fn warning
-
unsafe関数内でunsafe関数を呼び出している場合、unsafeブロックで囲っていないと警告をだすlintがデフォルトに
-
-
Disallow references to static mut
-
static mutな変数への参照がコンパイルエラーになるlintがデフォルトで有効になった
-
といったところでしょうか。unsafeとつけるべき箇所が増え、lintがより厳しくなりました
target features
1.86.0で#[target_feature]がsafe関数につけることができるようになりました。
target_featureが指定されているsafe関数を呼び出すとき通常はunsafeが必要ですが、target featureが指定されている関数内から同じtarget featureが指定されているsafe関数の呼び出しはunsafeではありません。
1.87.0でstd::archに含まれていたunsafeな関数がこのtarget featuresを利用してsafeな関数になり、1.89.0ではより多くの関数がsafeとなりました。
asm goto
インラインアセンブラの中で、Rustで書かれたコードのブロックにジャンプができるようになりました。
具体的にはこのように書くことができます(ドキュメントより引用)。
unsafe {
core::arch::asm!("jmp {}", label {
println!("Hello from inline assembly label");
});
}
その他
その他の変更は以下のようなものがあります。カッコ内は導入されたバージョンです
- extern "C"のfunctionでpanicした場合、unwinding中にdropが走るように(1.84.0)
- externでABIを省略した場合に警告するlintがデフォルトで有効に (1.86)
- doctestsがcross compileに対応 (1.89.0)
- i128とu128がextern "C"の関数で利用可能に (1.89.0)
- const genericsへの推論が可能に (1.89.0)
まとめ
いかがでしたか?低レイヤー関連に絞っても1年間でかなりの変更がありました。
Rustは低レイヤー分野を安全に触れる言語として注目されていますが、これらのアップデートを活用することでより安全に書けるかもしれません。
宣伝
12/21にオフラインイベントをします。LTも募集中なのでぜひ!
Discussion