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

Already on GitHub? Sign in to your account

Add withErrorMessage and withFailureMessage to Parsers.Parser, #21

Closed
wants to merge 1 commit into
from

Conversation

Projects
None yet
2 participants
Contributor

dcsobral commented Dec 2, 2011

which can be used to reliably override the default no success
messages.

Add withErrorMessage and withFailureMessage to Parsers.Parser,
which can be used to reliably override the default no success
messages.

@paulp paulp closed this Dec 2, 2011

gkossakowski added a commit to gkossakowski/scala that referenced this pull request Jan 11, 2012

Merge pull request #21 from gkossakowski/library-gwt
Scala library rewritings tailored to GWT

retronym added a commit to retronym/scala that referenced this pull request Jan 19, 2013

SI-6891 Fix value class + tailrec crasher.
rhs.substituteSymbols(old, new) leaves us with:

    def loop#12225(x#12226: A#15491): scala#21.this.Unit#1615 =
      loop#12225(x#12226)

In which the TermSymbol x#12226 has a stale info, pointing at
the A#7274, the class type parameter, rather than A#15491,
the corresponding type parameter of the synthetic backing
method.

I've improved `TreeSymSubstituter` to substitute not
only `Tree#{tpe, symbol}`, but also `DefTree#sym.info`.

The `pos` test that triggered the new code path are
listed here: https://gist.github.com/4575687

retronym referenced this pull request in retronym/scala Jan 20, 2013

WIP Ill-scoped reference checking in TreeCheckers
Find trees which have an info referring to an out-of-scope
type parameter, as could happen in cases on SI-6981,
in which tree transplanting did not substitute symbols
in symbol infos.

With the proposed fix for that bug reverted, and this
commit in place, one sees:

    ticket/6891 ~/code/scala2 ./build/quick/bin/scalac -uniqid -Ycheck:extmethods test/files/pos/t6891.scala
    [Now checking: extmethods]
    [check: extmethods] The info of tree @scala#21.annotation#1622.tailrec#2397 def loop#12389(x#12390: A#15658): Unit#1613 = loop#12389(x#12390) refers to a out-of-scope type parameter type A#7437
    [check: extmethods] The info of tree val x#12390: A#7437 = _ refers to a out-of-scope type parameter type A#7437
    [check: extmethods] The info of tree loop#12389(x#12390) refers to a out-of-scope type parameter type A#7437
    [check: extmethods] The info of tree loop#12389 refers to a out-of-scope type parameter type A#7437
    [check: extmethods] The info of tree x#12390 refers to a out-of-scope type parameter type A#7437
    [check: extmethods] The info of tree <synthetic> val x2#15642: O#7027.Foo#7436[A#7437] = (x1#15641.asInstanceOf#4726[O#7027.Foo#7436[A#15676]]: O#7027.Foo#7436[A#15676]) refers to a out-of-scope type parameter type A#7437
    [check: extmethods] The info of tree <synthetic> val Foo$1#12663: O#7027.Foo#7436[A#7437] = x$1#15678.asInstanceOf#4726[O#7027.Foo#7436[A#15676]] refers to a out-of-scope type parameter type A#7437
    [check: extmethods] The info of tree Foo$1#12663 refers to a out-of-scope type parameter type A#7437

TODO
  - extend this to find references to out-of-scope method
    parameters, etc.
  - look for more direct errors in the symbol of a RefTree

retronym added a commit to retronym/scala that referenced this pull request Jan 26, 2013

SI-6891 Fix value class + tailrec crasher.
rhs.substituteSymbols(old, new) leaves us with:

    def loop#12225(x#12226: A#15491): scala#21.this.Unit#1615 =
      loop#12225(x#12226)

In which the TermSymbol x#12226 has a stale info, pointing at
the A#7274, the class type parameter, rather than A#15491,
the corresponding type parameter of the synthetic backing
method.

I've improved `TreeSymSubstituter` to substitute not
only `Tree#{tpe, symbol}`, but also `DefTree#sym.info`.

The `pos` test that triggered the new code path are
listed here: https://gist.github.com/4575687

AFAICS, no special treatment of Function, Return, or Import
is needed in TreeSymSubstutor.

retronym added a commit to retronym/scala that referenced this pull request May 30, 2013

SI-6943 Fix existential type used to hide local classes
In:

    def foo = { object O { class C }; new O.C }

