Skip to content

Commit b13183d

Browse files
sjrdDarkDimius
authored andcommitted
Various expansions to the static SIP, including JS-related stuff.
1 parent e6a414b commit b13183d

File tree

1 file changed

+75
-22
lines changed

1 file changed

+75
-22
lines changed

sips/pending/_posts/2016-01-01-static-members.md

Lines changed: 75 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,68 +4,121 @@ title: SIP 25 - @static fields and methods in Scala objects(SI-4581)
44
disqus: true
55
---
66

7-
__Dmitry Petrashko__
7+
__Dmitry Petrashko and Sébastien Doeraene__
88

99
__first submitted TODO 2016__
1010

1111
## Motivation ##
1212

13-
We would like to allow methods and fields to be compiled as static. This is usable for interop with Java and other JVM languages and is convenient for optimizations.
13+
We would like to allow methods and fields to be compiled as static. This is usable for interop with Java and other JVM languages, as well as with JavaScript, and is convenient for optimizations.
1414

1515
## Use Cases
1616

17-
Some JVM and JavaScript frameworks require classes to have specific static fields.
17+
Some JVM and JavaScript frameworks require classes to have specific static fields and/or methods.
1818

1919
For example, classes extending `android.os.Parcelable` are required to have a static field named `CREATOR` of type `android.os.Parcelable$Creator`.
2020

2121
Another example is using an [`AtomicReferenceFieldUpdater`](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.html).
2222

