Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scala.js backend cannot emit static fields #14710

Open
TheElectronWill opened this issue Mar 18, 2022 · 1 comment
Open

Scala.js backend cannot emit static fields #14710

TheElectronWill opened this issue Mar 18, 2022 · 1 comment

Comments

@TheElectronWill
Copy link
Contributor

Compiler version

3.1.1

Minimized code

import scala.annotation.static

object Invoker:
  @static val x = ""
  @static def f(): Unit = println(x)

Output

 java.lang.IllegalArgumentException: requirement failed: a member can have a static constructor name iff it is in the static constructor namespace
Error:  	at scala.Predef$.require(Predef.scala:337)
Error:  	at org.scalajs.ir.Trees$MethodDef.<init>(Trees.scala:1148)
Error:  	at org.scalajs.ir.Trees$MethodDef$.apply(Trees.scala:1134)
Error:  	at dotty.tools.backend.sjs.JSCodeGen.genMethodDef(JSCodeGen.scala:1563)
Error:  	at dotty.tools.backend.sjs.JSCodeGen.genMethodWithCurrentLocalNameScope$$anonfun$1(JSCodeGen.scala:1529)
Error:  	at dotty.tools.backend.sjs.JSCodeGen.withPerMethodBodyState$$anonfun$1(JSCodeGen.scala:106)
Error:  	at dotty.tools.backend.sjs.ScopedVar$.withScopedVars(ScopedVar.scala:33)
Error:  	at dotty.tools.backend.sjs.JSCodeGen.withPerMethodBodyState(JSCodeGen.scala:107)
Error:  	at dotty.tools.backend.sjs.JSCodeGen.genMethodWithCurrentLocalNameScope(JSCodeGen.scala:1535)
...

Expectation

It should work with val just like it does with defs. The following compiles fine:

object Invoker:
  @static def x = "" // methods work fine
  @static def f(): Unit = println(x)
@sjrd sjrd self-assigned this Mar 18, 2022
@sjrd sjrd changed the title ScalaJS backend cannot emit static fields Scala.js backend cannot emit static fields Mar 18, 2022
@sjrd
Copy link
Member

sjrd commented Jun 22, 2022

I looked a bit at this, and I have some work-in-progress in the following branch:
main...sjrd:sjs-static-fields

The fields themselves and accesses to them can now be compiled. But the class initializer, which must actually initialize these fields with their right-hand-side, is not triggered.

It's unclear how to deal with that. The Scala.js IR doesn't have a notion of a class initializer that is called upon first access to a static field. It has static initializers, but those are never dead-code-eliminated. They are classpath-wide forced startup code.

We would have to manually generate a call to a one-off initializer at the beginning of every static method, and at the beginning of every instance constructor.

We also don't have any public ABI defined for mutating static fields, so that would have to be defined as well.


Workaround: don't use @static in Scala.js.

I'm afraid it's a half-baked feature in dotc to begin with: never discussed/validated in public discussions nor in SIP meetings, and not documented. So I don't think I will prioritize this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants