Skip to content

Wrong type representation when using typeMember to select a type inherited from a base class #19825

@OndrejSpanel

Description

@OndrejSpanel

When using typeMember function of TypeRepr.of[OuterType].typeSymbol, the resulting symbol is represented as Base.this.InnerType, not OuterType.InnerType. This is a problem when creating a macro which is expected to return an expression of OuterType.InnerType type.

This was found while working on Surface representation of types derived from Scala 2 Enumeration, see wvlet/airframe#3429.

Compiler version

3.3.2, 3.4.0, 3.4.1-RC1

Minimized code

trait Base {
  class InnerType
}

object OuterType extends Base {
  def create: InnerType = new InnerType
}

@main
def main(): Unit = {
  val typeDesc = TypeUtil.memberTypeName[OuterType.type, OuterType.InnerType]
  println(s"Type $typeDesc")
}
import scala.quoted.*

object TypeUtil {
  inline def memberTypeName[A, B] = ${ memberTypeNameImpl[A, B]}

  private def memberTypeNameImpl[A, B](using typeA: Type[A], typeB: Type[B], quotes: Quotes): Expr[String] = {
    import quotes.reflect.*
    val repr = TypeRepr.of(using typeA)
    val memberName = TypeRepr.of(using typeB).typeSymbol.name
    val result = repr.show + "." + memberName +": " + repr.typeSymbol.typeMember(memberName).typeRef.show
    Expr(result)
  }
}

Output

Type OuterType.InnerType: Base.this.InnerType

Expectation

The output should be OuterType.InnerType: OuterType.InnerType.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions