Skip to content

Mixin generates method signatures that confuse javac #6103

Open
@scabug

Description

@scabug

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();
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions