检查抽象类型时奇怪的 Scala 宏行为?

Strange scala macro behaviour when checking for abstract type?

我想在 scala 中编写一个简单的 type builder。不管怎样,它自己的类型构建器就像一个魅力。 我想在打字机中检查 abstract class.

运行时没有问题:

if (classSymbol.isAbstract) throw new IllegalArgumentException("Provided class is abstract")

我用 TypeTag 属性标记方法,因此 scala 不会在编译期间擦除时间。

def createInstance[T: TypeTag]: T

无论如何,这是可行的。我不喜欢这种方式,因为用户可以输入一个 摘要 class 并想要创建它。我不想在运行时检查参数异常。

所以我认为在编译时间期间检查正确的类型真的很酷。 这是函数的完整代码:

object ClassCheckMacro {

  def checkClass[T](x: T): T = macro checkClassImpl[T]

  def checkClassImpl[T: c.WeakTypeTag](c: blackbox.Context)(x: c.Tree) = {
    import c.universe._
    val symbol = weakTypeOf[T].typeSymbol
    if (symbol.isAbstract) {
        c.abort(c.enclosingPosition, s"${symbol.fullName} must be a class")
    } else {
        c.Expr(q"($x)")
    }
  }
}

每次我使用这个宏时,我都会收到中止消息 "must be a class"。 它是 class 还是抽象类型并不重要。 用法:

    val typeInfo = typeOf[T]
    val classSymbol = typeInfo.typeSymbol.asClass
    ClassCheckMacro.checkClass(classSymbol)

对于这种 "strange" 行为有任何提示吗?

x只是一个值。

$ scalam -language:_
Welcome to Scala 2.12.0-M5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92).
Type in expressions for evaluation. Or try :help.

scala> import reflect.macros._
import reflect.macros._

scala>   def checkClassImpl[T: c.WeakTypeTag](c: blackbox.Context)(x: c.Tree) = {
     |     import c.universe._
     |     val symbol = weakTypeOf[T].typeSymbol
     |     if (symbol.isAbstract) {
     |         c.abort(c.enclosingPosition, s"${symbol.fullName} must be a class")
     |     } else {
     |         c.Expr(q"($x)")
     |     }
     |   }
checkClassImpl: [T](c: scala.reflect.macros.blackbox.Context)(x: c.Tree)(implicit evidence: c.WeakTypeTag[T])c.Expr[T]

scala> def checkClass[T](x: T): T = macro checkClassImpl[T]
defined term macro checkClass: [T](x: T)T

scala> class C
defined class C

scala> checkClass[C](null)
res0: C = null

scala> abstract class K
defined class K

scala> checkClass[K](null)
<console>:17: error: K must be a class
       checkClass[K](null)
                    ^

正在将工作笔记本电脑升级到 Windows 10...