10000 case class companion object generates two apply methods · Issue #11207 · scala/bug · GitHub
[go: up one dir, main page]

Skip to content
case class companion object generates two apply methods #11207
@DieBauer

Description

@DieBauer

I've encountered an issue when upgrading the compiler to 2.12.7.

I have a piece of java code that uses the apply method of a scala case class.

final MyClass myClass = MyClass.apply(1, 2, 3L, 4)

When using MyClass compiled with Scala 2.12.7, I get: incompatible types: java.lang.Object cannot be converted to MyClass.

Where, before it compiled fine.

I'm now looking into the generated bytecode and can see this.

Test.scala:

case class MyClass(a: Int, b: Int, c: Long, d: Int)
$ scalac Test.scala
$ scala -classpath .
Welcome to Scala 2.12.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_162).
Type in expressions for evaluation. Or try :help.

scala> :javap -p MyClass
Compiled from "Test.scala"
public class MyClass implements scala.Product,scala.Serializable {
  private final int a;
  private final int b;
  private final long c;
  private final int d;
  public static java.lang.Object apply(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object);
  public static scala.Option<scala.Tuple4<java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object>> unapply(MyClass);
  public static MyClass apply(int, int, long, int);
  public static scala.Function1<scala.Tuple4<java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object>, MyClass> tupled();
  public static scala.Function1<java.lang.Object, scala.Function1<java.lang.Object, scala.Function1<java.lang.Object, scala.Function1<java.lang.Object, MyClass>>>> curried();
  public int a();
  public int b();
  public long c();
  public int d();
  public MyClass copy(int, int, long, int);
  public int copy$default$1();
  public int copy$default$2();
  public long copy$default$3();
  public int copy$default$4();
  public java.lang.String productPrefix();
  public int productArity();
  public java.lang.Object productElement(int);
  public scala.collection.Iterator<java.lang.Object> productIterator();
  public boolean canEqual(java.lang.Object);
  public int hashCode();
  public java.lang.String toString();
  public boolean equals(java.lang.Object);
  public MyClass(int, int, long, int);
}

When doing the same exercise on scala 2.12.6 I get:

$ scalac Test.scala
$ scala -classpath .
Welcome to Scala 2.12.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_162).
Type in expressions for evaluation. Or try :help.

scala> :javap -p MyClass
Compiled from "Test.scala"
public class MyClass implements scala.Product,scala.Serializable {
  private final int a;
  private final int b;
  private final long c;
  private final int d;
  public static scala.Option<scala.Tuple4<java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object>> unapply(MyClass);
  public static MyClass apply(int, int, long, int);
  public static scala.Function1<scala.Tuple4<java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object>, MyClass> tupled();
  public static scala.Function1<java.lang.Object, scala.Function1<java.lang.Object, scala.Function1<java.lang.Object, scala.Function1<java.lang.Object, MyClass>>>> curried();
  public int a();
  public int b();
  public long c();
  public int d();
  public MyClass copy(int, int, long, int);
  public int copy$default$1();
  public int copy$default$2();
  public long copy$default$3();
  public int copy$default$4();
  public java.lang.String productPrefix();
  public int productArity();
  public java.lang.Object productElement(int);
  public scala.collection.Iterator<java.lang.Object> productIterator();
  public boolean canEqual(java.lang.Object);
  public int hashCode();
  public java.lang.String toString();
  public boolean equals(java.lang.Object);
  public MyClass(int, int, long, int);
}

A duplicate apply method is generated in scala 2.12.7 with the following signature:
public static java.lang.Object apply(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object);
and it seems this one is being picked in my Java project, causing the exception.
It seems that this is an unintended breaking change between these two versions.

Of course a workaround is using the new keyword:

final MyClass myClass = new MyClass(1, 2, 3L, 4)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    0