Search code examples
scalareflectionstructural-typing

Structural subtyping reflection


Can we get the type of val s: String using reflection from the outside of the function f?

val f = (r: {val s: String}) => {
}

Solution

  • scala> import scala.reflect.runtime.{universe => ru}
    import scala.reflect.runtime.{universe=>ru}
    
    scala> import scala.reflect.runtime.universe._
    import scala.reflect.runtime.universe._
    
    scala> def typeOf[T: ru.TypeTag](x: T) = ru.typeOf[T] // capture compile-time type info
    typeOf: [T](x: T)(implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.Type
    
    scala> val f = (r: {val s: String}) => {}
    f: AnyRef{val s: String} => Unit = <function1>
    
    scala> val tpe = typeOf(f)
    tpe: reflect.runtime.universe.Type = scala.AnyRef{val s: String} => Unit
    
    scala> ru.showRaw(tpe)
    res0: String = TypeRef(ThisType(scala), scala.Function1, List(RefinedType(List(TypeRef(ThisType(scala), newTypeName("AnyRef"), List())), Scope(newTermName("s"))), TypeRef(ThisType(scala), scala.Unit, List())))
    
    scala> val ru.TypeRef(_, _, refinement :: _) = tpe
    refinement: reflect.runtime.universe.Type = scala.AnyRef{val s: String}
    

    With Scala reflection one can also generate mocks for structural types as follows: https://gist.github.com/4008389. The linked gist does this using toolboxes and runtime reflection, but this scenario looks implementable with macros as well.