scalametaprogrammingscala-macros

How can I get the correctly applied types in the body of a class in Scala 3 reflection?


Let's say I'm reflecting on this class using Scala 3 reflection:

class Foo[T](val thing: T):
  var store: Option[T] = None

Let's say I reflect with given type Foo[Boolean], and I get the TypeRef for this class as this:

AppliedType(TypeRef(TermRef(TermRef(TermRef(ThisType(TypeRef(NoPrefix,module class <root>)),object co),object blocke),object scala_reflection),class Foo),List(TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class <root>)),object scala),class Boolean)))

So far, so good. I can further reflect on the constructor fields and see that 'thing' is correctly applied as Boolean.

Where can I look to find the applied types for anything defined in the body? Everywhere I've looked so far I just see 'T', not Boolean. For example, using my reflection library I can output:

co.blocke.scala_reflection.Foo[Boolean]:
   fields ->
      thing: [T] Boolean
   non-constructor fields (non-case class) ->
      store: Option of T

I'm clearly not looking in the right place for the ValDefs defined in the body. They all come back 'T'.


Solution

  • Pattern matching on AST is the last resort when it comes to any operation in Tasty. Quotes offer quite a lot of utilities already.

    I you managed to find a TypeRepr (any subtype of it will do) then Quotes offer you the right API for asking for applied types:

    import quotes.*, quotes.reflect.*
    
    val repr: TypeRepr = ...
    typeArguments = repr.typeArgs
    

    If you need to have these types applied to some method, then you'd have to

    1. extract type arguments from type definition
    2. manually apply them to method type

    E.g.

    val method: Symbol = ... // method belonging to type represented by repr    
    
    if repr.typeArgs.isEmpty then repr.memberType(method)
    else repr.memberType(method).appliedTo(repr.typeArgs)
    

    Examples of such type parameter reapplication can be found in Chimney (disclaimer: I'm a co-author) as it's macro heavy library that needs to inspect types a lot.