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
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:
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.