Scala宏:生成的类无法使用未实现的成员进行编译

时间:2017-08-15 08:29:02

标签: scala macros scala-macro-paradise

我的问题是我生成的类成员没有被识别为已实现。这是为Scala 2.10 / 2.11 / 2.12构建的,默认为2.11。使用macroparadise 2.10。

这样做的目的是将某些特征标记为 freezable ,并为每个可冻结的方法生成scala.util.Try的实现类,这些方法将具有get访问数据时调用的方法。所有不可解冻的方法都填入throw new IllegalStateException。并创建了一个自定义freeze方法,该方法使用特征定义的方法创建填充了所需数据的Frozen类的实例。

我已将注释宏设置为 traits ,并生成一个伴随对象,其内部类名为Frozen,如下所示:

{
  abstract trait JavaInfo extends scala.AnyRef {
    @new CanFreeze() def isJavaInfo: Boolean;
    @new CannotFreeze() def toJavaInfo: AnyRef
  };
  object JavaInfo extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    class Frozen extends JavaInfo with java.io.Serializable {
      <paramaccessor> private val $isJavaInfo: scala.util.Try[Boolean] = _;
      def <init>($isJavaInfo: scala.util.Try[Boolean]) = {
        super.<init>();
        ()
      };
      override def isJavaInfo: Boolean = this.$isJavaInfo.get;
      override def toJavaInfo: AnyRef = throw new IllegalStateException("Method not frozen!")
    };
    def freeze(valueToFreeze: JavaInfo): Frozen = new Frozen(scala.util.Try.apply(valueToFreeze.isJavaInfo))
  };
  ()
}

当我尝试在特征JavaInfo上运行宏时发生以下错误:

[error] /Users/senk/projects/scala-debugger/scala-debugger-api/src/main/scala/org/scaladebugger/api/profiles/traits/info/JavaInfo.scala:9: class Frozen needs to be abstract, since:
[error] it has 2 unimplemented members.
[error] /** As seen from class Frozen, the missing signatures are as follows.
[error]  *  For convenience, these are usable as stub implementations.
[error]  */
[error]   override def isJavaInfo: Boolean = ???
[error]   override def toJavaInfo: AnyRef = ???
[error] @Freezable trait JavaInfo {
[error]  ^
[error] one error found

特质本身如下:

import org.scaladebugger.macros.freeze.{CanFreeze, CannotFreeze, Freezable}

@Freezable trait JavaInfo {
  @CanFreeze def isJavaInfo: Boolean
  @CannotFreeze def toJavaInfo: AnyRef
}

获取Frozen类没有实现任何内容的错误,即使我在我正在构建的树中看到了实现。

有问题的代码在这里:https://github.com/chipsenkbeil/scala-debugger/blob/AddFreezableMacroSupport/scala-debugger-macros/src/main/scala/org/scaladebugger/macros/freeze/FreezableMacro.scala

您可以通过检查该分支并运行sbt scalaDebuggerApi/compile来测试失败,这将编译Scala 2.11的宏项目,然后是API本身。

1 个答案:

答案 0 :(得分:0)

想出来。我正在创建方法并实现它们的主体,但是重用每个方法的旧修饰符,只需添加Flag.OVERRIDE: FlagSet。事实证明,未实现的方法对它们有Flag.DEFERRED,因此我生成了一个Modifiers(OVERRIDE | DEFERRED),考虑到它有一个正文,它没有意义。似乎具有DEFERRED的修饰符将导致编译器在检查方法时忽略正文,即使正文将显示在字节代码本身中。