Skip to content

Commit 9a723a8

Browse files
committed
Denotation#signature: take the "Java-ness" of the prefix into account
When comparing denotations using Denotation#matches, we check if they have matching signatures, but this could return false when comparing a Java and non-Java methods which can happen when doing overriding checks. Override checks are done as seen from some common prefix, but `asSeenFrom` does not change the Java-ness of a method (that is, change the result of MethodType#isJavaMethod). We could change `asSeenFrom` to do that, but that would be pretty expensive in terms of allocation. Instead, we change SingleDenotation#signature to rely on the prefix of the current denotation to decide how to compute its signature. This requires adding a special-case in SingleDenotation#computeAsSeenFrom to ensure that the prefix is always available when we need it to compute the Java-ness of a denotation. Note that even after this change, we cannot simply override a Java generic `Array[T]` with a Scala `Array[T]`, because we intentionally parse these Java types as `Array[T & Object]`, see `TypeApplications.translateJavaArrayElementType` for details and tests/{neg,pos}/i1747.scala for examples.
1 parent 4543d58 commit 9a723a8

File tree

3 files changed

+23
-8
lines changed

3 files changed

+23
-8
lines changed

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -585,8 +585,13 @@ object Denotations {
585585
final def signature(using Context): Signature =
586586
if (isType) Signature.NotAMethod // don't force info if this is a type SymDenotation
587587
else info match {
588-
case info: MethodicType =>
589-
try info.signature
588+
case info: MethodOrPoly =>
589+
val isJava =
590+
if prefix eq NoPrefix then
591+
symbol.is(JavaDefined)
592+
else
593+
prefix.classSymbol.is(JavaDefined)
594+
try info.signature(isJava)
590595
catch { // !!! DEBUG
591596
case scala.util.control.NonFatal(ex) =>
592597
report.echo(s"cannot take signature of $info")
@@ -1058,7 +1063,10 @@ object Denotations {
10581063
def needsPrefix =
10591064
// For opaque types, the prefix is used in `ElimOpaques#transform`,
10601065
// without this i7159.scala would fail when compiled from tasty.
1061-
symbol.is(Opaque)
1066+
symbol.is(Opaque) ||
1067+
// SingleDenotation#signature relies on the prefix to compute
1068+
// an appropriate signature for methods.
1069+
info.isInstanceOf[MethodOrPoly] && symbol.is(JavaDefined) != pre.classSymbol.is(JavaDefined)
10621070

10631071
val derivedInfo = info.asSeenFrom(pre, owner)
10641072
if Config.reuseSymDenotations && this.isInstanceOf[SymDenotation]

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3397,12 +3397,12 @@ object Types {
33973397
mySignature
33983398
end signature
33993399

3400+
/** The Scala signature of this method. When comparing this signature
3401+
* with signatures of Java definitions, the other overload
3402+
* of `signature` should be used instead.
3403+
*/
34003404
final override def signature(using Context): Signature =
3401-
def isJava(tp: Type): Boolean = tp match
3402-
case tp: PolyType => isJava(tp.resultType)
3403-
case tp: MethodType => tp.isJavaMethod
3404-
case _ => false
3405-
signature(isJava = isJava(this))
3405+
signature(isJava = false)
34063406

34073407
final override def hashCode: Int = System.identityHashCode(this)
34083408

tests/pos/i8615b.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class ArrayOrdering[N] extends Comparable[Array[N]] {
2+
override def compareTo(x: Array[N]): Int = 0
3+
}
4+
5+
class ArrayIntOrdering extends Comparable[Array[Int]] {
6+
override def compareTo(x: Array[Int]): Int = 0
7+
}

0 commit comments

Comments
 (0)