@@ -41,9 +41,36 @@ object GenericSignatures {
4141
4242 @ noinline
4343 private final def javaSig0 (sym0 : Symbol , info : Type )(using Context ): Option [String ] = {
44+ // This works as long as mangled names are always valid valid Java identifiers,
45+ // if we change our name encoding, we'll have to `throw new UnknownSig` here for
46+ // names which are not valid Java identifiers (see git history of this method).
47+ def sanitizeName (name : Name ): String = name.mangledString
48+
4449 val builder = new StringBuilder (64 )
4550 val isTraitSignature = sym0.enclosingClass.is(Trait )
4651
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+ }
59+ val methodTypeParamRenaming = collection.mutable.Map .empty[String , String ]
60+ def freshTypeParamName (sanitizedName : String ): String = {
61+ if ! usedNames.contains(sanitizedName) then sanitizedName
62+ else {
63+ var i = 1
64+ var newName = sanitizedName + i
65+ while usedNames.contains(newName) do
66+ i += 1
67+ newName = sanitizedName + i
68+ methodTypeParamRenaming(sanitizedName) = newName
69+ usedNames += newName
70+ newName
71+ }
72+ }
73+
4774 def superSig (cls : Symbol , parents : List [Type ]): Unit = {
4875 def isInterfaceOrTrait (sym : Symbol ) = sym.is(PureInterface ) || sym.is(Trait )
4976
@@ -133,15 +160,16 @@ object GenericSignatures {
133160 else
134161 Right (parent))
135162
136- def paramSig (param : TypeParamInfo ): Unit = {
137- builder.append(sanitizeName(param.paramName.lastPart))
163+ def tparamSig (param : TypeParamInfo ): Unit = {
164+ val freshName = freshTypeParamName(sanitizeName(param.paramName.lastPart))
165+ builder.append(freshName)
138166 boundsSig(hiBounds(param.paramInfo.bounds))
139167 }
140168
141169 def polyParamSig (tparams : List [TypeParamInfo ]): Unit =
142170 if (tparams.nonEmpty) {
143171 builder.append('<' )
144- tparams.foreach(paramSig )
172+ tparams.foreach(tparamSig )
145173 builder.append('>' )
146174 }
147175
@@ -151,6 +179,12 @@ object GenericSignatures {
151179 builder.append(';' )
152180 }
153181
182+ def typeParamSigWithName (sanitizedName : String ): Unit = {
183+ builder.append(ClassfileConstants .TVAR_TAG )
184+ builder.append(sanitizedName)
185+ builder.append(';' )
186+ }
187+
154188 def methodResultSig (restpe : Type ): Unit = {
155189 val finalType = restpe.finalResultType
156190 val sym = finalType.typeSymbol
@@ -160,11 +194,6 @@ object GenericSignatures {
160194 jsig(finalType)
161195 }
162196
163- // This works as long as mangled names are always valid valid Java identifiers,
164- // if we change our name encoding, we'll have to `throw new UnknownSig` here for
165- // names which are not valid Java identifiers (see git history of this method).
166- def sanitizeName (name : Name ): String = name.mangledString
167-
168197 // Anything which could conceivably be a module (i.e. isn't known to be
169198 // a type parameter or similar) must go through here or the signature is
170199 // likely to end up with Foo<T>.Empty where it needs Foo<T>.Empty$.
@@ -244,7 +273,11 @@ object GenericSignatures {
244273 // don't emit type param name if the param is upper-bounded by a primitive type (including via a value class)
245274 if erasedUnderlying.isPrimitiveValueType then
246275 jsig(erasedUnderlying, toplevel = toplevel, unboxedVCs = unboxedVCs)
247- else typeParamSig(ref.paramName.lastPart)
276+ else {
277+ val name = sanitizeName(ref.paramName.lastPart)
278+ val nameToUse = methodTypeParamRenaming.getOrElse(name, name)
279+ typeParamSigWithName(nameToUse)
280+ }
248281
249282 case ref : TermRef if ref.symbol.isGetter =>
250283 // If the type of a val is a TermRef to another val, generating the generic signature
@@ -258,7 +291,7 @@ object GenericSignatures {
258291
259292 case ref : SingletonType =>
260293 // Singleton types like `x.type` need to be widened to their underlying type
261- // For example, `def identity[A](x: A): x.type` should have signature
294+ // For example, `def identity[A](x: A): x.type` should have signature
262295 // with return type `A` (not `java.lang.Object`)
263296 jsig(ref.underlying, toplevel = toplevel, unboxedVCs = unboxedVCs)
264297
0 commit comments