I tested the following code of structural type:
trait Data
object Main
{
def main(args: Array[String]): Unit =
{
val data = new Data {
val value: Int = 1
}
println(data.value)
}
}
It compiled successfully in Scala 2.13.2 but failed in Dotty/Scala3. How to use structural types in Dotty/Scala3? Thanks!
From what I see:
val data: Data { val value: Int } = new Data {
val value: Int = 1
}
You can see it clearly when you run dotr
and check what is the inferred typeimport reflect.Selectable.reflectiveSelectable
Putting it together:
import reflect.Selectable.reflectiveSelectable
trait Data
object Main
{
def main(args: Array[String]): Unit =
{
val data: Data { val value: Int } = new Data {
val value: Int = 1
}
println(data.value)
}
}
I guess the reason why you have to do this is because many times when one didn't want to have refinement, one had it (e.g test all test fixtures new Fixture { ... }
were refined types unnecessarily). The other is that refinements use reflection when accessing refinements (in Scala 2) which causes performance penalty - so it is something we should do consciously and not accidentally.
In Scala 3, structural types are implemented using dynamics, which require mixing in Selectable
trait. Because of that you would have to import scala.reflect.Selectable.reflectiveSelectable
implicit conversion to allow it to work like in Scala 2. If you want to make things work like before you can add import reflect.Selectable.{ given _ }
as suggested by @Dmytro Mitin (and add reflection back).
You can try to do it globally e.g. by exporting it in your package, but it you would do it on your own risk.