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

时间:2016-07-25 06:00:09

标签: scala types macros abstract-syntax-tree

我想在scala中编写一个简单的类型构建器。无论如何,它自己的类型构建器就像一个魅力。 我想在typebuilder中查看抽象类。

运行时,没有问题:

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

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

def createInstance[T: TypeTag]: T

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

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

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)")
    }
  }
}

Evertime我使用这个宏,我得到中止消息"必须是一个类" 。 如果它是类或抽象类型并不重要。 用法:

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

对此有任何提示吗?#34;奇怪"行为?

1 个答案:

答案 0 :(得分:0)

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$1: 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 ......