Rustのdyn Traitをメモリレベルで可視化:vtableの仕組みを解剖する
Visualizing Rust's Vtables: How dyn Trait Works In Memory

Rustの動的ディスパッチ(dyn Trait)がメモリ上でどう機能するかを、C++の仮想関数やCRTPとの比較を交えながら徹底解説。ゼロサイズ型(ZST)の意外な挙動や、データポインタとvtableポインタからなるワイドポインタの構造、型とトレイトの組み合わせごとにvtableが生成される仕組みを、実際のコードと出力結果で検証します。Rustの哲学を「なぜ」の視点から理解したい人に最適です。
RustをC++の構文違いとして扱うなら、そこに革命的な価値はない。
HNでの議論
30- tialaramex
この記事にはオブジェクト安全性(Object Safety)に関するセクションがあります。確認したところ、この記事は今週書かれたものですが、「オブジェクト安全性」という名前はこの概念を表すには紛らわしいです。そのため、しばらく前からRustではこの概念を「dyn互換性(dyn compatibility)」と呼んでいます。なぜなら、トレイトが「dyn互換」であるときに得られる最も重要なことは、"dyn Trait"を使えることだからです - https://doc.rust-lang.org/1.98.1/reference/items/traits.html...
そのリンクには、ルールについてもより包括的に説明されています。
[編集:記事の最後にこの説明があることに気づきました。著者は数か月前に書き始めたので、おそらく改良された「dyn互換性」という命名について読む前だったのでしょう]
- Panzerschrek
> トレイトオブジェクトとして使うには、トレイトはオブジェクト安全性(object safety)と呼ばれるルールに従わなければなりません
これは私にはRustの大きな設計上の欠陥のように思えます。Rustはトレイトを動的ポリモーフィズムに流用しようとしていますが、完全には適合していません。C++の方が正直で、静的ポリモーフィズム(テンプレート)と動的ポリモーフィズム(継承)という2つの別々のメカニズムを持っています。
- Panzerschrek
私はかつて、Rustのファットポインタ(仮想テーブルを含む)に関する厄介なバグに直面したことがあります。そのようなポインタは、同じオブジェクトを参照していても、異なる場合があります。なぜなら、(何らかの理由で)コンパイラが仮想関数テーブルのコピーを2つ(またはそれ以上)作成し、それらを異なる場所で使うことがあるからです。
- evmar
私自身の探求の過程で、https://cheats.rs/ が非常に役立ちました。特に、その「メモリレイアウト」セクションには視覚化があります。(このサイトとは関係ありません。ただの満足した読者です!)
- returningfory2
とても良い記事です。フォローアップとして、vtable自体の構造をリバースエンジニアリングするのも面白いでしょう。おそらく、メソッド実装へのポインタのリストなのでしょうね?