The inferred return type of can't refer to the local
symbols; they must not leak out of the compilation unit.

Instead, `packSymbols` is used to choose a less precise
existential type, `(AnyRef { type C <: AnyRef })#C)`.

This is implemented as a `TypeMap`, which is supposed to
takes care of rebinding `C` to something valid in the new
prefix (`(AnyRef { type C <: AnyRef })`).

If `C` was orginally a type alias, and the original
prefix was a refinement type, this was handled in
`AliasTypeRef#coevolveSym`, which looks for a type
in the new prefix with the name `C`. But for other
type refs (e.g. a class type ref, as in this case),
a no-op `coevolveSym` was used, deferring the rebinding
of abstract classes until `typeRef`.

But our case falls between the cracks, and we end up
propagating a type ref in which the prefix does not
contain the member.

With the help of `-uniqid`, this is clear:

    <method> def foo#7445(): scala#21.this.AnyRef#2222{type Bar#12153 <: scala#21.this.AnyRef#2222}#Bar#12125

Notice the reference to symbol `#12125`, rather than `#12153`.

This commit moves the `coevolveSym` logic up to `TypeRef`,
generalizing it to work for any `pre1`. This example answered
the question in that code:

> // TODO: is there another way a typeref's symbol can refer to a symbol defined in its pre?

retronym added a commit to retronym/scala that referenced this pull request May 31, 2013

SI-6493 Fix existential type used to hide local classes
In:

    def foo = { object O { class C }; new O.C }

The inferred return type of can't refer to the local
symbols; they must not leak out of the compilation unit.

Instead, `packSymbols` is used to choose a less precise
existential type, `(AnyRef { type C <: AnyRef })#C)`.

This is implemented as a `TypeMap`, which is supposed to
takes care of rebinding `C` to something valid in the new
prefix (`(AnyRef { type C <: AnyRef })`).

If `C` was orginally a type alias, and the original
prefix was a refinement type, this was handled in
`AliasTypeRef#coevolveSym`, which looks for a type
in the new prefix with the name `C`. But for other
type refs (e.g. a class type ref, as in this case),
a no-op `coevolveSym` was used, deferring the rebinding
of abstract classes until `typeRef`.

But our case falls between the cracks, and we end up
propagating a type ref in which the prefix does not
contain the member.

With the help of `-uniqid`, this is clear:

    <method> def foo#7445(): scala#21.this.AnyRef#2222{type Bar#12153 <: scala#21.this.AnyRef#2222}#Bar#12125

Notice the reference to symbol `#12125`, rather than `#12153`.

This commit moves the `coevolveSym` logic up to `TypeRef`,
generalizing it to work for any `pre1`. This example answered
the question in that code:

> // TODO: is there another way a typeref's symbol can refer to a symbol defined in its pre?

retronym added a commit to retronym/scala that referenced this pull request Sep 25, 2013

SI-6493 Fix existential type used to hide local classes
In:

    def foo = { object O { class C }; new O.C }

The inferred return type of can't refer to the local
symbols; they must not leak out of the compilation unit.

Instead, `packSymbols` is used to choose a less precise
existential type, `(AnyRef { type C <: AnyRef })#C)`.

This is implemented as a `TypeMap`, which is supposed to
takes care of rebinding `C` to something valid in the new
prefix (`(AnyRef { type C <: AnyRef })`).

If `C` was orginally a type alias, and the original
prefix was a refinement type, this was handled in
`AliasTypeRef#coevolveSym`, which looks for a type
in the new prefix with the name `C`. But for other
type refs (e.g. a class type ref, as in this case),
a no-op `coevolveSym` was used, deferring the rebinding
of abstract classes until `typeRef`.

But our case falls between the cracks, and we end up
propagating a type ref in which the prefix does not
contain the member.

With the help of `-uniqid`, this is clear:

    <method> def foo#7445(): scala#21.this.AnyRef#2222{type Bar#12153 <: scala#21.this.AnyRef#2222}#Bar#12125

Notice the reference to symbol `#12125`, rather than `#12153`.

This commit moves the `coevolveSym` logic up to `TypeRef`,
generalizing it to work for any `pre1`. This example answered
the question in that code:

> // TODO: is there another way a typeref's symbol can refer to a symbol defined in its pre?

