在 Scala 2.9.3 编译器的擦除阶段之后获取具体类型的符号

Get reified type of symbol after the erasure phase of the Scala 2.9.3 compiler

本文关键字:之后 获取 符号 类型 段之后 Scala 编译器 擦除      更新时间:2023-10-16

我正在编写一个编译器插件,它将 Scala 的一个子集转换为 C++(忽略此任务的明显疯狂(。我正在使用许多必须在擦除阶段后运行的插件。但是,我需要完整的类型信息来输出有效的代码。

例如,对于斯卡拉;

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 签名的变化。 explicitoutererasure之前的阶段。

这个解决方案是由scala语言邮件列表提出的。在导入scala.tools.nsc.Global 的命名空间中,以下内容将在erasure阶段之前恢复方法的类型(更具体地说是 AST 中的DefDef(。

atPhase(currentRun.erasurePhase) { someDefDef.symbol.tpe }