Pinを追うにはRustを追わねば�(体験版)
hsjoihs
Part 1.
?Sized 構文
皆さんは
皆さんは
str型の変数
皆さんは
str型の変数
って見たことありますか?
fn main() {
let x : str;
}
fn main() {
let x : str;
}
fn main() {
let x : str;
}
str型の値のサイズはコンパイル時に知ることができない
型が何バイトなのかを知るのは大事
コンパイル時に何バイトなのか分からないと…
コンパイル時に何バイトなのか分からないと…
コンパイル時に何バイトなのか分からないと…
コンパイル時に何バイトなのか分からないと…
コンパイル時に何バイトなのか分からないと…
えっでも let x: T = …;書いたことあるよ
えっでも let x: T = …;書いたことあるよ
はい、書けます。
fn identity<T>(a: T) -> T {
let b: T = a;
b
}
えっでも let x: T = …;書いたことあるよ
はい、書けます。
fn identity<T>(a: T) -> T {
let b: T = a;
b
}
何故!?
なぜかというと
なぜかというと
なぜかというと
なぜかというと
Part 2.
?Move 案
「ムーブされると困る値」
「ムーブされると困る値」
「ムーブされると困る値」
左図は https://www.slideshare.net/HiroakiGoto/stdpin の p.5 から引用
「ムーブされると困る値」
「ムーブされると困る値」
Rust「ムーブは常にmemcpyです」
Rust「ムーブは常にmemcpyです」
Rust「ムーブは常にmemcpyです」
Rust「ムーブは常にmemcpyです」
Rust「ムーブは常にmemcpyです」
Rust「ムーブは常にmemcpyです」
余談:自己参照構造体以外に「困る値」ないの?
余談:自己参照構造体以外に「困る値」ないの?
余談:自己参照構造体以外に「困る値」ないの?
「ムーブされると困る値」の対処
?Sizedと同じことをしよう!
?Sizedと同じことをしよう!
?Sizedと同じことをしよう!
問題点
問題点
問題点
問題点
問題点
問題点
問題点
問題点
などなどいろいろあったのですが……
ポシャった
ポシャった
ポシャった
ポシャった
Part 4.
やっとPin
最初に一番大事なことから
最初に一番大事なことから
最初に一番大事なことから
最初に一番大事なことから
じゃあ Pin ってなんなのさ
じゃあ Pin ってなんなのさ
「ある値への参照 Pin<’a, P> (ただし P は参照型であるとする)が誕生したら、
じゃあ Pin ってなんなのさ
「ある値への参照 Pin<’a, P> (ただし P は参照型であるとする)が誕生したら、
それ以降は参照されている値が動くようなことがあってはなりません」
じゃあ Pin ってなんなのさ
「ある値への参照 Pin<’a, P> (ただし P は参照型であるとする)が誕生したら、
それ以降は参照されている値が動くようなことがあってはなりません」
という契約※1 ※2
※1 ただし Unpin な値を指している Pin<’a, P> に関してはこの契約は無効
※2 drop が return するか panic したときに契約は終了する
契約の破り方
契約の破り方
契約の破り方
OKな例
// new() から返ってくる段階では、まだ Pin 参照が存在しない
// よって new() で値が返るときのムーブは契約に違反しない
let mut obj : Foo = Foo::new();
OKな例
// new() から返ってくる段階では、まだ Pin 参照が存在しない
// よって new() で値が返るときのムーブは契約に違反しない
let mut obj : Foo = Foo::new();
// obj への参照を Pin に教え、「こいつは二度と動きません」と誓約する
// unsafe、それは誓いの言葉
// さて、その結果できた Pin 参照に obj と命名する
// すると旧 obj をムーブする方法がなくなる
// 二度と旧 obj の &mut を取ることもできない
let mut obj : Pin<&mut Foo> = unsafe { Pin::new_unchecked(&mut obj) };
OKな例
// 毎回誓約書に署名するのは面倒なので、
// pin_utils::pin_mut! マクロが便利
let obj = Foo::new();
pin_utils::pin_mut!(obj);
// new() から返ってくる段階では、まだ Pin 参照が存在しない
// よって new() で値が返るときのムーブは契約に違反しない
let mut obj : Foo = Foo::new();
// obj への参照を Pin に教え、「こいつは二度と動きません」と誓約する
// unsafe、それは誓いの言葉
// さて、その結果できた Pin 参照に obj と命名する
// すると旧 obj をムーブする方法がなくなる
// 二度と旧 obj の &mut を取ることもできない
let mut obj : Pin<&mut Foo> = unsafe { Pin::new_unchecked(&mut obj) };
アウトな例
// new() から返ってくる段階では、まだ Pin 参照が存在しない
// よって new() で値が返るときのムーブは契約に違反しない
let mut obj = Foo::new();
// obj への参照を Pin に教え、「こいつは二度と動きません」と誓約する
// unsafe、それは誓いの言葉
// さて、その結果できた Pin 参照に obj と命名しない
// すると旧 obj をムーブする方法がある
// 再度、旧 obj の &mut を取ることもできる
let mut obj2 = unsafe { Pin::new_unchecked(&mut obj) };
Final
結論
結論
結論
結論
以上です
ありがとうございました
hsjoihs