Skip to content

Conversation

@hamzaremmal
Copy link
Member

Have the correct generic signature generated (à la Scala 2) for value classes while at the same time preserving the fix in #20463

Closes #24276
Closes #22140

@hamzaremmal hamzaremmal force-pushed the generic-signatures-mima branch from cb8ed16 to f3d3cd8 Compare October 28, 2025 11:38
@hamzaremmal hamzaremmal marked this pull request as ready for review October 28, 2025 11:38
@hamzaremmal hamzaremmal requested review from lrytz and sjrd October 28, 2025 12:29
@lrytz
Copy link
Member

lrytz commented Oct 28, 2025

(there seems to be some failed test, but how on do you find the failure in this huge log file..?)

@hamzaremmal
Copy link
Member Author

So far, one test had to be disabled on Scala.js because of reflection and the other i8001 was just wrong.

@hamzaremmal
Copy link
Member Author

Another error here is the following:

class Box[A](val value: A) extends AnyVal
class ArrayBox[A](val value: Array[A]) extends AnyVal

class Foo:
  def foo(x: Box[Int]): Box[Int] = Box(x.value)

Now, foo is erased to (java.lang.Integer): java.lang.Integer and the generated generic signature is (int): int. I know erasure cannot change but I'm wondering why we erase to java.lang.Integer instead of int? @sjrd any ideas?

@hamzaremmal
Copy link
Member Author

Same for this method:

class ArrayBox[A](val value: Array[A]) extends AnyVal
class Foo:
  def foo(x: ArrayBox[Int]): ArrayBox[Int] = ArrayBox(x.value)

foo erased to (java.lang.Object): java.lang.Object rather than (int[]): int[].

@sjrd
Copy link
Member

sjrd commented Oct 28, 2025

Probably historical. There is often not a good explanation for things involving value classes. They are full of weird non-optimal stuff.

@sjrd
Copy link
Member

sjrd commented Oct 28, 2025

Now, foo is erased to (java.lang.Integer): java.lang.Integer and the generated generic signature is (int): int.

That is a real problem, though. We need the Java generic signature to be such that its (Java) erasure corresponds to the erased signature that we emit.

@lrytz
Copy link
Member

lrytz commented Oct 29, 2025

Now, foo is erased to (java.lang.Integer): java.lang.Integer and the generated generic signature is (int): int.

That is a real problem, though. We need the Java generic signature to be such that its (Java) erasure corresponds to the erased signature that we emit.

Scala 2 seems to do the same. ASM output:

  // signature (I)I
  public foo(Ljava/lang/Integer;)Ljava/lang/Integer;

With 3.7.3 I get

  // signature (Ljava/lang/Integer;)Ljava/lang/Integer;
  public foo(Ljava/lang/Integer;)Ljava/lang/Integer;

So in the current form, this PR would align with the wrong behavior of Scala 2, IIUC?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generating generic signatures in the presence of AnyVal is wrong Dotty emit wrong generic signature for generic value classes

4 participants