From fbe0e152ca3dc7149b1ca20e9e942985f79fab78 Mon Sep 17 00:00:00 2001 From: Hamza Remmal Date: Sat, 5 Oct 2024 13:55:59 +0200 Subject: [PATCH] Add support for clauseInterleaving in JVM generic signatures --- .../dotc/transform/GenericSignatures.scala | 51 +++++++++---------- tests/run/i21346.check | 10 ++++ tests/run/i21346.scala | 14 +++++ 3 files changed, 48 insertions(+), 27 deletions(-) create mode 100644 tests/run/i21346.check create mode 100644 tests/run/i21346.scala diff --git a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala index b5b75450272c..1798d938272c 100644 --- a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala +++ b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala @@ -19,6 +19,7 @@ import config.Printers.transforms import reporting.trace import java.lang.StringBuilder +import scala.annotation.tailrec import scala.collection.mutable.ListBuffer /** Helper object to generate generic java signatures, as defined in @@ -294,36 +295,13 @@ object GenericSignatures { case ExprType(restpe) => jsig(defn.FunctionType(0).appliedTo(restpe)) - case PolyType(tparams, mtpe: MethodType) => - assert(tparams.nonEmpty) + case mtd: MethodOrPoly => + val (tparams, vparams, rte) = collectMethodParams(mtd) if (toplevel && !sym0.isConstructor) polyParamSig(tparams) - jsig(mtpe) - - // Nullary polymorphic method - case PolyType(tparams, restpe) => - assert(tparams.nonEmpty) - if (toplevel) polyParamSig(tparams) - builder.append("()") - methodResultSig(restpe) - - case mtpe: MethodType => - // erased method parameters do not make it to the bytecode. - def effectiveParamInfoss(t: Type)(using Context): List[List[Type]] = t match { - case t: MethodType if t.hasErasedParams => - t.paramInfos.zip(t.erasedParams).collect{ case (i, false) => i } - :: effectiveParamInfoss(t.resType) - case t: MethodType => t.paramInfos :: effectiveParamInfoss(t.resType) - case _ => Nil - } - val params = effectiveParamInfoss(mtpe).flatten - val restpe = mtpe.finalResultType builder.append('(') - // TODO: Update once we support varargs - params.foreach { tp => - jsig(tp) - } + for vparam <- vparams do jsig(vparam) builder.append(')') - methodResultSig(restpe) + methodResultSig(rte) case tp: AndType => // Only intersections appearing as the upper-bound of a type parameter @@ -475,4 +453,23 @@ object GenericSignatures { } else x } + + private def collectMethodParams(mtd: MethodOrPoly)(using Context): (List[TypeParamInfo], List[Type], Type) = + val tparams = ListBuffer.empty[TypeParamInfo] + val vparams = ListBuffer.empty[Type] + + @tailrec def recur(tpe: Type): Type = tpe match + case mtd: MethodType => + vparams ++= mtd.paramInfos.filterNot(_.hasAnnotation(defn.ErasedParamAnnot)) + recur(mtd.resType) + case PolyType(tps, tpe) => + tparams ++= tps + recur(tpe) + case _ => + tpe + end recur + + val rte = recur(mtd) + (tparams.toList, vparams.toList, rte) + end collectMethodParams } diff --git a/tests/run/i21346.check b/tests/run/i21346.check new file mode 100644 index 000000000000..abef81307955 --- /dev/null +++ b/tests/run/i21346.check @@ -0,0 +1,10 @@ +======'bar'====== + +(X,Y) +scala.Tuple2 +============ +======'foo'====== + +(X,Y,Z,A) +scala.Tuple4 +============ diff --git a/tests/run/i21346.scala b/tests/run/i21346.scala new file mode 100644 index 000000000000..40999c3e27dc --- /dev/null +++ b/tests/run/i21346.scala @@ -0,0 +1,14 @@ +// scalajs: --skip + +object Foo: + def foo[X, Y, Z](x: X, y: Y)[A](z: Z, a: A): (X, Y, Z, A) = (x, y, z, a) + def bar[X](x: X)[Y <: x.type](y: Y): (X, Y) = (x, y) + +@main def Test = + val mtds = Foo.getClass().getDeclaredMethods().filterNot(_.getName() == "writeReplace").sortBy(_.getName()) + for mtd <- mtds do + println(s"======'${mtd.getName()}'======") + println(mtd.getTypeParameters().mkString("<", ";", ">")) + println(mtd.getGenericParameterTypes().mkString("(", ",", ")")) + println(mtd.getGenericReturnType()) + println("============") \ No newline at end of file