TL;DR

ポインタが指す値を、メモリ上の位置に固定(ピン留め)するための Rust の型。自己参照データ構造を安全に扱うために導入された。ただし、値を完全に固定できるわけでも、メモリ安全性を完全に保証するわけでもない。

なぜ必要か

コンパイラが生成する Future は、自分自身を指すポインタを含むことがある。これは Pin の最もよくある用途である。

These compiler-generated Futures may contain self-referential pointers, one of the most common use cases for Pin. More details on this point are provided in the pin module docs, but suffice it to say they require the guarantees provided by pinning to be implemented soundly.

自己参照データ構造の値がムーブされると、内部のポインタが古いアドレスを指したままになる。Pin は値をムーブできないようにして、この問題を防ぐ。

仕組み

Pin が固定するのは、ポインタそのものではなく、ポインタが指す値である。

It is important to stress that the thing in the Pin is not the value which we want to pin itself, but rather a pointer to that value! A Pin does not pin the Ptr but rather the pointer’s pointee value.

ヒープ上に値を固定したいときは、Box::pin を使う。ヒープ上のデータはポインタを通じて管理されるので、基本的にはムーブされにくい。

注意点

メモリアドレスを完全に固定できるわけではない

std::marker::Unpin を実装した型は、Pin::new でそのまま包めて、普通にムーブできる。そのため、完全な固定は保証されない。

If the pointee value’s type implements Unpin, we are free to disregard these requirements entirely and can wrap any pointer to that value in Pin directly via Pin::new.

適切に使うには unsafe を理解する必要がある

Pin は内部のデータへのアクセスを制限する。そのため、固定された値を直接変更しようとすると unsafe を使う必要がある。

関連

出典