読者です 読者をやめる 読者になる 読者になる

0x90

一回休み

Rustのfat pointerとclosure object

前回のコード、あれ多分間違ってます。

stackoverflow.com

みたいに、二重のBoxでFnを囲まないとだめな気がします。こんな感じ

Rust Playground

理由

Closureを型消去したTrait object、Fn(A) -> Bは、ここにあるみたいに、ポインタではなく

「data」ポインタと「vtable」ポインタから成る

usize二個分の構造体ということになります。このようなBox<Fn(A) -> B>のトレイトオブジェクトを作って初めて、closureを消費してヒープ上に持っていくことができるようになります。

いや別にinto_raw*mut Fn(A) -> Bにしてるじゃん!という気もしますが、実はこれではだめです。こちらを見てみてください。

Rust Playground

ここにも書いてありますが、Rustはfat pointerというものを持っていて、どうやらtrait objectへのポインタはメモリレイアウト上は構造体(fat pointer)でusize二個分の大きさなんだけれど、言語の中ではポインタとして扱われているようです。

ですから、fat pointerへのpointerとしなくてはなりません。

Trait object自体がfat pointerみたいなものなのに、Trait objectのポインタもfat pointerというのはなかなかうーんという感じです。あと型引数中では&Fnとかしなくてもtrait objectとして扱ってくれるのも盲点でした。