slickのTableQueryのmacroがScala 3で動かない場合があると思ったらおそらくScala 3自体のバグ?

以下のこれ

https://github.com/slick/slick/blob/v3.6.0/slick/src/main/scala-3/slick/lifted/TableQuery.scala#L37-L55

機能としては、詳細を省略してすごく雑に説明すると

TableQuery[A]

と書いたら

TableQuery[A](tag => new A(tag))

と展開してくれるだけだと思います。

「そんなのわざわざマクロとして提供する必要ある?」

みたいな気持ちになる可能性はありますが、その話は置いておくとして、Scala 2ではcompile通るのに、Scala 3では通らないパターンがあることがわかりました。

詳細はこっちにも書いたので、それ見てもらってもいいのですが、

https://github.com/scala/scala3/issues/19933#issuecomment-2816881828

動かないパターンとは

「TableQueryに渡す型の定義が内部classで、かつ、それの定義とTableQueryのmacro呼び出しが、継承関係がある別のsub class内の場合」

です。言葉よりコードの方がわかりやすい気がしますが、つまりこう

import slick.jdbc.JdbcProfile

case class C(x: Int)

trait A {
  protected val profile: JdbcProfile
  import profile.api.*

  protected class B(tag: Tag) extends Table[C](tag, "my_table") {
    override def * = ???
  }
}

trait D extends A {
  import profile.api.*
  val query = TableQuery[B]
}

これをやると、macro展開内部でtype errorになって、Scala詳しくない人にとっては「は???何これ???」となります

[error] 18 |  val query = TableQuery[B]
[error]    |              ^^^^^^^^^^^^^
[error]    |              Found:    A.this.B
[error]    |              Required: D.this.B

-Xprint:all するなどして内部の途中のTreeを見ると以下のようになってました

val query: slick.lifted.TableQuery[D.this.B] =
  slick.lifted.TableQuery.apply[D.this.B](
    (tag: slick.lifted.Tag) => new A.this.B(tag)):
    slick.lifted.TableQuery[D.this.B]

new してる部分だけ A.this.B になっていて、他は D.this.B なので、確かに型が合っていませんね。

そして適当に検索したらScala 3本体の上記のissueに辿り着きました。

このblog書いてる時点でコメントしたばかりなので、特にまだ反応かえってきてませんが、おそらくissueのタイトルと、slickのコードを見る限り、同じ問題・・・?

対策として思いつくものを3つくらいissueに書いておきましたが、どの方法がいいんでしょうかね。

単に new するコード書くだけなら、大抵scalafixで全自動書き換え可能だし、macro使わないものに書き換えてしまおうかなぁ、どうしようかなぁ・・・

追記:

xuwei-k.hatenablog.com