Slide 1

Slide 1 text

Scala 3 にコントリビュートしよう Lightning Talk@2024/02/27 Scalaわいわい勉強会

Slide 2

Slide 2 text

WHOAMI GitHub: i10416 X(Twitter): @by110416 Scala & Rust developer 最近の Scala OSS コントリビューション https://github.com/lampepfl/dotty/pulls?q=+is%3Apr+author%3Ai10416+ 前回の登壇資料 Lightning Talk@2023/10/13 Scalaわいわい勉強会: Scala をインタラクティブにデバッ グする方法あれこれ

Slide 3

Slide 3 text

なぜコンパイラに...? Prefer to push fixes upstream instead of working around problems downstream https://www.haskellforall.com/2020/07/the-golden-rule-of-software-quality.html アップストリームが修正・改善されることでより多くの開発者が恩恵を受けることがで きる 改善の余地が無限にある(Issue 1.3K+) コンパイラ、ドキュメンテーション、Dev Tools、JVM など広く深い学びがある JSON・Protobuf 詰め替えやクラウドピタゴラスイッチにはない複雑さ

Slide 4

Slide 4 text

おことわり デバッガを使ったりコンパイルオプションを駆使したりしてスマートに問題箇所を特定・対 処する方法もあるが、話を複雑にしないためにそれらに踏み込むのはあえて避ける. 興味がある人は以下のページを見るといい. https://dotty.epfl.ch/docs/contributing/diagnosing-your-issue/cause.html https://dotty.epfl.ch/docs/contributing/debugging-the-compiler/ide-debugging.html https://dotty.epfl.ch/docs/contributing/debugging-the-compiler/inspection.html また、今回はコンパイラのコア部分(※ )を中心に説明する. Scaladoc やビルドの改善などは別 の機会に... ※ : https://dotty.epfl.ch/docs/internals/overall-structure.html でカバーされる範囲

Slide 5

Slide 5 text

PR を送るまでのステップ 1. Issue を探す 2. tests/{pos|neg|warn|run}/{issue number}.scala ファイルにテストを書く 3. あたりをつけて dotty/compiler/src/dotty/tools/dotc 以下を修正する 4. sbt testCompilation {issue number} で特定のテストケースだけ実行する 5. テストが通ったら終わり. テストがコケたら 3 に戻る 6. testCompilation で他のテストがコケないかチェックする 7. コミットを整理 & 丁寧な PR のコメントを書く

Slide 6

Slide 6 text

Issue の探し方: 初心者~中級者向け 以下のタグで検索すると初心者~中心者向けのタスクが見つかる. spree: spree 向けのタスク候補 good first issue: Subject Says It All! exp:intermediate: 中級者向けだがそこまで実装がこみいっていないものが多い. ※ Spree は Scala Center がオープンソースへのコントリビューションを奨励するイベント.

Slide 7

Slide 7 text

Issue の探し方: 穴場 以下のタグがついているものは取り組みやすい. バグやクラッシュは解くべき問題が明確なのでテストさえ書ければすぐに直せることが多い. 特に regression は過去に動いていたものが動かなくなるケースなので原因の調査もしやすい. better-errors・area:reporting はコンパイラが既に持っている情報をユーザーに提示するだけ で済むので比較的実装量が少なく済む. itype:bug itype:crash regression better-errors・area:reporting

Slide 8

Slide 8 text

Issue の探し方: 難しいもの 以下のタグがついているものは問題のスコープが絞れていなかったり、そもそもあるべき状 態がわかっていなかったりするので難しいことが多い. stat:needs triage stat:needs minimization stat:needs spec itype:enhancement area:experimental:*

Slide 9

Slide 9 text

あたりのつけ方 後から振り返ると簡単だが一番時間がかかるのがここ. 根気よくやろう. Issue からあたりをつける 過去の Issue や Pull Request からあたりをつける コンパイラのログ・トレースからあたりをつける

Slide 10

Slide 10 text

あたりのつけ方: Issue や PR Issue には area:{area} というラベルがついていることがある. area:typer であれば compiler/src/dotty/tools/dotc/typer のコードをいじると修正ができそう、とあたりがつけら れる. また、Issue には関連する Issue や PR が紐づけられていることがある. これらを参考にすると 問題箇所をシュッと特定できたりする(e.g. バックポート・フォワードポート)

Slide 11

