How to extract type parameter from TypeLambda correctly?

38 views Asked by At

I have a macro processing types in Scala 3, the macro is a minimized repro of an issue I am facing with airframe-surface library. The macro apparently works fine, but as soon as I add option -Xcheck-macros into build.sbt, I get an assertion. I have tracked the issue down to a type parameter extracted from the BySkinny type lambda. As soon as I return that, I get an error:

assertion failed: orphan param: SkinnyA, hash of binder = 1384130361, tree = , type = ConstantType(Constant(TypeParamRef(SkinnyA)))

This makes debugging other macros hard, as the exception aborts the compilation.

The most important part of the recursive macro is this:

    def clsOf(t: TypeRepr): Expr[Class[_]] =
      Literal(ClassOfConstant(t)).asInstanceOf[Expr[Class[_]]]

    def extract(t: TypeRepr): Expr[Class[_]] = {
      t match

        case t if t.typeSymbol.isType && t.typeSymbol.isAliasType && !belongsToScalaDefault(t) =>
          val dealiased = t.dealias
          println(s"=== alias factory: ${t} => ${dealiased} == ${t.simplified}")
          extract(dealiased)

        case h: TypeLambda =>
          println(s"TypeLambda $h")
          val len = h.paramNames.size
          val args = Option.when(len > 0)(h.param(0)).map(extract)
          args.getOrElse(clsOf(h.resType))

        case a: AppliedType =>
          println(s"AppliedType")
          val typeArgs = a.args.map(extract)
          typeArgs.head

    }

I am just diving into the AST describing the type and locating a single node in it.

The type I am processing is Holder[Holder.BySkinny] where:

  trait Holder[M[_]]

  class MyTask[TaskA]

  object Holder {
    type BySkinny[SkinnyA] = MyTask[SkinnyA]
    def bySkinny: Holder[BySkinny] = ???
  }



I am not sure if the error is a bug in Scala 3 compiler, or if I (and airframe-surface) am doing something wrong.

Complete project is located at https://github.com/OndrejSpanel/OrphanParamIssue

0

There are 0 answers