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

JDK 11 gets confused about override methods: reference to X is ambiguous #11061

Closed
eed3si9n opened this issue Aug 8, 2018 · 9 comments
Closed
Labels
Milestone

Comments

@eed3si9n
Copy link
Member

eed3si9n commented Aug 8, 2018

This was originally reported by @chbatey in akka/akka#25449.

steps

$ jenv shell 11-ea
$ java -version
java version "11-ea" 2018-09-25
Java(TM) SE Runtime Environment 18.9 (build 11-ea+10)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11-ea+10, mixed mode)

Clone https://github.com/eed3si9n/override-in-jdk11

$ sbt
> clean
> compile

problem

[error] /private/tmp/override-in-jdk11/src/main/java/example/Test.java:9:1: reference to get is ambiguous
[error]   both method get(akka.actor.ActorSystem) in example.TestKitExtension and method get(akka.actor.ActorSystem) in example.TestKitExtension match
[error]     TestKitExtension.get(a);

expectation

It compiles.

note

It works on JDK 8, but note that there are two get when you look at it using javap:

  public static akka.testkit.TestKitSettings get(akka.actor.ActorSystem);
    descriptor: (Lakka/actor/ActorSystem;)Lakka/testkit/TestKitSettings;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #17                 // Field foo/TestKitExtension$.MODULE$:Lfoo/TestKitExtension$;
         3: aload_0
         4: invokevirtual #36                 // Method foo/TestKitExtension$.get:(Lakka/actor/ActorSystem;)Lakka/testkit/TestKitSettings;
         7: areturn
    MethodParameters:
      Name                           Flags
      system                         final

  public static akka.actor.Extension get(akka.actor.ActorSystem);
    descriptor: (Lakka/actor/ActorSystem;)Lakka/actor/Extension;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #17                 // Field foo/TestKitExtension$.MODULE$:Lfoo/TestKitExtension$;
         3: aload_0
         4: invokevirtual #38                 // Method foo/TestKitExtension$.get:(Lakka/actor/ActorSystem;)Lakka/actor/Extension;
         7: areturn
    MethodParameters:
      Name                           Flags
      system                         final

project/build.properties

sbt.version=1.2.1

build.sbt

ThisBuild / organization := "com.example"
ThisBuild / scalaVersion := "2.12.6"
ThisBuild / version      := "0.1.0-SNAPSHOT"

lazy val root = (project in file(".")).
  settings(
    name := "akka-jdk11",
    libraryDependencies ++= Seq(
      "com.typesafe.akka" %% "akka-testkit" % "2.5.13"
    )
  )

src/main/scala/example/TestObject.scala

package example

import akka.actor._
import akka.testkit._

object TestKitExtension extends ExtensionId[TestKitSettings] {
  override def get(system: ActorSystem): TestKitSettings = super.get(system)
  def createExtension(system: ExtendedActorSystem): TestKitSettings = new TestKitSettings(system.settings.config)
}

src/main/java/example/Test.java

package example;

import akka.actor.ActorSystem;

public class Test {
  public static void foo() {
    ActorSystem a = ActorSystem.apply();
    TestKitExtension.get(a);
  }
}
@SethTisue SethTisue added this to the 2.12.7 milestone Aug 8, 2018
@SethTisue SethTisue added the jdk11 label Aug 8, 2018
@retronym
Copy link
Member

retronym commented Aug 9, 2018

Perhaps already fixed by scala/scala#6531 / #10812

@eed3si9n
Copy link
Member Author

That's a great news.

eed3si9n added a commit to eed3si9n/scala that referenced this issue Aug 11, 2018
Fixes scala/bug#11061
Ref scala/bug#10812

On 2.13.x branch scala#6531 removed the forwarder for bridge methods. I would like to do same in 2.12.x since Java 11-ea started to find them ambiguous as seen in akka/akka#25449 / scala/bug#11061.

To keep binary compatibility, I am still emitting the forwarder for bridge methods, but with `ACC_BRIDGE` flag.
eed3si9n added a commit to eed3si9n/scala that referenced this issue Aug 20, 2018
Fixes scala/bug#11061
Ref scala/bug#10812

On 2.13.x branch scala#6531 removed the mirror class forwarders for bridge methods. I would like to do same in 2.12.x since Java 11-ea started to find them ambiguous as seen in akka/akka#25449 / scala/bug#11061.

To keep binary compatibility, I am still emitting the forwarders for bridge methods, but with `ACC_BRIDGE` flag.
eed3si9n added a commit to eed3si9n/scala that referenced this issue Aug 20, 2018
Fixes scala/bug#11061
Ref scala/bug#10812

On 2.13.x branch scala#6531 removed the mirror class forwarders for bridge methods. I would like to do same in 2.12.x since Java 11-ea started to find them ambiguous as seen in akka/akka#25449 / scala/bug#11061.

To keep binary compatibility, I am still emitting the forwarders for bridge methods, but with `ACC_BRIDGE` flag.
@oryjk
Copy link

oryjk commented Oct 10, 2018

I upgrade to 2.12.7, but also have this problem, I use jdk 11, scala 2.12.7 and akka 2.5.17

@oryjk
Copy link

oryjk commented Oct 11, 2018

code repo https://github.com/oryjk/scala_build_with_jdk11.git, sbt compile

@oryjk
Copy link

oryjk commented Oct 11, 2018

@SethTisue link to akka/akka#25777

@SethTisue
Copy link
Member

link to akka/akka#25777

ah, makes sense, the bug is fixed in 2.12.7, but a library such as Akka won't have the fix until they publish a release that was built with 2.12.7.

@eed3si9n
Copy link
Member Author

Maybe we should advertise that all libraries compiled and published with Scala 2.12.(0 - 6) are affected with this bug, if they interface with *.java on JDK11, and that they need to republish with Scala 2.12.7+ to lift the curse.

@SethTisue
Copy link
Member

I added " #6531 improve callability of some methods from Java" to the "Improved Java 9+ support" bullet at https://github.com/scala/scala/releases/tag/v2.12.7

@SethTisue
Copy link
Member

also announced at https://contributors.scala-lang.org/t/library-authors-rebuild-on-2-12-7-to-improve-callability-from-java-on-jdk-11/2465

I think it's probably niche enough that a scala_lang tweet isn't needed.

lrytz added a commit to lrytz/scala that referenced this issue Nov 27, 2018
In 2.12.6 and before, the Scala compiler emits static forwarders for
bridge methods in top-level modules. These forwarders are emitted by
mistake, the filter to exclude bridges did not work as expected. These
bridge forwarders make the Java compiler on JDK 11 report ambiguity
errors when using static forwarders (scala/bug#11061).

PR scala#7035 fixed this for 2.12.7 by adding the `ACC_BRIDGE` flag to static
forwarders for bridges. We decided to keep these bridges for binary
compatibility.

However, the new flag causes the eclipse Java compiler (and apparently
also IntelliJ) to report ambiguity errors when using static forwarders
(scala/bug#11271).

In 2.13.x the Scala compiler no longer emits static forwarders for
bridges (PR scala#6531). This PR brings the same behavior to 2.12.8.

This change breaks binary compatibility. However, in the examples we
tested, the Java compiler emits references to the non-bridge methods,
so compiled code continues to work if a library is replaced by a new
version that doesn't have forwarders for bridges:

```
$> cat T.scala
class A[T] {
  def get: T = ???
}
object T extends A[String] {
  override def get: String = "hi"
}

$> ~/scala/scala-2.12.7/bin/scalac T.scala
```

Generates two forwarders in `T.class`

```
// access flags 0x49
public static bridge get()Ljava/lang/Object;

// access flags 0x9
public static get()Ljava/lang/String;
```

```
$> javac -version
javac 1.8.0_181

$> cat Test.java
public class Test {
  public static void main(String[] args) {
    System.out.println(T.get());
  }
}

$> javac Test.java
```

Generates in Test.class
```
  INVOKESTATIC T.get ()Ljava/lang/String;
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants