WeakTypeTag不在隐式宏中工作,没有值参数

时间:2015-01-07 11:14:16

标签: scala macros scala-macros

我使用隐式宏来生成类型类。

trait ColumnType[+A]

object ColumnType {
  implicit def materializeColumnType[A <: Product]: ColumnType[A] = macro MappedColumnTypeMacro.materializeColumnType[A]
}

case class MappedColumnTypeMacro(c: Context) {
  import c.universe._

  def materializeColumnType[A: c.WeakTypeTag]: c.Tree = {
    val typeOfA = c.weakTypeOf[A]
    val companion = typeOfA.typeSymbol.companion
    val applyMethod = findMethod(companion.typeSignature, "apply", typeOfA)
    val unapplyMethod = findMethod(companion.typeSignature, "unapply", typeOfA)
    val typeOfB = applyMethod.paramLists.head.head.asTerm.typeSignature
    q"MappedColumnType[$typeOfA, $typeOfB]($companion.$applyMethod, $companion.$unapplyMethod(_).get)"
  }

  def findMethod(companionType: Type, name: String, typeOfA: Type) = {
    companionType.member(TermName(name)) match {
      case method: MethodSymbol if method.paramLists.flatten.length == 1 => method
      case _ => c.abort(c.enclosingPosition, s"No matching $name method found on $typeOfA")
    }
  }
}

def column[A](name: String)(implicit columnType: ColumnType[A]) =
  TableColumn[A](tableAlias, name)(columnType)

case class WrappedInt(int: Int)

// This fails
val myColumn = column[WrappedInt]("mycolumn")

失败的原因是因为typeOfA未被解析为WrappedInt。使用whitebox上下文时,此问题已解决为A,使用黑盒子上下文时,此问题将解析为Nothing

我做错了什么或有解决方法吗?

1 个答案:

答案 0 :(得分:1)

问题在于方差注释 - scalac认为ColumnType[Nothing]是最具体的隐式候选者,所以它会在A中推断materializeColumnType到{{ 1}}无论在Nothing的调用中提供了什么A

在我们的flatMap 2014宏观研讨会上,我们将解释如何解决这个问题:https://github.com/scalamacros/macrology201/commit/78779cc7f565dde003fe0da9e5357821b009917b