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