Skip to content

Commit e09ce8d

Browse files
committed
Fix scala#9392: Allow overriding a Java method when a same-named field is present
In scala#9126, Java fields were marked effectively finals to prevent false overrides. This poses a problem when a Java field and method of the same name are present, because a Scala val or def will match both of these according to Denotation#matches. This commit changes `matches` to prevent Java field from matching any Scala method, but we can't prevent them from matching Scala definitions with NotAMethod signature without introducing more complexity, so the following still doesn't compile unlike Scala 2: ```java package pkg; public class J { int i = 0; public int i() { return 1; } } ``` ```scala class S2 extends pkg.J { override def i: Int = 2 // error } ``` I have an alternative fix at scala#9412 which doesn't have this issue but is more hacky.
1 parent 91e3420 commit e09ce8d

File tree

4 files changed

+43
-3
lines changed

4 files changed

+43
-3
lines changed

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -976,8 +976,22 @@ object Denotations {
976976
case FullMatch =>
977977
true
978978
case MethodNotAMethodMatch =>
979-
// Java allows defining both a field and a zero-parameter method with the same name
980-
!ctx.erasedTypes && !(symbol.is(JavaDefined) && other.symbol.is(JavaDefined))
979+
!ctx.erasedTypes && {
980+
val isJava = symbol.is(JavaDefined)
981+
val otherIsJava = other.symbol.is(JavaDefined)
982+
// A Scala zero-parameter method and a Scala non-method always match.
983+
if !isJava && !otherIsJava then
984+
true
985+
// Java allows defining both a field and a zero-parameter method with the same name,
986+
// so they must not match.
987+
else if isJava && otherIsJava then
988+
false
989+
// A Java field never matches a Scala method.
990+
else if isJava then
991+
symbol.is(Method)
992+
else // otherIsJava
993+
other.symbol.is(Method)
994+
}
981995
case ParamMatch =>
982996
// The signatures do not tell us enough to be sure about matching
983997
!ctx.erasedTypes && info.matches(other.info)

tests/neg/i9115/B.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
class B extends A {
22
override val foo: String = "B" // error
3-
}
3+
}

tests/pos/i9392/J.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package pkg;
2+
3+
public class J {
4+
int i = 0;
5+
public int i() { return 1; }
6+
}

tests/pos/i9392/S.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class S1 extends pkg.J {
2+
override def i(): Int = 2
3+
}
4+
5+
// Unlike Scala 2 this doesn't compile, because this override of `i()`
6+
// also matches the non-overridable field `i`.
7+
// class S2 extends pkg.J {
8+
// override def i: Int = 2
9+
// }
10+
11+
object Test {
12+
val s1 = new S1
13+
14+
val i1 = s1.i
15+
val i2 = s1.i()
16+
17+
// val s2 = new S2
18+
19+
// val i3 = s2.i
20+
}

0 commit comments

Comments
 (0)