みたまのライフタイム借用の勉強会
参照は型、値では借用という用語の使い分け
'aをnamed lifetimeと正式に呼ぶ
扱いとしては型変数
Haskell的な考えだとLifetime kindで修飾された型変数か
参照のライフタイムと変数のライフタイムで乱用されたりするが、参照にしかライフタイムはつかないので後者はスコープと呼ぶ
The bookがわるい
outlives制約
'a: 'b
'a outlives 'bとよむ
ライフタイムは(型なので)静的に決まらないといけない
条件分岐とかでライフタイムが変わるような場合はtermから推測がうまくいかない
そういう場合はもちろん自分でannotationをかく
Lifetime elision
ライフタイムを省略するとよくあるパターンだと仮定してライフタイムをつけてコンパイルする
なので関数のライフタイム関連のエラーは信用できない
The Bookにも書いてある
これを推論にしようという試みは行われている
常に次のGoalに書かれてる
RustコンパイラはHIR -> MIR -> LLVM IR となる
HIRは主にsyntaxまわり
MIRはControl Flow Graph(CFG)になってる
ライフタイム、所有権周りはほぼすべてここで解析される
コンパイラはすべての借用と参照型にlifetimeをつける
その後named lifetime同士の包含関係をsubtype関係として導入する
outlives制約とlifetime subtypingからある点でのlifetime constraintが推論される
これで得られる各lifetimeのlifetime constraintsの各点でのlivenessがわかり、その点の集合がlifetimeとなる
live-analysisとよぶ
ループがある場合はいい感じにloop breakして深さ優先探索が回るようにしてる
スコープ周りはリージョン推論
StorageLiveとStorageDeadがLLVMのlifetime.startとlifetime.endに変換される
MIR段階でUBがあるとLLVM IRでもUBになってしまうのでMIRが超がんばってる
MIRのDropは特殊だが説明が大変なので後日
Skolemized Lifetimes
関数をまたぐライフタイムを考える
この名前は使われてない
提案者の人しかつかってない
NLLで導入されたあたらしいLifetime
SATソルバで解けるように定義を変更したlifetime
Lifetimeに名前をつけてそれに対する終了領域end('r)もセットで考える
Universal Region
わからないlifetimeに割り当てられる領域は'staticと同じCFG全体
エラーにたまに出る'staticをつけろはでかすぎるUniversal Regionが割り当てられる挙動による
outlives制約がないのにnamed lifetime使ってるとこれが起きる
outlives制約から終点領域の包含関係が得られるのでそれをsubtypeに変換する
終点領域の包含関係からリージョン推論
Rust Compiler Development Guideとか読むといい