我尝试使用一个tasty inspector将方法参数转换为case类,但是在运行时遇到了一个classcast异常。
我的代码:
import dotty.tools.dotc.ast.Trees.{PackageDef, Template}
import scala.quoted.*
import scala.tasty.inspector.*
class MyInspector extends Inspector:
def inspect(using Quotes)(tastys: List[Tasty[quotes.type]]): Unit =
for tasty <- tastys do
import tasty.quotes.reflect.*
tasty.ast match {
case PackageDef(pid, stats) =>
stats.collect { case TypeDef(typeName, Template(constr, parentsOrDerived, self, preBody: List[_])) =>
preBody.collect { case DefDef(name, paramss: List[List[_]] @unchecked, tpt, preRhs) =>
val params = paramss.flatten.map { case ValDef(name, tpt, preRhs) =>
s"$name : ${tpt.show}"
}
println(s"""
|case class ${typeName}_${name}_ccIn(${params.mkString(", ")})
|""".stripMargin)
println("------------------------")
}
}
}
@main def tryit() =
val tastyFiles = List("../example-commands/classpath-1/target/scala-3.2.1/classes/cp1/Cp1Exports.tasty")
TastyInspector.inspectTastyFiles(tastyFiles)(new MyInspector)
我对这个类运行这个代码(在我编译它并且编译器创建一个. tasty文件之后):
package cp1
import java.time.LocalDate
trait Cp1Exports:
def add(a: Int, b: Int): Int
def subtract(a: Int, b: Int): Int
def friends(p: Person, from: LocalDate): Seq[Person]
case class Person(id: Int, name: String)
但我得到了这个例外:
Exception in thread "main" java.lang.ClassCastException: class dotty.tools.dotc.ast.Trees$Import cannot be cast to class dotty.tools.dotc.ast.Trees$TypeDef (dotty.tools.dotc.ast.Trees$Import and dotty.tools.dotc.ast.Trees$TypeDef are in unnamed module of loader 'app')
at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeDef$.unapply(QuotesImpl.scala:339)
at console.macros.MyInspector$$anon$1.applyOrElse(MyInspector.scala:15)
导致此问题的行如下:
stats.collect { case TypeDef(typeName, Template(constr, parentsOrDerived, self, preBody: List[_])) =>
但是不应该这样,因为这是一个集合。错误是因为Cp1Exports中有一个导入而导致的。如果我删除导入,它就可以工作。
此外,任何建议,以简化代码将不胜感激。
我使用的是scala 3.2.1(包括该版本的scala编译器)
编辑:
好了,按照下面的建议,我结束了这个代码的工作(但似乎相当复杂):
import dotty.tools.dotc.ast.Trees.*
import scala.quoted.*
import scala.tasty.inspector.*
class MyInspector extends Inspector:
def inspect(using Quotes)(tastys: List[Tasty[quotes.type]]): Unit =
for tasty <- tastys do
given dotty.tools.dotc.core.Contexts.Context = scala.quoted.quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx
tasty.ast match {
case PackageDef(pid, stats) =>
stats.collect { case TypeDef(typeName, Template(constr, parentsOrDerived, self, preBody: List[_])) =>
preBody.collect { case DefDef(name, paramss: List[List[_]] @unchecked, tpt, preRhs) =>
val params = paramss.flatten.map { case ValDef(name, tpt, preRhs) =>
s"$name : ${tpt.show}"
}
println(s"""
|case class ${typeName}_${name}_ccIn(${params.mkString(", ")})
|""".stripMargin)
println("------------------------")
}
}
}
@main def tryit() =
val tastyFiles = List("../example-commands/classpath-1/target/scala-3.2.1/classes/cp1/Cp1Exports.tasty")
TastyInspector.inspectTastyFiles(tastyFiles)(new MyInspector)
谢啦,谢啦
1条答案
按热度按时间bejyjqdl1#
我注意到
不扔的时候
akka
确实如此。
区别似乎在于
dotty.tools.dotc.ast.Trees.TypeDef
是case类,而tasty.quotes.reflect.TypeDef
是抽象类型。原因似乎是类型擦除
Understanding why inlining function fixes runtime crash when collecting
复制更简单:
在这里,
X
、A
、B
、C
与Quotes
、Tree
、ValDef
、TypeDef
类似。