Skip to content

Commit 054dd3d

Browse files
committed
Fix generic signature for type params bounded by primitive
1 parent 7b9c1a8 commit 054dd3d

File tree

3 files changed

+48
-18
lines changed

3 files changed

+48
-18
lines changed

compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,19 @@ package transform
55
import core.Annotations._
66
import core.Contexts._
77
import core.Phases._
8+
import core.Decorators.*
89
import core.Definitions
910
import core.Flags._
1011
import core.Names.Name
1112
import core.Symbols._
1213
import core.TypeApplications.{EtaExpansion, TypeParamInfo}
13-
import core.TypeErasure.{erasedGlb, erasure, isGenericArrayElement}
14+
import core.TypeErasure.{erasedGlb, erasure, fullErasure, isGenericArrayElement}
1415
import core.Types._
1516
import core.classfile.ClassfileConstants
1617
import SymUtils._
1718
import TypeUtils._
19+
import config.Printers.transforms
20+
import reporting.trace
1821
import java.lang.StringBuilder
1922

2023
import scala.collection.mutable.ListBuffer
@@ -130,15 +133,17 @@ object GenericSignatures {
130133
else
131134
Right(parent))
132135

133-
def paramSig(param: LambdaParam): Unit = {
134-
builder.append(sanitizeName(param.paramName))
136+
def paramSig(param: TypeParamInfo): Unit = {
137+
builder.append(sanitizeName(param.paramName.lastPart))
135138
boundsSig(hiBounds(param.paramInfo.bounds))
136139
}
137140

138-
def polyParamSig(tparams: List[LambdaParam]): Unit =
139-
if (tparams.nonEmpty) {
141+
def polyParamSig(tparams: List[TypeParamInfo]): Unit =
142+
// remove type parameters that are upper-bounded by primitive types (including via a value class)
143+
val tparams1 = tparams.filter(p => !fullErasure(p.paramInfo.bounds.hi).isPrimitiveValueType)
144+
if (tparams1.nonEmpty) {
140145
builder.append('<')
141-
tparams.foreach(paramSig)
146+
tparams1.foreach(paramSig)
142147
builder.append('>')
143148
}
144149

@@ -236,7 +241,11 @@ object GenericSignatures {
236241
tp match {
237242

238243
case ref @ TypeParamRef(_: PolyType, _) =>
239-
typeParamSig(ref.paramName.lastPart)
244+
val erasedUnderlying = fullErasure(ref.underlying.bounds.hi)
245+
// don't emit type param name if the param is upper-bounded by a primitive type (including via a value class)
246+
if erasedUnderlying.isPrimitiveValueType then
247+
jsig(erasedUnderlying, toplevel, primitiveOK)
248+
else typeParamSig(ref.paramName.lastPart)
240249

241250
case defn.ArrayOf(elemtp) =>
242251
if (isGenericArrayElement(elemtp, isScala2 = false))
@@ -263,11 +272,11 @@ object GenericSignatures {
263272
else if (sym == defn.NullClass)
264273
builder.append("Lscala/runtime/Null$;")
265274
else if (sym.isPrimitiveValueClass)
266-
if (!primitiveOK) jsig(defn.ObjectType)
275+
if (!primitiveOK) ()
267276
else if (sym == defn.UnitClass) jsig(defn.BoxedUnitClass.typeRef)
268277
else builder.append(defn.typeTag(sym.info))
269278
else if (ValueClasses.isDerivedValueClass(sym)) {
270-
val erasedUnderlying = core.TypeErasure.fullErasure(tp)
279+
val erasedUnderlying = fullErasure(tp)
271280
if (erasedUnderlying.isPrimitiveValueType && !primitiveOK)
272281
classSig(sym, pre, args)
273282
else
@@ -334,15 +343,6 @@ object GenericSignatures {
334343
jsig(repr, primitiveOK = primitiveOK)
335344

336345
case ci: ClassInfo =>
337-
def polyParamSig(tparams: List[TypeParamInfo]): Unit =
338-
if (tparams.nonEmpty) {
339-
builder.append('<')
340-
tparams.foreach { tp =>
341-
builder.append(sanitizeName(tp.paramName.lastPart))
342-
boundsSig(hiBounds(tp.paramInfo.bounds))
343-
}
344-
builder.append('>')
345-
}
346346
val tParams = tp.typeParams
347347
if (toplevel) polyParamSig(tParams)
348348
superSig(ci.typeSymbol, ci.parents)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class Loc(val idx: Int) extends AnyVal
2+
3+
class Foo:
4+
def testNoParam[A <: Int]: A = 1.asInstanceOf[A] // ()I
5+
def testSingleParam[A <: Int](a: A): A = 2.asInstanceOf[A] // (I)I
6+
def testOtherReturn[A <: Int](a: A): String = "3" // (I)Ljava/lang/String;
7+
def testNoErasure[A <: String](a: A): A = "4".asInstanceOf[A] // (Ljava/lang/String;)Ljava/lang/String;
8+
def testMultiParam[A <: Int, B <: String](a: A, b: B): A = 5.asInstanceOf[A] // (ILjava/lang/String;)I
9+
10+
def testVCNoParam[A <: Loc]: A = Loc(1).asInstanceOf[A]
11+
def testVCSingleParam[A <: Loc](a: A): A = Loc(2).asInstanceOf[A]
12+
def testVCOtherReturn[A <: Loc](a: A): String = "3"
13+
def testVCNoErasure[A <: String](a: A): A = "4".asInstanceOf[A]
14+
def testVCMultiParam[A <: Loc, B <: String](a: A, b: B): A = Loc(5).asInstanceOf[A]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
public class Test {
2+
public static void main(String[] args) throws Exception {
3+
Foo foo = new Foo();
4+
System.out.println(foo.testNoParam());
5+
System.out.println(foo.testSingleParam(2));
6+
System.out.println(foo.testOtherReturn(3));
7+
System.out.println(foo.testNoErasure("4"));
8+
System.out.println(foo.testMultiParam(5, "5"));
9+
10+
System.out.println(foo.testVCNoParam());
11+
System.out.println(foo.testVCSingleParam(2));
12+
System.out.println(foo.testVCOtherReturn(3));
13+
System.out.println(foo.testVCNoErasure("4"));
14+
System.out.println(foo.testVCMultiParam(5, "5"));
15+
}
16+
}

0 commit comments

Comments
 (0)