0
我尝试写隐含物化播放格式化实例在需要时宏:编译错误泛型类型
class FormattableImpl(override val c: whitebox.Context) extends Utils(c) {
import c.universe._
def materializeFormatImpl[T : c.WeakTypeTag]: c.Expr[play.api.libs.json.Format[T]] = {
val tpe = implicitly[c.WeakTypeTag[T]].tpe
val x = c.Expr[play.api.libs.json.Format[T]](q" com.ubookr.macros.Json.format[$tpe] ")
println(show(x))
x
}
}
object Format {
implicit def materializeFormat[T]: play.api.libs.json.Format[T] = macro FormattableImpl.materializeFormatImpl[T]
}
这只是正常的非参数化类型(例如
case class Apple(id: Long, name: String)
val x = materializeFormat[Apple]
)。
它也适用于集合
val xx = materializeFormat[Seq[Apple]]
当我试图用我自己的参数化类型,但是,它失去了类型参数的值:与
响应case class Proxy[+T](id: Long, name: String)
val xxx = materializeFormat[Proxy[Apple]]
[error] package.scala:112: type mismatch;
[error] found : play.api.libs.json.OFormat[com.ubookr.macros.Proxy[Nothing]]
[error] required: play.api.libs.json.Format[com.ubookr.macros.Proxy[Apple]]
[error] Note: com.ubookr.macros.Proxy[Nothing] <: com.ubookr.macros.Proxy[Apple], but trait Format is invariant in type A.
[error] You may wish to define A as +A instead. (SLS 4.5)
[error] val xxx: Any = com.ubookr.macros.Format.materializeFormat[Proxy[Apple]]
[error]
这是有道理的,因为WeakTypeTag不知道T.我的第一个问题是为什么这与Seq正确工作?
不过,我想出了什么,我觉得应该是一个可行的解决方法:
def materializeProxy[T]: play.api.libs.json.Format[Proxy[T] = macro FormattableImpl.materializeProxyImpl[T]
其中materializeProxyImpl
实现是
def materializeProxyImpl[T : c.WeakTypeTag]: c.Expr[play.api.libs.json.Format[Proxy[T]]] = materializeFormatImpl[Proxy[T]]
的println
在materializeFormatImpl
现在正确显示参数类型t的实际值:
Expr[play.api.libs.json.Format[com.ubookr.macros.Proxy[Apple]]](com.ubookr.macros.Json.format[com.ubookr.macros.Proxy[Apple]])
,但我仍然后,立即得到了同样的错误:
[error] package.scala:112: type mismatch;
[error] found : play.api.libs.json.OFormat[com.ubookr.macros.Proxy[Nothing]]
[error] required: play.api.libs.json.Format[com.ubookr.macros.Proxy[Apple]]
[error] Note: com.ubookr.macros.Proxy[Nothing] <: com.ubookr.macros.Proxy[Apple], but trait Format is invariant in type A.
[error] You may wish to define A as +A instead. (SLS 4.5)
[error] val xxx: Any = Format.materializeProxy[Apple]
[error]
我试图改变对两者分别materializeProxy
和materializeProxyImpl
到Any
和Tree
类型标注,但语法错误仍然出现,反映走势将转我发现类型不匹配发生在宏引擎的内部。
我做错了什么?或者这是宏引擎中的一个错误?
嗯,我认为它对Seq正确工作的事实是一个线索。 JsMacroImpl代码具有Seq参数的显式帮助器。我怀疑发生错误是因为播放宏忽略了我的类型参数。 –
这是一个已知的限制,现在已修复:https://github.com/playframework/playframework/pull/5384 – cchantep