Scala 需要宏取消类型检查
我在使用宏生成代码的开源项目中遇到了问题。如果我使用Scala 需要宏取消类型检查,scala,macros,Scala,Macros,我在使用宏生成代码的开源项目中遇到了问题。如果我使用c.untypecheck,一切都很好,但理想情况下,我不想这样做 以下是相关代码: 如果删除c.untypecheck,则会出现以下编译时错误: [error] (reactifyJVM/test:compileIncremental) java.lang.AssertionError: assertion failed: [error] transformCaseApply: name = previousVal tree = pre
c.untypecheck
,一切都很好,但理想情况下,我不想这样做
以下是相关代码:
如果删除c.untypecheck
,则会出现以下编译时错误:
[error] (reactifyJVM/test:compileIncremental) java.lang.AssertionError: assertion failed:
[error] transformCaseApply: name = previousVal tree = previousVal / class scala.reflect.internal.Trees$Ident
[error] while compiling: /home/mhicks/projects/open-source/reactify/shared/src/test/scala/specs/BasicSpec.scala
[error] during phase: refchecks
[error] library version: version 2.12.1
[error] compiler version: version 2.12.1
[error] reconstructed args: -classpath /home/mhicks/projects/open-source/reactify/jvm/target/scala-2.12/test-classes:/home/mhicks/projects/open-source/reactify/jvm/target/scala-2.12/classes:/home/mhicks/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.12.1.jar:/home/mhicks/.ivy2/cache/org.scalatest/scalatest_2.12/bundles/scalatest_2.12-3.0.1.jar:/home/mhicks/.ivy2/cache/org.scalactic/scalactic_2.12/bundles/scalactic_2.12-3.0.1.jar:/home/mhicks/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12/bundles/scala-xml_2.12-1.0.5.jar:/home/mhicks/.ivy2/cache/org.scala-lang.modules/scala-parser-combinators_2.12/bundles/scala-parser-combinators_2.12-1.0.4.jar -bootclasspath /usr/java/jdk1.8.0_92/jre/lib/resources.jar:/usr/java/jdk1.8.0_92/jre/lib/rt.jar:/usr/java/jdk1.8.0_92/jre/lib/sunrsasign.jar:/usr/java/jdk1.8.0_92/jre/lib/jsse.jar:/usr/java/jdk1.8.0_92/jre/lib/jce.jar:/usr/java/jdk1.8.0_92/jre/lib/charsets.jar:/usr/java/jdk1.8.0_92/jre/lib/jfr.jar:/usr/java/jdk1.8.0_92/jre/classes:/home/mhicks/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.12.1.jar
[error]
[error] last tree to typer: TypeTree(class Position)
[error] tree position: line 148 of /home/mhicks/projects/open-source/reactify/shared/src/test/scala/specs/BasicSpec.scala
[error] tree tpe: org.scalactic.source.Position
[error] symbol: case class Position in package source
[error] symbol definition: case class Position extends Product with Serializable (a ClassSymbol)
[error] symbol package: org.scalactic.source
[error] symbol owners: class Position
[error] call site: <$anon: com.outr.reactify.ChangeListener[Int]> in package specs
[error]
[error] == Source file context for tree position ==
[error]
[error] 145 current should be(15)
[error] 146 }
[error] 147 "observe a complex change" in {
[error] 148 val v1 = Var(5)
[error] 149 val v2 = Var(10)
[error] 150 val v3 = Var(v1 + v2)
[error] 151 var changed = 0
[error] Total time: 1 s, completed Jan 31, 2017 4:43:03 PM
[错误](reactifyJVM/test:compileIncremental)java.lang.AssertionError:断言失败:
[错误]transformCaseApply:name=previousVal tree=previousVal/class scala.reflect.internal.Trees$Ident
编译时发生[错误]:home/mhicks/projects/open-source/reactify/shared/src/test/scala/specs/basicsec.scala
阶段期间[错误]:参考检查
[错误]库版本:版本2.12.1
[错误]编译器版本:版本2.12.1
[错误]重构参数:-类路径/home/mhicks/projects/open-source/reactify/jvm/target/scala-2.12/test classes:/home/mhicks/projects/reactify/jvm/target/scala-2.12/classes:/home/mhicks/.ivy2/cache/org.scala lang/scala reflect/jars/scala-reflect-2.12.1.jar:/home/mhicks/.ivy2/cache/org.scalatest/scalatest/scalatest\u 2.12/3.0.1.1.jar:/home/icks/或ivy2/g、 scalactic/scalactic_2.12/bundles/scalactic_2.12-3.0.1.jar:/home/mhicks/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12/bundles/scala-xml_2.12-1.0.5.jar:/home/mhicks/.ivy2/cache/org.scala-lang.modules/scala-parser-combinators_2.12/bundles/scala-parser-combinators_2.12-1.0.4.jar-类路径/1/7/java/jdk1.8/java/java/JDK11.8.8/java/java/JDK11.8.8.9 9 9/9 9 9/JJ9/9 9 9/jre///////java/java/JDK11.8.8.8.8.8.8.8.8.1/1/java/java/java/java/java/JDK11.8.8.8.8.8.8.8.8.0 0 0/9/9 9 9 9 9/9 9 9 9 9///////J9 9 9 9 9 9/////////9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9/J荣荣9////////////////////////////////////////////////J荣荣荣荣荣荣9 9 9 8.0_92/jre/classes:/home/mhicks/.ivy2/cache/org.scalalang/scala-library/jars/scala-library-2.12.1.jar
[错误]
[错误]打字机的最后一棵树:TypeTree(类位置)
[错误]树位置:第148行/home/mhicks/projects/open-source/reactify/shared/src/test/scala/specs/basicsec.scala
[错误]树tpe:org.scalatic.source.Position
[错误]符号:包源中的案例类位置
[错误]符号定义:案例类位置使用可序列化(类符号)扩展产品
[错误]符号包:org.scalactic.source
[错误]符号所有者:类位置
[错误]调用站点:在程序包规范中
[错误]
[错误]==树位置的源文件上下文==
[错误]
[错误]145电流应为(15)
[错误]146}
[错误]147“观察复杂的变化”{
[错误]148 val v1=Var(5)
[错误]149 val v2=Var(10)
[错误]150 val v3=Var(v1+v2)
[错误]151变量已更改=0
[错误]总时间:1秒,已完成2017年1月31日下午4:43:03
如果我把它加回去,一切都可以编译并正常工作。在更复杂的用例中,我在编译时遇到了一些问题,无法找到…
的代理,我想这可能就是原因
如果您有任何建议,我们将不胜感激。您正在将非类型树引入到类型树中 输入树将进行类型检查,然后输出树(宏发出的)将再次进行类型检查,但打字机不会下降到已进行类型检查的树(即,已为其指定类型的树)中 因为要引入新符号,所以不能仅使用传入的上下文来检查引用 因此,最简单的解决方案是,取消对传出树的类型检查。取消对
转换后的树的类型检查也就足够了,这样打字机就可以下降到新的非类型树
我不得不通过注释代码来减少爆炸性测试。不幸的是,现在还不清楚是什么源代码行导致了错误。如果您熟悉所涉及的宏,可能更明显
class Sample {
def sample(): Unit = {
val v = Var(5)
v := v + 5
}
}
正在讨论的树,来自-Xprint:typer-Yshow trees
:
Apply( // def +(x: Int): Int in class Int, tree.tpe=Int
com.outr.reactify.`package`.state2Value[Int](previousVal)."$plus" // def +(x: Int): Int in class Int, tree.tpe=(x: Int)Int
5
)
还值得一提的是,在错误消息中使用“重构的参数”编写快速编译脚本更容易,从而消除sbt增量编译、ScalaTest宏和其他谜团
编辑,手动设置的API:
def setStateChannel(value: c.Tree): c.Tree = {
val observables = retrieveObservables(c)(value)
val channel = c.prefix.tree
val selfReference = observables.exists(_.equalsStructure(channel))
val untyped =
q"""
val previousValue = com.outr.reactify.State.internalFunction($channel)
val previousVal = com.outr.reactify.Val(previousValue())
"""
val retyped = c.typecheck(untyped)
val transformed = if (selfReference) {
val transformer = new Transformer {
override def transform(tree: c.universe.Tree): c.universe.Tree = if (tree.equalsStructure(channel)) {
val t = q"previousVal"
val Block(_ :: v :: Nil, _) = retyped
c.internal.setSymbol(t, v.symbol)
c.internal.setType(t, v.tpe)
} else {
super.transform(tree)
}
}
transformer.transform(value)
} else {
value
}
val res = q"$channel.update(List(..$observables), $transformed)"
q"$retyped ; $res"
}
您正在将非类型化树引入类型化树
输入树将进行类型检查,然后输出树(宏发出的)将再次进行类型检查,但打字机不会下降到已进行类型检查的树(即,已为其指定类型的树)中
因为要引入新符号,所以不能仅使用传入的上下文来检查引用
因此,最简单的解决方案是,取消对传出树的类型检查。取消对转换后的树的类型检查也就足够了,这样打字机就可以下降到新的非类型树
我不得不通过注释代码来减少爆炸性测试。不幸的是,现在还不清楚是什么源代码行导致了错误。如果您熟悉所涉及的宏,可能更明显
class Sample {
def sample(): Unit = {
val v = Var(5)
v := v + 5
}
}
正在讨论的树,来自-Xprint:typer-Yshow trees
:
Apply( // def +(x: Int): Int in class Int, tree.tpe=Int
com.outr.reactify.`package`.state2Value[Int](previousVal)."$plus" // def +(x: Int): Int in class Int, tree.tpe=(x: Int)Int
5
)
还值得一提的是,在错误消息中使用“重构的参数”编写快速编译脚本更容易,从而消除sbt增量编译、ScalaTest宏和其他谜团
编辑,手动设置的API:
def setStateChannel(value: c.Tree): c.Tree = {
val observables = retrieveObservables(c)(value)
val channel = c.prefix.tree
val selfReference = observables.exists(_.equalsStructure(channel))
val untyped =
q"""
val previousValue = com.outr.reactify.State.internalFunction($channel)
val previousVal = com.outr.reactify.Val(previousValue())
"""
val retyped = c.typecheck(untyped)
val transformed = if (selfReference) {
val transformer = new Transformer {
override def transform(tree: c.universe.Tree): c.universe.Tree = if (tree.equalsStructure(channel)) {
val t = q"previousVal"
val Block(_ :: v :: Nil, _) = retyped
c.internal.setSymbol(t, v.symbol)
c.internal.setType(t, v.tpe)
} else {
super.transform(tree)
}
}
transformer.transform(value)
} else {
value
}
val res = q"$channel.update(List(..$observables), $transformed)"
q"$retyped ; $res"
}
我很感谢您的反馈,但我有点不确定这将如何使我更接近解决方案。我知道它是在previousVal
上爆炸的,我的问题是如何在不使用非类型树的情况下解决这个问题。previousVal
的目的是避免递归自调用,因为:=
采用了onymous函数,因此v+5
将创建一个递归场景。previousVal
在赋值时获取该值,并将其存储为s