我正在编写一个编译器插件,将Scala的子集转换为C ++(忽略此任务的明显精神错乱)。我正在使用一些必须在擦除阶段之后运行的插件。但是,我需要完整的类型信息来输出有效的代码。
例如,对于Scala;
def foo(f: Type1 => Type2): Unit = { /* Snip */ }
我想输出C ++;
void foo(scala::Function1<Type1, Type2> f) { /* Snip */ }
然而,在擦除阶段之后,foo
看起来像这样:
def foo(f: Function1): Unit = { /* Snip */ }
即,参数f
的泛型类型信息已丢失。我需要把它拿回去。有什么建议吗?
回复cdshines的评论
以下是一个例子:
example.scala
object Example {
def func(f: Int => Boolean) { }
}
当我编译时;
# scalac -version
Scala compiler version 2.9.3 -- Copyright 2002-2011, LAMP/EPFL
# scalac -Xprint:explicitouter -Xprint:erasure example.scala
[[syntax trees at end of explicitouter]]// Scala source: example.scala
package <empty> {
final object Example extends java.lang.Object with ScalaObject {
def this(): object Example = {
Example.super.this();
()
};
def func(f: Int => Boolean): Unit = ()
}
}
[[syntax trees at end of erasure]]// Scala source: example.scala
package <empty> {
final object Example extends java.lang.Object with ScalaObject {
def this(): object Example = {
Example.super.this();
()
};
def func(f: Function1): Unit = ()
}
}
请注意func
签名的更改。 explicitouter
是erasure
之前的阶段。
答案 0 :(得分:0)
这个解决方案是由scala语言邮件列表提出的。在导入scala.tools.nsc.Global
命名空间的内容中,以下内容将在DefDef
阶段之前恢复方法的类型(更具体地说,在AST中为erasure
)。
atPhase(currentRun.erasurePhase) { someDefDef.symbol.tpe }