Skip to content

Commit

Permalink
Fix generic signature for type params bounded by primitive (#16442)
Browse files Browse the repository at this point in the history
Fixes #15385
  • Loading branch information
smarter authored Dec 14, 2022
2 parents 8fbf826 + be10979 commit 2e409c6
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 15 deletions.
28 changes: 13 additions & 15 deletions compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ package transform
import core.Annotations._
import core.Contexts._
import core.Phases._
import core.Decorators.*
import core.Definitions
import core.Flags._
import core.Names.Name
import core.Symbols._
import core.TypeApplications.{EtaExpansion, TypeParamInfo}
import core.TypeErasure.{erasedGlb, erasure, isGenericArrayElement}
import core.TypeErasure.{erasedGlb, erasure, fullErasure, isGenericArrayElement}
import core.Types._
import core.classfile.ClassfileConstants
import SymUtils._
import TypeUtils._
import config.Printers.transforms
import reporting.trace
import java.lang.StringBuilder

import scala.collection.mutable.ListBuffer
Expand Down Expand Up @@ -130,12 +133,12 @@ object GenericSignatures {
else
Right(parent))

def paramSig(param: LambdaParam): Unit = {
builder.append(sanitizeName(param.paramName))
def paramSig(param: TypeParamInfo): Unit = {
builder.append(sanitizeName(param.paramName.lastPart))
boundsSig(hiBounds(param.paramInfo.bounds))
}

def polyParamSig(tparams: List[LambdaParam]): Unit =
def polyParamSig(tparams: List[TypeParamInfo]): Unit =
if (tparams.nonEmpty) {
builder.append('<')
tparams.foreach(paramSig)
Expand Down Expand Up @@ -236,7 +239,11 @@ object GenericSignatures {
tp match {

case ref @ TypeParamRef(_: PolyType, _) =>
typeParamSig(ref.paramName.lastPart)
val erasedUnderlying = fullErasure(ref.underlying.bounds.hi)
// don't emit type param name if the param is upper-bounded by a primitive type (including via a value class)
if erasedUnderlying.isPrimitiveValueType then
jsig(erasedUnderlying, toplevel, primitiveOK)
else typeParamSig(ref.paramName.lastPart)

case defn.ArrayOf(elemtp) =>
if (isGenericArrayElement(elemtp, isScala2 = false))
Expand Down Expand Up @@ -267,7 +274,7 @@ object GenericSignatures {
else if (sym == defn.UnitClass) jsig(defn.BoxedUnitClass.typeRef)
else builder.append(defn.typeTag(sym.info))
else if (ValueClasses.isDerivedValueClass(sym)) {
val erasedUnderlying = core.TypeErasure.fullErasure(tp)
val erasedUnderlying = fullErasure(tp)
if (erasedUnderlying.isPrimitiveValueType && !primitiveOK)
classSig(sym, pre, args)
else
Expand Down Expand Up @@ -334,15 +341,6 @@ object GenericSignatures {
jsig(repr, primitiveOK = primitiveOK)

case ci: ClassInfo =>
def polyParamSig(tparams: List[TypeParamInfo]): Unit =
if (tparams.nonEmpty) {
builder.append('<')
tparams.foreach { tp =>
builder.append(sanitizeName(tp.paramName.lastPart))
boundsSig(hiBounds(tp.paramInfo.bounds))
}
builder.append('>')
}
val tParams = tp.typeParams
if (toplevel) polyParamSig(tParams)
superSig(ci.typeSymbol, ci.parents)
Expand Down
24 changes: 24 additions & 0 deletions tests/generic-java-signatures/i15385/Lib.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class Loc(val idx: Int) extends AnyVal

class Foo:
def testNoParam[A <: Int]: A = 1.asInstanceOf[A]
def testSingleParam[A <: Int](a: A): A = 2.asInstanceOf[A] // <A:Ljava/lang/Object;>(I)I
def testSingleParam2[A <: Int](a: A): Box[A] = new Box[A](a) // <A:Ljava/lang/Object;>(I)LBox<Ljava/lang/Object;>;
def testSingleParam3[A <: Int](box: Box[A]): A = box.value // <A:Ljava/lang/Object;>(LBox<Ljava/lang/Object;>;)I
def testOtherReturn[A <: Int](a: A): String = "3"
def testNoErasure[A <: String](a: A): A = "4".asInstanceOf[A]
def testMultiParam[A <: Int, B <: String](a: A, b: B): A = 5.asInstanceOf[A]

def testVCNoParam[A <: Loc]: A = Loc(1).asInstanceOf[A]
def testVCSingleParam[A <: Loc](a: A): A = Loc(2).asInstanceOf[A]
def testVCOtherReturn[A <: Loc](a: A): String = "3"
def testVCNoErasure[A <: String](a: A): A = "4".asInstanceOf[A]
def testVCMultiParam[A <: Loc, B <: String](a: A, b: B): A = Loc(5).asInstanceOf[A]

class Box[T](val value: T)

class BarParent[X, Y]
trait BarInterface[F, G]
abstract class Bar[A <: Int](a: A) extends BarParent[A, String] with BarInterface[Int, A]:
def getMap: Map[String, A]
def bar[B](a: A, b: B): (A, B, Int)
18 changes: 18 additions & 0 deletions tests/generic-java-signatures/i15385/Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
public class Test {
public static void main(String[] args) throws Exception {
Foo foo = new Foo();
System.out.println(foo.testNoParam());
System.out.println(foo.testSingleParam(2));
System.out.println(foo.testSingleParam2(21).value());
System.out.println(foo.testSingleParam3(new Box(22)));
System.out.println(foo.testOtherReturn(3));
System.out.println(foo.testNoErasure("4"));
System.out.println(foo.testMultiParam(5, "5"));

System.out.println(foo.testVCNoParam());
System.out.println(foo.testVCSingleParam(2));
System.out.println(foo.testVCOtherReturn(3));
System.out.println(foo.testVCNoErasure("4"));
System.out.println(foo.testVCMultiParam(5, "5"));
}
}

0 comments on commit 2e409c6

Please sign in to comment.