@@ -582,11 +582,30 @@ object Denotations {
582582 */
583583 def prefix : Type = NoPrefix
584584
585+ /** Either the Scala or Java signature of the info, depending on where the
586+ * symbol is defined.
587+ *
588+ * Invariants:
589+ * - Before erasure, the signature of a denotation is always equal to the
590+ * signature of its corresponding initial denotation.
591+ * - Two distinct overloads will have SymDenotations with distinct
592+ * signatures (the SELECTin tag in Tasty relies on this to refer to an
593+ * overload unambiguously). Note that this only applies to
594+ * SymDenotations, in general we cannot assume that distinct
595+ * SingleDenotations will have distinct signatures (cf #9050).
596+ */
585597 final def signature (using Context ): Signature =
586- if (isType) Signature .NotAMethod // don't force info if this is a type SymDenotation
598+ signature(isJava = ! isType && symbol.is(JavaDefined ))
599+
600+ /** Overload of `signature` which lets the caller pick between the Java and
601+ * Scala signature of the info. Useful to match denotations defined in
602+ * different classes (see `matchesLoosely`).
603+ */
604+ def signature (isJava : Boolean )(using Context ): Signature =
605+ if (isType) Signature .NotAMethod // don't force info if this is a type denotation
587606 else info match {
588- case info : MethodicType =>
589- try info.signature
607+ case info : MethodOrPoly =>
608+ try info.signature(isJava)
590609 catch { // !!! DEBUG
591610 case scala.util.control.NonFatal (ex) =>
592611 report.echo(s " cannot take signature of $info" )
@@ -992,34 +1011,45 @@ object Denotations {
9921011 symbol.hasTargetName(other.symbol.targetName)
9931012 && matchesLoosely(other)
9941013
995- /** matches without a target name check */
1014+ /** `matches` without a target name check.
1015+ *
1016+ * We consider a Scala method and a Java method to match if they have
1017+ * matching Scala signatures. This allows us to override some Java
1018+ * definitions even if they have a different erasure (see i8615b,
1019+ * i9109b), Erasure takes care of adding any necessary bridge to make
1020+ * this work at runtime.
1021+ */
9961022 def matchesLoosely (other : SingleDenotation )(using Context ): Boolean =
997- val d = signature.matchDegree(other.signature)
998- d match
999- case FullMatch =>
1000- true
1001- case MethodNotAMethodMatch =>
1002- ! ctx.erasedTypes && {
1003- val isJava = symbol.is(JavaDefined )
1004- val otherIsJava = other.symbol.is(JavaDefined )
1005- // A Scala zero-parameter method and a Scala non-method always match.
1006- if ! isJava && ! otherIsJava then
1007- true
1008- // Java allows defining both a field and a zero-parameter method with the same name,
1009- // so they must not match.
1010- else if isJava && otherIsJava then
1011- false
1012- // A Java field never matches a Scala method.
1013- else if isJava then
1014- symbol.is(Method )
1015- else // otherIsJava
1016- other.symbol.is(Method )
1017- }
1018- case ParamMatch =>
1019- // The signatures do not tell us enough to be sure about matching
1020- ! ctx.erasedTypes && info.matches(other.info)
1021- case noMatch =>
1022- false
1023+ if isType then true
1024+ else
1025+ val isJava = symbol.is(JavaDefined )
1026+ val otherIsJava = other.symbol.is(JavaDefined )
1027+ val useJavaSig = isJava && otherIsJava
1028+ val sig = signature(isJava = useJavaSig)
1029+ val otherSig = other.signature(isJava = useJavaSig)
1030+ sig.matchDegree(otherSig) match
1031+ case FullMatch =>
1032+ true
1033+ case MethodNotAMethodMatch =>
1034+ ! ctx.erasedTypes && {
1035+ // A Scala zero-parameter method and a Scala non-method always match.
1036+ if ! isJava && ! otherIsJava then
1037+ true
1038+ // Java allows defining both a field and a zero-parameter method with the same name,
1039+ // so they must not match.
1040+ else if isJava && otherIsJava then
1041+ false
1042+ // A Java field never matches a Scala method.
1043+ else if isJava then
1044+ symbol.is(Method )
1045+ else // otherIsJava
1046+ other.symbol.is(Method )
1047+ }
1048+ case ParamMatch =>
1049+ // The signatures do not tell us enough to be sure about matching
1050+ ! ctx.erasedTypes && info.matches(other.info)
1051+ case noMatch =>
1052+ false
10231053
10241054 def mapInherited (ownDenots : PreDenotation , prevDenots : PreDenotation , pre : Type )(using Context ): SingleDenotation =
10251055 if hasUniqueSym && prevDenots.containsSym(symbol) then NoDenotation
0 commit comments