Skip to content

Bridge or omit troublesome additional abstract methods in specialized traits #36

Closed
@retronym

Description

@retronym

Interaction with specialization

Specialization adds another small challenge. In the example below, notice how apply : (Int)V has been added to the specialized sub interface. A Java subclass of T$mcI$sp would need to implement both apply-s. T$mcI$sp is not a functional interface, so can't be used in LambdaMetafactory / (e.g. as the target type of a Java lambda expressions).

We run straight into this problem with the specialized Scala function traits.

% cat sandbox/spec.scala
trait T[@specialized A] {
  def t(a: A): Unit
}

% scalac sandbox/spec.scala && javap -classpath . T 'T$mcI$sp'
Compiled from "spec.scala"
public interface T{
    public abstract void t(java.lang.Object);
    public abstract void t$mcZ$sp(boolean);
    public abstract void t$mcB$sp(byte);
    public abstract void t$mcC$sp(char);
    public abstract void t$mcD$sp(double);
    public abstract void t$mcF$sp(float);
    public abstract void t$mcI$sp(int);
    public abstract void t$mcJ$sp(long);
    public abstract void t$mcS$sp(short);
    public abstract void t$mcV$sp(scala.runtime.BoxedUnit);
}

Compiled from "spec.scala"
public interface T$mcI$sp extends T{
    public abstract void t(int);
}

Contrast with a regular trait that inherits another trait:

cat sandbox/spec.scala && scalac sandbox/spec.scala && javap -classpath . U V
trait U[A] {
  def t(a: A): Unit
}
trait V extends U[Int]
Compiled from "spec.scala"
public interface U{
    public abstract void t(java.lang.Object);
}

Compiled from "spec.scala"
public interface V extends U{
}

We should investigate whether addition of this method by specialization is necessary / intentional. If we cannot omit it, we do have the possibility to bridge it.

public interface T$mcI$sp extends T{
    public abstract void t(int) = UNBOX(t$mcI$sp(BOX(arg)))
}

Scala callers never route into this method:

% cat sandbox/spec.scala && scalac sandbox/spec.scala && javap -c -classpath . Client
trait T[@specialized -A] {
  def t(a: A): Unit
}

class Client {
  def f(tint:  T[Int])= tint.t(0)
  def g[A](t: T[A], a: A) = t.t(a)
}
Compiled from "spec.scala"
public class Client extends java.lang.Object{
public void f(T);
  Code:
   0:   aload_1
   1:   iconst_0
   2:   invokeinterface #16,  2; //InterfaceMethod T.t$mcI$sp:(I)V
   7:   return

public void g(T, java.lang.Object);
  Code:
   0:   aload_1
   1:   aload_2
   2:   invokeinterface #26,  2; //InterfaceMethod T.t:(Ljava/lang/Object;)V
   7:   return

public Client();
  Code:
   0:   aload_0
   1:   invokespecial   #32; //Method java/lang/Object."<init>":()V
   4:   return

}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions