プログラマブル深海魚

目立たないけど華やかに

Scala 3 への移行方法を調べる

Scala 3が正式リリースされてからしばらく経っているので、以前作成したPlay FrameworkのサンプルプログラムをScala 3に移行できるか調べました。

目次

Scala 3 への移行ツール

プロジェクトが依存しているプラグインScala 3に対応しているかどうかを確認できるプラグインがあるため、それを利用します。
https://scalacenter.github.io/scala-3-migration-guide/docs/tooling/scala-3-migrate-plugin.html

plugin.sbtに以下を追加すると、migrate-libsコマンドでScala 3 Migrate Pluginが利用できます。

addSbtPlugin("ch.epfl.scala" % "sbt-scala3-migrate" % "0.4.2")
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.5.3")

プラグインを実行すると、大まかに分けて「Scala 3では使えない(Scala 3対応のバージョンがない)」「そのままScala 3で使える」「Scala 3対応版のバージョンに上げる必要がある」の3種類のどれかが出力されます。

実際に使ってみる

実際にサンプルプロジェクトに対して使用してみます。

サンプルプロジェクトの元のplugin.sbtは以下。

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.8")
addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.13.1")
addSbtPlugin("org.wartremover" % "sbt-wartremover" % "2.4.16")
addSbtPlugin("com.github.tototoshi" % "sbt-slick-codegen" % "1.4.0")

libraryDependencies += "org.postgresql" % "postgresql" % "42.2.23"

build.sbtは以下。

name := """PlayScalaSample"""
organization := "com.example"

version := "1.0-SNAPSHOT"

lazy val root = (project in file(".")).enablePlugins(PlayScala, CodegenPlugin)

scalaVersion := "2.13.6"

libraryDependencies += guice
libraryDependencies += "com.google.inject" % "guice" % "5.1.0"
libraryDependencies += "com.google.inject.extensions" % "guice-assistedinject" % "5.1.0"
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "5.1.0" % Test
libraryDependencies += "org.typelevel" %% "discipline-scalatest" % "2.1.5"
libraryDependencies += "com.typesafe.play" %% "play-slick" % "5.0.0"
libraryDependencies += "com.typesafe.slick" %% "slick" % "3.3.3"
libraryDependencies += "com.typesafe.slick" %% "slick-hikaricp" % "3.3.3"
libraryDependencies += "com.typesafe.slick" %% "slick-codegen" % "3.3.3"
libraryDependencies += "org.postgresql" % "postgresql" % "42.3.1"
libraryDependencies += "org.typelevel" %% "cats-core" % "2.7.0"
libraryDependencies += "org.typelevel" %% "cats-laws" % "2.7.0"

routesGenerator := InjectedRoutesGenerator

wartremoverErrors ++= Seq()
wartremoverWarnings ++= Warts.unsafe ++ Warts.all
wartremoverExcluded ++= (Compile / routes).value
wartremoverExcluded += (Compile / baseDirectory).value / "target"

Compile / sourceGenerators += slickCodegen
slickCodegenDatabaseUrl := "jdbc:postgresql://localhost:5432/mydb"
slickCodegenDatabaseUser := "postgres"
slickCodegenDatabasePassword := "postgres"
slickCodegenDriver := slick.jdbc.PostgresProfile
slickCodegenJdbcDriver := "org.postgresql.Driver"
slickCodegenOutputPackage := "entities"
slickCodegenExcludedTables := Seq("schema_version")

plugin.sbtにScala 3 Migrate Pluginを追加して、migrate-libs <プロジェクトの変数>を実行すると結果が出力されます。(今回なら'migrate-libs root')
ただ、今回はこれだけだとsbtの起動時に以下のエラーが出ました。

[error] stack trace is suppressed; run 'last update' for the full output
[error] stack trace is suppressed; run 'last ssExtractDependencies' for the full output
[error] (update) sbt.librarymanagement.ResolveException: Error downloading org.scalameta:semanticdb-scalac_2.13.6:4.4.10

SemanticDBというライブラリのバージョンがsbtに依存しているらしく、使用しているScalaのバージョンのアーティファクトが存在しないバージョンを参照しようとしているみたいです。 SemanticDBのバージョンをbuild.sbtで指定できるので、以下を追加します。

semanticdbVersion := "4.4.33"

プラグインの出力結果は以下のとおりでした。

[info] com.typesafe.slick:slick:3.3.3                              -> X : Contains Macros and is not yet published for 3.0.0
[info] org.wartremover:wartremover:2.4.16:plugin->default(compile) -> X : Scala 2 compiler plugins are not supported in scala 3.0.0. You need to find an alternative
[info] org.postgresql:postgresql:42.3.1                            -> Valid
[info] com.google.inject.extensions:guice-assistedinject:5.1.0     -> Valid
[info] com.google.inject:guice:5.1.0                               -> Valid
[info] com.typesafe.play:twirl-api:1.5.1                           -> "com.typesafe.play" % "twirl-api_2.13" % "1.5.1"
[info] com.typesafe.play:play-docs:2.8.8:docs                      -> "com.typesafe.play" % "play-docs_2.13" % "2.8.8" % "docs"
[info] com.typesafe.play:play-logback:2.8.8                        -> "com.typesafe.play" % "play-logback_2.13" % "2.8.8"
[info] org.typelevel:cats-laws:2.7.0                               -> "org.typelevel" % "cats-laws_2.13" % "2.7.0"
[info] com.typesafe.play:play-slick:5.0.0                          -> "com.typesafe.play" % "play-slick_2.13" % "5.0.0"
[info] com.typesafe.play:play-guice:2.8.8                          -> "com.typesafe.play" % "play-guice_2.13" % "2.8.8"
[info] com.typesafe.play:play-test:2.8.8:test                      -> "com.typesafe.play" % "play-test_2.13" % "2.8.8" % "test"
[info] org.scalatestplus.play:scalatestplus-play:5.1.0:test        -> "org.scalatestplus.play" % "scalatestplus-play_2.13" % "5.1.0" % "test"
[info] org.typelevel:discipline-scalatest:2.1.5                    -> "org.typelevel" % "discipline-scalatest_2.13" % "2.1.5"
[info] com.typesafe.slick:slick-hikaricp:3.3.3                     -> "com.typesafe.slick" % "slick-hikaricp_2.13" % "3.3.3"
[info] com.typesafe.slick:slick-codegen:3.3.3                      -> "com.typesafe.slick" % "slick-codegen_2.13" % "3.3.3"
[info] org.typelevel:cats-core:2.7.0                               -> "org.typelevel" % "cats-core_2.13" % "2.7.0"
[info] com.typesafe.play:filters-helpers:2.8.8                     -> "com.typesafe.play" % "filters-helpers_2.13" % "2.8.8"
[info] com.typesafe.play:play-server:2.8.8                         -> "com.typesafe.play" % "play-server_2.13" % "2.8.8"
[info] com.typesafe.play:play-akka-http-server:2.8.8               -> "com.typesafe.play" % "play-akka-http-server_2.13" % "2.8.8"

Slick(DBライブラリ)はScala 2のマクロを使用しているため、Scala 3では使用できないようです。(Scala 2とScala 3ではマクロの互換性がないらしい)
また、WartRemoverはScala 2用のプラグインなので使用できません。
その他は、そのまま使えるか、もしくは2.13用のアーティファクトScala 3でも使用できるようです。

おわり

SlickがScala 3で使えないとのことなので、しばらくはまだ移行できなさそうです。
SlickのScala 3サポート自体は、着々と進められているようでした。
https://github.com/slick/slick/pull/2187

参考文献

New in Scala 3 | Scala Documentation
https://docs.scala-lang.org/ja/scala3/new-in-scala3.html

Scala 3への道
https://www.infoq.com/jp/news/2021/05/scala3/

Scala 3 Migrate Plugin · Scala 3 Migration guide
https://scalacenter.github.io/scala-3-migration-guide/docs/tooling/scala-3-migrate-plugin.html

業務アプリケーションのScala 3アップデートを試してみた - FLINTERS Engineer's Blog
https://labs.septeni.co.jp/entry/2021/07/05/110000

Error downloading org.scalameta:semanticdb-scalac_2.13.8:4.4.28 · Issue #1560 · scalacenter/scalafix · GitHub
https://github.com/scalacenter/scalafix/issues/1560