Slide 11 text

あたりのつけ方: ログ・トレース・Print デバッグ・Grep scalac に -Xprint:{PHASE}{,PHASE}* を渡せば指定したコンパイラフェーズの後の AST を確認できる. また、 -Ylog:{PHASE}{,PHASE}* を渡せば指定したフェーズのログを有効化できる....がこ れはあまりいい感じのログを出してくれないのでダメそうなら素直に print デバッグを仕 込もう import dotty.tools.dotc.core.Decorators.* でちょっとリッチな string interpolation が使える. ちなみに scalac をグローバルにインストールしていなくても大丈夫. dotty のコードベースの sbt シェルから scalac を直接呼び出すことができる エラーメッセージで dotty のソースを grep するのも手.

Slide 12

Slide 12 text

テストコードの書き方 コンパイルが通るべきものが通っていない問題の時は tests/pos/{issue number}.scala にファイルを追加 コンパイルエラーになるべきものがならない、あるいは"間違った"エラーが出ている場 合は tests/neg/{issue number}.scala にコードを追加 警告の内容を検査したい場合は tests/warn/{issue number}.scala にコードを追加 コンパイルだけでなく実行時の結果も検査したい場合は tests/run/{issue number}.scala にコードを追加

Slide 13

Slide 13 text

テストコードの書き方: コンパイルエラー・警告のマーク エラーになるべきところに // error コメントを追加する type Foo[A] = A match { case Int => String } type B = Foo[Boolean] // error https://github.com/lampepfl/dotty/blob/8b8caa98d2f40c026e1022339942e3bbcf6c65 78/tests/neg/10747.scala#L5

Slide 14

Slide 14 text

テストコードの書き方: コンパイルエラー・警告のマーク 警告を出すべきところに // warn コメントを追加する package +.* { // warn // warn class Bar } https://github.com/lampepfl/dotty/blob/8b8caa98d2f40c026e1022339942e3bbcf6c65 78/tests/warn/symbolic-packages.scala#L7 複数のエラーや警告を期待する場合は // warn // warn // warn // ... と、期待する個 数分コメントを書く

Slide 15

Slide 15 text

コンパイル時オプションの指定 Scala CLI と同様に using directives でコンパイラオプションを指定できる. //> using options -Wnonunit-statement -Wvalue-discard -source:3.3 https://github.com/lampepfl/dotty/blob/26642043cded4bf3daba90b9e9f16013cb627e e9/tests/warn/nonunit-statement.scala#L4

Slide 16

Slide 16 text

コンパイラの出力のチェック 1. 空の tests/{pos|neg|warn|run}/{issue number}.check ファイルを作成する 2. testCompilation {issue number} --update-checkfiles を実行する 3. 生成された tests/{pos|neg|warn|run}/{issue number}.check を期待する出力に なるように調整する 4. コードを修正する 5. テストを実行しエラーがなくなるまで 4, 5 を繰り返す. https://dotty.epfl.ch/docs/contributing/testing.html#checking-compilation-errors-1

Slide 17

Slide 17 text

そのほか注意事項 Java のコードを含むテストケースを作る場合、 tests/run で Scala.js のテストが通らないので // scalajs: --skip でスキップする必 要があること pickling が壊れるので compiler/test/dotc/pos-test-pickling.blacklist や compiler/test/dotc/run-test-pickling.blacklist 除外する必要があること に注意しよう.

Slide 18

Slide 18 text

コミットを整理して PR を作る コンパイル・テストが通る単位にコミットをまとめる コミットが加える変更や修正するバグを説明する Issue や他の PR へのリンクを貼る(e.g. close #42 , scala/scala#43 )

Slide 19

Slide 19 text

まとめ 最初は右も左もわからないはずなので、過去の Issue・PR に目を通したり print デバッグ を仕込んだりしてコンパイラのメンタルモデルを作ろう. 実際に手を動かさないとはじまらないので、まずは fork & clone & compile! gh repo fork lampepfl/dotty sbt compile

Slide 20

Slide 20 text

References Scala 3 コンパイラのアーキテクチャ: https://dotty.epfl.ch/docs/contributing/architecture/index.html コンパイラのコア部分の構造: https://dotty.epfl.ch/docs/internals/overall-structure.html 公式コントリビューションガイド: https://dotty.epfl.ch/docs/contributing/index.html