opaque type をトップレベルで定義した際の挙動は
An opaque type alias on the top-level is transparent in all other top-level definitions in the sourcefile where it appears, but is opaque in nested objects and classes and in all other source files
https://dotty.epfl.ch/docs/reference/other-new-features/opaques-details.html
と書かれていますが、この挙動についてもう少し調べてみました。
Scala の version は 3.3.1 になります。
ネストしたobject
ドキュメントの例の通りコンパイルエラーになります。
// in test1.scala
opaque type A = String
val x: A = "abc"
object obj:
val y: A = "abc" // error: found: "abc", required: A
同階層で case class に対しての companion object
こちらもコンパイルエラーになります。 trait に対しての companion object に対してもコンパイルエラーとなります。
// in test1.scala
opaque type A = String
val x: A = "abc"
case class B(value: String)
object B:
val y: A = "abc" // error: found: "abc", required: A
opaque type に対しての companion object
こちらはコンパイルエラーになりません
// in test1.scala
opaque type A = String
val x: A = "abc"
opaque type B = String
object B:
val y: A = "abc" // コンパイルエラーとならない実行も可能
また opaque type の companion object からネストした場合もコンパイルエラーととならないです。
// in test1.scala
opaque type A = String
val x: A = "abc"
opaque type B = String
object B:
val y: A = "abc" // コンパイルエラーとならない実行も可能
object BB:
val z: A = "abc" // コンパイルエラーとならない実行も可能
type に対しての companion object
使うことはあまりないと思うのですが、 type に対してもどうか調べてみました。こちらも opaque type の時と同じでコンパイルエラーになりません
// in test1.scala
opaque type A = String
val x: A = "abc"
type B = String
object B:
val y: A = "abc" // コンパイルエラーとならない実行も可能
まとめ
opaque type は Scala 3 で追加された機能でドキュメントも少ないのでどのような挙動をするのか把握できていないところがあります。 特に同一階層で opaque type の companion object を定義することはあると思うので思わぬ落とし穴にハマらないように注意が必要です。 opaque type の使用頻度はこれから高まってくると思うので、同じような問題に遭遇した場合はこの記事が参考になればと思います。