Description
Strictly speaking, this is not a regression, but causes other regressions in the standard library (see #6101, #5976), and may be a blocker.
Scala file:
trait Func1[R] {
def apply(): R = null.asInstanceOf[R]
}
class Func1ReturnString extends Func1[String]
Java file:
public class Test {
public static void main(String[] args) {
Func1ReturnString b = new Func1ReturnString() {};
b.apply();
}
}
This crashes javac
:
Test.java:7: error: apply() in Func1ReturnString cannot implement apply() in Func1
Func1ReturnString b = new Func1ReturnString() {};
^
return type Object is not compatible with String
where R is a type-variable:
R extends Object declared in interface Func1
1 error
The reason is that mixin
does not generate an appropriate signature for apply
. Trees at the end of cleanup
:
package <empty> {
abstract trait Func1 extends Object {
def apply(): Object
};
class Func1ReturnString extends Object with Func1 {
def apply(): Object = Func1$class.apply(Func1ReturnString.this);
def <init>(): Func1ReturnString = {
Func1ReturnString.super.<init>();
Func1$class./*Func1$class*/$init$(Func1ReturnString.this);
()
}
};
abstract trait Func1$class extends {
def apply($this: Func1): Object = null;
def /*Func1$class*/$init$($this: Func1): Unit = {
()
}
}
}
If you look at apply
above, the return type is Object
instead of String
. This happens in general whenever a method signature changes due to a more refined type environment in an inheriting class and the method is not overridden/implemented in the inheriting class.
In some other situations javac
compiles the file, but produces bytecode which refers to a non-existing method (signature-wise). See an example in a comment below.
This happens both with Scala 2.9.2 and Scala 2.10.x.
It does not happen with Scala 2.8.2, but we think this is because in Scala 2.8.2 the generic signatures were broken in other ways. Furthermore, it also breaks with 2.8.2 if you change the Java code a bit:
public class Test {
public static void main(String[] args) {
Func1ReturnString b = new Func1ReturnString() {};
String s = b.apply();
}
}