Skip to content

No Java generic signatures generated for static forwarders in companions of objects for vals and paramless defs #10347

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

Closed
DieBauer opened this issue Nov 16, 2020 · 7 comments · Fixed by #12710

Comments

@DieBauer
Copy link
Contributor

Minimized code

package modes

import java.util.{List => JList}
import scala.jdk.CollectionConverters._

object Mode {
  val AllowedModes: List[Mode] = List(
    On,
    Off,
  )
}

sealed trait Mode {
  def name: String
}

case object On extends Mode {
  override val name: String = "on"
}

case object Off extends Mode {
  override val name: String = "off"
}

/** object for Java compatibility */
object Modes {
  val AllowedModes: JList[Mode] = Mode.AllowedModes.asJava
}
package mode;

import modes.Modes;
import modes.Mode;
import java.util.stream.Collectors;

class Converter {
    private final String modes = Modes.AllowedModes()
        .stream()
        .map(Mode::name)
        .collect(Collectors.joining(", "));
}

Output

> compile
[info] compiling 1 Scala source and 1 Java source to /Users/jens/Developer/dotty/java-interop/library/target/scala-3.0.0-M2/classes ...
[error] /Users/jens/Developer/dotty/java-interop/library/src/main/java/mode/Modes.java:10:1: incompatible types: invalid method reference
[error]     method name in interface modes.Mode cannot be applied to given types
[error]       required: no arguments
[error]       found: java.lang.Object
[error]       reason: actual and formal argument lists differ in length
[info] Some messages have been simplified; recompile with -Xdiags:verbose to get full output
[error] (lib / Compile / compileIncremental) javac returned non-zero exit code

Expectation

Fails with latest 3.0.0-M2-bin-20201115-3c04f9b-NIGHTLY and 3.0.0-M1. While this succeeds with scala 2.13.3.

java -version
openjdk version "11.0.8" 2020-07-14
OpenJDK Runtime Environment GraalVM CE 20.2.0 (build 11.0.8+10-jvmci-20.2-b03)
OpenJDK 64-Bit Server VM GraalVM CE 20.2.0
@smarter
Copy link
Member

smarter commented Nov 16, 2020

It's because we don't generate Java generic signatures on the static forwarders we create in a class for each method in the corresponding companion object, minimized:

object A {
  def foo: List[String] = Nil
}

Compiled with Scala 2:

# javap -p -v 'A$.class'
...
public scala.collection.immutable.List<java.lang.String> foo();
# javap -p -v 'A.class'
...
public static scala.collection.immutable.List<java.lang.String> foo();

Compiled with Dotty:

# javap -p -v 'A$.class'
...
public scala.collection.immutable.List<java.lang.String> foo();
# javap -p -v 'A.class'
...
public static scala.collection.immutable.List foo(); // <-- no type parameter info

@smarter smarter changed the title java-interop: incompatible types in java lambda No generic signatures generated for static forwarders in companions of objects Nov 16, 2020
@smarter smarter changed the title No generic signatures generated for static forwarders in companions of objects No Java generic signatures generated for static forwarders in companions of objects Nov 16, 2020
@smarter
Copy link
Member

smarter commented Nov 16, 2020

Workaround: add parens to the method, then the correct signature gets generated:

object A {
  def foo(): List[String] = Nil
}

@smarter smarter changed the title No Java generic signatures generated for static forwarders in companions of objects No Java generic signatures generated for static forwarders in companions of objects for vals and paramless defs Nov 16, 2020
@griggt
Copy link
Contributor

griggt commented Nov 16, 2020

Is this related to #8631?

@smarter
Copy link
Member

smarter commented Nov 16, 2020

Yep same issue

@lrytz
Copy link
Member

lrytz commented Jun 4, 2021

@smarter the issue here is that is that the nullary method has an ExprType(List[String]), which seems to be used for both nullary methods and by-name params, and erasure turns it into a Function0 favoring the latter interpretation.

Then this test fails (Function0 vs (): List): https://github.com/lampepfl/dotty/blob/0f0d6ad4b663fe9d7a8d73afaa2e0f72bdcff647/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala#L928-L930

Do you have a suggestion how to fix this?

@smarter
Copy link
Member

smarter commented Jun 4, 2021

seems like we should use TypeErasure.transformInfo (or directly TypeErasure#eraseInfo) instead of fullErasure.

@lrytz
Copy link
Member

lrytz commented Jun 4, 2021

👍 thanks!

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

Successfully merging a pull request may close this issue.

5 participants