Skip to content

Commit 2f002f8

Browse files
committed
Denotation#signature: Compute the Java-ness of the prefix more precisely
Instead of relying on `prefix.classSymbol.is(JavaDefined)`, we now explicitly check if every part of the prefix is Java-defined. Being precise like this doesn't seem necessary in practice (we support having multiple denotations with the same signature since the introduction of SELECTin in tasty), but it's important that we stay consistent across versions for tasty compatibility so it's better to be explicit than rely on the implementation details of `classSymbol`.
1 parent 98960f3 commit 2f002f8

File tree

3 files changed

+63
-5
lines changed

3 files changed

+63
-5
lines changed

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -586,11 +586,19 @@ object Denotations {
586586
if (isType) Signature.NotAMethod // don't force info if this is a type SymDenotation
587587
else info match {
588588
case info: MethodOrPoly =>
589-
val isJava =
590-
if prefix eq NoPrefix then
591-
symbol.is(JavaDefined)
592-
else
593-
prefix.classSymbol.is(JavaDefined)
589+
def isJavaPrefix(tp: Type): Boolean = tp match
590+
case tp: ThisType => tp.cls.is(JavaDefined)
591+
case tp: ClassInfo => tp.cls.is(JavaDefined)
592+
case tp: AndOrType => isJavaPrefix(tp.tp1) && isJavaPrefix(tp.tp2)
593+
case tp: TypeRef if tp.symbol.isClass => tp.symbol.is(JavaDefined)
594+
case tp: TypeProxy => isJavaPrefix(tp.underlying)
595+
case _: JavaArrayType => true
596+
case _ => false
597+
598+
// Use the Java signature of this method if all parts of its prefix
599+
// are Java-defined or if it doesn't have a prefix (i.e., it is a
600+
// SymDenotation) and is defined in a Java class.
601+
val isJava = if prefix eq NoPrefix then symbol.is(JavaDefined) else isJavaPrefix(prefix)
594602
try info.signature(isJava)
595603
catch { // !!! DEBUG
596604
case scala.util.control.NonFatal(ex) =>

compiler/test/dotty/tools/SignatureTest.scala

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import dotc.core.Contexts._
1010
import dotc.core.Phases._
1111
import dotc.core.Types._
1212
import dotc.core.Symbols._
13+
import dotc.core.Signature
14+
import dotc.core.TypeErasure.sigName
1315

1416
import java.io.File
1517
import java.nio.file._
@@ -38,3 +40,40 @@ class SignatureTest:
3840
|${ref.denot.signature}""".stripMargin)
3941
}
4042
}
43+
44+
@Test def prefixDependentJavaness: Unit =
45+
inCompilerContext(TestConfiguration.basicClasspath, separateRun = false,
46+
"""trait MyComparable[T] { def compareTo(x: Array[T]): Int }
47+
|trait MyComparable2[T] { def compareTo(x: Array[T]): Int }
48+
|class Foo[T] {
49+
| val jj: Comparable[Array[T]] & Serializable = ???
50+
| val js: Comparable[Array[T]] & MyComparable[T] = ???
51+
| val sj: MyComparable[T] & Comparable[Array[T]] = ???
52+
| val ss: MyComparable[T] & MyComparable2[T] = ???
53+
|}""".stripMargin) {
54+
55+
atPhase(picklerPhase) {
56+
val cls = requiredClass("Foo")
57+
58+
def checkSignature(prefix: String, expectedSig: Signature) =
59+
val meth = cls.requiredMethodRef(prefix)
60+
val denot = meth.select("compareTo".toTermName)
61+
val actualSig = denot.signature
62+
assert(actualSig == expectedSig,
63+
s"""Incorrect signature found for $denot with prefix $meth
64+
|Expected: $expectedSig
65+
|Actual : $actualSig""")
66+
67+
val objSigName = defn.ObjectClass.fullName.asTypeName
68+
val resSigName = defn.IntClass.fullName.asTypeName
69+
val javaSig = Signature(List(objSigName ++ "[]"), resSigName)
70+
val scalaSig = Signature(List(objSigName), resSigName)
71+
72+
// If all parts of the prefix are Java-defined, we use the Java
73+
// signature, otherwise we use the Scala signature.
74+
checkSignature("jj", javaSig)
75+
checkSignature("js", scalaSig)
76+
checkSignature("sj", scalaSig)
77+
checkSignature("ss", scalaSig)
78+
}
79+
}

tests/pos/i8615b.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,14 @@ class ArrayOrdering[N] extends Comparable[Array[N]] {
55
class ArrayIntOrdering extends Comparable[Array[Int]] {
66
override def compareTo(x: Array[Int]): Int = 0
77
}
8+
9+
class ArrayOrdering2[N] extends Comparable[Array[N]] {
10+
self: Serializable =>
11+
override def compareTo(x: Array[N]): Int = 0
12+
}
13+
14+
class ArrayIntOrdering2 extends Comparable[Array[Int]] {
15+
self: Serializable =>
16+
17+
override def compareTo(x: Array[Int]): Int = 0
18+
}

0 commit comments

Comments
 (0)