[FIR, IR] Prohibit actualization of expect Kotlin property to Java field

The problem from KT-63624 was that during matching phase we must choose
only one candidate, but in Java we can have two successfully matched
properties: 1) from field and 2) from method, which overrides Kotlin
property.
See test `propertyAgainstJavaPrivateFieldAndPublicMethod.kt`.
As a result, we choose field candidate, throw away method candidate, and
then fail during visibility check.

Instead of inventing special rule of prioritizing field over method
it was decided to prohibit actualization to Java field at all because:

1. It doesn't seem that Java fields actualization was implemented in K1
on purpose
2. People usually don't use public Java fields, and use instead
private field + getter, especially when compatibility is important, so
it shouldn't be a breaking change

Besides that, such solution simplifies code and is consistent with
the current logic of matcher, which doesn't expect that two members
can be matched successfully. Also, it fixes KT-63624 and KT-63667.

^KT-63624 Fixed
^KT-63667 Fixed
This commit is contained in:
Roman Efremov
2023-12-19 15:32:38 +01:00
committed by Space Team
parent 3f95e99e29
commit 30aad31ece
16 changed files with 89 additions and 7 deletions
@@ -10,7 +10,7 @@ expect class Foo : I {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> = JavaFoo
actual typealias Foo = JavaFoo
// FILE: JavaFoo.java
public class JavaFoo implements I {
@@ -1 +0,0 @@
Fails in K2 due to KT-63667
@@ -0,0 +1,23 @@
// MODULE: m1-common
// FILE: common.kt
expect class Foo {
val foo: Int
}
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual typealias Foo = JavaFoo
interface I {
val foo: Int
}
// FILE: JavaFoo.java
public class JavaFoo implements I {
public final int foo = 1;
@Override
public int getFoo() {
return 0;
}
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// MODULE: m1-common
// FILE: common.kt
expect class Foo {
@@ -1 +0,0 @@
Fails in K2 due to KT-63667
@@ -0,0 +1,14 @@
// MODULE: m1-common
// FILE: common.kt
<!EXPECT_ACTUAL_INCOMPATIBILITY{JVM}!>expect class Foo {
<!EXPECT_ACTUAL_MISMATCH{JVM}!>var foo: Int<!>
}<!>
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> = JavaFoo
// FILE: JavaFoo.java
public class JavaFoo {
public int foo = 0;
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// MODULE: m1-common
// FILE: common.kt
expect class Foo {
@@ -0,0 +1,14 @@
// MODULE: m1-common
// FILE: common.kt
expect class Foo {
var foo: Int
}
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> = JavaFoo
// FILE: JavaFoo.java
public class JavaFoo {
public int foo = 0;
}
@@ -1 +0,0 @@
Fails in K2 due to KT-63667
@@ -0,0 +1,23 @@
// MODULE: m1-common
// FILE: common.kt
expect class Foo {
var foo: Int
}
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
interface I {
val foo: Int
}
actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> = JavaFoo
// FILE: JavaFoo.java
public class JavaFoo implements I {
public int foo;
@Override
public int getFoo() {
return 0;
}
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// MODULE: m1-common
// FILE: common.kt
expect class Foo {