diff --git a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala index cf5386ea65e2..64ac05a6882f 100644 --- a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala +++ b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala @@ -49,25 +49,31 @@ object GenericSignatures { val builder = new StringBuilder(64) val isTraitSignature = sym0.enclosingClass.is(Trait) - // Collect class-level type parameter names to avoid conflicts with method-level type parameters - val usedNames = collection.mutable.Set.empty[String] + // Collect class-level type parameter names from all enclosing classes to avoid conflicts with method-level type parameters + val usedNames = collection.mutable.Map.empty[String, Name] if(sym0.is(Method)) { - sym0.enclosingClass.typeParams.foreach { tp => - usedNames += sanitizeName(tp.name) + var enclosing = sym0.enclosingClass + while (enclosing.exists) { + enclosing.typeParams.foreach { tp => + usedNames(sanitizeName(tp.name)) = tp.name + } + enclosing = enclosing.owner.enclosingClass } } - val methodTypeParamRenaming = collection.mutable.Map.empty[String, String] - def freshTypeParamName(sanitizedName: String): String = { - if !usedNames.contains(sanitizedName) then sanitizedName + val methodTypeParamRenaming = collection.mutable.Map.empty[Name, Name] + def freshTypeParamName(originalName: Name): Name = { + val sanitizedName = sanitizeName(originalName) + if !usedNames.contains(sanitizedName) then originalName else { var i = 1 var newName = sanitizedName + i while usedNames.contains(newName) do i += 1 newName = sanitizedName + i - methodTypeParamRenaming(sanitizedName) = newName - usedNames += newName - newName + val freshName = newName.toTypeName + methodTypeParamRenaming(originalName) = freshName + usedNames(newName) = freshName + freshName } } @@ -161,8 +167,8 @@ object GenericSignatures { Right(parent)) def tparamSig(param: TypeParamInfo): Unit = { - val freshName = freshTypeParamName(sanitizeName(param.paramName.lastPart)) - builder.append(freshName) + val freshName = freshTypeParamName(param.paramName.lastPart) + builder.append(sanitizeName(freshName)) boundsSig(hiBounds(param.paramInfo.bounds)) } @@ -179,12 +185,6 @@ object GenericSignatures { builder.append(';') } - def typeParamSigWithName(sanitizedName: String): Unit = { - builder.append(ClassfileConstants.TVAR_TAG) - builder.append(sanitizedName) - builder.append(';') - } - def methodResultSig(restpe: Type): Unit = { val finalType = restpe.finalResultType val sym = finalType.typeSymbol @@ -274,9 +274,9 @@ object GenericSignatures { if erasedUnderlying.isPrimitiveValueType then jsig(erasedUnderlying, toplevel = toplevel, unboxedVCs = unboxedVCs) else { - val name = sanitizeName(ref.paramName.lastPart) + val name = ref.paramName.lastPart val nameToUse = methodTypeParamRenaming.getOrElse(name, name) - typeParamSigWithName(nameToUse) + typeParamSig(nameToUse) } case ref: TermRef if ref.symbol.isGetter => diff --git a/compiler/test/dotc/pos-test-pickling.excludelist b/compiler/test/dotc/pos-test-pickling.excludelist index c9a5b86eb0fe..31febe48e6c0 100644 --- a/compiler/test/dotc/pos-test-pickling.excludelist +++ b/compiler/test/dotc/pos-test-pickling.excludelist @@ -34,6 +34,7 @@ i11982a.scala i17255 i17735.scala i24134 +i24134-nested # Tree is huge and blows stack for printing Text i7034.scala diff --git a/tests/pos/i24134-nested/JavaPartialFunction.scala b/tests/pos/i24134-nested/JavaPartialFunction.scala new file mode 100644 index 000000000000..069b534a41cf --- /dev/null +++ b/tests/pos/i24134-nested/JavaPartialFunction.scala @@ -0,0 +1,2 @@ +class Container[A]: + abstract class JavaPartialFunction[B] extends PartialFunction[A, B] diff --git a/tests/pos/i24134-nested/Main.java b/tests/pos/i24134-nested/Main.java new file mode 100644 index 000000000000..8e03c2de5045 --- /dev/null +++ b/tests/pos/i24134-nested/Main.java @@ -0,0 +1,15 @@ +public class Main { + public static void main(String[] args) { + Container container = new Container<>(); + Container.JavaPartialFunction pf = container.new JavaPartialFunction() { + @Override + public boolean isDefinedAt(String x) { + return x != null && !x.isEmpty(); + } + @Override + public Integer apply(String x) { + return x.length(); + } + }; + } +}