在 Scala 编译器插件中为合成类定义构造函数参数?

发布于 2024-12-11 14:07:02 字数 1475 浏览 0 评论 0原文

我正在尝试在 Scala 编译器插件中生成一个类。我有一个特征 Test,并且需要一个 TestWrapper 类,大致如下:

class TestWrapper(wrapped: Test) extends Test { ... }

我像这样定义构造函数参数:

val pName = newTermName("wrapped")
val paramSym = myNewClass.newValueParameter(owner.pos.focus, pName)
paramSym.setInfo(wrapped.tpe).setFlag(SYNTHETIC)
val param = ValDef(paramSym)

然后

ClassDef(myNewClass, NoMods, List(List(param)), List(Nil),
        members, owner.pos)

是接收参数的 ClassDef: 。目前,我得到的是:

// Scala source: Test.scala
[[syntax trees at end of generatewrappers]]
package test {
  <synthetic> class TestWrapper extends Object with test.Test {
    <synthetic> val wrapped: test.Test = _;
    def this(wrapped: test.Test): test.TestWrapper = {
      TestWrapper.super.this();
      ()
    };
    <synthetic> def m3: Int = TestWrapper.this.wrapped.m3;
  };

编译器似乎会自动生成一个与参数同名的字段。我没有看到从参数到字段的分配,但我认为它是“隐式的”。我可以用 Test 的具体实例实例化这个 TestWrapper,但是调用 m3 会导致异常:

java.lang.NoSuchFieldError: wrapped
    at test.TestWrapper.m3(Test.scala:1)
    ...

“wrapped”实际上应该是 3 个不同的东西:

1) A constructor parameter
2) An class instance field
3) A getter for the class instance field

编译器的输出显示毕竟有一个字段:

<synthetic> val wrapped: test.Test = _;

并且它是定义的,因为“= _”,而不是未定义,当没有“= ...”时

那么,我错过了什么?

I'm trying to generate a class in a Scala compiler Plugin. I have a trait Test, and need a class TestWrapper, approximately like this:

class TestWrapper(wrapped: Test) extends Test { ... }

I define the constructor parameter like this:

val pName = newTermName("wrapped")
val paramSym = myNewClass.newValueParameter(owner.pos.focus, pName)
paramSym.setInfo(wrapped.tpe).setFlag(SYNTHETIC)
val param = ValDef(paramSym)

and later the ClassDef:

ClassDef(myNewClass, NoMods, List(List(param)), List(Nil),
        members, owner.pos)

which receives the parameter. Currently, what I get is:

// Scala source: Test.scala
[[syntax trees at end of generatewrappers]]
package test {
  <synthetic> class TestWrapper extends Object with test.Test {
    <synthetic> val wrapped: test.Test = _;
    def this(wrapped: test.Test): test.TestWrapper = {
      TestWrapper.super.this();
      ()
    };
    <synthetic> def m3: Int = TestWrapper.this.wrapped.m3;
  };

The compiler seems to be automatically generating a field with the same name as the parameter. What I don't see is the assignment from the parameter to the field, but I had assumed it was "implicit". I can than instantiate this TestWrapper with a concrete instance of Test, but calling m3 causes an Exception:

java.lang.NoSuchFieldError: wrapped
    at test.TestWrapper.m3(Test.scala:1)
    ...

"wrapped" should in fact be 3 different things:

1) A constructor parameter
2) An class instance field
3) A getter for the class instance field

The output of the compiler shows after all that there is a field:

<synthetic> val wrapped: test.Test = _;

and that it is defined, because of the "= _", as opposed to undefined, when there is no "= ..."

So, what am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夏末染殇 2024-12-18 14:07:02

知道了。我需要添加以下行:

myNewClass.info.decls.enter(paramSym)

呃!

Got it. I needed to add the following line:

myNewClass.info.decls.enter(paramSym)

Duh!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文