在 scala 2 中已知宏是严格本地的,并且只在定义类时执行一次。当与抽象类型结合时,这一特性似乎特别弱,因为将抽象类型转换为具体类型的过程通常会绕过宏并使用其自己的原始规则。
下面的测试代码中展示了一个反直觉结果的简单示例:
trait BB {
def ttag = implicitly[TypeTag[this.type]]
}
case class AA() extends BB
it("can TypeTag") {
val kk = AA()
TypeViz(kk.ttag).peek // this function visualise the full type tree of the type tag
}
如果执行,kk的类型变成:
-+ BB.this.type
!-+ InfoCTSpec.this.BB
!-+ Object
!-- Any
糟糕,类型 AA 完全被忽略了,因为implicitly[TypeTag[this.type]]
它由内置宏隐式支持,该宏仅在定义 BB 时执行一次,而不是在定义 AA 并具体化实际时执行kk.this.type
。我发现它非常笨拙并且容易导致一些其他特性(例如模式匹配、类型 lambda)由于运行时类型擦除而降级。
我想编写/使用语言扩展,例如制作TypeTag[this.type]
AA 的子类型,而不引入运行时开销和超出范围的上下文对象(因此,没有隐含)。我怎样才能以最少的黑客攻击做到这一点?我对编译器扩展和宏等非常核心的解决方案持开放态度,但显然首选可以顺利转移到 scala 3/dotty 的优雅解决方案。
PS 似乎有点“内联/编译时”功能已经部分实现了我的设想。这是正确的印象吗?