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