Rustの「dyn Trait」を丸裸に!メモリ上のvtable構造を徹底解剖
Visualizing Rust's Vtables: How dyn Trait Works In Memory
Visualizing Rust's Vtables: How dyn Trait Works In Memory
Rustのポリモーフィズムの要である「dyn Trait」。でも、実際にメモリ上でどのようなデータ構造になっているのか、意外と知られていないのではないでしょうか?この記事では、Rustのvtable(仮想関数テーブル)が裏側でどう動いているのか、メモリレイアウトの仕組みとともに分かりやすく解説します。dyn Traitの仕組みを理解して、Rustのパフォーマンスをより深く最適化しましょう。
Rustの場合、その問いに対する答えはコンパイル時にボローチェッカーが教えてくれるよね。(ゼロサイズオブジェクトが同一かどうかについて)でも、だからといってプログラマーが確認する必要が一切なくなるってわけじゃないよね?もしボローチェッカーからその情報を知りたい場合、どうやって取得すればいいんだろ?C++の導入部みたいに「C++では2つのポインタが同じオブジェクトを指しているか確認するためにこうする」といった動機づけがRustにはないんだ。ボローチェッカーはすでにそのことを知っているはずなのに、なぜプログラマーがそれを知る必要があったり、ケースを分けたいと考えることを妨げることになるの?
すごくいいね。続編として、vtable自体の構造をリバースエンジニアリングするのも面白そう。たぶん、メソッド実装へのポインタのリストってことだよね?
この記事には「Object Safety(オブジェクトの安全性)」についてのセクションがあるけど、確認したら今週書かれたものだった。ただ「Object Safety」っていう名前だと混乱を招きやすいから、Rustでは少し前からこの概念を「dyn compatibility(dyn互換性)」と呼ぶようになったんだ。というのも、トレイトが「dyn compatible」であれば得られる最大のメリットが「dyn Trait」を使えるようになることだからなんだよ - https://doc.rust-lang.org/1.98.1/reference/items/traits.html... (https://doc.rust-lang.org/1.98.1/reference/items/traits.html#dyn-compatibility) そのリンクの方がルールについてもより包括的に説明しているよ。[追記:記事の最後の方でこのことに触れてた。著者は数ヶ月前から書き始めていたみたいだし、おそらく「dyn compatibility」という名称への改善を知る前だったんだろうね]