-
Notifications
You must be signed in to change notification settings - Fork 1k
Add @static SIP #491
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
Add @static SIP #491
Conversation
{% endhighlight %} | ||
``` | ||
|
||
## Comparisson with mirror classes ## |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comparison
This pull request implements most of machinery needed for scala/docs.scala-lang#491 Only 3-rd check is not implemented by this commit. I propose to get this in faster to fix scala#1149
This pull request implements most of machinery needed for scala/docs.scala-lang#491 Only 3-rd check is not implemented by this commit. I propose to get this in faster to fix scala#1149
The implementation was merged into Dotty. |
|
||
For example, classes extending `android.os.Parcelable` are required to have a static field named `CREATOR` of type `android.os.Parcelable$Creator`. | ||
|
||
Another example is using an [`AtomicReferenceFieldUpdater`](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.html). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/7/8/ ?
why can't we have static as a keyword? |
Because adding new keywords breaks existing code that used them as identifiers. Adding keywords must be done very sparingly, only when there is no other option. |
I guess libs doing interop with Java code will be avoiding that. |
@DarkDimius is there any change you want to do here before the SIP review? |
Why would they? You may want some data to be seen as Java static field, and you can use |
@jvican, I've applied those changes now and cleared git history. Feel free to merge if it looks good. |
Great changes, let's merge it for next week's discussion. |
The proposal should go into more detail on:
Some relevant bugs: |
I'd like to see the "Compilation scheme" section fleshed out. Currently, it talks about how this would fit into the compiler pipeline, but lacks details about how things would be compiled to bytecode. Here's an example I'm interested in: package p1; object C { @static val foo: AnyRef = C; val bar: AnyRef = C } If I translate this according to the intuitive description herein, taking a few guesses at the details, I start with: public class Test {
public static void main(String[] args) {
System.out.println(C$.MODULE$.foo()); // null
}
}
class C {
public static final Object foo;
static {
foo = C$.MODULE$; // initializer moved to CompanionClass.<clinit>
}
}
final class C$ {
public static C$ MODULE$;
private final Object bar;
public static Object foo() { return C.foo; }
static {
Object x = C.foo; // or UNSAFE.ensureClassInitialized(classOf[C])
new C$();
}
private C$() {
super();
MODULE$ = this;
bar = this;
}
} Running this prints final class C$ {
public static C$ MODULE$;
private final Object bar;
public static Object foo() { return C.foo; }
static {
new C$();
}
private C$() {
super();
MODULE$ = this;
Object x = C.foo; // or UNSAFE.ensureClassInitialized(classOf[C])
bar = this;
}
} Which avoids the NPE. But in that case, triggering Both of these variations have another drawback: References to So maybe we instead should put leave all the initalization code in the module class? class C {
public static Object foo; // can't be final
}
final class C$ {
public static C$ MODULE$;
private final Object bar;
public static Object foo() { return C.foo; }
static {
new C$();
}
private C$() {
super();
MODULE$ = this;
C.foo = this;
bar = this;
}
} This looks more promising for thread-safe initialization, and preserving semantics. But we are no unable to declare |
We could also consider omitting the accessor methods for |
class C {
public static Object foo;
static {
foo = C$.MODULE$;
}
}
final class C$ {
public static C$ MODULE$;
private final Object bar;
public static Object foo() { return C.foo; }
static {
new C$();
}
private C$() {
super();
MODULE$ = this;
Object x = C.foo; // or UNSAFE.ensureClassInitialized(classOf[C])
bar = this;
}
} Is the proposed desugaring.
I guess you've meant
In case you did, the order in which initializer for foo and the super constructor of the module class is run indeed may change under the proposed sip. It's discussed here https://github.com/scala/scala.github.com/pull/658/files#diff-9284321b7900073f358a16a971c06881R159 , do you want me to expand this discussion?
If we always trigger initialization of Thanks for the questions, I'll expand the "Compilation scheme" section. |
Yes, it would be useful to talk about the super constructor thing explicitly,
I still think that we're introducing a new form of cycle by moving |
```java | ||
{% highlight java %} | ||
class Foo { | ||
public static int x = 5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this be final?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
Add @static SIP