Search code examples
scalastructural-typingdottyscala-3

Structural types in Dotty/Scala 3 compiled failed?


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!


Solution

  • From what I see:

    • inference changed, so you have to refine type explicitly:
      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 type
    • to make use of refinement you have to let compiler know that you don't mind reflection
      import 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.