[FIR] 1/2 match and check expect fake-overrides vs actuals

^KT-63550 Fixed
Review: https://jetbrains.team/p/kt/reviews/13094/timeline

Now it's required to create a new ScopeSession when searching for expect
members for actuals. If you keep reusing actualScopeSession then members
declared in platform may "slip into" the search results, resulting an
incorrect expect for actual (e.g. it happens in
supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.fir.kt)

I suppose that it always has been a bug that we reused
actualScopeSession because we were mixing actualScopeSession and
expect FirSession (which is a bad idea), but we simply didn't have cases
where this bug could be observed. Now after we started matching
fake-overrides, we have such cases.

But creating a new ScopeSession every time is a suboptimal solution. We
need to design a scope caching KT-63773
This commit is contained in:
Nikita Bobko
2023-11-15 19:25:18 +01:00
committed by teamcity
parent 5aa0475aa7
commit a1ce8ac175
58 changed files with 182 additions and 69 deletions
@@ -10,6 +10,6 @@ open class Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
override fun <R> foo(t: R) {}
}
@@ -10,6 +10,6 @@ expect open class Foo : Base
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
override fun <R> foo(t: R) {}
}
@@ -13,7 +13,7 @@ open class Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
override lateinit var red1: String
override var red2: String = ""
override lateinit var green: String
@@ -13,7 +13,7 @@ expect open class Foo : Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
override lateinit var red1: String
override var red2: String = ""
override lateinit var green: String
@@ -10,6 +10,6 @@ interface Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base {
final override fun foo() {}
}
@@ -10,6 +10,6 @@ expect open <!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Foo<!> : Base
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base {
final override fun foo() {}
}
@@ -12,6 +12,6 @@ interface Base {
// Mismatched scope must be reported here. But it's false negative checker in K1.
// For some reason, K1 says that modality of `exect_Foo.foo` is `abstract`.
// https://youtrack.jetbrains.com/issue/KT-59739
actual open class Foo : Base {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base {
override fun foo() {}
}
@@ -12,6 +12,6 @@ expect open <!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Foo<!>() : Base
// Mismatched scope must be reported here. But it's false negative checker in K1.
// For some reason, K1 says that modality of `exect_Foo.foo` is `abstract`.
// https://youtrack.jetbrains.com/issue/KT-59739
actual open class Foo : Base {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base {
override fun foo() {}
}
@@ -9,6 +9,6 @@ interface Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual abstract class Foo : Base {
actual abstract class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base {
abstract override fun foo()
}
@@ -9,6 +9,6 @@ expect abstract class Foo() : Base
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual abstract class Foo : Base {
actual abstract class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base {
abstract override fun foo()
}
@@ -10,6 +10,6 @@ open class Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
final override fun foo() {}
}
@@ -10,6 +10,6 @@ expect open class Foo : Base
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
final override fun foo() {}
}
@@ -10,6 +10,6 @@ open class Base<T> {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base<String>() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base<String>() {
final override fun foo(t: String) {}
}
@@ -10,6 +10,6 @@ expect open class Foo : Base<String>
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base<String>() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base<String>() {
final override fun foo(t: String) {}
}
@@ -6,6 +6,6 @@
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> {
final override fun toString() = "Foo"
}
@@ -6,6 +6,6 @@ expect open class Foo
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> {
final override fun toString() = "Foo"
}
@@ -14,7 +14,7 @@ expect open class Foo3 {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo1 : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo1<!> : Base() {
override fun foo(paramNameChanged: Int) {}
}
@@ -14,7 +14,7 @@ expect open class Foo3 {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo1 : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo1<!> : Base() {
override fun foo(paramNameChanged: Int) {}
}
@@ -11,6 +11,6 @@ open class Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
override fun foo(bar: IntArray) {}
}
@@ -11,6 +11,6 @@ expect open class Foo : Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
override fun foo(bar: IntArray) {}
}
@@ -10,6 +10,6 @@ open class Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
public override fun foo() {}
}
@@ -10,6 +10,6 @@ expect open class Foo : Base
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
public override fun foo() {}
}
@@ -12,6 +12,6 @@ open class Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
override fun foo(): String = ""
}
@@ -12,6 +12,6 @@ expect open class Foo : Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
override fun foo(): String = ""
}
@@ -13,6 +13,6 @@ open class Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo<T : I> : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!><T : I> : Base() {
override fun foo(): T = null!!
}
@@ -13,6 +13,6 @@ expect open class Foo<T : I> : Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo<T : I> : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!><T : I> : Base() {
override fun foo(): T = null!!
}
@@ -11,6 +11,6 @@ open class Base<R> {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo<E, F : E> : Base<E>() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!><E, F : E> : Base<E>() {
override fun foo(): F = null!!
}
@@ -11,6 +11,6 @@ expect open class Foo<R, T : R> : Base<R> {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo<E, F : E> : Base<E>() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!><E, F : E> : Base<E>() {
override fun foo(): F = null!!
}
@@ -11,6 +11,6 @@ open class Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
override val foo: String = ""
}
@@ -11,6 +11,6 @@ expect open class Foo : Base
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
override val foo: String = ""
}
@@ -14,7 +14,7 @@ expect open class Base {
actual typealias Base = BaseJava
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
// K1 doesn't report a diagnostic here because when it compares scopes it sees flexible type
// K2 will likely report a diagnostic here
// I don't think we can fix this 'K1 green -> K2 red'. It must be a rare case anyway.
@@ -14,7 +14,7 @@ expect open class Foo : Base {
actual typealias Base = BaseJava
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
// K1 doesn't report a diagnostic here because when it compares scopes it sees flexible type
// K2 will likely report a diagnostic here
// I don't think we can fix this 'K1 green -> K2 red'. It must be a rare case anyway.
@@ -10,6 +10,6 @@ open class Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
override var foo: Int = 1
}
@@ -10,6 +10,6 @@ expect open class Foo : Base
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
override var foo: Int = 1
}
@@ -16,7 +16,7 @@ open class Base() {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
actual fun existingMethod() {}
actual val existingParam: Int = 904
@@ -16,7 +16,7 @@ expect open class Foo : Base {
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual open class Foo : Base() {
actual open class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base() {
actual fun existingMethod() {}
actual val existingParam: Int = 904
@@ -0,0 +1,29 @@
// MODULE: m1-common
// FILE: common.kt
open class A {
open fun foo(): String = "Fail"
}
expect class C1() : A
expect class C2() : A
// MODULE: m2-jvm()()(m1-common)
// FILE: A_J.java
public class A_J {}
// FILE: B_J.java
public class B_J extends A_J {
public String foo() { return "O"; }
}
// FILE: C2_J.java
public class C2_J extends B_J {
public String foo() { return "K"; }
}
// FILE: main.kt
actual typealias <!ACTUAL_WITHOUT_EXPECT!>A<!> = A_J
// Indirect subtyping is allowed in K2 KT-59356
actual class C1 : B_J()
actual typealias C2 = C2_J
@@ -0,0 +1,29 @@
// MODULE: m1-common
// FILE: common.kt
open class <!PACKAGE_OR_CLASSIFIER_REDECLARATION{JVM}!>A<!> {
open fun foo(): String = "Fail"
}
expect class C1() : A
expect class C2() : A
// MODULE: m2-jvm()()(m1-common)
// FILE: A_J.java
public class A_J {}
// FILE: B_J.java
public class B_J extends A_J {
public String foo() { return "O"; }
}
// FILE: C2_J.java
public class C2_J extends B_J {
public String foo() { return "K"; }
}
// FILE: main.kt
actual typealias <!ACTUAL_WITHOUT_EXPECT, PACKAGE_OR_CLASSIFIER_REDECLARATION!>A<!> = A_J
// Indirect subtyping is allowed in K2 KT-59356
actual class C1 : <!ACTUAL_WITHOUT_EXPECT!>B_J()<!>
actual typealias <!ACTUAL_WITHOUT_EXPECT!>C2<!> = C2_J
@@ -2,6 +2,6 @@
<!EXPECT_ACTUAL_INCOMPATIBILITY{JVM}, EXPECT_ACTUAL_INCOMPATIBILITY{JVM}!>expect interface Base<!>
// MODULE: m1-jvm()()(m1-common)
actual interface Base {
actual interface <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Base<!> {
override fun equals(other: Any?): Boolean
}
@@ -2,6 +2,6 @@
expect interface Base
// MODULE: m1-jvm()()(m1-common)
actual interface Base {
actual interface <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Base<!> {
override fun equals(other: Any?): Boolean
}
@@ -12,4 +12,4 @@
import java.util.AbstractMap
public actual abstract class AbstractMutableMap<K, V>() : MutableMap<K, V>, AbstractMap<K, V>()
public actual abstract class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>AbstractMutableMap<!><K, V>() : MutableMap<K, V>, AbstractMap<K, V>()
@@ -12,4 +12,4 @@ public expect abstract class AbstractMutableMap<K, V> : MutableMap<K, V> {
import java.util.AbstractMap
public actual abstract class AbstractMutableMap<K, V>() : MutableMap<K, V>, AbstractMap<K, V>()
public actual abstract class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>AbstractMutableMap<!><K, V>() : MutableMap<K, V>, AbstractMap<K, V>()
@@ -9,5 +9,5 @@
typealias MyNothing = Nothing
<!ACTUAL_TYPE_ALIAS_TO_NOTHING!>actual typealias E01 = Nothing<!>
<!ACTUAL_TYPE_ALIAS_NOT_TO_CLASS!>actual typealias E02 = MyNothing<!>
<!ACTUAL_TYPE_ALIAS_TO_NOTHING!>actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>E01<!> = Nothing<!>
<!ACTUAL_TYPE_ALIAS_NOT_TO_CLASS!>actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>E02<!> = MyNothing<!>
@@ -9,5 +9,5 @@ expect class E02
typealias MyNothing = Nothing
<!ACTUAL_TYPE_ALIAS_TO_NOTHING!>actual typealias E01 = Nothing<!>
<!ACTUAL_TYPE_ALIAS_NOT_TO_CLASS!>actual typealias E02 = MyNothing<!>
<!ACTUAL_TYPE_ALIAS_TO_NOTHING!>actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>E01<!> = Nothing<!>
<!ACTUAL_TYPE_ALIAS_NOT_TO_CLASS!>actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>E02<!> = MyNothing<!>
@@ -10,5 +10,5 @@
typealias MyNothing = Nothing
actual typealias E01 = Nothing
<!ACTUAL_TYPE_ALIAS_NOT_TO_CLASS!>actual typealias E02 = MyNothing<!>
actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>E01<!> = Nothing
<!ACTUAL_TYPE_ALIAS_NOT_TO_CLASS!>actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>E02<!> = MyNothing<!>
@@ -10,5 +10,5 @@ expect class E02
typealias MyNothing = Nothing
actual typealias E01 = Nothing
<!ACTUAL_TYPE_ALIAS_NOT_TO_CLASS!>actual typealias E02 = MyNothing<!>
actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>E01<!> = Nothing
<!ACTUAL_TYPE_ALIAS_NOT_TO_CLASS!>actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>E02<!> = MyNothing<!>