- 
  Notifications
 You must be signed in to change notification settings 
- Fork 1.1k
Scala3 type bug when used with java #16029
-
In a new Scala3 types system, if I write two simple classes in Scala as follows
final class ScalaClass(val in: "Hello") {
 override def toString: String = s"ScalaClass($in)"
 def printAllCharacters(): Unit = in.foreach(println)
}
&
final class ScalaClass1(private var in: "Hello") {
 def getIn: "Hello" = in
 def setIn(in1: "Hello"): Unit = {
 in = in1
 }
 def printAllCharacters(): Unit = in.foreach(println)
 override def toString: String = s"ScalaClass1($in)"
}
And then use them in Java as well as in Scala would produce different output, for example:
public class JavaClass {
 public static void main(String[] args) {
 ScalaClass scalaClass = new ScalaClass("jhjhjhjh");
 System.out.println(scalaClass);
 System.out.println(">>>>>>>>>>>>>>>>>>>>>>>");
 ScalaClass1 scalaClass1 = new ScalaClass1("sasas");
 System.out.println(scalaClass1);
 System.out.println(scalaClass1.getIn());
 scalaClass1.setIn("asasasas");
 System.out.println(scalaClass1.getIn());
 System.out.println(scalaClass1);
 }
}
Would will produce output as:
ScalaClass(Hello)
>>>>>>>>>>>>>>>>>>>>>>>
ScalaClass1(sasas)
sasas
Hello
ScalaClass1(Hello)
And running the same in Scala would be something different:
@main def runScalaClass(): Unit = {
 // val a = ScalaClass("As") Compilation Error
 val a = ScalaClass("Hello")
 println(a)
}
&
@main def runScalaMain1(): Unit = {
 // val a = new ScalaClass1("asas") Compilation Error
 val a = new ScalaClass1("Hello")
 println(a)
 println(a.getIn)
 // a.setIn("sss") Compilation Error
 a.setIn("Hello")
 println(a)
}
So the same simple API works differently for Java as well as in Scala.
- What if someone needs to write simple Scala classes that are interoperable with Java?
- In this case, the same code should produce identical results when used with Java and Scala, which is not the case!
- Such a typing system makes the project more prone to developer bugs in projects that contain code that combines Java and Scala.
- Hard to understand, for example, someone reading the code would see a simple Scala class with getter and setter but when run through java: getter, setter, and constructor all three produce unexpected results, resulting in confusion between what is written and what is output.
Beta Was this translation helpful? Give feedback.
All reactions
A Scalafix rule could lint features not supported in Java or known interop issues.
At a glance, I don't see that such a rule has been written at https://scalacenter.github.io/scalafix/docs/rules/community-rules.html
Replies: 3 comments 1 reply
-
The above two classes ScalaClass & ScalaClass1 would look something like this
import java.lang.invoke.SerializedLambda;
import scala.Function1;
import scala.Predef$;
import scala.collection.StringOps$;
public final class ScalaClass
{
 private final String in;
 
 public ScalaClass(final String in) {
 this.in = in;
 }
 
 public String in() {
 return this.in;
 }
 
 @Override
 public String toString() {
 return new StringBuilder(17).append("ScalaClass(").append("Hello").append(")").toString();
 }
 
 public void printAllCharacters() {
 StringOps$.MODULE$.foreach$extension(Predef$.MODULE$.augmentString("Hello"), (Function1)(x -> Predef$.MODULE$.println(x)));
 }
}
&
import java.lang.invoke.SerializedLambda;
import scala.Function1;
import scala.Predef$;
import scala.collection.StringOps$;
public final class ScalaClass1
{
 private String in;
 
 public ScalaClass1(final String in) {
 this.in = in;
 }
 
 private String in() {
 return this.in;
 }
 
 private void in_$eq(final String x0ドル) {
 this.in = x0ドル;
 }
 
 public String getIn() {
 return this.in();
 }
 
 public void setIn(final String in1) {
 this.in_$eq("Hello");
 }
 
 public void printAllCharacters() {
 StringOps$.MODULE$.foreach$extension(Predef$.MODULE$.augmentString(this.in()), (Function1)(x -> Predef$.MODULE$.println(x)));
 }
 
 @Override
 public String toString() {
 return new StringBuilder(13).append("ScalaClass1(").append(this.in()).append(")").toString();
 }
}
Beta Was this translation helpful? Give feedback.
All reactions
-
What would happen if instead of using constants like:
public void setIn(final String in1) {
 this.in_$eq("Hello");
}
we use the variable instead
public void setIn(final String in1) {
 this.in_$eq(in1);
}
or produce runtime exception/compile time exception when compiling java/scala code combinedly.
Beta Was this translation helpful? Give feedback.
All reactions
-
A Scalafix rule could lint features not supported in Java or known interop issues.
At a glance, I don't see that such a rule has been written at https://scalacenter.github.io/scalafix/docs/rules/community-rules.html
Beta Was this translation helpful? Give feedback.
All reactions
-
This fix rule in indeed required to reduce programmer error.
Thank you
Beta Was this translation helpful? Give feedback.