Note: The first attempt at the commit failed to bootstrap GenSeqLike,
for reasons mimimized in pos/t6493b.scala. In AliasTypeRef it was
sufficient to look at `decls` to find the corresponding member, but
in other cases we need to do a member lookup.

retronym referenced this pull request in retronym/scala May 19, 2015

[indystructural] Prototype structural calls using invokedynamic
See also: https://github.com/retronym/indy-structural

```
qscalac -target:jvm-1.8 -Ybackend:GenBCode sandbox/structural.scala && qscala Test && javap -v 'Test$' | cat -v
warning: there was one feature warning; re-run with -feature for details
one warning found

QUACK! A
QUICK! A

Classfile /Users/jason/code/scala2/Test$.class
{
  public static final Test$ MODULE$;
    descriptor: LTest$;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL

  public void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=4, locals=2, args_size=2
         0: getstatic     #19                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
         3: aload_0
         4: new           #21                 // class C
         7: dup
         8: invokespecial #22                 // Method C."<init>":()V
        11: invokevirtual #26                 // Method duckduck:(Ljava/lang/Object;)Ljava/lang/String;
        14: invokevirtual #30                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
        17: getstatic     #19                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
        20: aload_0
        21: new           #32                 // class D
        24: dup
        25: invokespecial #33                 // Method D."<init>":()V
        28: invokevirtual #26                 // Method duckduck:(Ljava/lang/Object;)Ljava/lang/String;
        31: invokevirtual #30                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
        34: return

  public java.lang.String duckduck(java.lang.Object);
    descriptor: (Ljava/lang/Object;)Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_1
         1: ldc           #38                 // String A
         3: invokedynamic #49,  0             // InvokeDynamic #0:"dyn:callMethod:quack":(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;
         8: checkcast     #51                 // class java/lang/String
        11: areturn

}
BootstrapMethods:
  0: #45 invokestatic jdk/internal/dynalink/DefaultBootstrapper.bootstrap:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:

```

retronym referenced this pull request in retronym/scala May 19, 2015

[indystructural] Prototype structural calls using invokedynamic
See also: https://github.com/retronym/indy-structural

```
// sandbox/structural.scala
object Test {
  def main(args: Array[String]): Unit = {
    println(duckduck(new C))
    println(duckduck(new D))
  }

  def duckduck(a: { def quack(a: String): String }): String = {
    a.quack("A")
  }

}

class C {
  def quack(a: String) = "QUACK! " + a
}

class D {
  def quack(a: String) = "QUICK! " + a
}
```

```
qscalac -target:jvm-1.8 -Ybackend:GenBCode sandbox/structural.scala && qscala Test && javap -v 'Test$' | cat -v
warning: there was one feature warning; re-run with -feature for details
one warning found

QUACK! A
QUICK! A

Classfile /Users/jason/code/scala2/Test$.class
{
  public static final Test$ MODULE$;
    descriptor: LTest$;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL

  public void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=4, locals=2, args_size=2
         0: getstatic     #19                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
         3: aload_0
         4: new           #21                 // class C
         7: dup
         8: invokespecial #22                 // Method C."<init>":()V
        11: invokevirtual #26                 // Method duckduck:(Ljava/lang/Object;)Ljava/lang/String;
        14: invokevirtual #30                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
        17: getstatic     #19                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
        20: aload_0
        21: new           #32                 // class D
        24: dup
        25: invokespecial #33                 // Method D."<init>":()V
        28: invokevirtual #26                 // Method duckduck:(Ljava/lang/Object;)Ljava/lang/String;
        31: invokevirtual #30                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
        34: return

  public java.lang.String duckduck(java.lang.Object);
    descriptor: (Ljava/lang/Object;)Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_1
         1: ldc           #38                 // String A
         3: invokedynamic #49,  0             // InvokeDynamic #0:"dyn:callMethod:quack":(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;
         8: checkcast     #51                 // class java/lang/String
        11: areturn

}
BootstrapMethods:
  0: #45 invokestatic jdk/internal/dynalink/DefaultBootstrapper.bootstrap:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:

```

retronym referenced this pull request in retronym/scala May 19, 2015

[indystructural] Prototype structural calls using invokedynamic
See also: https://github.com/retronym/indy-structural

```
// sandbox/structural.scala
object Test {
  def main(args: Array[String]): Unit = {
    println(duckduck(new C))
    println(duckduck(new D))
  }

  def duckduck(a: { def quack(a: String): String }): String = {
    a.quack("A")
  }

}

class C {
  def quack(a: String) = "QUACK! " + a
}

class D {
  def quack(a: String) = "QUICK! " + a
}
```

```
qscalac -target:jvm-1.8 -Ybackend:GenBCode sandbox/structural.scala && qscala Test && javap -v 'Test$' | cat -v
warning: there was one feature warning; re-run with -feature for details
one warning found

QUACK! A
QUICK! A

Classfile /Users/jason/code/scala2/Test$.class
{
  public static final Test$ MODULE$;
    descriptor: LTest$;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL

  public void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=4, locals=2, args_size=2
         0: getstatic     #19                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
         3: aload_0
         4: new           #21                 // class C
         7: dup
         8: invokespecial #22                 // Method C."<init>":()V
        11: invokevirtual #26                 // Method duckduck:(Ljava/lang/Object;)Ljava/lang/String;
        14: invokevirtual #30                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
        17: getstatic     #19                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
        20: aload_0
        21: new           #32                 // class D
        24: dup
        25: invokespecial #33                 // Method D."<init>":()V
        28: invokevirtual #26                 // Method duckduck:(Ljava/lang/Object;)Ljava/lang/String;
        31: invokevirtual #30                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
        34: return

  public java.lang.String duckduck(java.lang.Object);
    descriptor: (Ljava/lang/Object;)Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_1
         1: ldc           #38                 // String A
         3: invokedynamic #49,  0             // InvokeDynamic #0:"dyn:callMethod:quack":(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;
         8: checkcast     #51                 // class java/lang/String
        11: areturn

}
BootstrapMethods:
  0: #45 invokestatic jdk/internal/dynalink/DefaultBootstrapper.bootstrap:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:

```

retronym referenced this pull request in retronym/scala Dec 2, 2015

Support trait fields in the post-implclass world
```
⚡ cat sandbox/test.scala
trait T {
  def m = v
  val v = 42
}

class C extends T

object Test {
  def main(args: Array[String]): Unit = {
    assert(new C().m == 42)
  }
}
/code/scala on topic/nuke-impl-classes*
⚡ qscalac -Xprint:fields,constructors,erasure,mixin sandbox/test.scala  && qscala Test
[[syntax trees at end of                    fields]] // test.scala
package <empty> {
  abstract <sub_synth> trait T extends scala.AnyRef {
    <accessor> <sub_synth> def T$_setter_$v_=(x$1: Int): Unit;
    def /*T*/$init$(): Unit = {
      ()
    };
    def m: Int = T.this.v;
    <stable> <accessor> <sub_synth> def v: Int = 42
  };
  <sub_synth> class C extends AnyRef with T {
    override <stable> <accessor> def v: Int = C.this.v;
    private[this] val v: Int = _;
    override <accessor> def T$_setter_$v_=(x$1: Int): Unit = C.this.v = x$1;
    def <init>(): C = {
      C.super.<init>();
      ()
    }
  };
  object Test extends scala.AnyRef {
    def <init>(): Test.type = {
      Test.super.<init>();
      ()
    };
    def main(args: Array[String]): Unit = scala.Predef.assert(new C().m.==(42))
  }
}

[[syntax trees at end of                   erasure]] // test.scala
package <empty> {
  abstract <sub_synth> trait T extends Object {
    <accessor> <defaultmethod> <sub_synth> def T$_setter_$v_=(x$1: Int): Unit;
    def /*T*/$init$(): Unit = {
      ()
    };
    <defaultmethod> def m(): Int = T.this.v();
    <stable> <accessor> <defaultmethod> <sub_synth> def v(): Int = 42
  };
  <sub_synth> class C extends Object with T {
    override <stable> <accessor> def v(): Int = C.this.v;
    private[this] val v: Int = _;
    override <accessor> def T$_setter_$v_=(x$1: Int): Unit = C.this.v = x$1;
    def <init>(): C = {
      C.super.<init>();
      C.super./*T*/$init$();
      ()
    }
  };
  <sub_synth> object Test extends Object {
    def <init>(): Test.type = {
      Test.super.<init>();
      ()
    };
    def main(args: Array[String]): Unit = scala.Predef.assert(new C().m().==(42))
  }
}

[[syntax trees at end of              constructors]] // test.scala
package <empty> {
  abstract <sub_synth> trait T extends Object {
    <accessor> <defaultmethod> <sub_synth> def T$_setter_$v_=(x$1: Int): Unit;
    <defaultmethod> def m(): Int = T.this.v();
    <stable> <accessor> <defaultmethod> <sub_synth> def v(): Int;
    def /*T*/$init$(): Unit = {
      T.this.T$_setter_$v_=(42);
      ()
    }
  };
  <sub_synth> class C extends Object with T {
    override <stable> <accessor> def v(): Int = C.this.v;
    private[this] val v: Int = _;
    override <accessor> def T$_setter_$v_=(x$1: Int): Unit = C.this.v = x$1;
    def <init>(): C = {
      C.super.<init>();
      C.super./*T*/$init$();
      ()
    }
  };
  <sub_synth> object Test extends Object {
    def main(args: Array[String]): Unit = scala.Predef.assert(new C().m().==(42));
    def <init>(): Test.type = {
      Test.super.<init>();
      ()
    }
  }
}

[[syntax trees at end of                     mixin]] // test.scala: tree is unchanged since constructors
/code/scala on topic/nuke-impl-classes*
⚡ javap -c -classpath . T C
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$v_$eq(int);

  public int m();
    Code:
       0: aload_0
       1: invokeinterface #15,  1           // InterfaceMethod v:()I
       6: ireturn

  public abstract int v();

  public void $init$();
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface #21,  2           // InterfaceMethod T$_setter_$v_$eq:(I)V
       8: return
}
Compiled from "test.scala"
public class C implements T {
  public int v();
    Code:
       0: aload_0
       1: getfield      #15                 // Field v:I
       4: ireturn

  public void T$_setter_$v_$eq(int);
    Code:
       0: aload_0
       1: iload_1
       2: putfield      #15                 // Field v:I
       5: return

  public C();
    Code:
       0: aload_0
       1: invokespecial #24                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: invokespecial #27                 // Method T.$init$:()V
       8: return
}
```

lrytz pushed a commit to lrytz/scala that referenced this pull request May 20, 2016

Remove nonsensical body for trait getter
This corrects an error in the change to the trait encoding
in #5003: getters in traits should have empty bodies and
be emitted as abstract.

```
% ~/scala/2.12.0-M4/bin/scalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public int x();
    Code:
       0: aload_0
       1: invokeinterface #15,  1           // InterfaceMethod x:()I
       6: ireturn

  public int y();
    Code:
       0: aload_0
       1: invokeinterface #20,  1           // InterfaceMethod y:()I
       6: ireturn

  public void y_$eq(int);
    Code:
       0: aload_0
       1: iload_1
       2: invokeinterface #24,  2           // InterfaceMethod y_$eq:(I)V
       7: return

  public void $init$();
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface #29,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface #24,  2           // InterfaceMethod y_$eq:(I)V
      16: return
}

% qscalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public abstract int x();

  public abstract int y();

  public abstract void y_$eq(int);

  public static void $init$(T);
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface #21,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface #23,  2           // InterfaceMethod y_$eq:(I)V
      16: return

  public void $init$();
    Code:
       0: aload_0
       1: invokestatic  #27                 // Method $init$:(LT;)V
       4: return
}
```

lrytz pushed a commit to lrytz/scala that referenced this pull request May 25, 2016

Remove nonsensical body for trait getter
This corrects an error in the change to the trait encoding
in #5003: getters in traits should have empty bodies and
be emitted as abstract.

```
% ~/scala/2.12.0-M4/bin/scalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public int x();
    Code:
       0: aload_0
       1: invokeinterface #15,  1           // InterfaceMethod x:()I
       6: ireturn

  public int y();
    Code:
       0: aload_0
       1: invokeinterface #20,  1           // InterfaceMethod y:()I
       6: ireturn

  public void y_$eq(int);
    Code:
       0: aload_0
       1: iload_1
       2: invokeinterface #24,  2           // InterfaceMethod y_$eq:(I)V
       7: return

  public void $init$();
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface #29,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface #24,  2           // InterfaceMethod y_$eq:(I)V
      16: return
}

% qscalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public abstract int x();

  public abstract int y();

  public abstract void y_$eq(int);

  public static void $init$(T);
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface #21,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface #23,  2           // InterfaceMethod y_$eq:(I)V
      16: return

  public void $init$();
    Code:
       0: aload_0
       1: invokestatic  #27                 // Method $init$:(LT;)V
       4: return
}
```

