Skip to content

Apparently intersecting structural types compile, but throw at runtime on field access. #19223

Open
@Quafadas

Description

@Quafadas

Compiler version

3.3.1

Minimized code

import reflect.Selectable.reflectiveSelectable

class Record(elems: (String, Any)*) extends Selectable:
  private val fields = elems.toMap
  def selectDynamic(name: String): Any = fields(name)

type Person = Record { val name: String; val age: Int }

@main def main(): Unit = {
  val person = Record("name" -> "Emma", "age" -> 42).asInstanceOf[Person]

  type Named = { val name: String }
  def typeTest(x: Named) =
    println(x.name)

  typeTest(person)
}

yields

Output

Exception in thread "main" java.lang.NoSuchMethodException: Record.name()
        at java.base/java.lang.Class.getMethod(Class.java:2395)
        at scala.reflect.Selectable.applyDynamic(Selectable.scala:38)
        at scala.reflect.Selectable.applyDynamic$(Selectable.scala:11)
        at scala.reflect.Selectable$DefaultSelectable.applyDynamic(Selectable.scala:51)
        at scala.reflect.Selectable.selectDynamic(Selectable.scala:28)
        at scala.reflect.Selectable.selectDynamic$(Selectable.scala:11)
        at scala.reflect.Selectable$DefaultSelectable.selectDynamic(Selectable.scala:51)
        at plotnetwork$package$.typeTest$1(plotnetwork.scala:38)
        at plotnetwork$package$.plotNetwork(plotnetwork.scala:40)
        at plotNetwork.main(plotnetwork.scala:32)

Expectation

My intuition would be that this would be either a compile error, or print "Emma"... but I can see that with the "asInstanceOf" and "reflection", that intuition may not be the right thing here.

Referenced / discovered in this discussion
tarao/record4s#45

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions