Slide 1

Slide 1 text

#kyotogo NilAway による静的解析で 「10 億ドル」を節約する  チェシャ猫 (@y_taka_23) Kyoto.go #56 オフライン忘年 LT 大会 (15th Dec. 2024)

Slide 2

Slide 2 text

#kyotogo 第 1 問(初級)

Slide 3

Slide 3 text

#kyotogo 何が起こる? 1. 改行のみ出力して正常終了 2. 何も出力せず正常終了 3. panic になる

Slide 4

Slide 4 text

#kyotogo 何が起こる? 1. 改行のみ出力して正常終了 2. 何も出力せず正常終了 3. panic になる【正解】

Slide 5

Slide 5 text

#kyotogo 第 2 問(中級)

Slide 6

Slide 6 text

#kyotogo 何が起こる? 1. 改行のみ出力して正常終了 2. 何も出力せず正常終了 3. panic になる

Slide 7

Slide 7 text

#kyotogo 何が起こる? 1. 改行のみ出力して正常終了 2. 何も出力せず正常終了 3. panic になる【正解】

Slide 8

Slide 8 text

#kyotogo 第 3 問(上級)

Slide 9

Slide 9 text

#kyotogo あなたは nil 判定をどうやって解いた?

Slide 10

Slide 10 text

#kyotogo 無効な参照によるエラー ● 10 億ドルの過ち(The Billion Dollar Mistake) ○ null を「発明」した Hoare による 2009 年の後悔の言 ○ Dijkstra 「独身者が全員一人の null と重婚した状態」 ● nil 参照は実行時エラーとしてはかなり厄介 ○ あらゆる型に対し nil チェックが必要になってしまう ○ 原因と結果がコード的にも時間的にも遠く離れがち 参考:https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/

Slide 11

Slide 11 text

#kyotogo 実行前に静的に nil 参照を検出したい

Slide 12

Slide 12 text

#kyotogo NilAway by Uber https://github.com/uber-go/nilaway

Slide 13

Slide 13 text

#kyotogo NilAway の特徴 ● ソースコードから静的に nil エラーを発見 ○ 関数やパッケージを跨いだエラーが検知可能 ○ nil になり得る具体的な原因をメッセージとして表示 ● go/analysis パッケージを使用 ○ 内部は複数の Analyzer でモジュール化され並列動作 ○ golangci-lint や bazel+nogo などのツールから呼び出し可能 参考:静的解析のモジュール化(https://zenn.dev/tenntenn/books/d168faebb1a739/viewer/9d590e)

Slide 14

Slide 14 text

#kyotogo NilAway による検査結果 ● ソースコードの nil flow を解析 ○ foo() が nil リテラルを返却(10 行目) ○ foo() を参照(6 行目)

Slide 15

Slide 15 text

#kyotogo nil flow による因果推論 ● nil の発生と参照の因果関係を辺としたグラフを構築 ○ 発生:nil リテラル、var 宣言、関数の引数など ○ 参照:デリファレンス、フィールドアクセスなど ● 各ノードに対して「nil であり得るか」をマーク ○ 発生側を true、参照側を false として伝播・確定させていく ○ true かつ false の矛盾したノードが現れたら nil エラー

Slide 16

Slide 16 text

#kyotogo *foo(x, bar()) bar() foo の x foo の y foo(x, y) main の x bar の nil リテラル var 宣言 引数 return 引数 デリファレンス return if x == nil

Slide 17

Slide 17 text

#kyotogo *foo(x, bar()) bar() foo の x foo の y foo(x, y) main の x bar の nil リテラル var 宣言 引数 return 引数 デリファレンス return if x == nil 赤は nil 確定 緑は nil 不可能 黒は矛盾

Slide 18

Slide 18 text

#kyotogo *foo(x, bar()) bar() foo の x foo の y foo(x, y) main の x bar の nil リテラル var 宣言 引数 return 引数 デリファレンス return if x == nil 赤は nil 確定 緑は nil 不可能 黒は両方(矛盾)

Slide 19

Slide 19 text

#kyotogo というかそれは自明では?

Slide 20

Slide 20 text

#kyotogo 冒頭の第 3 問への回答 ● ちゃんとした形式化の複雑さ ○ 人間も基本的には因果関係を辿って nil を発見 ○ 意外なトリックがあるという感じではない ○ しかしアルゴリズムに落とし込むとなると割と複雑 ● 計算機科学の裏付けによるスケール可能性 ○ 因果グラフ推論は 2-SAT 問題とみなせ、線形時間で判定可能

Slide 21

Slide 21 text

#kyotogo まとめ ● nil 参照は厄介なタイプの実行時エラー ○ 考案者 Hoare 自身も後に「10 億ドルの過ち」と認める ● NilAway により静的に解析が可能 ○ nil の可能性を制約としてグラフ上で伝播させ矛盾を検出 ● 人間が頭の中で行う「普通にわかる」の形式化 ○ 意外と複雑な処理だが、厳密に記述できればスケール可能

Slide 22

Slide 22 text

#kyotogo Save the Billion Dollars by NilAway! Presented by チェシャ猫 (@y_taka_23)