lrytz pushed a commit to lrytz/scala that referenced this pull request Jun 6, 2016

Remove nonsensical body for trait getter
This corrects an error in the change to the trait encoding
in #5003: getters in traits should have empty bodies and
be emitted as abstract.

```
% ~/scala/2.12.0-M4/bin/scalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public int x();
    Code:
       0: aload_0
       1: invokeinterface #15,  1           // InterfaceMethod x:()I
       6: ireturn

  public int y();
    Code:
       0: aload_0
       1: invokeinterface #20,  1           // InterfaceMethod y:()I
       6: ireturn

  public void y_$eq(int);
    Code:
       0: aload_0
       1: iload_1
       2: invokeinterface #24,  2           // InterfaceMethod y_$eq:(I)V
       7: return

  public void $init$();
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface #29,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface #24,  2           // InterfaceMethod y_$eq:(I)V
      16: return
}

% qscalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public abstract int x();

  public abstract int y();

  public abstract void y_$eq(int);

  public static void $init$(T);
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface #21,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface #23,  2           // InterfaceMethod y_$eq:(I)V
      16: return

  public void $init$();
    Code:
       0: aload_0
       1: invokestatic  #27                 // Method $init$:(LT;)V
       4: return
}
```

lrytz pushed a commit that referenced this pull request Jun 29, 2016

Remove nonsensical body for trait getter
This corrects an error in the change to the trait encoding
in #5003: getters in traits should have empty bodies and
be emitted as abstract.

```
% ~/scala/2.12.0-M4/bin/scalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public int x();
    Code:
       0: aload_0
       1: invokeinterface #15,  1           // InterfaceMethod x:()I
       6: ireturn

  public int y();
    Code:
       0: aload_0
       1: invokeinterface #20,  1           // InterfaceMethod y:()I
       6: ireturn

  public void y_$eq(int);
    Code:
       0: aload_0
       1: iload_1
       2: invokeinterface #24,  2           // InterfaceMethod y_$eq:(I)V
       7: return

  public void $init$();
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface #29,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface #24,  2           // InterfaceMethod y_$eq:(I)V
      16: return
}

% qscalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public abstract int x();

  public abstract int y();

  public abstract void y_$eq(int);

  public static void $init$(T);
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface #21,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface #23,  2           // InterfaceMethod y_$eq:(I)V
      16: return

  public void $init$();
    Code:
       0: aload_0
       1: invokestatic  #27                 // Method $init$:(LT;)V
       4: return
}
```

adriaanm pushed a commit that referenced this pull request Aug 22, 2016

SD-194 Tweak module initialization to comply with JVM spec
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

@scabug scabug referenced this pull request in scala/bug Apr 7, 2017

Closed

@todo, @note and @example don't work? #4421

adriaanm pushed a commit that referenced this pull request May 25, 2017

Avoid non-local return in typedSelect
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 #32                 // Method java/lang/Object."<init>":()V
       7: astore_1
       8: getstatic     #36                 // Field $line4/$read$$iw$$iw$.MODULE$:L$line4/$read$$iw$$iw$;
      11: aload_1
      12: invokedynamic #59,  0             // InvokeDynamic #0:apply:(Ljava/lang/Object;)Lscala/Function0;
      17: invokevirtual #63                 // Method $line4/$read$$iw$$iw$.foo:(Lscala/Function0;)Ljava/lang/Object;
      20: goto          44
      23: astore_2
      24: aload_2
      25: invokevirtual #66                 // Method scala/runtime/NonLocalReturnControl.key:()Ljava/lang/Object;
      28: aload_1
      29: if_acmpne     39
      32: aload_2
      33: invokevirtual #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 #28                 // Method .foo:(Lscala/Function0;)Ljava/lang/Object;
      23: goto          39
      26: astore_2
      27: aload_2
      28: invokevirtual #31                 // Method scala/runtime/NonLocalReturnControl.key:()Ljava/lang/Object;
      31: aload_1
      32: if_acmpne     40
      35: aload_2
      36: invokevirtual #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
```

OlivierBlanvillain pushed a commit to OlivierBlanvillain/scala that referenced this pull request Jun 27, 2017

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