diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 27b1e7f2eee..777f2088202 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -11838,6 +11838,18 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/fieldRename/derivedClassPropertyShadowsBaseClassField13.kt"); } + @Test + @TestMetadata("javaFieldKotlinPropertyDifferentType.kt") + public void testJavaFieldKotlinPropertyDifferentType() throws Exception { + runTest("compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType.kt"); + } + + @Test + @TestMetadata("javaFieldKotlinPropertyDifferentType2.kt") + public void testJavaFieldKotlinPropertyDifferentType2() throws Exception { + runTest("compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType2.kt"); + } + @Test @TestMetadata("javaFieldKotlinPropertyJavaFieldInPackagePrivate.kt") public void testJavaFieldKotlinPropertyJavaFieldInPackagePrivate() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index 985fc6ea386..78f2370e0d2 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -11838,6 +11838,18 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/fieldRename/derivedClassPropertyShadowsBaseClassField13.kt"); } + @Test + @TestMetadata("javaFieldKotlinPropertyDifferentType.kt") + public void testJavaFieldKotlinPropertyDifferentType() throws Exception { + runTest("compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType.kt"); + } + + @Test + @TestMetadata("javaFieldKotlinPropertyDifferentType2.kt") + public void testJavaFieldKotlinPropertyDifferentType2() throws Exception { + runTest("compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType2.kt"); + } + @Test @TestMetadata("javaFieldKotlinPropertyJavaFieldInPackagePrivate.kt") public void testJavaFieldKotlinPropertyJavaFieldInPackagePrivate() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 21e5028dbc3..477fa11ea11 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -11838,6 +11838,18 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/fieldRename/derivedClassPropertyShadowsBaseClassField13.kt"); } + @Test + @TestMetadata("javaFieldKotlinPropertyDifferentType.kt") + public void testJavaFieldKotlinPropertyDifferentType() throws Exception { + runTest("compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType.kt"); + } + + @Test + @TestMetadata("javaFieldKotlinPropertyDifferentType2.kt") + public void testJavaFieldKotlinPropertyDifferentType2() throws Exception { + runTest("compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType2.kt"); + } + @Test @TestMetadata("javaFieldKotlinPropertyJavaFieldInPackagePrivate.kt") public void testJavaFieldKotlinPropertyJavaFieldInPackagePrivate() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index 45435fe951e..aa5c69d2406 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -11844,6 +11844,18 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/fieldRename/derivedClassPropertyShadowsBaseClassField13.kt"); } + @Test + @TestMetadata("javaFieldKotlinPropertyDifferentType.kt") + public void testJavaFieldKotlinPropertyDifferentType() throws Exception { + runTest("compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType.kt"); + } + + @Test + @TestMetadata("javaFieldKotlinPropertyDifferentType2.kt") + public void testJavaFieldKotlinPropertyDifferentType2() throws Exception { + runTest("compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType2.kt"); + } + @Test @TestMetadata("javaFieldKotlinPropertyJavaFieldInPackagePrivate.kt") public void testJavaFieldKotlinPropertyJavaFieldInPackagePrivate() throws Exception { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmPropertyVsFieldAmbiguityCallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmPropertyVsFieldAmbiguityCallChecker.kt index 253933205a5..67db347032c 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmPropertyVsFieldAmbiguityCallChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmPropertyVsFieldAmbiguityCallChecker.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.load.java.lazy.descriptors.isJavaField +import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptorWithoutName import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext @@ -42,8 +43,13 @@ object JvmPropertyVsFieldAmbiguityCallChecker : CallChecker { val hasLateInit = basePropertyDescriptor.selfOrBaseForFakeOverride { it.isLateInit } val hasCustomGetter = basePropertyDescriptor.selfOrBaseForFakeOverride { it.getter?.isDefault == false } val hasCustomSetter = basePropertyDescriptor.selfOrBaseForFakeOverride { it.setter?.isDefault == false } + + val jvmDescriptorForField = resultingDescriptor.computeJvmDescriptorWithoutName() + val jvmDescriptorForProperty = alternativePropertyDescriptor.computeJvmDescriptorWithoutName() + if (!hasLateInit && !hasCustomGetter && !hasCustomSetter && - basePropertyDescriptor.modality == Modality.FINAL + basePropertyDescriptor.modality == Modality.FINAL && + jvmDescriptorForField == jvmDescriptorForProperty ) return@forEach if (fieldClassDescriptor != null && propertyClassDescriptor != null && DescriptorUtils.isSubclass(fieldClassDescriptor, propertyClassDescriptor) @@ -58,7 +64,8 @@ object JvmPropertyVsFieldAmbiguityCallChecker : CallChecker { val factory = when { hasCustomGetter -> ErrorsJvm.BASE_CLASS_FIELD_SHADOWS_DERIVED_CLASS_PROPERTY hasLateInit || hasCustomSetter -> ErrorsJvm.BACKING_FIELD_ACCESSED_DUE_TO_PROPERTY_FIELD_CONFLICT - else -> ErrorsJvm.BASE_CLASS_FIELD_MAY_SHADOW_DERIVED_CLASS_PROPERTY + basePropertyDescriptor.modality != Modality.FINAL -> ErrorsJvm.BASE_CLASS_FIELD_MAY_SHADOW_DERIVED_CLASS_PROPERTY + else -> ErrorsJvm.BASE_CLASS_FIELD_WITH_DIFFERENT_SIGNATURE_THAN_DERIVED_CLASS_PROPERTY } context.trace.report( factory.on( diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java index 278abe78820..6c00babb18d 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java @@ -250,6 +250,12 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { "This behavior will be changed soon in favor of the property. " + "Please use explicit cast to {0} if you wish to preserve current behavior. " + "See https://youtrack.jetbrains.com/issue/KT-55017 for details", STRING, STRING); + + MAP.put(BASE_CLASS_FIELD_WITH_DIFFERENT_SIGNATURE_THAN_DERIVED_CLASS_PROPERTY, + "Now field from base class {0} shadows the property with different type from derived class {1}. " + + "This behavior will be changed soon in favor of the property. " + + "Please use explicit cast to {0} if you wish to preserve current behavior. " + + "See https://youtrack.jetbrains.com/issue/KT-55017 for details", STRING, STRING); } @NotNull diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java index 60ada841fa7..380e5488839 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java @@ -214,6 +214,8 @@ public interface ErrorsJvm { DiagnosticFactory2 BACKING_FIELD_ACCESSED_DUE_TO_PROPERTY_FIELD_CONFLICT = DiagnosticFactory2.create(WARNING); + DiagnosticFactory2 BASE_CLASS_FIELD_WITH_DIFFERENT_SIGNATURE_THAN_DERIVED_CLASS_PROPERTY = DiagnosticFactory2.create(WARNING); + @SuppressWarnings("UnusedDeclaration") Object _initializer = new Object() { { diff --git a/compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType.fir.kt b/compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType.fir.kt new file mode 100644 index 00000000000..b7d0e296252 --- /dev/null +++ b/compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType.fir.kt @@ -0,0 +1,19 @@ +// ISSUE: KT-57905 + +// FILE: Base.java +public class Base { + String value = null; + String extension = null; +} + +// FILE: Main.kt +class Derived: Base() { + val value: Int = 42 + val something: String = value + + val String.extension: Int get() = 42 + fun String.foo() { + // K1 & K2 work in the same way here (resolve to an extension property) + val something: String = extension + } +} diff --git a/compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType.kt b/compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType.kt new file mode 100644 index 00000000000..948662b9492 --- /dev/null +++ b/compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType.kt @@ -0,0 +1,19 @@ +// ISSUE: KT-57905 + +// FILE: Base.java +public class Base { + String value = null; + String extension = null; +} + +// FILE: Main.kt +class Derived: Base() { + val value: Int = 42 + val something: String = value + + val String.extension: Int get() = 42 + fun String.foo() { + // K1 & K2 work in the same way here (resolve to an extension property) + val something: String = extension + } +} diff --git a/compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType2.fir.kt b/compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType2.fir.kt new file mode 100644 index 00000000000..6bb60c40fab --- /dev/null +++ b/compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType2.fir.kt @@ -0,0 +1,16 @@ +// ISSUE: KT-57905 + +// FILE: BasicSliderUI.java +public class BasicSliderUI { + Rectangle thumbRect = null; +} + +// FILE: Main.kt + +class Rectangle + +class TimelineSliderUI: BasicSliderUI() { + // K1: ok + // K2: INITIALIZER_TYPE_MISMATCH (actual kotlin/Function0>, expected kotlin/Function0) + val thumbRect: () -> Rectangle = { thumbRect } +} diff --git a/compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType2.kt b/compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType2.kt new file mode 100644 index 00000000000..86633a28647 --- /dev/null +++ b/compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType2.kt @@ -0,0 +1,16 @@ +// ISSUE: KT-57905 + +// FILE: BasicSliderUI.java +public class BasicSliderUI { + Rectangle thumbRect = null; +} + +// FILE: Main.kt + +class Rectangle + +class TimelineSliderUI: BasicSliderUI() { + // K1: ok + // K2: INITIALIZER_TYPE_MISMATCH (actual kotlin/Function0>, expected kotlin/Function0) + val thumbRect: () -> Rectangle = { thumbRect } +} 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 73fc97c33a4..9690ba9f7d5 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 @@ -11844,6 +11844,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/fieldRename/derivedClassPropertyShadowsBaseClassField13.kt"); } + @Test + @TestMetadata("javaFieldKotlinPropertyDifferentType.kt") + public void testJavaFieldKotlinPropertyDifferentType() throws Exception { + runTest("compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType.kt"); + } + + @Test + @TestMetadata("javaFieldKotlinPropertyDifferentType2.kt") + public void testJavaFieldKotlinPropertyDifferentType2() throws Exception { + runTest("compiler/testData/diagnostics/tests/fieldRename/javaFieldKotlinPropertyDifferentType2.kt"); + } + @Test @TestMetadata("javaFieldKotlinPropertyJavaFieldInPackagePrivate.kt") public void testJavaFieldKotlinPropertyJavaFieldInPackagePrivate() throws Exception { diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt index 40b23de0b32..bd64253c3cf 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt @@ -44,6 +44,22 @@ fun FunctionDescriptor.computeJvmDescriptor(withReturnType: Boolean = true, with } } +fun PropertyDescriptor.computeJvmDescriptorWithoutName() = buildString { + append("(") + + extensionReceiverParameter?.let { + appendErasedType(it.type) + } + + append(")") + + if (hasVoidReturnType(this@computeJvmDescriptorWithoutName)) { + append("V") + } else { + appendErasedType(returnType!!) + } +} + // Boxing is only necessary for 'remove(E): Boolean' of a MutableCollection implementation // Otherwise this method might clash with 'remove(I): E' defined in the java.util.List JDK interface (mapped to kotlin 'removeAt') fun forceSingleValueParameterBoxing(f: CallableDescriptor): Boolean {