From 1b81018b696b2a7f0f6d26913ab46c647113e9e8 Mon Sep 17 00:00:00 2001 From: Andrey Zinovyev Date: Fri, 6 Aug 2021 14:11:40 +0300 Subject: [PATCH] [FIR] Fix overloading of renamed jvm methods #KT-48102 Fixed --- ...irOldFrontendDiagnosticsTestGenerated.java | 6 +++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 +++ .../scopes/JavaClassUseSiteMemberScope.kt | 13 +++++++ .../src/org/jetbrains/kotlin/fir/CopyUtils.kt | 6 ++- .../mappedFunctionNotImplemented.kt | 13 +++++++ .../mappedFunctionNotImplemented.txt | 21 ++++++++++ .../overridesBuiltinNoMagic.fir.kt | 6 +-- .../collectionOverrides/removeAtInt.fir.kt | 32 ---------------- .../j+k/collectionOverrides/removeAtInt.kt | 1 + .../j+k/kt1730_implementCharSequence.fir.kt | 24 ------------ .../tests/j+k/kt1730_implementCharSequence.kt | 1 + .../test/runners/DiagnosticTestGenerated.java | 6 +++ ...CompilerTestFE10TestdataTestGenerated.java | 6 +++ .../memberScopeByFqName/java.lang.String.txt | 38 +++---------------- 14 files changed, 86 insertions(+), 93 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/declarationChecks/mappedFunctionNotImplemented.kt create mode 100644 compiler/testData/diagnostics/tests/declarationChecks/mappedFunctionNotImplemented.txt delete mode 100644 compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.fir.kt diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 92b8ac89496..6180ba65515 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -7495,6 +7495,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/declarationChecks/localVariablesWithTypeParameters_1_4.kt"); } + @Test + @TestMetadata("mappedFunctionNotImplemented.kt") + public void testMappedFunctionNotImplemented() throws Exception { + runTest("compiler/testData/diagnostics/tests/declarationChecks/mappedFunctionNotImplemented.kt"); + } + @Test @TestMetadata("mulitpleVarargParameters.kt") public void testMulitpleVarargParameters() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index 2fda0495226..f7625c0550b 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -7495,6 +7495,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/declarationChecks/localVariablesWithTypeParameters_1_4.kt"); } + @Test + @TestMetadata("mappedFunctionNotImplemented.kt") + public void testMappedFunctionNotImplemented() throws Exception { + runTest("compiler/testData/diagnostics/tests/declarationChecks/mappedFunctionNotImplemented.kt"); + } + @Test @TestMetadata("mulitpleVarargParameters.kt") public void testMulitpleVarargParameters() throws Exception { diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt index e592d617b42..47dd4e6e0d8 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty import org.jetbrains.kotlin.fir.declarations.utils.isInterface +import org.jetbrains.kotlin.fir.declarations.utils.isOperator import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass @@ -299,6 +300,13 @@ class JavaClassUseSiteMemberScope( ): 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 @@ -308,6 +316,7 @@ class JavaClassUseSiteMemberScope( 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 } @@ -415,6 +424,10 @@ class JavaClassUseSiteMemberScope( 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())) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt index b4bc25ff502..c40c2010a02 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt @@ -179,9 +179,10 @@ fun FirDeclarationStatus.copy( isExpect: Boolean = this.isExpect, newModality: Modality? = null, newVisibility: Visibility? = null, - newEffectiveVisibility: EffectiveVisibility? = null + newEffectiveVisibility: EffectiveVisibility? = null, + isOperator: Boolean = this.isOperator ): FirDeclarationStatus { - return if (this.isExpect == isExpect && newModality == null && newVisibility == null) { + return if (this.isExpect == isExpect && newModality == null && newVisibility == null && this.isOperator == isOperator) { this } else { require(this is FirDeclarationStatusImpl) { "Unexpected class ${this::class}" } @@ -191,6 +192,7 @@ fun FirDeclarationStatus.copy( newEffectiveVisibility ?: EffectiveVisibility.Public ).apply { this.isExpect = isExpect + this.isOperator = isOperator } } } diff --git a/compiler/testData/diagnostics/tests/declarationChecks/mappedFunctionNotImplemented.kt b/compiler/testData/diagnostics/tests/declarationChecks/mappedFunctionNotImplemented.kt new file mode 100644 index 00000000000..d709d9b658b --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/mappedFunctionNotImplemented.kt @@ -0,0 +1,13 @@ +// KT-48102 +// FIR_IDENTICAL + +// FILE: MyCharSequence.java +public class MyCharSequence implements CharSequence { + public char charAt(int index) { return ' '; } + public int length() { return 1; } + public CharSequence subSequence(int start, int end) { return this; } + public String toString() { return " "; } +} + +// FILE: CharSeq.kt +class KtCharSeq : MyCharSequence() // false-positive 'get' not implemented \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/mappedFunctionNotImplemented.txt b/compiler/testData/diagnostics/tests/declarationChecks/mappedFunctionNotImplemented.txt new file mode 100644 index 00000000000..25520b35bbf --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/mappedFunctionNotImplemented.txt @@ -0,0 +1,21 @@ +package + +public final class KtCharSeq : MyCharSequence { + public constructor KtCharSeq() + public open override /*1*/ /*fake_override*/ val length: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun get(/*0*/ index: kotlin.Int): kotlin.Char + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun subSequence(/*0*/ startIndex: kotlin.Int, /*1*/ endIndex: kotlin.Int): kotlin.CharSequence + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class MyCharSequence : kotlin.CharSequence { + public constructor MyCharSequence() + public open override /*1*/ val length: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun get(/*0*/ index: kotlin.Int): kotlin.Char + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ fun subSequence(/*0*/ startIndex: kotlin.Int, /*1*/ endIndex: kotlin.Int): kotlin.CharSequence + public open override /*1*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.fir.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.fir.kt index 104ba2ee53e..a25795d18de 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.fir.kt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.fir.kt @@ -150,14 +150,14 @@ class Y2 : X() { fun main() { X().remove("") - X().removeAt(1) + X().removeAt(1) val y: MutableList = Y() y.removeAt(1) Y().remove("") - Y().removeAt(1) + Y().removeAt(1) X().remove("") - X().removeAt(1) + X().removeAt(1) } diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.fir.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.fir.kt deleted file mode 100644 index 60d481ca3a9..00000000000 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.fir.kt +++ /dev/null @@ -1,32 +0,0 @@ -// JAVAC_EXPECTED_FILE -// FILE: A.java -abstract public class A extends B { - public Integer removeAt(int x) { } - public boolean remove(Integer x) { } -} - -// FILE: main.kt -import java.util.*; - -abstract class B : MutableList, AbstractList() { - override fun removeAt(index: Int): Int = null!! - override fun remove(element: Int): Boolean = null!! -} - -abstract class D : AbstractList() { - // removeAt() doesn't exist in java/util/AbstractList, it's a - // fake override of the method from kotlin/collections/MutableList - override fun removeAt(index: Int): Int = null!! - // AbstractList::remove() should return Int here. No fake overrides created. - // This may be a bug because the old compiler doesn't report a diagnostic here. - override fun remove(element: Int): Boolean = null!! -} - -fun main(a: A, b: B, c: ArrayList) { - a.remove(1) - a.removeAt(0) - b.remove(1) - b.removeAt(0) - c.remove(1) - c.removeAt(0) -} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.kt index 8510bc01ac0..581138898ae 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.kt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // JAVAC_EXPECTED_FILE // FILE: A.java abstract public class A extends B { diff --git a/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.fir.kt b/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.fir.kt deleted file mode 100644 index 44e6aaa4666..00000000000 --- a/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.fir.kt +++ /dev/null @@ -1,24 +0,0 @@ -// KT-1730 Method which has been implemented by Java is recognized to be abstract. - -// FILE: C.java -public class C implements java.lang.CharSequence { - @Override - public int length() { - return 3; - } - @Override - public char charAt(int index) { - return 48; - } - @Override - public CharSequence subSequence(int start, int end) { - return "ab"; - } - @Override - public String toString() { - return "abc"; - } -} - -// FILE: T.kt -class T : C() diff --git a/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.kt b/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.kt index 7efe604a0e4..5ff49bd9058 100644 --- a/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.kt +++ b/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // KT-1730 Method which has been implemented by Java is recognized to be abstract. // FILE: C.java diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index aa64ae61bdc..ca320c3de02 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -7501,6 +7501,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/declarationChecks/localVariablesWithTypeParameters_1_4.kt"); } + @Test + @TestMetadata("mappedFunctionNotImplemented.kt") + public void testMappedFunctionNotImplemented() throws Exception { + runTest("compiler/testData/diagnostics/tests/declarationChecks/mappedFunctionNotImplemented.kt"); + } + @Test @TestMetadata("mulitpleVarargParameters.kt") public void testMulitpleVarargParameters() throws Exception { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index b6a24e7db7e..ba356974241 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -7495,6 +7495,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/declarationChecks/localVariablesWithTypeParameters_1_4.kt"); } + @Test + @TestMetadata("mappedFunctionNotImplemented.kt") + public void testMappedFunctionNotImplemented() throws Exception { + runTest("compiler/testData/diagnostics/tests/declarationChecks/mappedFunctionNotImplemented.kt"); + } + @Test @TestMetadata("mulitpleVarargParameters.kt") public void testMulitpleVarargParameters() throws Exception { diff --git a/idea/idea-frontend-fir/testData/memberScopeByFqName/java.lang.String.txt b/idea/idea-frontend-fir/testData/memberScopeByFqName/java.lang.String.txt index 3e10ea76399..f7545245182 100644 --- a/idea/idea-frontend-fir/testData/memberScopeByFqName/java.lang.String.txt +++ b/idea/idea-frontend-fir/testData/memberScopeByFqName/java.lang.String.txt @@ -110,32 +110,6 @@ KtFirFunctionSymbol: valueParameters: [] visibility: Public -KtFirFunctionSymbol: - annotatedType: [] kotlin/Char - annotationClassIds: [] - annotations: [] - callableIdIfNonLocal: java/lang/String.charAt - dispatchType: java/lang/String - hasStableParameterNames: false - isExtension: false - isExternal: false - isInfix: false - isInline: false - isOperator: false - isOverride: false - isStatic: false - isSuspend: false - modality: OPEN - name: charAt - origin: JAVA - receiverType: null - symbolKind: MEMBER - typeParameters: [] - valueParameters: [ - KtFirValueParameterSymbol(p0) - ] - visibility: Public - KtFirFunctionSymbol: annotatedType: [] kotlin/Int annotationClassIds: [] @@ -1511,9 +1485,9 @@ KtFirFunctionSymbol: annotatedType: [] kotlin/Char annotationClassIds: [] annotations: [] - callableIdIfNonLocal: kotlin/CharSequence.get - dispatchType: @EnhancedNullability kotlin/CharSequence - hasStableParameterNames: true + callableIdIfNonLocal: java/lang/String.get + dispatchType: java/lang/String + hasStableParameterNames: false isExtension: false isExternal: false isInfix: false @@ -1522,14 +1496,14 @@ KtFirFunctionSymbol: isOverride: false isStatic: false isSuspend: false - modality: ABSTRACT + modality: OPEN name: get - origin: LIBRARY + origin: JAVA receiverType: null symbolKind: MEMBER typeParameters: [] valueParameters: [ - KtFirValueParameterSymbol(index) + KtFirValueParameterSymbol(p0) ] visibility: Public