Scala 2.13.4からのTASTy読み取り機能

というものが追加されるらしいです。

簡単に用語や前提や現状の解説

  • これ書いている2020年7月現在、Scalaの最新安定版は2.13.3
  • つまり2.13.4は次にリリースされるversion
  • 2.13.xの次のメジャー(?)リリースは、2.14ではなく3.0( = Dotty)
  • 3.0もまだ正式安定版はリリースされてない。結構先になりそう?
  • 2.13と3の間の互換性やスムーズな移行を頑張る動きが色々活発だが、今回のこれもそのうちの一つ
  • TASTyとは、次のScala 3におけるScala独自の情報を保持した内部構造のフォーマット(の仕様の名前?実装の名前?拡張子名でもある)
  • Scala 2ではScalaSignature https://github.com/scala/scala/blob/v2.13.3/src/library/scala/reflect/ScalaSignature.java というアノテーションに全部埋め込んでいた
  • Scala 3では、 class名とか.tasty という .class ファイルとは別のファイルがjarの中に埋め込まれる(ちなみにフォーマットは違うが、jarに別ファイルが埋め込まれる点はscala-jsやscala-nativeでも同じ方式)
  • Scala 2のScalaSignatureとScala 3のTASTyは互換がない(はず?)
  • Scala 3とScala 2.13では、標準ライブラリ( scala-library.jar )は同じものを使っているので、バイナリ自体はそれなりに互換がある
  • しかし、今まではScala 3(Dotty)からは、ある意味Scala 2.13でビルドされたものは読み込める(= 使える)機能が搭載されていた
    • 言い換えると、DottyのcompilerにはScalaSignature読み取り機能がある
  • しかし、その逆、つまりDottyでビルドされたものを、Scala 2.13から使おうとすると、Scala 2.13のcompilerはTASTyのフォーマットを理解できないので、最低限の単なるclassファイルとしては使えなくもないが、たとえばimplicitやデフォルト引数やその他色々Scala独自の機能( = 普通のJavaにはない機能)全てがうまく使えない状態だった、はず
  • それを解決したのが今回の変更

github.com

試し方

build.sbtに以下のようなのを書く。すると、あとは普通に使える。 いまのところ、scalacOptionsの追加などの特別な設定は、なにも必要ないみたい?

// SNAPSHOT版を使うためのresolver
resolvers += "scala-integration" at "https://scala-ci.typesafe.com/artifactory/scala-integration/"

// Scala 2.13.4はまだリリースされてないので、このblog書いてる時点の最新版SNAPSHOT指定
// https://github.com/scala/scala/tree/9b3de110792c41d4b9b98a3269a69f97a9f49815
scalaVersion := "2.13.4-bin-9b3de11"

// dotty 0.23でbuildされた任意のライブラリの依存を書く
// 現状だと、0.24や0.25だとformat違うと言われてエラーになって動かない・・・
libraryDependencies += "com.github.scalaprops" % "scalaprops_0.23" % "0.8.0"

つい昨日くらいに入ったばかりなのに、なぜか対応しているDottyというかTASTyのformaのversionが2世代古い、辛い・・・

https://github.com/scala/scala/blob/9b3de110792c41d4b9b98a3269a69f97a9f49815/src/compiler/scala/tools/tasty/TastyFormat.scala#L18-L19 https://github.com/scala/scala/blob/9b3de110792c41d4b9b98a3269a69f97a9f49815/project/DottySupport.scala#L15-L16

これだけだと嬉しさがわかりにくいが、dottyのみでしかビルドされてないライブラリが将来出たとしても、それをScala 2.13から使える、ということ。 どのくらい制約があるのか?はよくわかってないです。(今制約があったところで、今後まだまだ変わりそうだし)

Scala 2.13とScala 3(Dotty) は、言語の表面上の見た目というかSyntaxはものすごく変わりますが、バイナリ自体は今までにない謎の相互の互換をそれなりに保つ方向性になってきたので、 面白いですね。