23-
@sjrd could you please illustrate JS exaples?
23+
On the JavaScript side, one example is [Relay Route Definitions](https://facebook.github.io/relay/docs/guides-routes.html), whose subclasses must define static fields such as `queries`.
24+
Static methods and fields for JavaScript classes are one of the very few things (if not the only thing) that Scala.js "cannot do" at the moment, at least not declaratively.
25+
26+
## Overview ##
2427

25-
## Syntax ##
2628
In order for method or field to be considered static it needs to be defined in an `object` and annotated `@static`.
2729
There is no special syntax proposed to access these members, they are accessed as if they were a member of defining objects with all appropriate access requirements for accessing them.
2830

31+
For example:
32+
33+
{% highlight scala %}
34+
class Foo
35+
36+
object Foo {
37+
@static val x = 5
38+
@static def bar(y: Int): Int = x + y
39+
}
40+
41+
println(Foo.x)
42+
println(Foo.bar(12))
43+
{% endhighlight %}
44+
45+
Intuively, the presence of the `@static` annotation ensures that a field/method is declared as a static member of the companion class.
46+
For the JVM, the above would therefore look to other Java code as if it had been declared with the following Java code:
47+
48+
{% highlight java %}
49+
class Foo {
50+
public static int x = 5;
51+
public static int bar(int y) {
52+
return x + y;
53+
}
54+
}
55+
{% endhighlight %}
56+
57+
In Scala.js, the `@static` annotation has no semantic effect in Scala objects, as they are not visible from JavaScript anyway (it could be used for optimizations).
58+
It has a semantic effect on Scala.js-defined JS classes, for example:
59+
60+
{% highlight scala %}
61+
@ScalaJSDefined
62+
class Foo extends js.Object
63+
64+
@ScalaJSDefined
65+
object Foo extends js.Object {
66+
@static val x = 5
67+
@static def bar(y: Int): Int = x + y
68+
}
69+
{% endhighlight %}
70+
71+
would look to JavaScript code as if it had been declared with the following JavaScript code:
72+
73+
{% highlight javascript %}
74+
class Foo extends Object {
75+
static bar(y) {
76+
return x + y;
77+
}
78+
}
79+
Foo.x = 5; // in ES6, there is no declarative syntax for static fields yet
80+
{% endhighlight %}
81+
2982
## Restrictions ##
3083

3184
The following rules ensure that method can be correctly compiled into static member on both JVM and JavaScript:
3285

33-
1. Only objects can have members annotated as `@static`
86+
1. Only objects can have members annotated with `@static`
3487

3588
2. The fields annotated with `@static` should preceed any non-`@static` fields. This ensures that we do not introduce surprises for users in initialization order.
3689

37-
3. The right hand side of method or field annotated as `@static` can only refer to members of globally accessible objects and `@static` members. In particular, for non-static objects `this` is not accesable. `super` is never accessable.
90+
3. The right hand side of a method or field annotated with `@static` can only refer to members of globally accessible objects and `@static` members. In particular, for non-static objects `this` is not accesible. `super` is never accessible.
3891

39-
4. If member `foo` of `object C` is annotated `@static`, companion class `C` is not allowed to define term members with name `foo`.
92+
4. If a member `foo` of an `object C` is annotated with `@static`, the companion class `C` is not allowed to define term members with name `foo`.
4093

41-
5. If member `foo` of `object C` is annotated `@static`, companion class `C` is not allowed to inherit classes that define a term member with name `foo`..
94+
5. If a member `foo` of an `object C` is annotated with `@static`, the companion class `C` is not allowed to inherit classes that define a term member with name `foo`.
4295

43-
6. Only @static methods and vals are suppoerted in companions of traits. Java8 supports those, but not vars.
96+
6. Only @static methods and vals are supported in companions of traits. Java8 supports those, but not vars, and JavaScript does not have interfaces at all.
4497

4598
## Compilation scheme ##
46-
No modificaiton of typer is planned. The current proposed scheme piggybacks on already existing scoping restrictions in typer, thus requiring `@static` methods to be defined in `objects`.
47-
If implemented in dotty code base, such modifications would be needed:
48-
- extend RefChecks to check restrictions 1, 2, 4, 5 and 6. This can be done in a separate mini-phase;
49-
- extend LamdaLift.CollectDependencies to be aware that accessing member annotated `@static` should not trigger capturing object that contains this member;
50-
- extend LambdaLift to trigger error if `@static` annotated method cannot be lifted to top level scope;
51-
- extend GenBCode to emmit static fields and methods in companion classes and forwarders to them in companion modules.
99+
No modificaiton of the typer is planned. The current proposed scheme piggybacks on already existing scoping restrictions in the typer, thus requiring `@static` methods to be defined in `objects`.
100+
If implemented in the dotty code base, the following modifications would be needed:
101+
- extend `RefChecks` to check restrictions 1, 2, 4, 5 and 6. This can be done in a separate mini-phase;
102+
- extend `LamdaLift.CollectDependencies` to be aware that accessing a member annotated `@static` should not trigger capturing the object that contains this member;
103+
- extend `LambdaLift` to trigger an error if a method annotated with `@static` method cannot be lifted to the top level scope;
104+
- extend `GenBCode` to emit static fields and methods in companion classes and forwarders to them in companion modules.
52105

53106
## Overriding&Hiding ##
54-
Java allows classes to define static methods with same name and signature as a static method of superclass. In order to define semantics of what does it mean,
55-
Java Specification introduces a notion of [hiding](http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8.2).
107+
Java allows classes to define static methods with the same name and signature as a static method of a superclass. In order to define the semantics of such cases, the Java Specification introduces the notion of [hiding](http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8.2).
56108

57-
This is required because in Java calling `@static` method on class instance is supported.
109+
This is required because in Java calling a `static` method on a class instance is supported.
58110
This proposal does not need to introduce this notion as we do not support such calls.
59111

60-
## Comparison with @lrytz [proposal](https://gist.github.com/lrytz/80f3141de8240f9629da) ##
61-
Lucas Rytz has proposed a similar SIP, but his SIP requires changes to typer to ensure that `@static` fields do not capture `this`, as in his proposal `@static` fields are defined in class body.
62-
It also does not address the question of `@static` members in inner objects and inheritance\hiding of those methods in subclasses.
112+
## Comparison with [@lrytz's proposal](https://gist.github.com/lrytz/80f3141de8240f9629da) ##
113+
Lucas Rytz has proposed a similar SIP, but his SIP requires changes to the typer to ensure that `@static` fields do not capture `this`, as in his proposal `@static` fields are defined in the class, rather than its companion object.
114+
It also does not address the question of `@static` members in inner objects and inheritance/hiding of those methods in subclasses.
63115

64116
## Open questions ##
65117
- @static lazy val
66118

67119
## See Also ##
68120
* [SI-4581](https://issues.scala-lang.org/browse/SI-4581) is a request for a `@static` annotation
121+
* [Scala.js issue #1902](https://github.com/scala-js/scala-js/issues/1902) is a request for defining static fields in Scala.js-defined JS classes
69122
* [Another proposal by @lrytz](https://gist.github.com/lrytz/80f3141de8240f9629da)
70123
* [Old discussion on scala-internals mailing list](https://groups.google.com/forum/#!searchin/scala-internals/static/scala-internals/vOps4k8CADY/Dq1I3Ysvao0J)
71124
* [Another discussion of scala-internals mailing list](https://groups.google.com/forum/#!searchin/scala-internals/static/scala-internals/Y3OlFWPvnyM/tGE5BQw4Pe0J)

0 commit comments

Comments
 (0)