Dotty: dotc requires `override` to implement abstract java method

Created on 23 Mar 2019  路  8Comments  路  Source: lampepfl/dotty

A.java

public abstract class A {
  public abstract Object f();

  public static abstract class B extends A {
    @Override
    public abstract String f();
  }
}

Test.scala

class C extends A.B {
  def f() = ""
}

gives

-- Error: Test.scala:2:6 -------------------------------------------------------
2 |  def f() = ""
  |      ^
  |      error overriding method f in class B of type (): Object;
  |        method f of type (): String needs `override' modifier
one error found
java scala2 bug

All 8 comments

Looks like it sees the Java-emitted bridge. I did not know that Java emits bridges for abstract methods.

I cannot reproduce it at commit 5f28215ac via dotc A.java Test.scala command from the SBT console.

I manage to reproduce it with -language:Scala2

Hm, strange, dotc -language:Scala2 A.java Test.scala doesn't reproduce it either. What commit are you on @newca12?

Sorry -language:Scala2 was not relevant. You can reproduce it with 2 separate compilation steps :
javac A.java
dotc Test.scala

To understand why there's a difference here, it's helpful to know that:

  • Under joint compilation of .java and .scala sources, the compiler will parse the .java source files and generate symbols for them (https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala)
  • Under separate compilation, the compiler will parse the classfiles generated by javac and generate symbols for them (https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala)

Both of these approaches should be equivalent and if they're not it's probably a bug. In both cases the parsing code was adapted from scalac years ago (https://github.com/scala/scala/blob/2.13.x/src/compiler/scala/tools/nsc/javac/JavaParsers.scala, https://github.com/scala/scala/blob/2.13.x/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala) and there might have been improvements done on the scalac side that haven't been ported to dotty (e.g. https://github.com/lampepfl/dotty/issues/6136)

Also various parts of the compiler check the JavaDefined flag which is set on symbols coming from java source files and classfiles.

Some more observations: it's interesting to note that member in Scala 2 excludes members with the bridge flag by default, where as member in Dotty doesn't do that. Exclusion also works differently in both compiler, in Scala 2 if a symbol with an excluded flag overrides a symbol without the flag, the overridden symbol is returned, whereas no symbol is returned in Dotty. Aligning ourselves with Scala 2's behavior here might be enough to fix this issue. Alternatively we could also simply skip bridge methods found by the ClassfileParser since they shouldn't influence compilation anyway.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

deusaquilus picture deusaquilus  路  3Comments

ohze picture ohze  路  3Comments

Blaisorblade picture Blaisorblade  路  3Comments

andreaTP picture andreaTP  路  3Comments

NightMachinary picture NightMachinary  路  3Comments