@@ -49,24 +49,21 @@ object GenericSignatures {
4949 val builder = new StringBuilder (64 )
5050 val isTraitSignature = sym0.enclosingClass.is(Trait )
5151
52- // Collect class-level type parameter names to avoid conflicts with method-level type parameters
53- val usedNames = collection.mutable.Set .empty[String ]
54- if (sym0.is(Method )) {
55- sym0.enclosingClass.typeParams.foreach { tp =>
56- usedNames += sanitizeName(tp.name)
57- }
58- }
52+ // Track class type parameter names that are shadowed by method type parameters
53+ // Used to trigger renaming of method type parameters to avoid conflicts
54+ val shadowedClassTypeParamNames = collection.mutable.Set .empty[String ]
5955 val methodTypeParamRenaming = collection.mutable.Map .empty[String , String ]
56+
6057 def freshTypeParamName (sanitizedName : String ): String = {
61- if ! usedNames .contains(sanitizedName) then sanitizedName
58+ if ! shadowedClassTypeParamNames .contains(sanitizedName) then sanitizedName
6259 else {
6360 var i = 1
6461 var newName = sanitizedName + i
65- while usedNames .contains(newName) do
62+ while shadowedClassTypeParamNames .contains(newName) do
6663 i += 1
6764 newName = sanitizedName + i
6865 methodTypeParamRenaming(sanitizedName) = newName
69- usedNames += newName
66+ shadowedClassTypeParamNames += newName
7067 newName
7168 }
7269 }
@@ -347,7 +344,22 @@ object GenericSignatures {
347344
348345 case mtd : MethodOrPoly =>
349346 val (tparams, vparams, rte) = collectMethodParams(mtd)
350- if (toplevel && ! sym0.isConstructor) polyParamSig(tparams)
347+ if (toplevel && ! sym0.isConstructor) {
348+ if (sym0.is(Method )) {
349+ val (usedMethodTypeParamNames, usedClassTypeParams) = collectUsedTypeParams(vparams :+ rte, sym0)
350+ val methodTypeParamNames = tparams.map(tp => sanitizeName(tp.paramName.lastPart)).toSet
351+ // Only add class type parameters to shadowedClassTypeParamNames if they are:
352+ // 1. Referenced in the method signature, AND
353+ // 2. Shadowed by a method type parameter with the same name
354+ // This will trigger renaming of the method type parameter
355+ usedClassTypeParams.foreach { classTypeParam =>
356+ val classTypeParamName = sanitizeName(classTypeParam.name)
357+ if methodTypeParamNames.contains(classTypeParamName) then
358+ shadowedClassTypeParamNames += classTypeParamName
359+ }
360+ }
361+ polyParamSig(tparams)
362+ }
351363 builder.append('(' )
352364 for vparam <- vparams do jsig1(vparam)
353365 builder.append(')' )
@@ -528,4 +540,27 @@ object GenericSignatures {
528540 val rte = recur(mtd)
529541 (tparams.toList, vparams.toList, rte)
530542 end collectMethodParams
543+
544+ /** Collect type parameters that are actually used in the given types. */
545+ private def collectUsedTypeParams (types : List [Type ], initialSymbol : Symbol )(using Context ): (Set [Name ], Set [Symbol ]) =
546+ assert(initialSymbol.is(Method ))
547+ def isTypeParameterInMethSig (sym : Symbol , initialSymbol : Symbol )(using Context ) =
548+ ! sym.maybeOwner.isTypeParam && // check if it's not higher order type param
549+ sym.isTypeParam && sym.owner == initialSymbol
550+
551+ val usedMethodTypeParamNames = collection.mutable.Set .empty[Name ]
552+ val usedClassTypeParams = collection.mutable.Set .empty[Symbol ]
553+
554+ def collect (tp : Type ): Unit = tp.foreachPart:
555+ case ref @ TypeParamRef (_ : PolyType , _) =>
556+ usedMethodTypeParamNames += ref.paramName
557+ case tp : TypeRef =>
558+ val sym = tp.typeSymbol
559+ if sym.isTypeParam && sym.isContainedIn(initialSymbol.topLevelClass) then
560+ usedClassTypeParams += sym
561+ case _ =>
562+
563+ types.foreach(collect)
564+ (usedMethodTypeParamNames.toSet, usedClassTypeParams.toSet)
565+ end collectUsedTypeParams
531566}
0 commit comments