Skip to content

No static forwarder methods in companion of trait #13572

Closed
@jlprat

Description

@jlprat

First of all sorry if this was already discussed or if it's intentional, but I encountered a discrepancy in bytecode generation between Scala 2.13 and 3.x.
In Scala 2.13 when an object and a trait shared the same name, all methods belonging to the object were copied over to the class representing the trait as static ones.
This bit is important for the Java interoperability aspect, as the Scala 2.13 bytecode made it easy to use Scala classes from Java, while in Scala 3, we would need to fall back to referencing members of the object using the synthetic name (class name plus $ sign).

Note that when the combination is an object and a class the bytecode generated is compatible with the one generated for Scala 2.13, for more details see the reproducer here.

Compiler version

Scala 3.0.2 and 3.1.0-RC2

Minimized code

You can find a reproducer here

package example

object ObjectTraitPair {
  val Constant: String = "Some Text"
}

// In Scala 2.13 this class bytecode will carry over
// any val and def defined in the object with the same name
// but not in Scala 3.0
trait ObjectTraitPair {
  val method: String = "bye"
}

Output

If we inspect the bytecode of the trait (ObjectTraitPair.class) we see:
javap ObjectTraitPair.class

public interface ObjectTraitPair {
  public static void $init$(example.ObjectTraitPair);
  public abstract java.lang.String method();
  public abstract void example$ObjectTraitPair$_setter_$method_$eq(java.lang.String);
}

Expectation

In Scala 2.13 the same trait's bytecode would be

public interface ObjectTraitPair {
  public static java.lang.String Constant();
  public abstract void example$ObjectTraitPair$_setter_$method_$eq(java.lang.String);
  public abstract java.lang.String method();
  public static void $init$(example.ObjectTraitPair);
}

Please note the missing public static java.lang.String Constant(); on the Scala 3 bytecode.

Workaround

When this needs to be used from Java, the workaround can be this:

// This won't compile if the `ObjectTraitPair` is compiled in Scala 3.
// Instead of referencing it like this:
ObjectTraitPair.Constant();

// It can be referenced like this:
ObjectTraitPair$.MODULE$.Constant();

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions