[FIR] Replace single supertype scope with list of scopes of supertypes in use site scopes

This big refactoring is needed to cleanup building of overrides
  mappings and prevent creating redundant intersection overrides in
  cases when there is no need in them:

```kotlin
interface A {
    fun foo()
}

interface B {
    fun foo()
}

interface C : A, B {
    override fun foo()
}
```

Before this refactoring there was next override tree:
C.foo
  intersection override (A.foo, B.foo)
    A.foo
    B.foo

Also this commit fixes special mapping of overrides in jvm scopes
  for declarations which have kotlin builtins in supertypes with
  special java mapping rules (collections, for example)
This commit is contained in:
Dmitriy Novozhilov
2022-01-13 18:22:42 +03:00
parent 17916d4a63
commit c80cfb0fdb
82 changed files with 2564 additions and 636 deletions
@@ -3482,6 +3482,100 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
}
}
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/scopes")
@TestDataPath("$PROJECT_ROOT")
public class Scopes {
@Test
public void testAllFilesPresentInScopes() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/scopes"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("explicitOverrideOfTwoMembers.kt")
public void testExplicitOverrideOfTwoMembers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/explicitOverrideOfTwoMembers.kt");
}
@Test
@TestMetadata("explicitOverrideOfTwoMembers_java.kt")
public void testExplicitOverrideOfTwoMembers_java() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/explicitOverrideOfTwoMembers_java.kt");
}
@Test
@TestMetadata("getterOverrideAndKotlinProperty.kt")
public void testGetterOverrideAndKotlinProperty() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/getterOverrideAndKotlinProperty.kt");
}
@Test
@TestMetadata("intersectionOverrideOfTwoMembers.kt")
public void testIntersectionOverrideOfTwoMembers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/intersectionOverrideOfTwoMembers.kt");
}
@Test
@TestMetadata("intersectionOverrideOfTwoMembers_java.kt")
public void testIntersectionOverrideOfTwoMembers_java() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/intersectionOverrideOfTwoMembers_java.kt");
}
@Test
@TestMetadata("javaFunctionAndKotlinPropertyFromDifferentSupertypes.kt")
public void testJavaFunctionAndKotlinPropertyFromDifferentSupertypes() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/javaFunctionAndKotlinPropertyFromDifferentSupertypes.kt");
}
@Test
@TestMetadata("kotlinAccessorsLikeFunctionsThrowJavaClass.kt")
public void testKotlinAccessorsLikeFunctionsThrowJavaClass() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/kotlinAccessorsLikeFunctionsThrowJavaClass.kt");
}
@Test
@TestMetadata("noIntersectionOverrideOfTwoMembers.kt")
public void testNoIntersectionOverrideOfTwoMembers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/noIntersectionOverrideOfTwoMembers.kt");
}
@Test
@TestMetadata("noIntersectionOverrideOfTwoMembers_java.kt")
public void testNoIntersectionOverrideOfTwoMembers_java() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/noIntersectionOverrideOfTwoMembers_java.kt");
}
@Test
@TestMetadata("publicJavaAndPrivateKotlinVar.kt")
public void testPublicJavaAndPrivateKotlinVar() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/publicJavaAndPrivateKotlinVar.kt");
}
@Test
@TestMetadata("specialFunctionInJava_1.kt")
public void testSpecialFunctionInJava_1() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_1.kt");
}
@Test
@TestMetadata("specialFunctionInJava_2.kt")
public void testSpecialFunctionInJava_2() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_2.kt");
}
@Test
@TestMetadata("specialFunctionInJava_3.kt")
public void testSpecialFunctionInJava_3() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_3.kt");
}
@Test
@TestMetadata("specialFunctionInJava_4.kt")
public void testSpecialFunctionInJava_4() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_4.kt");
}
}
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts")
@TestDataPath("$PROJECT_ROOT")
@@ -3077,6 +3077,89 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/scopes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Scopes extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInScopes() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/scopes"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("explicitOverrideOfTwoMembers.kt")
public void testExplicitOverrideOfTwoMembers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/explicitOverrideOfTwoMembers.kt");
}
@TestMetadata("explicitOverrideOfTwoMembers_java.kt")
public void testExplicitOverrideOfTwoMembers_java() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/explicitOverrideOfTwoMembers_java.kt");
}
@TestMetadata("getterOverrideAndKotlinProperty.kt")
public void testGetterOverrideAndKotlinProperty() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/getterOverrideAndKotlinProperty.kt");
}
@TestMetadata("intersectionOverrideOfTwoMembers.kt")
public void testIntersectionOverrideOfTwoMembers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/intersectionOverrideOfTwoMembers.kt");
}
@TestMetadata("intersectionOverrideOfTwoMembers_java.kt")
public void testIntersectionOverrideOfTwoMembers_java() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/intersectionOverrideOfTwoMembers_java.kt");
}
@TestMetadata("javaFunctionAndKotlinPropertyFromDifferentSupertypes.kt")
public void testJavaFunctionAndKotlinPropertyFromDifferentSupertypes() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/javaFunctionAndKotlinPropertyFromDifferentSupertypes.kt");
}
@TestMetadata("kotlinAccessorsLikeFunctionsThrowJavaClass.kt")
public void testKotlinAccessorsLikeFunctionsThrowJavaClass() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/kotlinAccessorsLikeFunctionsThrowJavaClass.kt");
}
@TestMetadata("noIntersectionOverrideOfTwoMembers.kt")
public void testNoIntersectionOverrideOfTwoMembers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/noIntersectionOverrideOfTwoMembers.kt");
}
@TestMetadata("noIntersectionOverrideOfTwoMembers_java.kt")
public void testNoIntersectionOverrideOfTwoMembers_java() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/noIntersectionOverrideOfTwoMembers_java.kt");
}
@TestMetadata("publicJavaAndPrivateKotlinVar.kt")
public void testPublicJavaAndPrivateKotlinVar() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/publicJavaAndPrivateKotlinVar.kt");
}
@TestMetadata("specialFunctionInJava_1.kt")
public void testSpecialFunctionInJava_1() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_1.kt");
}
@TestMetadata("specialFunctionInJava_2.kt")
public void testSpecialFunctionInJava_2() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_2.kt");
}
@TestMetadata("specialFunctionInJava_3.kt")
public void testSpecialFunctionInJava_3() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_3.kt");
}
@TestMetadata("specialFunctionInJava_4.kt")
public void testSpecialFunctionInJava_4() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_4.kt");
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -0,0 +1,22 @@
FILE: explicitOverrideOfTwoMembers.kt
public abstract interface A : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Any|
public abstract val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface B : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Any|
public abstract val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface C : R|A|, R|B| {
public abstract override fun foo(): R|kotlin/Any|
public abstract override val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
@@ -0,0 +1,16 @@
// SCOPE_DUMP: C:foo;x
interface A {
fun foo(): Any
val x: Any
}
interface B {
fun foo(): Any
val x: Any
}
interface C : A, B {
override fun foo(): Any
override val x: Any
}
@@ -0,0 +1,8 @@
C:
[Source]: public abstract override fun foo(): R|kotlin/Any| from Use site scope of /C [id: 0]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /A [id: 1]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /B [id: 2]
[Source]: public abstract override val x: R|kotlin/Any| from Use site scope of /C [id: 0]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /A [id: 1]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /B [id: 2]
@@ -0,0 +1,26 @@
FILE: lib.kt
public abstract interface A : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Any|
public abstract val x: R|kotlin/Int|
public get(): R|kotlin/Int|
public abstract val y: R|kotlin/Int|
public get(): R|kotlin/Int|
}
public abstract interface B : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Any|
public abstract val x: R|kotlin/String|
public get(): R|kotlin/String|
public abstract val y: R|kotlin/Int|
public get(): R|kotlin/Int|
}
FILE: main.kt
public final fun test(d: R|D|): R|kotlin/Unit| {
lval a: R|kotlin/Int| = R|<local>/d|.R|/C.x|
lval b: R|kotlin/Int| = R|<local>/d|.R|/D.y|
}
@@ -0,0 +1,42 @@
// SCOPE_DUMP: C:foo;x;y;getX, D:x;y;getX, E:x;getX
// FILE: lib.kt
interface A {
fun foo(): Any
val x: Int
val y: Int
}
interface B {
fun foo(): Any
val x: String
val y: Int
}
// FILE: C.java
public abstract class C {
public int x;
private int y;
}
// FILE: D.java
public abstract class D extends C implements A, B {
public abstract Object foo();
public abstract Object getX();
public abstract int getY();
}
// FILE: E.java
public abstract class E implements A, B {
public abstract Object foo();
public abstract Object getX();
}
// FILE: main.kt
fun test(d: D) {
val a = d.x
val b = d.y
}
@@ -0,0 +1,21 @@
C:
[Java]: public open field x: R|kotlin/Int| from Java enhancement scope for /C [id: 0]
[Java]: private open field y: R|kotlin/Int| from Java enhancement scope for /C [id: 0]
D:
[Java]: public open field x: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[IntersectionOverride]: public abstract val x: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[Source]: public abstract val x: R|kotlin/Int| from Use site scope of /A [id: 1]
[Source]: public abstract val x: R|kotlin/String| from Use site scope of /B [id: 2]
[Java]: private open field y: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[Synthetic]: public abstract val y: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[Source]: public abstract val y: R|kotlin/Int| from Use site scope of /A [id: 1]
[Source]: public abstract val y: R|kotlin/Int| from Use site scope of /B [id: 2]
[Enhancement]: public abstract fun getX(): R|ft<kotlin/Any, kotlin/Any?>| from Java enhancement scope for /D [id: 0]
E:
[IntersectionOverride]: public abstract val x: R|kotlin/Int| from Java enhancement scope for /E [id: 0]
[Source]: public abstract val x: R|kotlin/Int| from Use site scope of /A [id: 1]
[Source]: public abstract val x: R|kotlin/String| from Use site scope of /B [id: 2]
[Enhancement]: public abstract fun getX(): R|ft<kotlin/Any, kotlin/Any?>| from Java enhancement scope for /E [id: 0]
@@ -0,0 +1,24 @@
FILE: B.kt
public abstract class B : R|A| {
public constructor(): R|B| {
super<R|kotlin/Any|>()
}
private final val foo: R|kotlin/Int| = Int(1)
private get(): R|kotlin/Int|
public open override fun getFoo(): R|kotlin/String| {
^getFoo String(foo)
}
}
FILE: main.kt
public final class D : R|C| {
public constructor(): R|D| {
super<R|C|>()
}
}
public final fun test(d: R|D|): R|kotlin/Unit| {
R|<local>/d|.R|/B.foo|.R|kotlin/String.length|
}
@@ -0,0 +1,22 @@
// SCOPE_DUMP: A:getFoo, B:getFoo, C:getFoo, D:getFoo
// FILE: A.java
public interface A {
String getFoo();
}
// FILE: B.kt
abstract class B : A {
private val foo: Int = 1
override fun getFoo(): String = "foo"
}
// FILE: C.java
public abstract class C extends B implements A {}
// FILE: main.kt
class D : C()
fun test(d: D) {
d.foo.length
}
@@ -0,0 +1,15 @@
A:
[Enhancement]: public abstract fun getFoo(): R|ft<kotlin/String, kotlin/String?>| from Java enhancement scope for /A [id: 0]
B:
[Source]: public open override fun getFoo(): R|kotlin/String| from Use site scope of /B [id: 0]
[Enhancement]: public abstract fun getFoo(): R|ft<kotlin/String, kotlin/String?>| from Java enhancement scope for /A [id: 1]
C:
[Source]: public open override fun getFoo(): R|kotlin/String| from Java enhancement scope for /C [id: 0]
[Enhancement]: public abstract fun getFoo(): R|ft<kotlin/String, kotlin/String?>| from Java enhancement scope for /A [id: 1]
D:
[Source]: public open override fun getFoo(): R|kotlin/String| from Use site scope of /D [id: 0]
[Enhancement]: public abstract fun getFoo(): R|ft<kotlin/String, kotlin/String?>| from Java enhancement scope for /A [id: 1]
@@ -0,0 +1,24 @@
FILE: intersectionOverrideOfTwoMembers.kt
public abstract interface A : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Any|
public abstract val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface B : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Any|
public abstract val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface C : R|A|, R|B| {
}
public abstract interface D : R|C| {
public abstract override fun foo(): R|kotlin/Any|
public abstract override val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
@@ -0,0 +1,18 @@
// SCOPE_DUMP: C:foo;x, D:foo;x
interface A {
fun foo(): Any
val x: Any
}
interface B {
fun foo(): Any
val x: Any
}
interface C : A, B
interface D : C {
override fun foo(): Any
override val x: Any
}
@@ -0,0 +1,18 @@
C:
[IntersectionOverride]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /C [id: 0]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /A [id: 1]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /B [id: 2]
[IntersectionOverride]: public abstract val x: R|kotlin/Any| from Use site scope of /C [id: 0]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /A [id: 1]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /B [id: 2]
D:
[Source]: public abstract override fun foo(): R|kotlin/Any| from Use site scope of /D [id: 0]
[IntersectionOverride]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /C [id: 1]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /A [id: 2]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /B [id: 3]
[Source]: public abstract override val x: R|kotlin/Any| from Use site scope of /D [id: 0]
[IntersectionOverride]: public abstract val x: R|kotlin/Any| from Use site scope of /C [id: 1]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /A [id: 2]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /B [id: 3]
@@ -0,0 +1,24 @@
FILE: intersectionOverrideOfTwoMembers_java.kt
public abstract interface A : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Any|
public abstract val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface B : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Any|
public abstract val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface C : R|A|, R|B| {
}
public abstract interface D : R|C| {
public abstract override fun foo(): R|kotlin/Any|
public abstract override val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
@@ -0,0 +1,18 @@
// SCOPE_DUMP: C:foo;x, D:foo;x
interface A {
fun foo(): Any
val x: Any
}
interface B {
fun foo(): Any
val x: Any
}
interface C : A, B
interface D : C {
override fun foo(): Any
override val x: Any
}
@@ -0,0 +1,17 @@
C:
[IntersectionOverride]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /C [id: 0]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /A [id: 1]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /B [id: 2]
[IntersectionOverride]: public abstract val x: R|kotlin/Any| from Use site scope of /C [id: 0]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /A [id: 1]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /B [id: 2]
D:
[Source]: public abstract override fun foo(): R|kotlin/Any| from Use site scope of /D [id: 0]
[IntersectionOverride]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /C [id: 1]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /A [id: 2]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /B [id: 3]
[Source]: public abstract override val x: R|kotlin/Any| from Use site scope of /D [id: 0]
[IntersectionOverride]: public abstract val x: R|kotlin/Any| from Use site scope of /C [id: 1]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /A [id: 2]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /B [id: 3]
@@ -0,0 +1,13 @@
FILE: B.kt
public abstract interface B : R|kotlin/Any| {
public abstract val foo: R|kotlin/Int|
public get(): R|kotlin/Int|
}
FILE: main.kt
public final class D : R|C| {
public constructor(): R|D| {
super<R|C|>()
}
}
@@ -0,0 +1,18 @@
// SCOPE_DUMP: C:foo;getFoo
// FILE: A.java
public abstract class A {
public int getFoo() {
return 42;
}
}
// FILE: B.kt
interface B {
val foo: Int
}
// FILE: C.java
public class C extends A implements B {}
// FILE: main.kt
class D : C()
@@ -0,0 +1,4 @@
C:
[Synthetic]: public open val foo: R|kotlin/Int| from Java enhancement scope for /C [id: 0]
[Source]: public abstract val foo: R|kotlin/Int| from Use site scope of /B [id: 1]
@@ -0,0 +1,24 @@
FILE: A.kt
public open class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
public open fun getScope(): R|kotlin/String?| {
^getScope Null(null)
}
public final fun setScope(scope: R|kotlin/String?|): R|A| {
^setScope this@R|/A|
}
protected final var scope: R|kotlin/String?| = Null(null)
protected get(): R|kotlin/String?|
protected set(value: R|kotlin/String?|): R|kotlin/Unit|
}
FILE: main.kt
public final fun test(b: R|B|): R|kotlin/Unit| {
lval s: R|kotlin/String?| = R|<local>/b|.R|/B.getScope|()
R|<local>/b|.R|/A.setScope|(R|<local>/s|)
}
@@ -0,0 +1,23 @@
// FILE: A.kt
open class A {
open fun getScope(): String? = null
fun setScope(scope: String?): A {
return this
}
protected var scope: String? = null
}
// FILE: B.java
public class B extends A {
@java.lang.Override
public String getScope() {
return null;
}
}
// FILE: main.kt
fun test(b: B) {
val s = b.getScope()
b.setScope(s)
}
@@ -0,0 +1,33 @@
FILE: noIntersectionOverrideOfTwoMembers.kt
public abstract interface A : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Any|
public abstract val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface B : R|A| {
public abstract override fun foo(): R|kotlin/Any|
public abstract override val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface C : R|A|, R|B| {
}
public abstract interface D : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Int|
public abstract val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface Explicit : R|C|, R|D| {
public abstract override fun foo(): R|kotlin/Int|
public abstract override val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface Implicit : R|C|, R|D| {
}
@@ -0,0 +1,25 @@
// SCOPE_DUMP: C:foo;x, Explicit:foo;x, Implicit:foo;x
interface A {
fun foo(): Any
val x: Any
}
interface B : A {
override fun foo(): Any
override val x: Any
}
interface C : A, B
interface D {
fun foo(): Int
val x: Any
}
interface Explicit : C, D {
override fun foo(): Int
override val x: Any
}
interface Implicit : C, D
@@ -0,0 +1,26 @@
C:
[Source]: public abstract override fun foo(): R|kotlin/Any| from Use site scope of /C [id: 0]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /A [id: 1]
[Source]: public abstract override val x: R|kotlin/Any| from Use site scope of /C [id: 0]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /A [id: 1]
Explicit:
[Source]: public abstract override fun foo(): R|kotlin/Int| from Use site scope of /Explicit [id: 0]
[Source]: public abstract override fun foo(): R|kotlin/Any| from Use site scope of /C [id: 1]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /A [id: 2]
[Source]: public abstract fun foo(): R|kotlin/Int| from Use site scope of /D [id: 3]
[Source]: public abstract override val x: R|kotlin/Any| from Use site scope of /Explicit [id: 0]
[Source]: public abstract override val x: R|kotlin/Any| from Use site scope of /C [id: 1]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /A [id: 2]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /D [id: 3]
Implicit:
[IntersectionOverride]: public abstract fun foo(): R|kotlin/Int| from Use site scope of /Implicit [id: 0]
[Source]: public abstract override fun foo(): R|kotlin/Any| from Use site scope of /C [id: 1]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /A [id: 2]
[Source]: public abstract fun foo(): R|kotlin/Int| from Use site scope of /D [id: 3]
[IntersectionOverride]: public abstract override val x: R|kotlin/Any| from Use site scope of /Implicit [id: 0]
[Source]: public abstract override val x: R|kotlin/Any| from Use site scope of /C [id: 1]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /A [id: 2]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /D [id: 3]
@@ -0,0 +1,33 @@
FILE: noIntersectionOverrideOfTwoMembers_java.kt
public abstract interface A : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Any|
public abstract val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface B : R|A| {
public abstract override fun foo(): R|kotlin/Any|
public abstract override val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface C : R|A|, R|B| {
}
public abstract interface D : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Int|
public abstract val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface Explicit : R|C|, R|D| {
public abstract override fun foo(): R|kotlin/Int|
public abstract override val x: R|kotlin/Any|
public get(): R|kotlin/Any|
}
public abstract interface Implicit : R|C|, R|D| {
}
@@ -0,0 +1,25 @@
// SCOPE_DUMP: C:foo;x, Explicit:foo;x, Implicit:foo;x
interface A {
fun foo(): Any
val x: Any
}
interface B : A {
override fun foo(): Any
override val x: Any
}
interface C : A, B
interface D {
fun foo(): Int
val x: Any
}
interface Explicit : C, D {
override fun foo(): Int
override val x: Any
}
interface Implicit : C, D
@@ -0,0 +1,25 @@
C:
[Source]: public abstract override fun foo(): R|kotlin/Any| from Use site scope of /C [id: 0]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /A [id: 1]
[Source]: public abstract override val x: R|kotlin/Any| from Use site scope of /C [id: 0]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /A [id: 1]
Explicit:
[Source]: public abstract override fun foo(): R|kotlin/Int| from Use site scope of /Explicit [id: 0]
[Source]: public abstract override fun foo(): R|kotlin/Any| from Use site scope of /C [id: 1]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /A [id: 2]
[Source]: public abstract fun foo(): R|kotlin/Int| from Use site scope of /D [id: 3]
[Source]: public abstract override val x: R|kotlin/Any| from Use site scope of /Explicit [id: 0]
[Source]: public abstract override val x: R|kotlin/Any| from Use site scope of /C [id: 1]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /A [id: 2]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /D [id: 3]
Implicit:
[IntersectionOverride]: public abstract fun foo(): R|kotlin/Int| from Use site scope of /Implicit [id: 0]
[Source]: public abstract override fun foo(): R|kotlin/Any| from Use site scope of /C [id: 1]
[Source]: public abstract fun foo(): R|kotlin/Any| from Use site scope of /A [id: 2]
[Source]: public abstract fun foo(): R|kotlin/Int| from Use site scope of /D [id: 3]
[IntersectionOverride]: public abstract override val x: R|kotlin/Any| from Use site scope of /Implicit [id: 0]
[Source]: public abstract override val x: R|kotlin/Any| from Use site scope of /C [id: 1]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /A [id: 2]
[Source]: public abstract val x: R|kotlin/Any| from Use site scope of /D [id: 3]
@@ -0,0 +1,23 @@
FILE: C.kt
public open class C : R|B<kotlin/Any?>| {
public constructor(name: R|kotlin/String|): R|C| {
super<R|kotlin/Any|>()
}
private final var name: R|kotlin/String| = R|<local>/name|
private get(): R|kotlin/String|
private set(value: R|kotlin/String|): R|kotlin/Unit|
public open override fun getName(): R|kotlin/String| {
^getName this@R|/C|.R|/C.name|
}
public open override fun setName(newName: R|kotlin/String|): R|kotlin/Any?| {
^setName Null(null)
}
}
FILE: main.kt
public final fun test(d: R|D|): R|kotlin/Unit| {
lval name: R|kotlin/String| = R|<local>/d|.R|/C.name|
}
@@ -0,0 +1,25 @@
// SCOPE_DUMP: C:getName;setName;name, D:getName;setName;name
// FILE: A.java
public interface A {
String getName();
}
// FILE: B.java
public interface B<T> extends A {
T setName(String newName);
}
// FILE: C.kt
open class C(private var name: String) : B<Any?> {
override fun getName(): String = name
override fun setName(newName: String): Any? = null
}
// FILE: D.java
public class D extends C {}
// FILE: main.kt
fun test(d: D) {
val name = d.name
}
@@ -0,0 +1,14 @@
C:
[Source]: public open override fun getName(): R|kotlin/String| from Use site scope of /C [id: 0]
[Enhancement]: public abstract fun getName(): R|ft<kotlin/String, kotlin/String?>| from Substitution scope for [Java enhancement scope for /B] for type C [id: 1]
[Source]: public open override fun setName(newName: R|kotlin/String|): R|kotlin/Any?| from Use site scope of /C [id: 0]
[SubstitutionOverride]: public abstract fun setName(newName: R|ft<kotlin/String, kotlin/String?>|): R|kotlin/Any?| from Substitution scope for [Java enhancement scope for /B] for type C [id: 1]
[Enhancement]: public abstract fun setName(newName: R|ft<kotlin/String, kotlin/String?>|): R|ft<T, T?>| from Java enhancement scope for /B [id: 2]
[Source]: private final var name: R|kotlin/String| = R|<local>/name| from Use site scope of /C [id: 0]
D:
[Source]: public open override fun getName(): R|kotlin/String| from Java enhancement scope for /D [id: 0]
[Enhancement]: public abstract fun getName(): R|ft<kotlin/String, kotlin/String?>| from Substitution scope for [Java enhancement scope for /B] for type C [id: 1]
[Source]: private final var name: R|kotlin/String| = R|<local>/name| from Java enhancement scope for /D [id: 0]
[Source]: private final var name: R|kotlin/String| = R|<local>/name| from Use site scope of /C [id: 0]
@@ -0,0 +1,41 @@
// SCOPE_DUMP: Some:toByte;byteValue;toShort;shortValue;toInt;intValue;toLong;longValue MyNumber:toByte;byteValue
// FILE: MyBaseNumber.java
public interface MyBaseNumber {
byte byteValue(); // (1)
short shortValue(); // (1)
}
// FILE: MyNumber.java
public interface MyNumber extends MyBaseNumber {
@Override
byte byteValue(); // (2)
@Override
short shortValue(); // (1)
int intValue();
}
// FILE: Some.java
public abstract class Some extends Number implements MyNumber {
@Override
public abstract byte byteValue() // (3)
}
/*
* Some.toByte() (3', renamed) overrides Number.toByte & MyNumber.toByte(2', renamed)
* MyNumber.toByte(2', renamed) overrides ???
*/
fun test(some: Some) {
some.toByte()
some.toShort()
some.toInt()
some.toLong()
some.byteValue()
some.shortValue()
some.intValue()
some.longValue()
}
@@ -0,0 +1,18 @@
Some:
[Enhancement]: public abstract operator fun toByte(): R|kotlin/Byte| from Java enhancement scope for /Some [id: 0]
[Library]: public abstract fun toByte(): R|kotlin/Byte| from Use site scope of kotlin/Number [id: 1]
[RenamedForOverride]: public abstract fun toByte(): R|kotlin/Byte| from Java enhancement scope for /MyNumber [id: 2]
[Enhancement]: public abstract fun byteValue(): R|kotlin/Byte| from Java enhancement scope for /MyBaseNumber [id: 3]
[IntersectionOverride]: public abstract fun toShort(): R|kotlin/Short| from Java enhancement scope for /Some [id: 0]
[Library]: public abstract fun toShort(): R|kotlin/Short| from Use site scope of kotlin/Number [id: 1]
[RenamedForOverride]: public abstract fun toShort(): R|kotlin/Short| from Java enhancement scope for /MyNumber [id: 2]
[Enhancement]: public abstract fun shortValue(): R|kotlin/Short| from Java enhancement scope for /MyBaseNumber [id: 3]
[IntersectionOverride]: public abstract fun toInt(): R|kotlin/Int| from Java enhancement scope for /Some [id: 0]
[Library]: public abstract fun toInt(): R|kotlin/Int| from Use site scope of kotlin/Number [id: 1]
[RenamedForOverride]: public abstract fun toInt(): R|kotlin/Int| from Java enhancement scope for /MyNumber [id: 2]
[Library]: public abstract fun toLong(): R|kotlin/Long| from Java enhancement scope for /Some [id: 0]
MyNumber:
[Enhancement]: public abstract fun byteValue(): R|kotlin/Byte| from Java enhancement scope for /MyNumber [id: 0]
[Enhancement]: public abstract fun byteValue(): R|kotlin/Byte| from Java enhancement scope for /MyBaseNumber [id: 1]
@@ -0,0 +1,11 @@
FILE: main.kt
public final fun test(map: R|SomeMap<kotlin/Int, kotlin/String>|): R|kotlin/Unit| {
R|<local>/map|.R|SubstitutionOverride</SomeMap.containsKey: R|kotlin/Boolean|>|(Int(1))
R|<local>/map|.<Inapplicable(INAPPLICABLE): /SomeMap.containsKey>#(String())
R|<local>/map|.R|SubstitutionOverride</SomeMap.containsValue: R|kotlin/Boolean|>|(String())
R|<local>/map|.<Inapplicable(INAPPLICABLE): /SomeMap.containsValue>#(Int(1))
R|<local>/map|.R|SubstitutionOverride</SomeMap.get: R|kotlin/String?|>|(Int(1))
R|<local>/map|.<Inapplicable(INAPPLICABLE): /SomeMap.get>#(String())
R|<local>/map|.R|SubstitutionOverride</SomeMap.remove: R|kotlin/String?|>|(Int(1))
R|<local>/map|.<Inapplicable(INAPPLICABLE): /SomeMap.remove>#(String())
}
@@ -0,0 +1,42 @@
// SCOPE_DUMP: SomeMap:containsKey;containsValue;get;remove, MyMap:containsKey;containsValue;get
// FILE: MyBaseMap.java
public interface MyBaseMap<K1, V1> {
boolean containsKey(Object key);
}
// FILE: MyMap.java
public interface MyMap<K2, V2> extends MyBaseMap<K2, V2> {
@Override
boolean containsKey(Object key);
boolean containsValue(Object key);
V2 get(K2 key);
}
// FILE: SomeMap.java
import java.util.Map;
public abstract class SomeMap<K3, V3> implements Map<K3, V3>, MyMap<K3, V3> {
@Override
public abstract boolean containsKey(Object key);
@Override
public abstract V3 remove(Object key);
}
// FILE: main.kt
fun test(map: SomeMap<Int, String>) {
map.containsKey(1) // ok
map.containsKey(<!ARGUMENT_TYPE_MISMATCH!>""<!>) // error
map.containsValue("") // ok
map.containsValue(<!ARGUMENT_TYPE_MISMATCH!>1<!>) // error
map.get(1) // ok
map.get(<!ARGUMENT_TYPE_MISMATCH!>""<!>) // error
map.remove(1) // ok
map.remove(<!ARGUMENT_TYPE_MISMATCH!>""<!>) // error
}
@@ -0,0 +1,39 @@
SomeMap:
[Enhancement]: public abstract fun containsKey(key: R|ft<K3, K3?>|): R|kotlin/Boolean| from Java enhancement scope for /SomeMap [id: 0]
[SubstitutionOverride]: public abstract fun containsKey(key: R|ft<K3, K3?>|): R|kotlin/Boolean| from Substitution scope for [Use site scope of kotlin/collections/MutableMap] for type SomeMap<K3, V3> [id: 1]
[SubstitutionOverride]: public abstract fun containsKey(key: R|K|): R|kotlin/Boolean| from Use site scope of kotlin/collections/MutableMap [id: 2]
[Library]: public abstract fun containsKey(key: R|K|): R|kotlin/Boolean| from Use site scope of kotlin/collections/Map [id: 3]
[Library]: public abstract fun containsKey(key: R|K|): R|kotlin/Boolean| from Use site scope of kotlin/collections/Map [id: 3]
[SubstitutionOverride]: public abstract fun containsKey(key: R|ft<kotlin/Any, kotlin/Any?>|): R|kotlin/Boolean| from Substitution scope for [Java enhancement scope for /MyMap] for type SomeMap<K3, V3> [id: 4]
[Enhancement]: public abstract fun containsKey(key: R|ft<kotlin/Any, kotlin/Any?>|): R|kotlin/Boolean| from Java enhancement scope for /MyMap [id: 5]
[SubstitutionOverride]: public abstract fun containsKey(key: R|ft<kotlin/Any, kotlin/Any?>|): R|kotlin/Boolean| from Substitution scope for [Java enhancement scope for /MyBaseMap] for type MyMap<K2, V2> [id: 6]
[Enhancement]: public abstract fun containsKey(key: R|ft<kotlin/Any, kotlin/Any?>|): R|kotlin/Boolean| from Java enhancement scope for /MyBaseMap [id: 7]
[SubstitutionOverride]: public abstract fun containsKey(key: R|ft<kotlin/Any, kotlin/Any?>|): R|kotlin/Boolean| from Substitution scope for [Java enhancement scope for /MyBaseMap] for type MyMap<K2, V2> [id: 6]
[Enhancement]: public abstract fun containsKey(key: R|ft<kotlin/Any, kotlin/Any?>|): R|kotlin/Boolean| from Java enhancement scope for /MyBaseMap [id: 7]
[IntersectionOverride]: public abstract fun containsValue(value: R|ft<V3, V3?>|): R|kotlin/Boolean| from Java enhancement scope for /SomeMap [id: 0]
[SubstitutionOverride]: public abstract fun containsValue(value: R|ft<V3, V3?>|): R|kotlin/Boolean| from Substitution scope for [Use site scope of kotlin/collections/MutableMap] for type SomeMap<K3, V3> [id: 1]
[SubstitutionOverride]: public abstract fun containsValue(value: R|V|): R|kotlin/Boolean| from Use site scope of kotlin/collections/MutableMap [id: 2]
[Library]: public abstract fun containsValue(value: R|V|): R|kotlin/Boolean| from Use site scope of kotlin/collections/Map [id: 3]
[Library]: public abstract fun containsValue(value: R|V|): R|kotlin/Boolean| from Use site scope of kotlin/collections/Map [id: 3]
[SubstitutionOverride]: public abstract fun containsValue(key: R|ft<kotlin/Any, kotlin/Any?>|): R|kotlin/Boolean| from Substitution scope for [Java enhancement scope for /MyMap] for type SomeMap<K3, V3> [id: 4]
[Enhancement]: public abstract fun containsValue(key: R|ft<kotlin/Any, kotlin/Any?>|): R|kotlin/Boolean| from Java enhancement scope for /MyMap [id: 5]
[IntersectionOverride]: public abstract operator fun get(key: R|ft<K3, K3?>|): R|V3?| from Java enhancement scope for /SomeMap [id: 0]
[SubstitutionOverride]: public abstract operator fun get(key: R|ft<K3, K3?>|): R|V3?| from Substitution scope for [Use site scope of kotlin/collections/MutableMap] for type SomeMap<K3, V3> [id: 1]
[SubstitutionOverride]: public abstract operator fun get(key: R|K|): R|V?| from Use site scope of kotlin/collections/MutableMap [id: 2]
[Library]: public abstract operator fun get(key: R|K|): R|V?| from Use site scope of kotlin/collections/Map [id: 3]
[Library]: public abstract operator fun get(key: R|K|): R|V?| from Use site scope of kotlin/collections/Map [id: 3]
[SubstitutionOverride]: public abstract operator fun get(key: R|ft<K3, K3?>|): R|ft<V3, V3?>| from Substitution scope for [Java enhancement scope for /MyMap] for type SomeMap<K3, V3> [id: 4]
[Enhancement]: public abstract operator fun get(key: R|ft<K2, K2?>|): R|ft<V2, V2?>| from Java enhancement scope for /MyMap [id: 5]
[Enhancement]: public abstract fun remove(key: R|ft<K3, K3?>|): R|V3?| from Java enhancement scope for /SomeMap [id: 0]
[SubstitutionOverride]: public abstract fun remove(key: R|ft<K3, K3?>|): R|V3?| from Substitution scope for [Use site scope of kotlin/collections/MutableMap] for type SomeMap<K3, V3> [id: 1]
[Library]: public abstract fun remove(key: R|K|): R|V?| from Use site scope of kotlin/collections/MutableMap [id: 2]
[SubstitutionOverride]: public open fun remove(key: R|ft<K3, K3?>|, value: R|ft<V3, V3?>|): R|kotlin/Boolean| from Java enhancement scope for /SomeMap [id: 0]
[Library]: public open fun remove(key: R|K|, value: R|V|): R|kotlin/Boolean| from Use site scope of kotlin/collections/MutableMap [id: 1]
MyMap:
[Enhancement]: public abstract fun containsKey(key: R|ft<kotlin/Any, kotlin/Any?>|): R|kotlin/Boolean| from Java enhancement scope for /MyMap [id: 0]
[SubstitutionOverride]: public abstract fun containsKey(key: R|ft<kotlin/Any, kotlin/Any?>|): R|kotlin/Boolean| from Substitution scope for [Java enhancement scope for /MyBaseMap] for type MyMap<K2, V2> [id: 1]
[Enhancement]: public abstract fun containsKey(key: R|ft<kotlin/Any, kotlin/Any?>|): R|kotlin/Boolean| from Java enhancement scope for /MyBaseMap [id: 2]
[Enhancement]: public abstract fun containsValue(key: R|ft<kotlin/Any, kotlin/Any?>|): R|kotlin/Boolean| from Java enhancement scope for /MyMap [id: 0]
[Enhancement]: public abstract operator fun get(key: R|ft<K2, K2?>|): R|ft<V2, V2?>| from Java enhancement scope for /MyMap [id: 0]
@@ -0,0 +1,23 @@
FILE: main.kt
public abstract class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
public open val x: R|kotlin/Int|
public get(): R|kotlin/Int| {
^ Int(1)
}
public open val y: R|kotlin/Int|
public get(): R|kotlin/Int| {
^ Int(2)
}
}
public final class DImpl : R|D| {
public constructor(): R|DImpl| {
super<R|D|>()
}
}
@@ -0,0 +1,28 @@
// SCOPE_DUMP: D:x;getX;y;getY
// FILE: B.java
public abstract class B extends A {
@Override
public int getX() { return 0; }
}
// FILE: C.java
public interface C {
int getX();
int getY();
}
// FILE: D.java
public abstract class D extends B implements C {}
// FILE: main.kt
abstract class A {
open val x: Int
get() = 1
open val y: Int
get() = 2
}
class DImpl : D()
@@ -0,0 +1,8 @@
D:
[Synthetic]: public open val x: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[Synthetic]: public open val x: R|kotlin/Int| from Java enhancement scope for /B [id: 1]
[Source]: public open val x: R|kotlin/Int| from Use site scope of /A [id: 2]
[Synthetic]: public open val y: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[Source]: public open val y: R|kotlin/Int| from Java enhancement scope for /B [id: 1]
[Source]: public open val y: R|kotlin/Int| from Use site scope of /A [id: 1]
@@ -0,0 +1,28 @@
// SCOPE_DUMP: Some:toByte;byteValue MyNumber:toByte;byteValue
// -SCOPE_DUMP: Some:toInt;intValue;toByte;byteValue;toLong;longValue
// FILE: MyBaseNumber.java
public interface MyBaseNumber {
byte byteValue(); // (1)
}
// FILE: MyNumber.java
public interface MyNumber extends MyBaseNumber {
@Override
byte byteValue(); // (2)
}
// FILE: Some.java
public abstract class Some extends Number implements MyNumber {
@Override
public abstract byte byteValue() // (3)
}
/*
* Some.toByte() (3', renamed) overrides Number.toByte & MyNumber.toByte(2', renamed)
* MyNumber.toByte(2', renamed) overrides ???
*/
fun test(some: Some) {
some.toByte()
}
@@ -0,0 +1,10 @@
Some:
[Enhancement]: public abstract operator fun toByte(): R|kotlin/Byte| from Java enhancement scope for /Some [id: 0]
[Library]: public abstract fun toByte(): R|kotlin/Byte| from Use site scope of kotlin/Number [id: 1]
[RenamedForOverride]: public abstract fun toByte(): R|kotlin/Byte| from Java enhancement scope for /MyNumber [id: 2]
[Enhancement]: public abstract fun byteValue(): R|kotlin/Byte| from Java enhancement scope for /MyBaseNumber [id: 3]
MyNumber:
[Enhancement]: public abstract fun byteValue(): R|kotlin/Byte| from Java enhancement scope for /MyNumber [id: 0]
[Enhancement]: public abstract fun byteValue(): R|kotlin/Byte| from Java enhancement scope for /MyBaseNumber [id: 1]
@@ -3482,6 +3482,100 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
}
}
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/scopes")
@TestDataPath("$PROJECT_ROOT")
public class Scopes {
@Test
public void testAllFilesPresentInScopes() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/scopes"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("explicitOverrideOfTwoMembers.kt")
public void testExplicitOverrideOfTwoMembers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/explicitOverrideOfTwoMembers.kt");
}
@Test
@TestMetadata("explicitOverrideOfTwoMembers_java.kt")
public void testExplicitOverrideOfTwoMembers_java() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/explicitOverrideOfTwoMembers_java.kt");
}
@Test
@TestMetadata("getterOverrideAndKotlinProperty.kt")
public void testGetterOverrideAndKotlinProperty() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/getterOverrideAndKotlinProperty.kt");
}
@Test
@TestMetadata("intersectionOverrideOfTwoMembers.kt")
public void testIntersectionOverrideOfTwoMembers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/intersectionOverrideOfTwoMembers.kt");
}
@Test
@TestMetadata("intersectionOverrideOfTwoMembers_java.kt")
public void testIntersectionOverrideOfTwoMembers_java() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/intersectionOverrideOfTwoMembers_java.kt");
}
@Test
@TestMetadata("javaFunctionAndKotlinPropertyFromDifferentSupertypes.kt")
public void testJavaFunctionAndKotlinPropertyFromDifferentSupertypes() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/javaFunctionAndKotlinPropertyFromDifferentSupertypes.kt");
}
@Test
@TestMetadata("kotlinAccessorsLikeFunctionsThrowJavaClass.kt")
public void testKotlinAccessorsLikeFunctionsThrowJavaClass() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/kotlinAccessorsLikeFunctionsThrowJavaClass.kt");
}
@Test
@TestMetadata("noIntersectionOverrideOfTwoMembers.kt")
public void testNoIntersectionOverrideOfTwoMembers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/noIntersectionOverrideOfTwoMembers.kt");
}
@Test
@TestMetadata("noIntersectionOverrideOfTwoMembers_java.kt")
public void testNoIntersectionOverrideOfTwoMembers_java() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/noIntersectionOverrideOfTwoMembers_java.kt");
}
@Test
@TestMetadata("publicJavaAndPrivateKotlinVar.kt")
public void testPublicJavaAndPrivateKotlinVar() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/publicJavaAndPrivateKotlinVar.kt");
}
@Test
@TestMetadata("specialFunctionInJava_1.kt")
public void testSpecialFunctionInJava_1() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_1.kt");
}
@Test
@TestMetadata("specialFunctionInJava_2.kt")
public void testSpecialFunctionInJava_2() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_2.kt");
}
@Test
@TestMetadata("specialFunctionInJava_3.kt")
public void testSpecialFunctionInJava_3() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_3.kt");
}
@Test
@TestMetadata("specialFunctionInJava_4.kt")
public void testSpecialFunctionInJava_4() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_4.kt");
}
}
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts")
@TestDataPath("$PROJECT_ROOT")
@@ -3482,6 +3482,100 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
}
}
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/scopes")
@TestDataPath("$PROJECT_ROOT")
public class Scopes {
@Test
public void testAllFilesPresentInScopes() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/scopes"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("explicitOverrideOfTwoMembers.kt")
public void testExplicitOverrideOfTwoMembers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/explicitOverrideOfTwoMembers.kt");
}
@Test
@TestMetadata("explicitOverrideOfTwoMembers_java.kt")
public void testExplicitOverrideOfTwoMembers_java() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/explicitOverrideOfTwoMembers_java.kt");
}
@Test
@TestMetadata("getterOverrideAndKotlinProperty.kt")
public void testGetterOverrideAndKotlinProperty() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/getterOverrideAndKotlinProperty.kt");
}
@Test
@TestMetadata("intersectionOverrideOfTwoMembers.kt")
public void testIntersectionOverrideOfTwoMembers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/intersectionOverrideOfTwoMembers.kt");
}
@Test
@TestMetadata("intersectionOverrideOfTwoMembers_java.kt")
public void testIntersectionOverrideOfTwoMembers_java() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/intersectionOverrideOfTwoMembers_java.kt");
}
@Test
@TestMetadata("javaFunctionAndKotlinPropertyFromDifferentSupertypes.kt")
public void testJavaFunctionAndKotlinPropertyFromDifferentSupertypes() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/javaFunctionAndKotlinPropertyFromDifferentSupertypes.kt");
}
@Test
@TestMetadata("kotlinAccessorsLikeFunctionsThrowJavaClass.kt")
public void testKotlinAccessorsLikeFunctionsThrowJavaClass() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/kotlinAccessorsLikeFunctionsThrowJavaClass.kt");
}
@Test
@TestMetadata("noIntersectionOverrideOfTwoMembers.kt")
public void testNoIntersectionOverrideOfTwoMembers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/noIntersectionOverrideOfTwoMembers.kt");
}
@Test
@TestMetadata("noIntersectionOverrideOfTwoMembers_java.kt")
public void testNoIntersectionOverrideOfTwoMembers_java() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/noIntersectionOverrideOfTwoMembers_java.kt");
}
@Test
@TestMetadata("publicJavaAndPrivateKotlinVar.kt")
public void testPublicJavaAndPrivateKotlinVar() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/publicJavaAndPrivateKotlinVar.kt");
}
@Test
@TestMetadata("specialFunctionInJava_1.kt")
public void testSpecialFunctionInJava_1() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_1.kt");
}
@Test
@TestMetadata("specialFunctionInJava_2.kt")
public void testSpecialFunctionInJava_2() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_2.kt");
}
@Test
@TestMetadata("specialFunctionInJava_3.kt")
public void testSpecialFunctionInJava_3() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_3.kt");
}
@Test
@TestMetadata("specialFunctionInJava_4.kt")
public void testSpecialFunctionInJava_4() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/scopes/specialFunctionInJava_4.kt");
}
}
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts")
@TestDataPath("$PROJECT_ROOT")
@@ -24,12 +24,10 @@ import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenMembers
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
import org.jetbrains.kotlin.fir.scopes.impl.multipleDelegatesWithTheSameSignature
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.scopes.MemberWithBaseScope
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenMembersWithBaseScope
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
import org.jetbrains.kotlin.util.ImplementationStatus
@@ -58,19 +56,25 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
fun collectSymbol(symbol: FirCallableSymbol<*>) {
val delegatedWrapperData = symbol.delegatedWrapperData
if (delegatedWrapperData != null) {
val directOverriddenMembers = classScope.getDirectOverriddenMembers(
symbol,
unwrapIntersectionAndSubstitutionOverride = true
val directOverriddenMembersWithBaseScope = classScope.getDirectOverriddenMembersWithBaseScope(
symbol
)
@Suppress("UNCHECKED_CAST")
val filteredOverriddenMembers = when (symbol) {
is FirNamedFunctionSymbol -> filterOutOverriddenFunctions(directOverriddenMembersWithBaseScope as List<MemberWithBaseScope<FirNamedFunctionSymbol>>)
is FirPropertySymbol -> filterOutOverriddenProperties(directOverriddenMembersWithBaseScope as List<MemberWithBaseScope<FirPropertySymbol>>)
else -> directOverriddenMembersWithBaseScope
}.map { it.member }
val delegatedTo = delegatedWrapperData.wrapped.unwrapFakeOverrides().symbol
if (symbol.multipleDelegatesWithTheSameSignature == true) {
manyImplementationsDelegationSymbols.add(symbol)
}
val firstFinal = directOverriddenMembers.firstOrNull { it.isFinal }
val firstOpen = directOverriddenMembers.firstOrNull { it.isOpen && delegatedTo != it.unwrapFakeOverrides() }
val firstFinal = filteredOverriddenMembers.firstOrNull { it.isFinal }
val firstOpen = filteredOverriddenMembers.firstOrNull { it.isOpen && delegatedTo != it.unwrapFakeOverrides() }
when {
firstFinal != null ->
@@ -333,7 +333,14 @@ object FirOverrideChecker : FirClassChecker() {
with(FirOptInUsageBaseChecker) {
val overriddenExperimentalities = mutableSetOf<Experimentality>()
val session = context.session
for (overriddenMemberSymbol in overriddenMemberSymbols) {
val overriddenSymbolsWithUnwrappedIntersectionOverrides = overriddenMemberSymbols.flatMap {
when (it) {
is FirIntersectionOverridePropertySymbol -> it.intersections
is FirIntersectionOverrideFunctionSymbol -> it.intersections
else -> listOf(it)
}
}
for (overriddenMemberSymbol in overriddenSymbolsWithUnwrappedIntersectionOverrides) {
overriddenMemberSymbol.loadExperimentalitiesFromAnnotationTo(session, overriddenExperimentalities)
}
reportNotAcceptedOverrideExperimentalities(
@@ -97,18 +97,10 @@ object JavaScopeProvider : FirScopeProvider() {
}
JavaClassUseSiteMemberScope(
regularClass, useSiteSession,
FirTypeIntersectionScope.prepareIntersectionScope(
useSiteSession,
JavaOverrideChecker(
useSiteSession,
regularClass.javaTypeParameterStack,
baseScope = null,
considerReturnTypeKinds = false,
),
superTypeScopes,
regularClass.defaultType(),
), declaredScope
regularClass,
useSiteSession,
superTypeScopes,
declaredScope
)
}
}
@@ -7,13 +7,15 @@ package org.jetbrains.kotlin.fir.java.scopes
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.initialSignatureAttr
import org.jetbrains.kotlin.fir.java.enhancement.FirSignatureEnhancement
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenMembers
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.Name
@@ -22,24 +24,18 @@ class JavaClassMembersEnhancementScope(
private val owner: FirRegularClassSymbol,
private val useSiteMemberScope: JavaClassUseSiteMemberScope,
) : FirTypeScope() {
private val overriddenFunctions = mutableMapOf<FirNamedFunctionSymbol, Collection<FirNamedFunctionSymbol>>()
private val overriddenProperties = mutableMapOf<FirPropertySymbol, Collection<FirPropertySymbol>>()
private val enhancedToOriginalFunctions = mutableMapOf<FirNamedFunctionSymbol, FirNamedFunctionSymbol>()
private val enhancedToOriginalProperties = mutableMapOf<FirPropertySymbol, FirPropertySymbol>()
private val overrideBindCache = mutableMapOf<Name, Map<FirCallableSymbol<*>?, List<FirCallableDeclaration>>>()
private val signatureEnhancement = FirSignatureEnhancement(owner.fir, session) {
overriddenMembersForEnhancement(name)
overriddenMembers()
}
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
useSiteMemberScope.processPropertiesByName(name) process@{ original ->
val enhancedPropertySymbol = signatureEnhancement.enhancedProperty(original, name)
val originalFir = original.fir
if (originalFir is FirProperty && enhancedPropertySymbol is FirPropertySymbol) {
val enhancedProperty = enhancedPropertySymbol.fir
overriddenProperties[enhancedPropertySymbol] =
originalFir
.overriddenMembers(enhancedProperty.name)
.mapNotNull { it.symbol as? FirPropertySymbol }
if (original is FirPropertySymbol && enhancedPropertySymbol is FirPropertySymbol) {
enhancedToOriginalProperties[enhancedPropertySymbol] = original
}
processor(enhancedPropertySymbol)
@@ -55,9 +51,7 @@ class JavaClassMembersEnhancementScope(
val enhancedFunctionSymbol = enhancedFunction?.symbol ?: symbol
if (enhancedFunctionSymbol is FirNamedFunctionSymbol) {
overriddenFunctions[enhancedFunctionSymbol] = original.fir
.overriddenMembers(enhancedFunctionSymbol.fir.name)
.mapNotNull { it.symbol as? FirNamedFunctionSymbol }
enhancedToOriginalFunctions[enhancedFunctionSymbol] = original
processor(enhancedFunctionSymbol)
}
}
@@ -65,33 +59,12 @@ class JavaClassMembersEnhancementScope(
return super.processFunctionsByName(name, processor)
}
private fun FirCallableDeclaration.overriddenMembersForEnhancement(name: Name): List<FirCallableDeclaration> {
val directlyOverriddensFromScopeFir = overriddenMembers(name)
val superTypesScope = useSiteMemberScope.superTypesScope as? FirTypeIntersectionScope ?: return directlyOverriddensFromScopeFir
val directlyOverriddensFromScope = directlyOverriddensFromScopeFir.map { it.symbol }
val result = mutableSetOf<FirCallableSymbol<*>>()
for (intersectedOverriddenSymbol in directlyOverriddensFromScope) {
val newOverriddens = superTypesScope.getDirectOverriddenSymbols(intersectedOverriddenSymbol).map { it.member }
if (newOverriddens.isNotEmpty()) {
result += newOverriddens
} else {
result += intersectedOverriddenSymbol
}
}
return result.map { it.fir }
}
private fun FirCallableDeclaration.overriddenMembers(name: Name): List<FirCallableDeclaration> {
val backMap = overrideBindCache.getOrPut(name) {
val result = mutableMapOf<FirCallableSymbol<*>?, MutableList<FirCallableDeclaration>>()
for ((key, value) in useSiteMemberScope.overrideByBase) {
val resultItem = result.getOrPut(value) { mutableListOf() }
resultItem.add(key.fir)
}
result
}
return backMap[this.symbol] ?: emptyList()
private fun FirCallableDeclaration.overriddenMembers(): List<FirCallableDeclaration> {
return when (val symbol = this.symbol) {
is FirNamedFunctionSymbol -> useSiteMemberScope.getDirectOverriddenMembers(symbol)
is FirPropertySymbol -> useSiteMemberScope.getDirectOverriddenProperties(symbol)
else -> emptyList()
}.map { it.fir }
}
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
@@ -110,18 +83,32 @@ class JavaClassMembersEnhancementScope(
processor: (FirNamedFunctionSymbol, FirTypeScope) -> ProcessorAction
): ProcessorAction =
doProcessDirectOverriddenCallables(
functionSymbol, processor, overriddenFunctions, useSiteMemberScope,
FirTypeScope::processDirectOverriddenFunctionsWithBaseScope
functionSymbol, processor, enhancedToOriginalFunctions, FirTypeScope::processDirectOverriddenFunctionsWithBaseScope
)
override fun processDirectOverriddenPropertiesWithBaseScope(
propertySymbol: FirPropertySymbol,
processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction
): ProcessorAction = doProcessDirectOverriddenCallables(
propertySymbol, processor, overriddenProperties, useSiteMemberScope,
FirTypeScope::processDirectOverriddenPropertiesWithBaseScope
propertySymbol, processor, enhancedToOriginalProperties, FirTypeScope::processDirectOverriddenPropertiesWithBaseScope
)
private fun <S : FirCallableSymbol<*>> doProcessDirectOverriddenCallables(
callableSymbol: S,
processor: (S, FirTypeScope) -> ProcessorAction,
enhancedToOriginalMap: Map<S, S>,
processDirectOverriddenCallables: FirTypeScope.(S, (S, FirTypeScope) -> ProcessorAction) -> ProcessorAction
): ProcessorAction {
val unwrappedSymbol = if (callableSymbol.origin == FirDeclarationOrigin.RenamedForOverride) {
@Suppress("UNCHECKED_CAST")
callableSymbol.fir.initialSignatureAttr?.symbol as? S ?: callableSymbol
} else {
callableSymbol
}
val original = enhancedToOriginalMap[unwrappedSymbol] ?: return ProcessorAction.NONE
return useSiteMemberScope.processDirectOverriddenCallables(original, processor)
}
override fun getCallableNames(): Set<Name> {
return useSiteMemberScope.getCallableNames()
}
@@ -23,7 +23,7 @@ class JavaClassStaticUseSiteScope internal constructor(
) : FirContainingNamesAwareScope() {
private val functions = hashMapOf<Name, Collection<FirNamedFunctionSymbol>>()
private val properties = hashMapOf<Name, Collection<FirVariableSymbol<*>>>()
private val overrideChecker = JavaOverrideChecker(session, javaTypeParameterStack, baseScope = null, considerReturnTypeKinds = false)
private val overrideChecker = JavaOverrideChecker(session, javaTypeParameterStack, baseScopes = null, considerReturnTypeKinds = false)
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
functions.getOrPut(name) {
@@ -5,65 +5,64 @@
package org.jetbrains.kotlin.fir.java.scopes
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunctionCopy
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
import org.jetbrains.kotlin.fir.java.declarations.buildJavaMethodCopy
import org.jetbrains.kotlin.fir.java.declarations.buildJavaValueParameterCopy
import org.jetbrains.kotlin.fir.java.symbols.FirJavaOverriddenSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.AbstractFirUseSiteMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScopeContext.ResultOfIntersection
import org.jetbrains.kotlin.fir.scopes.impl.MembersByScope
import org.jetbrains.kotlin.fir.scopes.impl.similarFunctionsOrBothProperties
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmSignature
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.symbols.impl.isStatic
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.load.java.*
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_COLLECTION_PARAMETER_NAMES
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.sameAsBuiltinMethodWithErasedValueParameters
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.sameAsRenamedInJvmBuiltin
import org.jetbrains.kotlin.load.java.getPropertyNamesCandidatesByAccessorName
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.runIf
class JavaClassUseSiteMemberScope(
klass: FirJavaClass,
session: FirSession,
superTypesScope: FirTypeScope,
superTypeScopes: List<FirTypeScope>,
declaredMemberScope: FirContainingNamesAwareScope
) : AbstractFirUseSiteMemberScope(
klass.classId,
session,
JavaOverrideChecker(session, klass.javaTypeParameterStack, superTypesScope, considerReturnTypeKinds = true),
superTypesScope,
JavaOverrideChecker(session, klass.javaTypeParameterStack, superTypeScopes, considerReturnTypeKinds = true),
superTypeScopes,
klass.defaultType(),
declaredMemberScope
) {
private val typeParameterStack = klass.javaTypeParameterStack
private val specialFunctions = hashMapOf<Name, Collection<FirNamedFunctionSymbol>>()
private val syntheticPropertyByNameMap = hashMapOf<Name, FirSyntheticPropertySymbol>()
private val canUseSpecialGetters: Boolean by lazy { !klass.hasKotlinSuper(session) }
private val callableNamesCached by lazy(LazyThreadSafetyMode.PUBLICATION) {
declaredMemberScope.getCallableNames() + superTypesScope.getCallableNames()
}
override fun getCallableNames(): Set<Name> = callableNamesCached
override fun getClassifierNames(): Set<Name> {
return declaredMemberScope.getClassifierNames() + superTypesScope.getClassifierNames()
}
private fun generateSyntheticPropertySymbol(
getterSymbol: FirNamedFunctionSymbol,
setterSymbol: FirNamedFunctionSymbol?,
@@ -102,7 +101,7 @@ class JavaClassUseSiteMemberScope(
return minOf(a, b)
}
override fun doProcessProperties(name: Name): Collection<FirVariableSymbol<*>> {
override fun collectProperties(name: Name): Collection<FirVariableSymbol<*>> {
val fields = mutableSetOf<FirCallableSymbol<*>>()
val fieldNames = mutableSetOf<Name>()
val result = mutableSetOf<FirVariableSymbol<*>>()
@@ -115,36 +114,49 @@ class JavaClassUseSiteMemberScope(
result += variableSymbol
}
val fromSupertypes = superTypesScope.getProperties(name)
/*
* From supertype we can get at most two results:
* 1. Set of properties with same name
* 2. Field from some java superclass (only one, if class have more than one superclass then we can choose
* just one field because this is incorrect code anyway)
*/
val fromSupertypes = supertypeScopeContext.collectCallables(name, FirScope::processPropertiesByName)
for (propertyFromSupertype in fromSupertypes) {
if (propertyFromSupertype is FirFieldSymbol) {
if (propertyFromSupertype.fir.name !in fieldNames) {
result += propertyFromSupertype
}
continue
}
if (propertyFromSupertype !is FirPropertySymbol) continue
val overrideInClass =
propertyFromSupertype.createOverridePropertyIfExists(declaredMemberScope, takeModalityFromGetter = true)
?: propertyFromSupertype.createOverridePropertyIfExists(superTypesScope, takeModalityFromGetter = false)
when {
overrideInClass != null -> {
directOverriddenProperties.getOrPut(overrideInClass) { mutableListOf() }.add(propertyFromSupertype)
overrideByBase[propertyFromSupertype] = overrideInClass
result += overrideInClass
}
else -> result += propertyFromSupertype
val (fieldsFromSupertype, propertiesFromSupertypes) = fromSupertypes.partition {
it is ResultOfIntersection.SingleMember && it.chosenSymbol is FirFieldSymbol
}
assert(fieldsFromSupertype.size in 0..1)
assert(propertiesFromSupertypes.size in 0..1)
fieldsFromSupertype.firstOrNull()?.chosenSymbol?.let { fieldSymbol ->
require(fieldSymbol is FirFieldSymbol)
if (fieldSymbol.name !in fieldNames) {
result.addIfNotNull(fieldSymbol)
}
}
@Suppress("UNCHECKED_CAST")
val overriddenProperty = propertiesFromSupertypes.firstOrNull() as ResultOfIntersection<FirPropertySymbol>? ?: return result
val overrideInClass = overriddenProperty.overriddenMembers.firstNotNullOfOrNull { (symbol, _) ->
symbol.createOverridePropertyIfExists(declaredMemberScope, takeModalityFromGetter = true)
?: superTypeScopes.firstNotNullOfOrNull { scope ->
symbol.createOverridePropertyIfExists(scope, takeModalityFromGetter = false)
}
}
val chosenSymbol = overrideInClass ?: overriddenProperty.chosenSymbol
directOverriddenProperties[chosenSymbol] = listOf(overriddenProperty)
overriddenProperty.overriddenMembers.forEach { overrideByBase[it.member] = overrideInClass }
result += chosenSymbol
return result
}
private fun FirVariableSymbol<*>.createOverridePropertyIfExists(
private fun FirPropertySymbol.createOverridePropertyIfExists(
scope: FirScope,
takeModalityFromGetter: Boolean
): FirPropertySymbol? {
if (this !is FirPropertySymbol) return null
val getterSymbol = this.findGetterOverride(scope) ?: return null
val setterSymbol =
if (this.fir.isVar)
@@ -204,8 +216,7 @@ class JavaClassUseSiteMemberScope(
private fun FirPropertySymbol.getBuiltinSpecialPropertyGetterName(): Name? {
var result: Name? = null
superTypesScope.processOverriddenPropertiesAndSelf(this) { overridden ->
superTypeScopes.processOverriddenPropertiesAndSelf(this) { overridden ->
val fqName = overridden.fir.containingClass()?.classId?.asSingleFqName()?.child(overridden.fir.name)
BuiltinSpecialProperties.PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP[fqName]?.let { name ->
@@ -219,158 +230,375 @@ class JavaClassUseSiteMemberScope(
return result
}
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
// ---------------------------------------------------------------------------------------------------------
override fun FirNamedFunctionSymbol.isVisibleInCurrentClass(): Boolean {
val potentialPropertyNames = getPropertyNamesCandidatesByAccessorName(name)
val renamedSpecialBuiltInName = SpecialGenericSignatures.getBuiltinFunctionNamesByJvmName(name)
if (potentialPropertyNames.isEmpty() && renamedSpecialBuiltInName == null &&
!name.sameAsBuiltinMethodWithErasedValueParameters && !name.sameAsRenamedInJvmBuiltin
) {
return super.processFunctionsByName(name, processor)
val hasCorrespondingProperty = potentialPropertyNames.any { propertyName ->
getProperties(propertyName).any l@{ propertySymbol ->
// TODO: add magic overrides from LazyJavaClassMemberScope.isVisibleAsFunctionInCurrentClass
if (propertySymbol !is FirPropertySymbol) return@l false
propertySymbol.isOverriddenInClassBy(this)
}
}
if (hasCorrespondingProperty) return false
val overriddenProperties = potentialPropertyNames.flatMap(this::getProperties).filterIsInstance<FirPropertySymbol>()
return !doesOverrideRenamedBuiltins() &&
!shouldBeVisibleAsOverrideOfBuiltInWithErasedValueParameters() &&
!doesOverrideSuspendFunction()
}
specialFunctions.getOrPut(name) {
doProcessSpecialFunctions(name, overriddenProperties, renamedSpecialBuiltInName)
}.forEach {
processor(it)
private fun FirNamedFunctionSymbol.doesOverrideRenamedBuiltins(): Boolean {
// e.g. 'removeAt' or 'toInt'
val builtinName = SpecialGenericSignatures.getBuiltinFunctionNamesByJvmName(name) ?: return false
val builtinSpecialFromSuperTypes = supertypeScopeContext.collectMembersByScope(builtinName, FirScope::processFunctionsByName)
.flatMap { (scope, symbols) ->
symbols.filter { it.doesOverrideBuiltinWithDifferentJvmName(scope, session) }
}
if (builtinSpecialFromSuperTypes.isEmpty()) return false
return builtinSpecialFromSuperTypes.any {
// Here `this` and `it` have different names but it's ok because override checker does not consider
// names of declarations at all
overrideChecker.isOverriddenFunction(this.fir, it.fir)
}
}
private fun doProcessSpecialFunctions(
name: Name,
overriddenProperties: List<FirPropertySymbol>,
renamedSpecialBuiltInName: Name?
): List<FirNamedFunctionSymbol> {
/**
* Checks if function is a valid override of JDK analogue of built-in method with erased value parameters (e.g. Map.containsKey(k: K))
*
* Examples:
* - boolean containsKey(Object key) -> true
* - boolean containsKey(K key) -> false // Wrong JDK method override, while it's a valid Kotlin built-in override
*/
private fun FirNamedFunctionSymbol.shouldBeVisibleAsOverrideOfBuiltInWithErasedValueParameters(): Boolean {
if (!name.sameAsBuiltinMethodWithErasedValueParameters) return false
val candidatesToOverride = supertypeScopeContext.collectMembersByScope(name, FirScope::processFunctionsByName)
.flatMap { (scope, symbols) ->
symbols.mapNotNull {
BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(it, scope)
}
}
val jvmDescriptor = fir.computeJvmDescriptor()
return candidatesToOverride.any { candidate ->
candidate.fir.computeJvmDescriptor() == jvmDescriptor && this.hasErasedParameters()
}
}
private fun FirNamedFunctionSymbol.doesOverrideSuspendFunction(): Boolean {
val suspendView = createSuspendView() ?: return false
return superTypeScopes.any { scope ->
scope.getFunctions(name).any { it.isSuspend && overrideChecker.isOverriddenFunction(suspendView, it.fir) }
}
}
private fun FirNamedFunctionSymbol.createSuspendView(): FirSimpleFunction? {
val continuationParameter = fir.valueParameters.lastOrNull() ?: return null
val continuationParameterType = continuationParameter
.returnTypeRef
.coneTypeSafe<ConeKotlinType>()
?.lowerBoundIfFlexible() as? ConeClassLikeType
?: return null
if (continuationParameterType.lookupTag.classId.asSingleFqName() != StandardNames.CONTINUATION_INTERFACE_FQ_NAME) return null
return buildSimpleFunctionCopy(fir) {
valueParameters.clear()
valueParameters.addAll(fir.valueParameters.dropLast(1))
returnTypeRef = buildResolvedTypeRef {
type = continuationParameterType.typeArguments[0].type ?: return null
}
(status as FirDeclarationStatusImpl).isSuspend = true
symbol = FirNamedFunctionSymbol(callableId)
}
}
// ---------------------------------------------------------------------------------------------------------
override fun collectFunctions(name: Name): Collection<FirNamedFunctionSymbol> {
val result = mutableListOf<FirNamedFunctionSymbol>()
collectDeclaredFunctions(name, result)
val explicitlyDeclaredFunctions = result.toSet()
declaredMemberScope.processFunctionsByName(name) { functionSymbol ->
if (functionSymbol.isStatic) return@processFunctionsByName
if (overriddenProperties.none { it.isOverriddenInClassBy(functionSymbol) } &&
!functionSymbol.doesOverrideRenamedBuiltins(renamedSpecialBuiltInName) &&
!functionSymbol.shouldBeVisibleAsOverrideOfBuiltInWithErasedValueParameters()
) {
result += functionSymbol
val functionsWithScopeFromSupertypes = supertypeScopeContext.collectMembersByScope(name, FirScope::processFunctionsByName)
if (
!name.sameAsRenamedInJvmBuiltin &&
!name.sameAsBuiltinMethodWithErasedValueParameters &&
functionsWithScopeFromSupertypes.all { it.second.none { functionSymbol -> functionSymbol.isSuspend } }
) {
// Simple fast path in case of name is not suspicious (i.e. name is not one of builtins that have different signature in Java)
super.collectFunctionsFromSupertypes(name, result, explicitlyDeclaredFunctions)
return result
}
processSpecialFunctions(name, explicitlyDeclaredFunctions, functionsWithScopeFromSupertypes, result)
return result.toSet()
}
private fun processSpecialFunctions(
naturalName: Name,
explicitlyDeclaredFunctionsWithNaturalName: Collection<FirNamedFunctionSymbol>,
functionsFromSupertypesWithNaturalName: MembersByScope<FirNamedFunctionSymbol>, // candidates for override
destination: MutableCollection<FirNamedFunctionSymbol>
) {
val resultsOfIntersectionToSaveInCache = mutableListOf<ResultOfIntersection<FirNamedFunctionSymbol>>()
val list = supertypeScopeContext.collectCallablesImpl(functionsFromSupertypesWithNaturalName)
for (resultOfIntersectionWithNaturalName in list) {
val someSymbolWithNaturalNameFromSuperType = resultOfIntersectionWithNaturalName.extractSomeSymbolFromSuperType()
val explicitlyDeclaredFunctionWithNaturalName = explicitlyDeclaredFunctionsWithNaturalName.firstOrNull {
overrideChecker.isOverriddenFunction(it, someSymbolWithNaturalNameFromSuperType)
}
val jvmName = resultOfIntersectionWithNaturalName.overriddenMembers.firstNotNullOfOrNull {
it.member.getJvmMethodNameIfSpecial(it.baseScope, session)
}
if (jvmName != null) {
processOverridesForFunctionsWithDifferentJvmName(
jvmName,
someSymbolWithNaturalNameFromSuperType,
explicitlyDeclaredFunctionWithNaturalName,
naturalName,
resultOfIntersectionWithNaturalName,
destination,
resultsOfIntersectionToSaveInCache
)
continue
}
if (processOverridesForFunctionsWithErasedValueParameter(
resultOfIntersectionWithNaturalName.overriddenMembers,
naturalName,
explicitlyDeclaredFunctionsWithNaturalName,
destination,
resultOfIntersectionWithNaturalName,
explicitlyDeclaredFunctionWithNaturalName
)
) continue
// regular rules
when (explicitlyDeclaredFunctionWithNaturalName) {
null -> {
destination += resultOfIntersectionWithNaturalName.chosenSymbol
resultsOfIntersectionToSaveInCache += resultOfIntersectionWithNaturalName
}
else -> {
destination += explicitlyDeclaredFunctionWithNaturalName
directOverriddenFunctions[explicitlyDeclaredFunctionWithNaturalName] = listOf(resultOfIntersectionWithNaturalName)
for (overriddenMember in resultOfIntersectionWithNaturalName.overriddenMembers) {
overrideByBase[overriddenMember.member] = explicitlyDeclaredFunctionWithNaturalName
}
}
}
}
functionsFromSupertypes[naturalName] = resultsOfIntersectionToSaveInCache
}
private fun processOverridesForFunctionsWithErasedValueParameter(
overriddenMembers: List<MemberWithBaseScope<FirNamedFunctionSymbol>>,
naturalName: Name,
explicitlyDeclaredFunctionsWithNaturalName: Collection<FirNamedFunctionSymbol>,
destination: MutableCollection<FirNamedFunctionSymbol>,
resultOfIntersectionWithNaturalName: ResultOfIntersection<FirNamedFunctionSymbol>,
explicitlyDeclaredFunctionWithNaturalName: FirNamedFunctionSymbol?
): Boolean {
val overriddenMemberWithErasedValueParameters = overriddenMembers.firstOrNull {
BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(it) != null
}?.member ?: return false
val unwrappedSubstitutionOverride = overriddenMemberWithErasedValueParameters.fir.originalForSubstitutionOverride
?: overriddenMemberWithErasedValueParameters.fir
val functionFromSupertypeWithErasedParameterType = unwrappedSubstitutionOverride
.initialSignatureAttr
?.symbol as? FirNamedFunctionSymbol
?: unwrappedSubstitutionOverride.symbol
val originalDeclaredFunction = declaredMemberScope.getFunctions(naturalName).firstOrNull {
it.hasSameJvmDescriptorButDoesNotOverride(functionFromSupertypeWithErasedParameterType)
} ?: return false
val renamedDeclaredFunction = buildJavaMethodCopy(originalDeclaredFunction.fir as FirJavaMethod) {
name = naturalName
symbol = FirNamedFunctionSymbol(originalDeclaredFunction.callableId)
this.valueParameters.clear()
originalDeclaredFunction.fir.valueParameters.zip(overriddenMemberWithErasedValueParameters.fir.valueParameters)
.mapTo(this.valueParameters) { (overrideParameter, parameterFromSupertype) ->
buildJavaValueParameterCopy(overrideParameter) {
this@buildJavaValueParameterCopy.returnTypeRef = parameterFromSupertype.returnTypeRef
}
}
}.apply {
initialSignatureAttr = originalDeclaredFunction.fir
}.symbol
val hasAccidentalOverrideWithDeclaredFunction = explicitlyDeclaredFunctionsWithNaturalName.any {
overrideChecker.isOverriddenFunction(
renamedDeclaredFunction,
it
)
}
if (!hasAccidentalOverrideWithDeclaredFunction) {
destination += renamedDeclaredFunction
directOverriddenFunctions[renamedDeclaredFunction] = listOf(resultOfIntersectionWithNaturalName)
for (overriddenMember in overriddenMembers) {
overrideByBase[overriddenMember.member] = renamedDeclaredFunction
}
if (explicitlyDeclaredFunctionWithNaturalName != null) {
destination += explicitlyDeclaredFunctionWithNaturalName
}
return true
}
return false
}
private fun FirNamedFunctionSymbol.hasSameJvmDescriptorButDoesNotOverride(
builtinWithErasedParameters: FirNamedFunctionSymbol
): Boolean {
return fir.computeJvmDescriptor(includeReturnType = false) == builtinWithErasedParameters.fir.computeJvmDescriptor(includeReturnType = false)
&& overrideChecker.isOverriddenFunction(this, builtinWithErasedParameters)
}
private fun processOverridesForFunctionsWithDifferentJvmName(
jvmName: Name,
someSymbolWithNaturalNameFromSuperType: FirNamedFunctionSymbol,
explicitlyDeclaredFunctionWithNaturalName: FirNamedFunctionSymbol?,
naturalName: Name,
resultOfIntersectionWithNaturalName: ResultOfIntersection<FirNamedFunctionSymbol>,
destination: MutableCollection<FirNamedFunctionSymbol>,
resultsOfIntersectionToSaveInCache: MutableList<ResultOfIntersection<FirNamedFunctionSymbol>>
) {
/*
* name: toByte
*
* 1. find declared byteValue (a)
* 2. find toByte in supertypes (b)
* 3. find byteValue in supertypes (c)
* 4. create triples of (a), (b), (c) which are same overrides
* 5. for each triple:
* 6. if (a) is empty:
* 6.1. create renamed copies of (c): (c')
* 6.2. create result of intersection for (b) and (c'), save direct overrides
* 7. if (a) is not empty:
* 7.1 create renamed copies of (c): (c')
* 7.2 save direct overrides
*/
val overriddenMembers = resultOfIntersectionWithNaturalName.overriddenMembers
val explicitlyDeclaredFunctionWithBuiltinJvmName = declaredMemberScope.getFunctions(jvmName).firstOrNull {
overrideChecker.isOverriddenFunction(it, someSymbolWithNaturalNameFromSuperType)
}
val functionsFromSupertypesWithBuiltinJvmName = supertypeScopeContext.collectFunctions(jvmName).firstOrNull {
overrideChecker.similarFunctionsOrBothProperties(
it.extractSomeSymbolFromSuperType(),
someSymbolWithNaturalNameFromSuperType
)
}
val declaredFunction = explicitlyDeclaredFunctionWithNaturalName ?: explicitlyDeclaredFunctionWithBuiltinJvmName?.let {
val original = it.fir as FirJavaMethod
buildJavaMethodCopy(original) {
name = naturalName
symbol = FirNamedFunctionSymbol(it.callableId.copy(callableName = naturalName))
status = original.status.copy(isOperator = true)
}.apply {
initialSignatureAttr = original
}.symbol
}
val renamedFunctionsFromSupertypes = functionsFromSupertypesWithBuiltinJvmName?.overriddenMembers?.map {
val renamedFunction = buildSimpleFunctionCopy(it.member.fir) {
name = naturalName
symbol = FirNamedFunctionSymbol(it.member.callableId.copy(callableName = naturalName))
origin = FirDeclarationOrigin.RenamedForOverride
}.apply {
initialSignatureAttr = it.member.fir
}
it.baseScope to listOf(renamedFunction.symbol)
}
val resultsOfIntersection = when (renamedFunctionsFromSupertypes) {
null -> listOf(resultOfIntersectionWithNaturalName)
else -> {
val membersByScope = buildList {
overriddenMembers.mapTo(this) { it.baseScope to listOf(it.member) }
addAll(renamedFunctionsFromSupertypes)
}
supertypeScopeContext.collectCallablesImpl(membersByScope)
}
}
addOverriddenSpecialMethods(name, result, declaredMemberScope)
val overrideCandidates = result.toMutableSet()
superTypesScope.processFunctionsByName(name) { functionSymbol ->
val overriddenBy = functionSymbol.getOverridden(overrideCandidates)
if (overriddenBy == null && overriddenProperties.none { it.isOverriddenInClassBy(functionSymbol) }) {
result += functionSymbol
if (declaredFunction != null) {
destination += declaredFunction
directOverriddenFunctions[declaredFunction] = resultsOfIntersection
for (resultOfIntersection in resultsOfIntersection) {
for (overriddenMember in resultOfIntersection.overriddenMembers) {
overrideByBase[overriddenMember.member] = declaredFunction
}
}
} else {
for (resultOfIntersection in resultsOfIntersection) {
destination += resultOfIntersection.chosenSymbol
}
resultsOfIntersectionToSaveInCache += resultsOfIntersection
}
return result
}
private fun FirPropertySymbol.isOverriddenInClassBy(functionSymbol: FirNamedFunctionSymbol): Boolean {
val fir = fir as? FirSyntheticProperty ?: return false
if (fir.getter.delegate.symbol == functionSymbol || fir.setter?.delegate?.symbol == functionSymbol) return true
val accessorDescriptors = when (val fir = fir) {
is FirSyntheticProperty -> {
if (fir.getter.delegate.symbol == functionSymbol || fir.setter?.delegate?.symbol == functionSymbol) return true
val getterDescriptor = fir.getter.delegate.computeJvmDescriptor(includeReturnType = false)
val setterDescriptor = fir.setter?.delegate?.computeJvmDescriptor(includeReturnType = false)
listOf(getterDescriptor to setterDescriptor)
}
else -> {
val getterNames =
listOfNotNull(getJvmMethodNameIfSpecial(this@JavaClassUseSiteMemberScope, session))
.takeIf { it.isNotEmpty() }
?: possibleGetMethodNames(fir.name)
getterNames.map { getterName ->
val getterDescriptor = fir.computeJvmDescriptorForGetter(
customName = getterName.identifier,
includeReturnType = false
)
val setterDescriptor = runIf(isVar) {
fir.computeJvmDescriptorForSetter(
customName = setMethodName(getterName).identifier,
includeReturnType = false
)
}
getterDescriptor to setterDescriptor
}
}
}
val currentJvmDescriptor = functionSymbol.fir.computeJvmDescriptor(includeReturnType = false)
val getterJvmDescriptor = fir.getter.delegate.computeJvmDescriptor(includeReturnType = false)
val setterJvmDescriptor = fir.setter?.delegate?.computeJvmDescriptor(includeReturnType = false)
return currentJvmDescriptor == getterJvmDescriptor || currentJvmDescriptor == setterJvmDescriptor
}
private fun addOverriddenSpecialMethods(
name: Name,
result: MutableList<FirNamedFunctionSymbol>,
scope: FirScope,
) {
superTypesScope.processFunctionsByName(name) { fromSupertype ->
obtainOverrideForBuiltinWithDifferentJvmName(fromSupertype, scope, name)?.let {
directOverriddenFunctions[it] = listOf(fromSupertype)
overrideByBase[fromSupertype] = it
result += it
}
obtainOverrideForBuiltInWithErasedValueParametersInJava(fromSupertype, scope)?.let {
directOverriddenFunctions[it] = listOf(fromSupertype)
overrideByBase[fromSupertype] = it
result += it
}
}
}
private fun obtainOverrideForBuiltinWithDifferentJvmName(
symbol: FirNamedFunctionSymbol,
scope: FirScope,
name: Name,
): FirNamedFunctionSymbol? {
val overriddenBuiltin = symbol.getOverriddenBuiltinWithDifferentJvmName() ?: return null
//if (unrelated) method with special name is already defined, we don't add renamed method at all
//otherwise we get methods ambiguity
val alreadyDefined = declaredMemberScope.getFunctions(name).any { declaredSymbol ->
overrideChecker.isOverriddenFunction(declaredSymbol.fir, symbol.fir)
}
if (alreadyDefined) return null
val nameInJava =
SpecialGenericSignatures.SIGNATURE_TO_JVM_REPRESENTATION_NAME[overriddenBuiltin.fir.computeJvmSignature() ?: return null]
?: return null
for (candidateSymbol in scope.getFunctions(nameInJava)) {
val candidateFir = candidateSymbol.fir
val renamedCopy = buildJavaMethodCopy(candidateFir) {
this.name = name
this.symbol = FirNamedFunctionSymbol(CallableId(candidateFir.symbol.callableId.classId!!, name))
this.status = candidateFir.status.copy(isOperator = symbol.isOperator)
}.apply {
initialSignatureAttr = candidateFir
}
if (overrideChecker.isOverriddenFunction(renamedCopy, overriddenBuiltin.fir)) {
return renamedCopy.symbol
val getterDescriptorMatches = accessorDescriptors.any { (getterJvmDescriptor, _) ->
val gettersAreSame = currentJvmDescriptor == getterJvmDescriptor && run {
val propertyType = this.fir.returnTypeRef.probablyJavaTypeRefToConeType()
val functionType = functionSymbol.fir.returnTypeRef.probablyJavaTypeRefToConeType()
functionType.isSubtypeOf(propertyType, session)
}
gettersAreSame
}
return null
if (getterDescriptorMatches && this.isVal) return true
val setterDescriptorMatches = accessorDescriptors.any { (_, setterJvmDescriptor) ->
currentJvmDescriptor == setterJvmDescriptor
}
if (!setterDescriptorMatches) return false
val (getterOverride, setterOverride) = when (getterDescriptorMatches) {
true -> functionSymbol to findSetterOverride(this@JavaClassUseSiteMemberScope)
false -> findGetterOverride(this@JavaClassUseSiteMemberScope) to functionSymbol
}
return getterOverride?.modality == setterOverride?.modality
}
private fun obtainOverrideForBuiltInWithErasedValueParametersInJava(
symbol: FirNamedFunctionSymbol,
scope: FirScope,
): FirNamedFunctionSymbol? {
val overriddenBuiltin =
symbol.getOverriddenBuiltinFunctionWithErasedValueParametersInJava()
?: return null
return createOverrideForBuiltinFunctionWithErasedParameterIfNeeded(symbol, overriddenBuiltin, scope)
}
private fun createOverrideForBuiltinFunctionWithErasedParameterIfNeeded(
fromSupertype: FirNamedFunctionSymbol,
overriddenBuiltin: FirNamedFunctionSymbol,
scope: FirScope,
): FirNamedFunctionSymbol? {
return scope.getFunctions(overriddenBuiltin.fir.name).firstOrNull { candidateOverride ->
candidateOverride.fir.computeJvmDescriptor() == overriddenBuiltin.fir.computeJvmDescriptor() &&
candidateOverride.hasErasedParameters()
}?.let { override ->
buildJavaMethodCopy(override.fir) {
this.valueParameters.clear()
override.fir.valueParameters.zip(fromSupertype.fir.valueParameters)
.mapTo(this.valueParameters) { (overrideParameter, parameterFromSupertype) ->
buildJavaValueParameterCopy(overrideParameter) {
this@buildJavaValueParameterCopy.returnTypeRef = parameterFromSupertype.returnTypeRef
}
}
symbol = FirNamedFunctionSymbol(override.callableId)
}.apply {
initialSignatureAttr = override.fir
}.symbol
private fun FirTypeRef.probablyJavaTypeRefToConeType(): ConeKotlinType {
return when (this) {
is FirJavaTypeRef -> toConeKotlinTypeProbablyFlexible(session, typeParameterStack)
else -> coneType
}
}
@@ -392,22 +620,32 @@ class JavaClassUseSiteMemberScope(
return upperBound.classId == StandardClassIds.Any
}
private fun FirNamedFunctionSymbol.doesOverrideRenamedBuiltins(renamedSpecialBuiltInName: Name?): Boolean {
if (renamedSpecialBuiltInName == null) return false
// e.g. 'removeAt' or 'toInt'
val builtinSpecialFromSuperTypes =
getFunctionsFromSupertypes(renamedSpecialBuiltInName).filter { it.getOverriddenBuiltinWithDifferentJvmName() != null }
if (builtinSpecialFromSuperTypes.isEmpty()) return false
val currentJvmDescriptor = fir.computeJvmDescriptor(customName = renamedSpecialBuiltInName.asString())
return builtinSpecialFromSuperTypes.any { builtinSpecial ->
builtinSpecial.fir.computeJvmDescriptor() == currentJvmDescriptor
}
private fun FirProperty.computeJvmDescriptorForGetter(customName: String? = null, includeReturnType: Boolean = false): String {
getter?.computeJvmDescriptor(customName, includeReturnType)?.let { return it }
val syntheticGetter = FirDefaultPropertyGetter(
source = null,
moduleData = moduleData,
origin = origin,
propertyTypeRef = returnTypeRef,
visibility = status.visibility,
propertySymbol = symbol,
modality = status.modality ?: Modality.FINAL
)
return syntheticGetter.computeJvmDescriptor(customName, includeReturnType)
}
private fun FirFunction.computeJvmSignature(): String? {
return computeJvmSignature { it.toConeKotlinTypeProbablyFlexible(session, typeParameterStack) }
private fun FirProperty.computeJvmDescriptorForSetter(customName: String? = null, includeReturnType: Boolean = false): String {
setter?.computeJvmDescriptor(customName, includeReturnType)?.let { return it }
val syntheticSetter = FirDefaultPropertySetter(
source = null,
moduleData = moduleData,
origin = origin,
propertyTypeRef = returnTypeRef,
visibility = status.visibility,
propertySymbol = symbol,
modality = status.modality ?: Modality.FINAL
)
return syntheticSetter.computeJvmDescriptor(customName, includeReturnType)
}
private fun FirFunction.computeJvmDescriptor(customName: String? = null, includeReturnType: Boolean = false): String {
@@ -419,65 +657,6 @@ class JavaClassUseSiteMemberScope(
}
}
private fun getFunctionsFromSupertypes(name: Name): List<FirNamedFunctionSymbol> {
val result = mutableListOf<FirNamedFunctionSymbol>()
superTypesScope.processFunctionsByName(name) {
result += it
}
return result
}
private fun FirNamedFunctionSymbol.getOverriddenBuiltinWithDifferentJvmName(): FirNamedFunctionSymbol? {
var result: FirNamedFunctionSymbol? = null
if (SpecialGenericSignatures.SIGNATURE_TO_JVM_REPRESENTATION_NAME.containsKey(this.fir.computeJvmSignature())) {
return this
}
superTypesScope.processOverriddenFunctions(this) {
if (!it.isFromBuiltInClass(session)) return@processOverriddenFunctions ProcessorAction.NEXT
if (SpecialGenericSignatures.SIGNATURE_TO_JVM_REPRESENTATION_NAME.containsKey(it.fir.computeJvmSignature())) {
result = it
return@processOverriddenFunctions ProcessorAction.STOP
}
ProcessorAction.NEXT
}
return result
}
private fun FirNamedFunctionSymbol.shouldBeVisibleAsOverrideOfBuiltInWithErasedValueParameters(): Boolean {
val name = fir.name
if (!name.sameAsBuiltinMethodWithErasedValueParameters) return false
val candidatesToOverride =
getFunctionsFromSupertypes(name).mapNotNull {
it.getOverriddenBuiltinFunctionWithErasedValueParametersInJava()
}
val jvmDescriptor = fir.computeJvmDescriptor()
return candidatesToOverride.any { candidate ->
candidate.fir.computeJvmDescriptor() == jvmDescriptor && this.hasErasedParameters()
}
}
private fun FirNamedFunctionSymbol.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(): FirNamedFunctionSymbol? {
var result: FirNamedFunctionSymbol? = null
superTypesScope.processOverriddenFunctionsAndSelf(this) {
if (it.fir.computeJvmSignature() in SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SIGNATURES) {
result = it
return@processOverriddenFunctionsAndSelf ProcessorAction.STOP
}
ProcessorAction.NEXT
}
return result
}
/**
* Checks if class has any kotlin super-types apart from builtins and interfaces
*/
@@ -504,6 +683,3 @@ class JavaClassUseSiteMemberScope(
return "Java use site scope of $classId"
}
}
private fun FirCallableSymbol<*>.isFromBuiltInClass(session: FirSession) =
dispatchReceiverClassOrNull()?.toSymbol(session)?.fir?.origin == FirDeclarationOrigin.BuiltIns
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.name.StandardClassIds
class JavaOverrideChecker internal constructor(
private val session: FirSession,
private val javaTypeParameterStack: JavaTypeParameterStack,
private val baseScope: FirTypeScope?,
private val baseScopes: List<FirTypeScope>?,
private val considerReturnTypeKinds: Boolean,
) : FirAbstractOverrideChecker() {
private val context: ConeTypeContext = session.typeContext
@@ -121,7 +121,7 @@ class JavaOverrideChecker internal constructor(
var foundNonPrimitiveOverridden = false
baseScope?.processOverriddenFunctions(symbol) {
baseScopes?.processOverriddenFunctions(symbol) {
val type = it.fir.returnTypeRef.toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack)
if (!type.isPrimitiveInJava(isReturnType = true)) {
foundNonPrimitiveOverridden = true
@@ -0,0 +1,187 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.java.scopes
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull
import org.jetbrains.kotlin.fir.java.scopes.ClassicBuiltinSpecialProperties.getBuiltinSpecialPropertyGetterName
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmSignature
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_VALUE_PARAMETERS_SHORT_NAMES
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_VALUE_PARAMETERS_SIGNATURES
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.REMOVE_AT_NAME_AND_SIGNATURE
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.SIGNATURE_TO_JVM_REPRESENTATION_NAME
import org.jetbrains.kotlin.name.Name
fun FirCallableSymbol<*>.doesOverrideBuiltinWithDifferentJvmName(containingScope: FirTypeScope, session: FirSession): Boolean {
return getOverriddenBuiltinWithDifferentJvmName(containingScope, session) != null
}
fun <T : FirCallableSymbol<*>> T.getOverriddenBuiltinWithDifferentJvmName(containingScope: FirTypeScope, session: FirSession): T? {
if (
name !in SpecialGenericSignatures.ORIGINAL_SHORT_NAMES && name !in BuiltinSpecialProperties.SPECIAL_SHORT_NAMES
) return null
@Suppress("UNCHECKED_CAST")
return when (this) {
is FirNamedFunctionSymbol -> firstOverriddenFunction(containingScope) {
BuiltinMethodsWithDifferentJvmName.isBuiltinFunctionWithDifferentNameInJvm(it, session)
} as T?
is FirPropertySymbol -> ClassicBuiltinSpecialProperties.findBuiltinSpecialPropertyFqName(this, containingScope) as T?
else -> null
}
}
fun FirCallableSymbol<*>.getJvmMethodNameIfSpecial(containingScope: FirTypeScope, session: FirSession): Name? {
val overriddenBuiltin = getOverriddenBuiltinWithDifferentJvmName(containingScope, session)
?: return null
val name = when (overriddenBuiltin) {
is FirPropertySymbol -> overriddenBuiltin.getBuiltinSpecialPropertyGetterName(containingScope)
is FirNamedFunctionSymbol -> BuiltinMethodsWithDifferentJvmName.getJvmName(overriddenBuiltin)?.asString()
else -> null
} ?: return null
return Name.identifier(name)
}
object BuiltinMethodsWithSpecialGenericSignature {
private val FirNamedFunctionSymbol.hasErasedValueParametersInJava: Boolean
get() = fir.computeJvmSignature() in ERASED_VALUE_PARAMETERS_SIGNATURES
fun getOverriddenBuiltinFunctionWithErasedValueParametersInJava(
memberWithBaseScope: MemberWithBaseScope<FirNamedFunctionSymbol>
): FirNamedFunctionSymbol? {
return getOverriddenBuiltinFunctionWithErasedValueParametersInJava(memberWithBaseScope.member, memberWithBaseScope.baseScope)
}
@JvmStatic
fun getOverriddenBuiltinFunctionWithErasedValueParametersInJava(
functionSymbol: FirNamedFunctionSymbol,
containingScope: FirTypeScope
): FirNamedFunctionSymbol? {
if (!functionSymbol.name.sameAsBuiltinMethodWithErasedValueParameters) return null
return functionSymbol.firstOverriddenFunction(containingScope) { it.hasErasedValueParametersInJava }
}
val Name.sameAsBuiltinMethodWithErasedValueParameters: Boolean
get() = this in ERASED_VALUE_PARAMETERS_SHORT_NAMES
fun FirNamedFunctionSymbol.isBuiltinWithSpecialDescriptorInJvm(containingScope: FirTypeScope, session: FirSession): Boolean {
if (!isFromBuiltinClass(session)) return false
return getSpecialSignatureInfo(containingScope)?.isObjectReplacedWithTypeParameter ?: false ||
doesOverrideBuiltinWithDifferentJvmName(containingScope, session)
}
@JvmStatic
fun FirNamedFunctionSymbol.getSpecialSignatureInfo(containingScope: FirTypeScope): SpecialGenericSignatures.SpecialSignatureInfo? {
if (name !in ERASED_VALUE_PARAMETERS_SHORT_NAMES) return null
val builtinSignature = firstOverriddenFunction(containingScope) { it.hasErasedValueParametersInJava }
?.fir
?.computeJvmSignature()
?: return null
return SpecialGenericSignatures.getSpecialSignatureInfo(builtinSignature)
}
}
object BuiltinMethodsWithDifferentJvmName {
fun getJvmName(functionSymbol: FirNamedFunctionSymbol): Name? {
return SIGNATURE_TO_JVM_REPRESENTATION_NAME[functionSymbol.fir.computeJvmSignature() ?: return null]
}
fun isBuiltinFunctionWithDifferentNameInJvm(functionSymbol: FirNamedFunctionSymbol, session: FirSession): Boolean {
return functionSymbol.isFromBuiltinClass(session) && SIGNATURE_TO_JVM_REPRESENTATION_NAME.containsKey(functionSymbol.fir.computeJvmSignature())
}
val FirNamedFunctionSymbol.isRemoveAtByIndex: Boolean
get() = name.asString() == "removeAt" && fir.computeJvmSignature() == REMOVE_AT_NAME_AND_SIGNATURE.signature
}
object ClassicBuiltinSpecialProperties {
fun FirCallableSymbol<*>.getBuiltinSpecialPropertyGetterName(containingScope: FirTypeScope): String? {
val overridden = findBuiltinSpecialPropertyFqName(this, containingScope) ?: return null
return BuiltinSpecialProperties.PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP[overridden.callableId.asSingleFqName()]?.asString()
}
fun findBuiltinSpecialPropertyFqName(symbol: FirCallableSymbol<*>, containingScope: FirTypeScope): FirCallableSymbol<*>? {
if (symbol.name !in BuiltinSpecialProperties.SPECIAL_SHORT_NAMES) return null
return symbol.hasBuiltinSpecialPropertyFqNameImpl(containingScope)
}
private fun FirCallableSymbol<*>.hasBuiltinSpecialPropertyFqNameImpl(containingScope: FirTypeScope): FirCallableSymbol<*>? {
if (callableId.asSingleFqName() in BuiltinSpecialProperties.SPECIAL_FQ_NAMES && valueParametersAreEmpty()) return this
// if (!KotlinBuiltIns.isBuiltIn(this)) return false
var result: FirCallableSymbol<*>? = null
fun process(overridden: FirCallableSymbol<*>, scope: FirTypeScope): ProcessorAction {
val foundSymbol = findBuiltinSpecialPropertyFqName(overridden, scope)
return if (foundSymbol != null) {
result = foundSymbol
ProcessorAction.STOP
} else {
ProcessorAction.NEXT
}
}
when (this) {
is FirNamedFunctionSymbol -> containingScope.processDirectOverriddenFunctionsWithBaseScope(this) { overridden, scope ->
process(overridden, scope)
}
is FirPropertySymbol -> containingScope.processDirectOverriddenPropertiesWithBaseScope(this) { overridden, scope ->
process(overridden, scope)
}
}
return result
}
private fun FirCallableSymbol<*>.valueParametersAreEmpty(): Boolean {
return when (this) {
is FirNamedFunctionSymbol -> fir.valueParameters.isEmpty()
else -> true
}
}
}
private fun FirCallableSymbol<*>.isFromBuiltinClass(session: FirSession): Boolean {
return dispatchReceiverClassOrNull()?.toSymbol(session)?.fir?.origin == FirDeclarationOrigin.BuiltIns
}
private fun FirNamedFunctionSymbol.firstOverriddenFunction(
containingScope: FirTypeScope,
predicate: (FirNamedFunctionSymbol) -> Boolean
): FirNamedFunctionSymbol? {
return firstOverriddenCallable(containingScope, FirTypeScope::processOverriddenFunctionsAndSelf, predicate)
}
private inline fun <T : FirCallableSymbol<*>> T.firstOverriddenCallable(
containingScope: FirTypeScope,
processFunction: FirTypeScope.(T, (T) -> ProcessorAction) -> ProcessorAction,
noinline predicate: (T) -> Boolean,
): T? {
var result: T? = null
containingScope.processFunction(this) { symbol ->
if (predicate(symbol)) {
result = symbol
ProcessorAction.STOP
} else {
ProcessorAction.NEXT
}
}
return result
}
@@ -55,12 +55,9 @@ class FirKotlinScopeProvider(
useSiteSuperType.scopeForSupertype(useSiteSession, scopeSession, klass)
}
FirClassUseSiteMemberScope(
klass.classId,
klass,
useSiteSession,
FirTypeIntersectionScope.prepareIntersectionScope(
useSiteSession, FirStandardOverrideChecker(useSiteSession), scopes,
klass.defaultType(),
),
scopes,
decoratedDeclaredMemberScope,
)
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.scopes
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
interface FirOverrideChecker {
fun isOverriddenFunction(
@@ -20,3 +21,8 @@ interface FirOverrideChecker {
baseDeclaration: FirProperty
): Boolean
}
fun FirOverrideChecker.isOverriddenFunction(
overrideCandidate: FirNamedFunctionSymbol,
baseDeclaration: FirNamedFunctionSymbol
): Boolean = isOverriddenFunction(overrideCandidate.fir, baseDeclaration.fir)
@@ -56,3 +56,10 @@ internal fun FirOverrideChecker.similarFunctionsOrBothProperties(
else -> error("Unknown fir callable type: $overrideCandidate, $baseDeclaration")
}
}
fun FirOverrideChecker.similarFunctionsOrBothProperties(
overrideCandidate: FirCallableSymbol<*>,
baseDeclaration: FirCallableSymbol<*>
): Boolean {
return similarFunctionsOrBothProperties(overrideCandidate.fir, baseDeclaration.fir)
}
@@ -7,11 +7,10 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScopeContext.ResultOfIntersection
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeSimpleKotlinType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
@@ -19,100 +18,207 @@ abstract class AbstractFirUseSiteMemberScope(
val classId: ClassId,
session: FirSession,
overrideChecker: FirOverrideChecker,
val superTypesScope: FirTypeScope,
protected val superTypeScopes: List<FirTypeScope>,
dispatchReceiverType: ConeSimpleKotlinType,
protected val declaredMemberScope: FirContainingNamesAwareScope
) : AbstractFirOverrideScope(session, overrideChecker) {
protected val supertypeScopeContext = FirTypeIntersectionScopeContext(session, overrideChecker, superTypeScopes, dispatchReceiverType)
private val functions = hashMapOf<Name, Collection<FirNamedFunctionSymbol>>()
private val properties = hashMapOf<Name, Collection<FirVariableSymbol<*>>>()
val directOverriddenFunctions = hashMapOf<FirNamedFunctionSymbol, Collection<FirNamedFunctionSymbol>>()
protected val directOverriddenProperties = hashMapOf<FirPropertySymbol, MutableList<FirPropertySymbol>>()
private val functions: MutableMap<Name, Collection<FirNamedFunctionSymbol>> = hashMapOf()
private val properties: MutableMap<Name, Collection<FirVariableSymbol<*>>> = hashMapOf()
protected val directOverriddenFunctions: MutableMap<FirNamedFunctionSymbol, List<ResultOfIntersection<FirNamedFunctionSymbol>>> =
hashMapOf()
protected val directOverriddenProperties: MutableMap<FirPropertySymbol, List<ResultOfIntersection<FirPropertySymbol>>> = hashMapOf()
protected val functionsFromSupertypes: MutableMap<Name, List<ResultOfIntersection<FirNamedFunctionSymbol>>> = mutableMapOf()
protected val propertiesFromSupertypes: MutableMap<Name, List<ResultOfIntersection<FirPropertySymbol>>> = mutableMapOf()
protected val fieldsFromSupertypes: MutableMap<Name, List<FirFieldSymbol>> = mutableMapOf()
private val absentClassifiersFromSupertypes = mutableSetOf<Name>()
private val callableNamesCached by lazy(LazyThreadSafetyMode.PUBLICATION) {
declaredMemberScope.getCallableNames() + superTypesScope.getCallableNames()
buildSet {
addAll(declaredMemberScope.getCallableNames())
superTypeScopes.flatMapTo(this) { it.getCallableNames() }
}
}
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
private val classifierNamesCached by lazy(LazyThreadSafetyMode.PUBLICATION) {
buildSet {
addAll(declaredMemberScope.getClassifierNames())
superTypeScopes.flatMapTo(this) { it.getClassifierNames() }
}
}
final override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
functions.getOrPut(name) {
doProcessFunctions(name)
collectFunctions(name)
}.forEach {
processor(it)
}
}
private fun doProcessFunctions(
protected open fun collectFunctions(
name: Name
): Collection<FirNamedFunctionSymbol> = mutableListOf<FirNamedFunctionSymbol>().apply {
val overrideCandidates = mutableSetOf<FirFunctionSymbol<*>>()
collectDeclaredFunctions(name, this)
val explicitlyDeclaredFunctions = this.toSet()
collectFunctionsFromSupertypes(name, this, explicitlyDeclaredFunctions)
}
protected fun collectDeclaredFunctions(name: Name, destination: MutableList<FirNamedFunctionSymbol>) {
declaredMemberScope.processFunctionsByName(name) { symbol ->
if (symbol.isStatic) return@processFunctionsByName
val directOverridden = computeDirectOverridden(symbol)
this@AbstractFirUseSiteMemberScope.directOverriddenFunctions[symbol] = directOverridden
overrideCandidates += symbol
add(symbol)
if (!symbol.isVisibleInCurrentClass()) return@processFunctionsByName
val directOverridden = computeDirectOverriddenForDeclaredFunction(symbol)
directOverriddenFunctions[symbol] = directOverridden
destination += symbol
}
}
superTypesScope.processFunctionsByName(name) {
val overriddenBy = it.getOverridden(overrideCandidates)
protected abstract fun FirNamedFunctionSymbol.isVisibleInCurrentClass(): Boolean
protected fun collectFunctionsFromSupertypes(
name: Name,
destination: MutableList<FirNamedFunctionSymbol>,
explicitlyDeclaredFunctions: Set<FirNamedFunctionSymbol>
) {
for (chosenSymbolFromSupertype in getFunctionsFromSupertypesByName(name)) {
val superSymbol = chosenSymbolFromSupertype.extractSomeSymbolFromSuperType()
if (!superSymbol.isVisibleInCurrentClass()) continue
val overriddenBy = superSymbol.getOverridden(explicitlyDeclaredFunctions)
if (overriddenBy == null) {
add(it)
destination += chosenSymbolFromSupertype.chosenSymbol
}
}
}
private fun getFunctionsFromSupertypesByName(name: Name): List<ResultOfIntersection<FirNamedFunctionSymbol>> {
return functionsFromSupertypes.getOrPut(name) {
supertypeScopeContext.collectCallables(name, FirScope::processFunctionsByName)
}
}
final override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
properties.getOrPut(name) {
doProcessProperties(name)
collectProperties(name)
}.forEach {
processor(it)
}
}
protected abstract fun doProcessProperties(name: Name): Collection<FirVariableSymbol<*>>
protected abstract fun collectProperties(name: Name): Collection<FirVariableSymbol<*>>
private fun computeDirectOverridden(symbol: FirNamedFunctionSymbol): Collection<FirNamedFunctionSymbol> {
val result = mutableListOf<FirNamedFunctionSymbol>()
val firSimpleFunction = symbol.fir
superTypesScope.processFunctionsByName(symbol.callableId.callableName) { superSymbol ->
if (overrideChecker.isOverriddenFunction(firSimpleFunction, superSymbol.fir)) {
result.add(superSymbol)
private fun computeDirectOverriddenForDeclaredFunction(declaredFunctionSymbol: FirNamedFunctionSymbol): List<ResultOfIntersection<FirNamedFunctionSymbol>> {
val result = mutableListOf<ResultOfIntersection<FirNamedFunctionSymbol>>()
val declaredFunction = declaredFunctionSymbol.fir
for (resultOfIntersection in getFunctionsFromSupertypesByName(declaredFunctionSymbol.name)) {
val symbolFromSupertype = resultOfIntersection.extractSomeSymbolFromSuperType()
if (overrideChecker.isOverriddenFunction(declaredFunction, symbolFromSupertype.fir)) {
result.add(resultOfIntersection)
}
}
return result
}
protected fun <D : FirCallableSymbol<*>> ResultOfIntersection<D>.extractSomeSymbolFromSuperType(): D {
return if (this.isIntersectionOverride()) {
/*
* we don't want to create intersection override if some declared function actually overrides some functions
* from supertypes, so instead of intersection override symbol we check actual symbol from supertype
*
* TODO: is it enough to check only one function?
*/
firstMember
} else {
chosenSymbol
}
}
override fun processDirectOverriddenFunctionsWithBaseScope(
functionSymbol: FirNamedFunctionSymbol,
processor: (FirNamedFunctionSymbol, FirTypeScope) -> ProcessorAction
): ProcessorAction =
//directOverriddenFunctions might be not filled for functionSymbol if it is not from processFunctionsByName call
doProcessDirectOverriddenCallables(
functionSymbol, processor, directOverriddenFunctions, superTypesScope,
): ProcessorAction {
return processDirectOverriddenMembersWithBaseScopeImpl(
directOverriddenFunctions,
functionsFromSupertypes,
functionSymbol,
processor,
FirTypeScope::processDirectOverriddenFunctionsWithBaseScope
)
}
override fun processDirectOverriddenPropertiesWithBaseScope(
propertySymbol: FirPropertySymbol,
processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction
): ProcessorAction =
doProcessDirectOverriddenCallables(
propertySymbol, processor, directOverriddenProperties, superTypesScope,
): ProcessorAction {
return processDirectOverriddenMembersWithBaseScopeImpl(
directOverriddenProperties,
propertiesFromSupertypes,
propertySymbol,
processor,
FirTypeScope::processDirectOverriddenPropertiesWithBaseScope
)
}
private fun <D : FirCallableSymbol<*>> processDirectOverriddenMembersWithBaseScopeImpl(
directOverriddenMap: Map<D, List<ResultOfIntersection<D>>>,
callablesFromSupertypes: Map<Name, List<ResultOfIntersection<D>>>,
callableSymbol: D,
processor: (D, FirTypeScope) -> ProcessorAction,
processDirectOverriddenCallables: FirTypeScope.(D, (D, FirTypeScope) -> ProcessorAction) -> ProcessorAction
): ProcessorAction {
when (val directOverridden = directOverriddenMap[callableSymbol]) {
null -> {
val resultOfIntersection = callablesFromSupertypes[callableSymbol.name]
?.firstOrNull { it.chosenSymbol == callableSymbol }
?: return ProcessorAction.NONE
if (resultOfIntersection.isIntersectionOverride()) {
for ((overridden, baseScope) in resultOfIntersection.overriddenMembers) {
if (!processor(overridden, baseScope)) return ProcessorAction.STOP
}
return ProcessorAction.NONE
} else {
return resultOfIntersection.containingScope
?.processDirectOverriddenCallables(callableSymbol, processor)
?: ProcessorAction.NONE
}
}
else -> {
for (resultOfIntersection in directOverridden) {
for ((overridden, baseScope) in resultOfIntersection.overriddenMembers) {
if (!processor(overridden, baseScope)) return ProcessorAction.STOP
}
}
return ProcessorAction.NONE
}
}
}
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
declaredMemberScope.processClassifiersByNameWithSubstitution(name, processor)
superTypesScope.processClassifiersByNameWithSubstitution(name, processor)
if (name in absentClassifiersFromSupertypes) return
val classifiers = supertypeScopeContext.collectClassifiers(name)
if (classifiers.isEmpty()) {
absentClassifiersFromSupertypes += name
return
}
for ((symbol, substitution) in classifiers) {
processor(symbol, substitution)
}
}
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
declaredMemberScope.processDeclaredConstructors(processor)
}
override fun getCallableNames(): Set<Name> = callableNamesCached
override fun getCallableNames(): Set<Name> {
return callableNamesCached
}
override fun getClassifierNames(): Set<Name> {
return declaredMemberScope.getClassifierNames() + superTypesScope.getClassifierNames()
return classifierNamesCached
}
}
@@ -7,53 +7,86 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.isStatic
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.Name
class FirClassUseSiteMemberScope(
classId: ClassId,
klass: FirClass,
session: FirSession,
superTypesScope: FirTypeScope,
superTypeScopes: List<FirTypeScope>,
declaredMemberScope: FirContainingNamesAwareScope
) : AbstractFirUseSiteMemberScope(classId, session, FirStandardOverrideChecker(session), superTypesScope, declaredMemberScope) {
override fun doProcessProperties(name: Name): Collection<FirVariableSymbol<*>> {
val seen = mutableSetOf<FirVariableSymbol<*>>()
val result = mutableSetOf<FirVariableSymbol<*>>()
declaredMemberScope.processPropertiesByName(name) l@{
if (it.isStatic) return@l
if (it is FirPropertySymbol) {
val directOverridden = computeDirectOverridden(it.fir)
this@FirClassUseSiteMemberScope.directOverriddenProperties[it] = directOverridden
) : AbstractFirUseSiteMemberScope(
klass.classId,
session,
FirStandardOverrideChecker(session),
superTypeScopes,
klass.defaultType(),
declaredMemberScope
) {
override fun collectProperties(name: Name): Collection<FirVariableSymbol<*>> {
return buildList {
val explicitlyDeclaredProperties = mutableSetOf<FirVariableSymbol<*>>()
declaredMemberScope.processPropertiesByName(name) { symbol ->
if (symbol.isStatic) return@processPropertiesByName
if (symbol is FirPropertySymbol) {
val directOverridden = computeDirectOverriddenForDeclaredProperty(symbol)
directOverriddenProperties[symbol] = directOverridden
}
explicitlyDeclaredProperties += symbol
add(symbol)
}
seen += it
result += it
}
superTypesScope.processPropertiesByName(name) {
val overriddenBy = it.getOverridden(seen)
if (overriddenBy == null) {
result += it
val (properties, fields) = getPropertiesAndFieldsFromSupertypesByName(name)
for (propertyFromSupertype in properties) {
val superSymbol = propertyFromSupertype.extractSomeSymbolFromSuperType()
val overriddenBy = superSymbol.getOverridden(explicitlyDeclaredProperties)
if (overriddenBy == null) {
add(propertyFromSupertype.chosenSymbol)
}
}
addAll(fields)
}
}
private fun computeDirectOverriddenForDeclaredProperty(declaredPropertySymbol: FirPropertySymbol): List<FirTypeIntersectionScopeContext.ResultOfIntersection<FirPropertySymbol>> {
val result = mutableListOf<FirTypeIntersectionScopeContext.ResultOfIntersection<FirPropertySymbol>>()
val declaredProperty = declaredPropertySymbol.fir
for (resultOfIntersection in getPropertiesAndFieldsFromSupertypesByName(declaredPropertySymbol.name).first) {
val symbolFromSupertype = resultOfIntersection.extractSomeSymbolFromSuperType()
if (overrideChecker.isOverriddenProperty(declaredProperty, symbolFromSupertype.fir)) {
result.add(resultOfIntersection)
}
}
return result
}
private fun computeDirectOverridden(property: FirProperty): MutableList<FirPropertySymbol> {
val result = mutableListOf<FirPropertySymbol>()
superTypesScope.processPropertiesByName(property.name) l@{ superSymbol ->
if (superSymbol !is FirPropertySymbol) return@l
if (overrideChecker.isOverriddenProperty(property, superSymbol.fir)) {
result.add(superSymbol)
private fun getPropertiesAndFieldsFromSupertypesByName(name: Name): Pair<List<FirTypeIntersectionScopeContext.ResultOfIntersection<FirPropertySymbol>>, List<FirFieldSymbol>> {
propertiesFromSupertypes[name]?.let {
return it to fieldsFromSupertypes.getValue(name)
}
val fields = mutableListOf<FirFieldSymbol>()
val properties = supertypeScopeContext.collectCallables<FirPropertySymbol>(name) { propertyName, processor ->
processPropertiesByName(propertyName) {
when (it) {
is FirPropertySymbol -> processor(it)
is FirFieldSymbol -> fields += it
else -> {}
}
}
}
return result
propertiesFromSupertypes[name] = properties
fieldsFromSupertypes[name] = fields
return properties to fields
}
override fun FirNamedFunctionSymbol.isVisibleInCurrentClass(): Boolean {
return true
}
override fun toString(): String {
@@ -0,0 +1,63 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.PrivateForInline
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.MemberWithBaseScope
import org.jetbrains.kotlin.fir.scopes.ProcessOverriddenWithBaseScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
fun filterOutOverriddenFunctions(extractedOverridden: Collection<MemberWithBaseScope<FirNamedFunctionSymbol>>): Collection<MemberWithBaseScope<FirNamedFunctionSymbol>> {
return filterOutOverridden(extractedOverridden, FirTypeScope::processDirectOverriddenFunctionsWithBaseScope)
}
fun filterOutOverriddenProperties(extractedOverridden: Collection<MemberWithBaseScope<FirPropertySymbol>>): Collection<MemberWithBaseScope<FirPropertySymbol>> {
return filterOutOverridden(extractedOverridden, FirTypeScope::processDirectOverriddenPropertiesWithBaseScope)
}
@OptIn(PrivateForInline::class)
inline fun <D : FirCallableSymbol<*>> filterOutOverridden(
extractedOverridden: Collection<MemberWithBaseScope<D>>,
processAllOverridden: ProcessOverriddenWithBaseScope<D>,
): Collection<MemberWithBaseScope<D>> {
return extractedOverridden.filter { overridden1 ->
extractedOverridden.none { overridden2 ->
overridden1 !== overridden2 && overrides(
overridden2,
overridden1,
processAllOverridden
)
}
}
}
// Whether f overrides g
@PrivateForInline
inline fun <D : FirCallableSymbol<*>> overrides(
f: MemberWithBaseScope<D>,
g: MemberWithBaseScope<D>,
processAllOverridden: ProcessOverriddenWithBaseScope<D>,
): Boolean {
val (fMember, fScope) = f
val (gMember) = g
var result = false
fScope.processAllOverridden(fMember) { overridden, _ ->
if (overridden == gMember) {
result = true
ProcessorAction.STOP
} else {
ProcessorAction.NEXT
}
}
return result
}
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeSimpleKotlinType
import org.jetbrains.kotlin.name.Name
@@ -58,9 +55,10 @@ class FirTypeIntersectionScope private constructor(
return
}
for ((chosenSymbol, overriddenMembers) in callablesWithOverridden) {
overriddenSymbols[chosenSymbol] = overriddenMembers
processor(chosenSymbol)
for (resultOfIntersection in callablesWithOverridden) {
val symbol = resultOfIntersection.chosenSymbol
overriddenSymbols[symbol] = resultOfIntersection.overriddenMembers
processor(symbol)
}
}
@@ -17,16 +17,21 @@ import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.FirIntersectionOverrideStorage.ContextForIntersectionOverrideConstruction
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScopeContext.ResultOfIntersection
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.AbstractTypeChecker
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
typealias MembersByScope<D> = List<Pair<FirTypeScope, List<D>>>
class FirTypeIntersectionScopeContext(
val session: FirSession,
private val overrideChecker: FirOverrideChecker,
@property:PrivateForInline val scopes: List<FirTypeScope>,
val scopes: List<FirTypeScope>,
private val dispatchReceiverType: ConeSimpleKotlinType,
) {
private val typeCheckerState = session.typeContext.newTypeCheckerState(
@@ -37,14 +42,40 @@ class FirTypeIntersectionScopeContext(
val intersectionOverrides: FirCache<FirCallableSymbol<*>, MemberWithBaseScope<FirCallableSymbol<*>>, ContextForIntersectionOverrideConstruction<*>> =
session.intersectionOverrideStorage.cacheByScope.getValue(dispatchReceiverType).intersectionOverrides
data class ResultOfIntersection<D : FirCallableSymbol<*>>(
val chosenSymbol: D,
val overriddenMembers: List<MemberWithBaseScope<D>>
sealed class ResultOfIntersection<D : FirCallableSymbol<*>>(
val overriddenMembers: List<MemberWithBaseScope<D>>,
val containingScope: FirTypeScope?
) {
constructor(
chosenSymbol: D,
overriddenMember: MemberWithBaseScope<D>
) : this(chosenSymbol, listOf(overriddenMember))
abstract val chosenSymbol: D
class SingleMember<D : FirCallableSymbol<*>>(
override val chosenSymbol: D,
overriddenMembers: List<MemberWithBaseScope<D>>,
containingScope: FirTypeScope?
) : ResultOfIntersection<D>(overriddenMembers, containingScope) {
constructor(
chosenSymbol: D,
overriddenMember: MemberWithBaseScope<D>
) : this(chosenSymbol, listOf(overriddenMember), overriddenMember.baseScope)
}
class NonTrivial<D : FirCallableSymbol<*>>(
private val intersectionOverridesCache: FirCache<FirCallableSymbol<*>, MemberWithBaseScope<FirCallableSymbol<*>>, ContextForIntersectionOverrideConstruction<*>>,
private val context: ContextForIntersectionOverrideConstruction<D>,
overriddenMembers: List<MemberWithBaseScope<D>>,
containingScope: FirTypeScope?
) : ResultOfIntersection<D>(overriddenMembers, containingScope) {
override val chosenSymbol: D by lazy {
@Suppress("UNCHECKED_CAST")
intersectionOverridesCache.getValue(
context.mostSpecific,
context
).member as D
}
val firstMember: D
get() = context.extractedOverrides.first().member
}
}
@OptIn(PrivateForInline::class)
@@ -65,12 +96,16 @@ class FirTypeIntersectionScopeContext(
return result
}
fun collectFunctions(name: Name): List<ResultOfIntersection<FirNamedFunctionSymbol>> {
return collectCallables(name, FirScope::processFunctionsByName)
}
@OptIn(PrivateForInline::class)
inline fun <D : FirCallableSymbol<*>> collectCallables(
inline fun <D : FirCallableSymbol<*>> collectMembersByScope(
name: Name,
processCallables: FirScope.(Name, (D) -> Unit) -> Unit
): List<ResultOfIntersection<D>> {
val membersByScope = scopes.mapNotNull { scope ->
): MembersByScope<D> {
return scopes.mapNotNull { scope ->
val resultForScope = mutableListOf<D>()
scope.processCallables(name) {
if (it !is FirConstructorSymbol) {
@@ -82,19 +117,25 @@ class FirTypeIntersectionScopeContext(
scope to it
}
}
return collectCallablesImpl(membersByScope)
}
@PrivateForInline
@OptIn(PrivateForInline::class)
inline fun <D : FirCallableSymbol<*>> collectCallables(
name: Name,
processCallables: FirScope.(Name, (D) -> Unit) -> Unit
): List<ResultOfIntersection<D>> {
return collectCallablesImpl(collectMembersByScope(name, processCallables))
}
fun <D : FirCallableSymbol<*>> collectCallablesImpl(
membersByScope: List<Pair<FirTypeScope, MutableList<D>>>
membersByScope: List<Pair<FirTypeScope, List<D>>>
): List<ResultOfIntersection<D>> {
if (membersByScope.isEmpty()) {
return emptyList()
}
membersByScope.singleOrNull()?.let { (scope, members) ->
return members.map { ResultOfIntersection(it, MemberWithBaseScope(it, scope)) }
return members.map { ResultOfIntersection.SingleMember(it, MemberWithBaseScope(it, scope)) }
}
val allMembersWithScope = membersByScope.flatMapTo(linkedSetOf()) { (scope, members) ->
@@ -112,31 +153,32 @@ class FirTypeIntersectionScopeContext(
val baseMembersForIntersection = extractedOverrides.calcBaseMembersForIntersectionOverride()
if (baseMembersForIntersection.size > 1) {
val (mostSpecific, scopeForMostSpecific) = selectMostSpecificMember(baseMembersForIntersection)
val intersectionOverride = intersectionOverrides.getValue(
val intersectionOverrideContext = ContextForIntersectionOverrideConstruction(
mostSpecific,
ContextForIntersectionOverrideConstruction(
this,
extractedOverrides,
scopeForMostSpecific
)
this,
extractedOverrides,
scopeForMostSpecific
)
result += ResultOfIntersection.NonTrivial(
intersectionOverrides,
intersectionOverrideContext,
extractedOverrides,
containingScope = null
)
@Suppress("UNCHECKED_CAST")
result += ResultOfIntersection(intersectionOverride.member as D, extractedOverrides)
} else {
val mostSpecific = baseMembersForIntersection.single().member
result += ResultOfIntersection(mostSpecific, extractedOverrides)
val (mostSpecific, containingScope) = baseMembersForIntersection.single()
result += ResultOfIntersection.SingleMember(mostSpecific, extractedOverrides, containingScope)
}
}
if (allMembersWithScope.isNotEmpty()) {
val single = allMembersWithScope.single().member
result += ResultOfIntersection(single, allMembersWithScope.toList())
val (single, containingScope) = allMembersWithScope.single()
result += ResultOfIntersection.SingleMember(single, allMembersWithScope.toList(), containingScope)
}
return result
}
fun <D : FirCallableSymbol<*>> createIntersectionOverride(
extractedOverrides: List<MemberWithBaseScope<D>>,
mostSpecific: D,
@@ -384,45 +426,6 @@ class FirTypeIntersectionScopeContext(
}
}
private fun <D : FirCallableSymbol<*>> filterOutOverridden(
extractedOverridden: Collection<MemberWithBaseScope<D>>,
processAllOverridden: ProcessOverriddenWithBaseScope<D>,
): Collection<MemberWithBaseScope<D>> {
return extractedOverridden.filter { overridden1 ->
extractedOverridden.none { overridden2 ->
overridden1 !== overridden2 && overrides(
overridden2,
overridden1,
processAllOverridden
)
}
}
}
// Whether f overrides g
private fun <D : FirCallableSymbol<*>> overrides(
f: MemberWithBaseScope<D>,
g: MemberWithBaseScope<D>,
processAllOverridden: ProcessOverriddenWithBaseScope<D>,
): Boolean {
val (fMember, fScope) = f
val (gMember) = g
var result = false
fScope.processAllOverridden(fMember) { overridden, _ ->
if (overridden == gMember) {
result = true
ProcessorAction.STOP
} else {
ProcessorAction.NEXT
}
}
return result
}
private fun <D : FirCallableSymbol<*>> chooseIntersectionVisibility(
extractedOverrides: Collection<MemberWithBaseScope<D>>
): Visibility {
@@ -492,19 +495,6 @@ class FirTypeIntersectionScopeContext(
}
}
class MemberWithBaseScope<out D : FirCallableSymbol<*>>(val member: D, val baseScope: FirTypeScope) {
operator fun component1() = member
operator fun component2() = baseScope
override fun equals(other: Any?): Boolean {
return other is MemberWithBaseScope<*> && member == other.member
}
override fun hashCode(): Int {
return member.hashCode()
}
}
private fun <D : FirCallableSymbol<*>> D.withScope(baseScope: FirTypeScope) = MemberWithBaseScope(this, baseScope)
class FirIntersectionOverrideStorage(val session: FirSession) : FirSessionComponent {
@@ -513,12 +503,13 @@ class FirIntersectionOverrideStorage(val session: FirSession) : FirSessionCompon
class CacheForScope(cachesFactory: FirCachesFactory) {
val intersectionOverrides: FirCache<FirCallableSymbol<*>, MemberWithBaseScope<FirCallableSymbol<*>>, ContextForIntersectionOverrideConstruction<*>> =
cachesFactory.createCache { mostSpecific, context ->
val (intersectionScope, extractedOverrides, scopeForMostSpecific) = context
val (_, intersectionScope, extractedOverrides, scopeForMostSpecific) = context
intersectionScope.createIntersectionOverride(extractedOverrides, mostSpecific, scopeForMostSpecific)
}
}
data class ContextForIntersectionOverrideConstruction<D : FirCallableSymbol<*>>(
val mostSpecific: D,
val intersectionContext: FirTypeIntersectionScopeContext,
val extractedOverrides: List<MemberWithBaseScope<D>>,
val scopeForMostSpecific: FirTypeScope
@@ -529,3 +520,11 @@ class FirIntersectionOverrideStorage(val session: FirSession) : FirSessionCompon
}
private val FirSession.intersectionOverrideStorage: FirIntersectionOverrideStorage by FirSession.sessionComponentAccessor()
@OptIn(ExperimentalContracts::class)
fun <D : FirCallableSymbol<*>> ResultOfIntersection<D>.isIntersectionOverride(): Boolean {
contract {
returns(true) implies (this@isIntersectionOverride is ResultOfIntersection.NonTrivial<D>)
}
return this is ResultOfIntersection.NonTrivial
}
@@ -487,6 +487,7 @@ fun FirFunction.getAsForbiddenNamedArgumentsTarget(session: FirSession): Forbidd
}
}
FirDeclarationOrigin.Synthetic -> null
FirDeclarationOrigin.RenamedForOverride -> null
is FirDeclarationOrigin.Plugin -> null // TODO: figure out what to do with plugin generated functions
}
}
@@ -18,6 +18,7 @@ sealed class FirDeclarationOrigin(private val displayName: String? = null, val f
object SubstitutionOverride : FirDeclarationOrigin(fromSupertypes = true)
object IntersectionOverride : FirDeclarationOrigin(fromSupertypes = true)
object Delegated : FirDeclarationOrigin()
object RenamedForOverride : FirDeclarationOrigin()
class Plugin(val key: FirPluginKey) : FirDeclarationOrigin(displayName = "Plugin[$key]", generated = true)
@@ -60,7 +60,7 @@ fun FirTypeScope.processOverriddenFunctionsAndSelf(
): ProcessorAction {
if (!processor(functionSymbol)) return ProcessorAction.STOP
return processOverriddenFunctions(functionSymbol, processor)
return processOverriddenFunctions(functionSymbol, processor = processor)
}
fun FirTypeScope.processOverriddenPropertiesAndSelf(
@@ -69,7 +69,15 @@ fun FirTypeScope.processOverriddenPropertiesAndSelf(
): ProcessorAction {
if (!processor(propertySymbol)) return ProcessorAction.STOP
return processOverriddenProperties(propertySymbol, processor)
return processOverriddenProperties(propertySymbol, processor = processor)
}
fun List<FirTypeScope>.processOverriddenPropertiesAndSelf(
propertySymbol: FirPropertySymbol,
processor: (FirPropertySymbol) -> ProcessorAction
) {
if (!processor(propertySymbol)) return
processOverriddenProperties(propertySymbol, processor)
}
enum class ProcessorAction {
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir.scopes
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.isIntersectionOverride
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol
@@ -63,27 +62,18 @@ abstract class FirTypeScope : FirContainingNamesAwareScope() {
return "Empty scope"
}
}
}
protected companion object {
fun <S : FirCallableSymbol<*>> doProcessDirectOverriddenCallables(
callableSymbol: S,
processor: (S, FirTypeScope) -> ProcessorAction,
directOverriddenMap: Map<S, Collection<S>>,
baseScope: FirTypeScope,
processDirectOverriddenCallables: FirTypeScope.(S, (S, FirTypeScope) -> ProcessorAction) -> ProcessorAction
): ProcessorAction {
val directOverridden = directOverriddenMap[callableSymbol]?.takeIf { it.isNotEmpty() }
?: return baseScope.processDirectOverriddenCallables(callableSymbol, processor)
class MemberWithBaseScope<out D : FirCallableSymbol<*>>(val member: D, val baseScope: FirTypeScope) {
operator fun component1() = member
operator fun component2() = baseScope
for (overridden in directOverridden) {
if (overridden.fir.isIntersectionOverride) {
if (!baseScope.processDirectOverriddenCallables(overridden, processor)) return ProcessorAction.STOP
}
if (!processor(overridden, baseScope)) return ProcessorAction.STOP
}
override fun equals(other: Any?): Boolean {
return other is MemberWithBaseScope<*> && member == other.member
}
return ProcessorAction.NONE
}
override fun hashCode(): Int {
return member.hashCode()
}
}
@@ -100,6 +90,18 @@ fun FirTypeScope.processOverriddenFunctions(
mutableSetOf()
)
private fun FirTypeScope.processOverriddenFunctionsWithVisited(
functionSymbol: FirNamedFunctionSymbol,
visited: MutableSet<Pair<FirTypeScope, FirNamedFunctionSymbol>>,
processor: (FirNamedFunctionSymbol) -> ProcessorAction
): ProcessorAction =
doProcessAllOverriddenCallables(
functionSymbol,
processor,
FirTypeScope::processDirectOverriddenFunctionsWithBaseScope,
visited
)
fun FirTypeScope.processOverriddenProperties(
propertySymbol: FirPropertySymbol,
processor: (FirPropertySymbol) -> ProcessorAction
@@ -111,13 +113,45 @@ fun FirTypeScope.processOverriddenProperties(
mutableSetOf()
)
private fun FirTypeScope.processOverriddenPropertiesWithVisited(
propertySymbol: FirPropertySymbol,
visited: MutableSet<Pair<FirTypeScope, FirPropertySymbol>> = mutableSetOf(),
processor: (FirPropertySymbol) -> ProcessorAction
): ProcessorAction =
doProcessAllOverriddenCallables(
propertySymbol,
processor,
FirTypeScope::processDirectOverriddenPropertiesWithBaseScope,
visited
)
fun List<FirTypeScope>.processOverriddenFunctions(
functionSymbol: FirNamedFunctionSymbol,
processor: (FirNamedFunctionSymbol) -> ProcessorAction
) {
val visited = mutableSetOf<Pair<FirTypeScope, FirNamedFunctionSymbol>>()
for (scope in this) {
if (!scope.processOverriddenFunctionsWithVisited(functionSymbol, visited, processor)) return
}
}
fun List<FirTypeScope>.processOverriddenProperties(
propertySymbol: FirPropertySymbol,
processor: (FirPropertySymbol) -> ProcessorAction
) {
val visited = mutableSetOf<Pair<FirTypeScope, FirPropertySymbol>>()
for (scope in this) {
if (!scope.processOverriddenPropertiesWithVisited(propertySymbol, visited, processor)) return
}
}
private fun <S : FirCallableSymbol<*>> FirTypeScope.doProcessAllOverriddenCallables(
callableSymbol: S,
processor: (S, FirTypeScope) -> ProcessorAction,
processDirectOverriddenCallablesWithBaseScope: FirTypeScope.(S, (S, FirTypeScope) -> ProcessorAction) -> ProcessorAction,
visited: MutableSet<S>
visited: MutableSet<Pair<FirTypeScope, S>>
): ProcessorAction {
if (!visited.add(callableSymbol)) return ProcessorAction.NONE
if (!visited.add(this to callableSymbol)) return ProcessorAction.NONE
return processDirectOverriddenCallablesWithBaseScope(callableSymbol) { overridden, baseScope ->
if (!processor(overridden, baseScope)) return@processDirectOverriddenCallablesWithBaseScope ProcessorAction.STOP
@@ -129,7 +163,7 @@ private fun <S : FirCallableSymbol<*>> FirTypeScope.doProcessAllOverriddenCallab
callableSymbol: S,
processor: (S) -> ProcessorAction,
processDirectOverriddenCallablesWithBaseScope: FirTypeScope.(S, (S, FirTypeScope) -> ProcessorAction) -> ProcessorAction,
visited: MutableSet<S>
visited: MutableSet<Pair<FirTypeScope, S>>
): ProcessorAction =
doProcessAllOverriddenCallables(callableSymbol, { s, _ -> processor(s) }, processDirectOverriddenCallablesWithBaseScope, visited)
@@ -157,6 +191,41 @@ fun FirTypeScope.getDirectOverriddenMembers(
else -> emptyList()
}
fun FirTypeScope.getDirectOverriddenMembersWithBaseScope(member: FirCallableSymbol<*>): List<MemberWithBaseScope<FirCallableSymbol<*>>> {
return when (member) {
is FirNamedFunctionSymbol -> getDirectOverriddenFunctionsWithBaseScope(member)
is FirPropertySymbol -> getDirectOverriddenPropertiesWithBaseScope(member)
else -> emptyList()
}
}
fun FirTypeScope.getDirectOverriddenFunctionsWithBaseScope(
function: FirNamedFunctionSymbol,
): List<MemberWithBaseScope<FirNamedFunctionSymbol>> {
val overriddenFunctions = mutableSetOf<MemberWithBaseScope<FirNamedFunctionSymbol>>()
processDirectOverriddenFunctionsWithBaseScope(function) { symbol, baseScope ->
overriddenFunctions += MemberWithBaseScope(symbol, baseScope)
ProcessorAction.NEXT
}
return overriddenFunctions.toList()
}
fun FirTypeScope.getDirectOverriddenPropertiesWithBaseScope(
property: FirPropertySymbol,
): List<MemberWithBaseScope<FirPropertySymbol>> {
val overriddenProperties = mutableSetOf<MemberWithBaseScope<FirPropertySymbol>>()
processDirectOverriddenPropertiesWithBaseScope(property) { symbol, baseScope ->
overriddenProperties += MemberWithBaseScope(symbol, baseScope)
ProcessorAction.NEXT
}
return overriddenProperties.toList()
}
fun FirTypeScope.getDirectOverriddenFunctions(
function: FirNamedFunctionSymbol,
unwrapIntersectionAndSubstitutionOverride: Boolean = false,
@@ -1,5 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FIR status: wrong ABSTRACT_MEMBER_NOT_IMPLEMENTED, probably provoked by override mapping error
// TARGET_BACKEND: JVM
// FILE: J.java
@@ -1,5 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FIR status: wrong ABSTRACT_MEMBER_NOT_IMPLEMENTED, probably provoked by override mapping error
// FIR status: wrong CONFLICTING_INHERITED_JVM_DECLARATIONS, probably provoked by override mapping error
// TARGET_BACKEND: JVM
// FILE: J.java
@@ -1,85 +0,0 @@
// FILE: CollectionStringImpl.java
import java.util.Collection;
import java.util.Iterator;
public class CollectionStringImpl implements Collection<String> {
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean contains(Object o) {
return false;
}
@Override
public Iterator<String> iterator() {
return null;
}
@Override
public Object[] toArray() {
return new Object[0];
}
@Override
public <T> T[] toArray(T[] a) {
return null;
}
@Override
public boolean add(String s) {
return false;
}
@Override
public boolean remove(Object o) {
return false;
}
@Override
public boolean containsAll(Collection<?> c) {
return false;
}
@Override
public boolean addAll(Collection<? extends String> c) {
return false;
}
@Override
public boolean removeAll(Collection<?> c) {
return false;
}
@Override
public boolean retainAll(Collection<?> c) {
return false;
}
@Override
public void clear() {
}
public boolean contains(String o) {
return true;
}
}
// FILE: main.kt
fun test(x: CollectionStringImpl) {
x.<!OVERLOAD_RESOLUTION_AMBIGUITY!>contains<!>("")
(x as Collection<String>).contains("")
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: CollectionStringImpl.java
import java.util.Collection;
@@ -12,10 +12,10 @@ abstract class KA : A() {
}
fun foo(a: A, ka: KA) {
a.<!OVERLOAD_RESOLUTION_AMBIGUITY!>contains<!>("")
a.<!NONE_APPLICABLE!>contains<!>(1)
"" <!OVERLOAD_RESOLUTION_AMBIGUITY!>in<!> a
1 <!NONE_APPLICABLE!>in<!> a
a.contains("")
a.contains(<!ARGUMENT_TYPE_MISMATCH!>1<!>)
"" in a
<!ARGUMENT_TYPE_MISMATCH!>1<!> in a
ka.contains("")
ka.contains(<!ARGUMENT_TYPE_MISMATCH!>1<!>)
@@ -1,25 +0,0 @@
// FILE: AImpl.java
abstract public class AImpl {
public char charAt(int index) {
return '1';
}
public final int length() { return 1; }
}
// FILE: A.java
public class A extends AImpl implements CharSequence {
public CharSequence subSequence(int start, int end) {
return null;
}
}
// FILE: X.kt
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class X<!> : A()
fun main() {
val x = X()
x[0]
x.length
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: AImpl.java
abstract public class AImpl {
@@ -0,0 +1,16 @@
interface A {
fun foo() {}
}
interface B : A {
abstract override fun foo()
}
interface C : A {
abstract override fun foo()
}
interface D : A
// Fake override Z#foo should be abstract
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>class Z<!> : B, C, D
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
interface A {
fun foo() {}
}
+1 -1
View File
@@ -10,7 +10,7 @@ interface T {
}
class G : C(), T {
override fun foo() {} //should be an error "cannot infer visibility"; for now 'public' is inferred in such cases
override fun <!CANNOT_CHANGE_ACCESS_PRIVILEGE!>foo<!>() {} //should be an error "cannot infer visibility"; for now 'public' is inferred in such cases
}
open class A {
@@ -0,0 +1,72 @@
// !JVM_DEFAULT_MODE: enable
// !JVM_TARGET: 1.8
// FILE: JavaInterface.java
public interface JavaInterface {
default void test() {}
default void testForNonDefault() {}
void testAbstract();
}
// FILE: 1.kt
interface KotlinInterface : JavaInterface {
@<!DEPRECATION!>JvmDefault<!>
override fun test() {}
<!NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT!>override fun testForNonDefault()<!> {}
override fun testAbstract() {}
}
interface KotlinInterface2 : JavaInterface, KotlinInterface {
@<!DEPRECATION!>JvmDefault<!>
override fun test() {}
<!NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT!>override fun testForNonDefault()<!> {}
override fun testAbstract() {}
}
interface KotlinInterfaceForIndirect : JavaInterface {
}
interface KotlinInterfaceIndirectInheritance : KotlinInterfaceForIndirect {
@<!DEPRECATION!>JvmDefault<!>
override fun test() {}
<!NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT!>override fun testForNonDefault()<!> {}
override fun testAbstract() {}
}
open class KotlinClass : JavaInterface {
override fun test() {}
override fun testForNonDefault() {}
override fun testAbstract() {}
}
interface KotlinInterfaceX {
fun test() {}
fun testForNonDefault() {}
fun testAbstract() {}
}
interface KotlinInterfaceManySuper: JavaInterface, KotlinInterfaceX {
@<!DEPRECATION!>JvmDefault<!>
override fun test() {}
<!NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT!>override fun testForNonDefault()<!> {}
override fun testAbstract() {}
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// !JVM_DEFAULT_MODE: enable
// !JVM_TARGET: 1.8
+61
View File
@@ -0,0 +1,61 @@
FILE fqName:<root> fileName:/kt45853.kt
CLASS CLASS name:A modality:ABSTRACT visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.A
CONSTRUCTOR visibility:public <> () returnType:<root>.A [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:A modality:ABSTRACT visibility:public superTypes:[kotlin.Any]'
PROPERTY name:a visibility:public modality:ABSTRACT [val]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-a> visibility:public modality:ABSTRACT <> ($this:<root>.A) returnType:<root>.A?
correspondingProperty: PROPERTY name:a visibility:public modality:ABSTRACT [val]
$this: VALUE_PARAMETER name:<this> type:<root>.A
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
CLASS CLASS name:B modality:FINAL visibility:public superTypes:[<root>.AX]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.B
CONSTRUCTOR visibility:public <> () returnType:<root>.B [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.AX'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:B modality:FINAL visibility:public superTypes:[<root>.AX]'
FUN name:getA visibility:public modality:FINAL <> ($this:<root>.B) returnType:<root>.X?
overridden:
public abstract fun getA (): @[FlexibleNullability] <root>.X? [fake_override] declared in <root>.AX
$this: VALUE_PARAMETER name:<this> type:<root>.B
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun getA (): <root>.X? declared in <root>.B'
CALL 'public open fun <get-a> (): @[FlexibleNullability] <root>.AX? declared in <root>.AX' superQualifier='CLASS IR_EXTERNAL_JAVA_DECLARATION_STUB CLASS name:AX modality:ABSTRACT visibility:public superTypes:[<root>.A; <root>.X]' type=@[FlexibleNullability] <root>.AX? origin=GET_PROPERTY
$this: GET_VAR '<this>: <root>.B declared in <root>.B.getA' type=<root>.B origin=null
PROPERTY FAKE_OVERRIDE name:a visibility:public modality:OPEN [fake_override,val]
overridden:
public open a: @[FlexibleNullability] <root>.AX? [val]
FUN FAKE_OVERRIDE name:<get-a> visibility:public modality:OPEN <> ($this:<root>.AX) returnType:@[FlexibleNullability] <root>.AX? [fake_override]
annotations:
Override
correspondingProperty: PROPERTY FAKE_OVERRIDE name:a visibility:public modality:OPEN [fake_override,val]
overridden:
public open fun <get-a> (): @[FlexibleNullability] <root>.AX? declared in <root>.AX
$this: VALUE_PARAMETER name:<this> type:<root>.AX
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in <root>.AX
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int [fake_override] declared in <root>.AX
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String [fake_override] declared in <root>.AX
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
-3
View File
@@ -1,5 +1,4 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// SKIP_KT_DUMP
// DUMP_EXTERNAL_CLASS: X
// DUMP_EXTERNAL_CLASS: AX
@@ -9,8 +8,6 @@ abstract class A {
abstract val a: A?
}
//Fir doesn't treat B.getA as an override, because it is not return-type compatible with AX.getA
// Which might be correct behaivour. So disable fir till KT-46042
class B() : AX() {
override fun getA(): X? = super.a
}
@@ -9,6 +9,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
FUN DELEGATED_MEMBER name:add visibility:public modality:OPEN <> ($this:<root>.Impl, element:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Boolean
overridden:
public abstract fun add (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in <root>.Foo.A
public abstract fun add (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in <root>.Foo.B
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:element index:0 type:@[FlexibleNullability] kotlin.String?
BLOCK_BODY
@@ -20,6 +21,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
FUN DELEGATED_MEMBER name:addAll visibility:public modality:OPEN <> ($this:<root>.Impl, elements:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>) returnType:kotlin.Boolean
overridden:
public abstract fun addAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.A
public abstract fun addAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.B
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>
BLOCK_BODY
@@ -31,6 +33,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
FUN DELEGATED_MEMBER name:clear visibility:public modality:OPEN <> ($this:<root>.Impl) returnType:kotlin.Unit
overridden:
public abstract fun clear (): kotlin.Unit [fake_override] declared in <root>.Foo.A
public abstract fun clear (): kotlin.Unit [fake_override] declared in <root>.Foo.B
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
BLOCK_BODY
CALL 'public abstract fun clear (): kotlin.Unit [fake_override] declared in <root>.Foo.B' type=kotlin.Unit origin=null
@@ -39,6 +42,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
FUN DELEGATED_MEMBER name:iterator visibility:public modality:OPEN <> ($this:<root>.Impl) returnType:kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [operator]
overridden:
public abstract fun iterator (): kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [fake_override,operator] declared in <root>.Foo.A
public abstract fun iterator (): kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [fake_override,operator] declared in <root>.Foo.B
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun iterator (): kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [operator] declared in <root>.Impl'
@@ -48,6 +52,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
FUN DELEGATED_MEMBER name:remove visibility:public modality:OPEN <> ($this:<root>.Impl, element:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Boolean
overridden:
public abstract fun remove (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in <root>.Foo.A
public abstract fun remove (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in <root>.Foo.B
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:element index:0 type:@[FlexibleNullability] kotlin.String?
BLOCK_BODY
@@ -59,6 +64,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
FUN DELEGATED_MEMBER name:removeAll visibility:public modality:OPEN <> ($this:<root>.Impl, elements:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>) returnType:kotlin.Boolean
overridden:
public abstract fun removeAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.A
public abstract fun removeAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.B
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>
BLOCK_BODY
@@ -70,6 +76,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
FUN DELEGATED_MEMBER name:retainAll visibility:public modality:OPEN <> ($this:<root>.Impl, elements:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>) returnType:kotlin.Boolean
overridden:
public abstract fun retainAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.A
public abstract fun retainAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.B
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>
BLOCK_BODY
@@ -81,6 +88,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
FUN DELEGATED_MEMBER name:contains visibility:public modality:OPEN <> ($this:<root>.Impl, element:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Boolean [operator]
overridden:
public abstract fun contains (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override,operator] declared in <root>.Foo.A
public abstract fun contains (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override,operator] declared in <root>.Foo.B
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:element index:0 type:@[FlexibleNullability] kotlin.String?
BLOCK_BODY
@@ -92,6 +100,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
FUN DELEGATED_MEMBER name:containsAll visibility:public modality:OPEN <> ($this:<root>.Impl, elements:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>) returnType:kotlin.Boolean
overridden:
public abstract fun containsAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.A
public abstract fun containsAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.B
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>
BLOCK_BODY
@@ -103,6 +112,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
FUN DELEGATED_MEMBER name:isEmpty visibility:public modality:OPEN <> ($this:<root>.Impl) returnType:kotlin.Boolean
overridden:
public abstract fun isEmpty (): kotlin.Boolean [fake_override] declared in <root>.Foo.A
public abstract fun isEmpty (): kotlin.Boolean [fake_override] declared in <root>.Foo.B
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun isEmpty (): kotlin.Boolean declared in <root>.Impl'
@@ -112,10 +122,12 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
PROPERTY DELEGATED_MEMBER name:size visibility:public modality:OPEN [val]
overridden:
public abstract size: kotlin.Int [fake_override,val]
public abstract size: kotlin.Int [fake_override,val]
FUN DELEGATED_MEMBER name:<get-size> visibility:public modality:OPEN <> ($this:<root>.Impl) returnType:kotlin.Int
correspondingProperty: PROPERTY DELEGATED_MEMBER name:size visibility:public modality:OPEN [val]
overridden:
public abstract fun <get-size> (): kotlin.Int [fake_override] declared in <root>.Foo.A
public abstract fun <get-size> (): kotlin.Int [fake_override] declared in <root>.Foo.B
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-size> (): kotlin.Int declared in <root>.Impl'
@@ -154,6 +154,7 @@ FILE fqName:<root> fileName:/ImplicitReceiverStack.kt
FUN name:iterator visibility:public modality:FINAL <> ($this:<root>.PersistentImplicitReceiverStack) returnType:kotlin.collections.Iterator<<root>.ImplicitReceiverValue<*>> [operator]
overridden:
public abstract fun iterator (): kotlin.collections.Iterator<<root>.ImplicitReceiverValue<*>> [fake_override,operator] declared in <root>.ImplicitReceiverStack
public abstract fun iterator (): kotlin.collections.Iterator<T of kotlin.collections.Iterable> [operator] declared in kotlin.collections.Iterable
$this: VALUE_PARAMETER name:<this> type:<root>.PersistentImplicitReceiverStack
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun iterator (): kotlin.collections.Iterator<<root>.ImplicitReceiverValue<*>> [operator] declared in <root>.PersistentImplicitReceiverStack'
@@ -378,9 +378,9 @@ FILE fqName:<root> fileName:/MultiList.kt
public open fun sort (p0: @[FlexibleNullability] java.util.Comparator<in @[FlexibleNullability] E of java.util.ArrayList?>?): kotlin.Unit declared in java.util.ArrayList
$this: VALUE_PARAMETER name:<this> type:java.util.ArrayList<E of java.util.ArrayList>
VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] java.util.Comparator<in @[FlexibleNullability] <root>.Some<T of <root>.SomeList>?>?
FUN FAKE_OVERRIDE name:removeAt visibility:public modality:OPEN <> ($this:java.util.ArrayList<E of java.util.ArrayList>, p0:kotlin.Int) returnType:@[EnhancedNullability] <root>.Some<T of <root>.SomeList> [fake_override]
FUN FAKE_OVERRIDE name:removeAt visibility:public modality:OPEN <> ($this:java.util.ArrayList<E of java.util.ArrayList>, p0:kotlin.Int) returnType:@[EnhancedNullability] <root>.Some<T of <root>.SomeList> [fake_override,operator]
overridden:
public open fun removeAt (p0: kotlin.Int): @[EnhancedNullability] E of java.util.ArrayList declared in java.util.ArrayList
public open fun removeAt (p0: kotlin.Int): @[EnhancedNullability] E of java.util.ArrayList [operator] declared in java.util.ArrayList
$this: VALUE_PARAMETER name:<this> type:java.util.ArrayList<E of java.util.ArrayList>
VALUE_PARAMETER name:p0 index:0 type:kotlin.Int
CLASS CLASS name:FinalList modality:FINAL visibility:public superTypes:[<root>.SomeList<kotlin.String>]
@@ -572,8 +572,8 @@ FILE fqName:<root> fileName:/MultiList.kt
public open fun sort (p0: @[FlexibleNullability] java.util.Comparator<in @[FlexibleNullability] <root>.Some<T of <root>.SomeList>?>?): kotlin.Unit [fake_override] declared in <root>.SomeList
$this: VALUE_PARAMETER name:<this> type:java.util.ArrayList<E of java.util.ArrayList>
VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] java.util.Comparator<in @[FlexibleNullability] <root>.Some<kotlin.String>?>?
FUN FAKE_OVERRIDE name:removeAt visibility:public modality:OPEN <> ($this:java.util.ArrayList<E of java.util.ArrayList>, p0:kotlin.Int) returnType:@[EnhancedNullability] <root>.Some<kotlin.String> [fake_override]
FUN FAKE_OVERRIDE name:removeAt visibility:public modality:OPEN <> ($this:java.util.ArrayList<E of java.util.ArrayList>, p0:kotlin.Int) returnType:@[EnhancedNullability] <root>.Some<kotlin.String> [fake_override,operator]
overridden:
public open fun removeAt (p0: kotlin.Int): @[EnhancedNullability] <root>.Some<T of <root>.SomeList> [fake_override] declared in <root>.SomeList
public open fun removeAt (p0: kotlin.Int): @[EnhancedNullability] <root>.Some<T of <root>.SomeList> [fake_override,operator] declared in <root>.SomeList
$this: VALUE_PARAMETER name:<this> type:java.util.ArrayList<E of java.util.ArrayList>
VALUE_PARAMETER name:p0 index:0 type:kotlin.Int