forked from scala/scala
-
Notifications
You must be signed in to change notification settings - Fork 1
SIP-23 Account for literal types in varargs translation #13
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
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Before: sandbox/test.scala:2: error: type mismatch; found : Array[1] required: Array[Int]
adriaanm
added a commit
that referenced
this pull request
Oct 28, 2014
SIP-23 Account for literal types in varargs translation
adriaanm
pushed a commit
that referenced
this pull request
Aug 22, 2016
Top level modules in Scala currently desugar as:
```
class C; object O extends C { toString }
```
```
public final class O$ extends C {
public static final O$ MODULE$;
public static {};
Code:
0: new #2 // class O$
3: invokespecial #12 // Method "<init>":()V
6: return
private O$();
Code:
0: aload_0
1: invokespecial #13 // Method C."<init>":()V
4: aload_0
5: putstatic #15 // Field MODULE$:LO$;
8: aload_0
9: invokevirtual #21 // Method java/lang/Object.toString:()Ljava/lang/String;
12: pop
13: return
}
```
The static initalizer `<clinit>` calls the constructor `<init>`, which
invokes superclass constructor, assigns `MODULE$= this`, and then runs
the remainder of the object's constructor (`toString` in the example
above.)
It turns out that this relies on a bug in the JVM's verifier: assignment to a
static final must occur lexically within the <clinit>, not from within `<init>`
(even if the latter is happens to be called by the former).
I'd like to move the assignment to <clinit> but that would
change behaviour of "benign" cyclic references between modules.
Example:
```
package p1; class CC { def foo = O.bar}; object O {new CC().foo; def bar = println(1)};
// Exiting paste mode, now interpreting.
scala> p1.O
1
```
This relies on the way that we assign MODULE$ field after the super class constructors
are finished, but before the rest of the module constructor is called.
Instead, this commit removes the ACC_FINAL bit from the field. It actually wasn't
behaving as final at all, precisely the issue that the stricter verifier
now alerts us to.
```
scala> :paste -raw
// Entering paste mode (ctrl-D to finish)
package p1; object O
// Exiting paste mode, now interpreting.
scala> val O1 = p1.O
O1: p1.O.type = p1.O$@ee7d9f1
scala> scala.reflect.ensureAccessible(p1.O.getClass.getDeclaredConstructor()).newInstance()
res0: p1.O.type = p1.O$@64cee07
scala> O1 eq p1.O
res1: Boolean = false
```
We will still achieve safe publication of the assignment to other threads
by virtue of the fact that `<clinit>` is executed within the scope of
an initlization lock, as specified by:
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.5
Fixes scala/scala-dev#SD-194
adriaanm
pushed a commit
that referenced
this pull request
Jun 10, 2017
Non local returns aren't eliminated after inlined in 2.11 or 2.12
```
⚡ scala
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_112).
Type in expressions for evaluation. Or try :help.
scala> @inlune def foo(a: => Any) = if ("".isEmpty) a else ""
<console>:11: error: not found: type inlune
@inlune def foo(a: => Any) = if ("".isEmpty) a else ""
^
scala> @inline def foo(a: => Any) = if ("".isEmpty) a else ""
foo: (a: => Any)Any
scala> class InlineReturn { def test: Any = foo(return "") }
defined class InlineReturn
scala> :javap -c InlineReturn#test
public java.lang.Object test();
Code:
0: new #4 // class java/lang/Object
3: dup
4: invokespecial scala#32 // Method java/lang/Object."<init>":()V
7: astore_1
8: getstatic scala#36 // Field $line4/$read$$iw$$iw$.MODULE$:L$line4/$read$$iw$$iw$;
11: aload_1
12: invokedynamic scala#59, 0 // InvokeDynamic #0:apply:(Ljava/lang/Object;)Lscala/Function0;
17: invokevirtual scala#63 // Method $line4/$read$$iw$$iw$.foo:(Lscala/Function0;)Ljava/lang/Object;
20: goto 44
23: astore_2
24: aload_2
25: invokevirtual scala#66 // Method scala/runtime/NonLocalReturnControl.key:()Ljava/lang/Object;
28: aload_1
29: if_acmpne 39
32: aload_2
33: invokevirtual scala#69 // Method scala/runtime/NonLocalReturnControl.value:()Ljava/lang/Object;
36: goto 41
39: aload_2
40: athrow
41: goto 44
44: areturn
Exception table:
from to target type
8 20 23 Class scala/runtime/NonLocalReturnControl
```
```
⚡ ~/scala/2.11.8/bin/scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_112).
Type in expressions for evaluation. Or try :help.
scala> @inline def foo(a: => Any) = if ("".isEmpty) a else ""
foo: (a: => Any)Any
scala> class InlineReturn { def test: Any = foo(return "") }
defined class InlineReturn
scala> :javap -c InlineReturn#test
public java.lang.Object test();
Code:
0: new #4 // class java/lang/Object
3: dup
4: invokespecial #13 // Method java/lang/Object."<init>":()V
7: astore_1
8: getstatic #19 // Field .MODULE$:L;
11: new #21 // class InlineReturn$$anonfun$test$1
14: dup
15: aload_0
16: aload_1
17: invokespecial #24 // Method InlineReturn$$anonfun$test$1."<init>":(LInlineReturn;Ljava/lang/Object;)V
20: invokevirtual scala#28 // Method .foo:(Lscala/Function0;)Ljava/lang/Object;
23: goto 39
26: astore_2
27: aload_2
28: invokevirtual scala#31 // Method scala/runtime/NonLocalReturnControl.key:()Ljava/lang/Object;
31: aload_1
32: if_acmpne 40
35: aload_2
36: invokevirtual scala#34 // Method scala/runtime/NonLocalReturnControl.value:()Ljava/lang/Object;
39: areturn
40: aload_2
41: athrow
Exception table:
from to target type
8 26 26 Class scala/runtime/NonLocalReturnControl
scala> :quit
```
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Before: