diff --git a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala index 9a6ab233e239..050abf7f3cb7 100644 --- a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala +++ b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala @@ -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 @@ -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) @@ -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)) @@ -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 @@ -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) diff --git a/tests/generic-java-signatures/i15385/Lib.scala b/tests/generic-java-signatures/i15385/Lib.scala new file mode 100644 index 000000000000..81b00d964b3f --- /dev/null +++ b/tests/generic-java-signatures/i15385/Lib.scala @@ -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] // (I)I + def testSingleParam2[A <: Int](a: A): Box[A] = new Box[A](a) // (I)LBox; + def testSingleParam3[A <: Int](box: Box[A]): A = box.value // (LBox;)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) diff --git a/tests/generic-java-signatures/i15385/Test.java b/tests/generic-java-signatures/i15385/Test.java new file mode 100644 index 000000000000..184f104d0fb0 --- /dev/null +++ b/tests/generic-java-signatures/i15385/Test.java @@ -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")); + } +}