airframe
airframe copied to clipboard
Scala 3 unnecessarily resolves type aliases in function argument types
object MyMacros {
def typeNameOf[A: Type](using Quotes): Expr[String] = {
val name = Type.show[A]
Expr(name)
}
}
object Test extends App {
inline def typeNameOf[A]: String = ${
MyMacros.typeNameOf[A]
}
inline def typeNameOfF1[A](f: A => Unit): String = ${
MyMacros.typeNameOf[A]
}
type MyString = String
println(typeNameOf[MyString])
// MyString (OK)
println(typeNameOfF1 { (x: MyString) => })
// java.lang.String <---------- NG: This should be MyString
println(typeNameOfF1[MyString] { (x: MyString) => })
// MyString <--- OK. If the type name is given as type param, the alias is preserved
println(typeNameOfF1 { (x: Seq[MyString]) => })
// scala.colleciton.immutable.Seq[MyString]
prinrln(typeNameOfF1 { (x: (MyString, Int)) => })
// scala.Tuple2[MyString, scala.Int]
}
Scala 3 (3.1.2) shows inconsistent behavior in resolving type aliases.
It looks like a bug of Scala 3 inline methods. Reported this issue https://github.com/lampepfl/dotty/issues/15304
Related https://github.com/lampepfl/dotty/issues/9421
This problem causes an issue in DI if provider binding with alias type arguments:
type MyString = String
Design.newDesign
.bind[MyString].toInstance("hello")
.bind[X].toProvider{ (s: MyString) => println(s) } /// MISSING_DEPENDENCY String
A workaround is using type tag (@@
):
import wvlet.airframe.surface.tag.*
trait Env
Design.newDesign
.bind[String @@ Env].toInstance("hello")
.bind[X].toProvider{ (s: String @@ Env) => println(s) }
Let's close this ticket as Scala 3 might not be fixed to make type resolver lazy.