Support fake Java property overrides in function equality in bridges
A synthetic property descriptor created for `B.value` (see the added test) should not be equal to the normal descriptor created by the fake override construction algorithm. Otherwise we can't reach this synthetic non-abstract descriptor when building bridges in `C`, which results in exception. #KT-31367 Fixed
This commit is contained in:
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.codegen.state.GenerationState
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||||
|
import org.jetbrains.kotlin.load.java.descriptors.JavaForKotlinOverridePropertyDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmDefaultAnnotation
|
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmDefaultAnnotation
|
||||||
import org.jetbrains.kotlin.resolve.jvm.annotations.hasPlatformDependentAnnotation
|
import org.jetbrains.kotlin.resolve.jvm.annotations.hasPlatformDependentAnnotation
|
||||||
@@ -42,18 +44,27 @@ class DescriptorBasedFunctionHandleForJvm(
|
|||||||
override val mightBeIncorrectCode: Boolean
|
override val mightBeIncorrectCode: Boolean
|
||||||
get() = state.classBuilderMode.mightBeIncorrectCode
|
get() = state.classBuilderMode.mightBeIncorrectCode
|
||||||
|
|
||||||
override fun hashCode(): Int = descriptor.containerEntityForEqualityAndHashCode().hashCode() + 31 * asmMethod.hashCode()
|
override fun hashCode(): Int =
|
||||||
override fun equals(other: Any?): Boolean {
|
(descriptor.containerEntityForEqualityAndHashCode().hashCode() * 31 +
|
||||||
if (other !is DescriptorBasedFunctionHandleForJvm) return false
|
descriptor.isJavaForKotlinOverrideProperty.hashCode()) * 31 +
|
||||||
|
asmMethod.hashCode()
|
||||||
|
|
||||||
return asmMethod == other.asmMethod &&
|
override fun equals(other: Any?): Boolean {
|
||||||
descriptor.containerEntityForEqualityAndHashCode() == other.descriptor.containerEntityForEqualityAndHashCode()
|
if (this === other) return true
|
||||||
|
|
||||||
|
return other is DescriptorBasedFunctionHandleForJvm &&
|
||||||
|
asmMethod == other.asmMethod &&
|
||||||
|
descriptor.containerEntityForEqualityAndHashCode() == other.descriptor.containerEntityForEqualityAndHashCode() &&
|
||||||
|
descriptor.isJavaForKotlinOverrideProperty == other.descriptor.isJavaForKotlinOverrideProperty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FunctionDescriptor.containerEntityForEqualityAndHashCode(): Any =
|
private fun FunctionDescriptor.containerEntityForEqualityAndHashCode(): Any =
|
||||||
(containingDeclaration as? ClassDescriptor)?.typeConstructor ?: containingDeclaration
|
(containingDeclaration as? ClassDescriptor)?.typeConstructor ?: containingDeclaration
|
||||||
|
|
||||||
|
private val FunctionDescriptor.isJavaForKotlinOverrideProperty: Boolean
|
||||||
|
get() = this is PropertyAccessorDescriptor && correspondingProperty is JavaForKotlinOverridePropertyDescriptor
|
||||||
|
|
||||||
private fun CallableMemberDescriptor.isJvmDefaultOrPlatformDependent() =
|
private fun CallableMemberDescriptor.isJvmDefaultOrPlatformDependent() =
|
||||||
hasJvmDefaultAnnotation() || hasPlatformDependentAnnotation()
|
hasJvmDefaultAnnotation() || hasPlatformDependentAnnotation()
|
||||||
|
|
||||||
|
|||||||
compiler/testData/loadJava/kotlinAgainstCompiledJavaWithKotlin/javaGetterImplementsKotlinProperty.kt
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class C : B(), I
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public abstract class A {
|
||||||
|
public constructor A()
|
||||||
|
public open fun getValue(): kotlin.String!
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class B : test.A, test.I {
|
||||||
|
public constructor B()
|
||||||
|
public open override /*2*/ /*fake_override*/ val value: kotlin.String?
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class C : test.B, test.I {
|
||||||
|
public constructor C()
|
||||||
|
public open override /*2*/ /*fake_override*/ val value: kotlin.String?
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface I {
|
||||||
|
public abstract val value: kotlin.String?
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
public abstract class A {
|
||||||
|
public String getValue() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
public class B extends A implements I {
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
interface I {
|
||||||
|
val value: String?
|
||||||
|
}
|
||||||
+2
-2
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
|
|||||||
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace;
|
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace;
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM;
|
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM;
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt;
|
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt;
|
||||||
|
import org.jetbrains.kotlin.codegen.GenerationUtils;
|
||||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
|
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
|
||||||
import org.jetbrains.kotlin.config.*;
|
import org.jetbrains.kotlin.config.*;
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||||
@@ -26,7 +27,6 @@ import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
|
|||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil;
|
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor;
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor;
|
||||||
import org.jetbrains.kotlin.test.*;
|
import org.jetbrains.kotlin.test.*;
|
||||||
import org.jetbrains.kotlin.test.util.DescriptorValidator;
|
import org.jetbrains.kotlin.test.util.DescriptorValidator;
|
||||||
@@ -237,7 +237,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
|
|||||||
configureEnvironment(environment);
|
configureEnvironment(environment);
|
||||||
KtFile ktFile = KotlinTestUtils.createFile(kotlinSrc.getPath(), FileUtil.loadFile(kotlinSrc, true), environment.getProject());
|
KtFile ktFile = KotlinTestUtils.createFile(kotlinSrc.getPath(), FileUtil.loadFile(kotlinSrc, true), environment.getProject());
|
||||||
|
|
||||||
ModuleDescriptor module = JvmResolveUtil.analyzeAndCheckForErrors(Collections.singleton(ktFile), environment).getModuleDescriptor();
|
ModuleDescriptor module = GenerationUtils.compileFiles(Collections.singletonList(ktFile), environment).getModule();
|
||||||
PackageViewDescriptor packageView = module.getPackage(TEST_PACKAGE_FQNAME);
|
PackageViewDescriptor packageView = module.getPackage(TEST_PACKAGE_FQNAME);
|
||||||
assertFalse(packageView.isEmpty());
|
assertFalse(packageView.isEmpty());
|
||||||
|
|
||||||
|
|||||||
@@ -5052,6 +5052,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
|||||||
runTest("compiler/testData/loadJava/kotlinAgainstCompiledJavaWithKotlin/InheritParameterName.kt");
|
runTest("compiler/testData/loadJava/kotlinAgainstCompiledJavaWithKotlin/InheritParameterName.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaGetterImplementsKotlinProperty.kt")
|
||||||
|
public void testJavaGetterImplementsKotlinProperty() throws Exception {
|
||||||
|
runTest("compiler/testData/loadJava/kotlinAgainstCompiledJavaWithKotlin/javaGetterImplementsKotlinProperty.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("javaRefersToKotlin.kt")
|
@TestMetadata("javaRefersToKotlin.kt")
|
||||||
public void testJavaRefersToKotlin() throws Exception {
|
public void testJavaRefersToKotlin() throws Exception {
|
||||||
runTest("compiler/testData/loadJava/kotlinAgainstCompiledJavaWithKotlin/javaRefersToKotlin.kt");
|
runTest("compiler/testData/loadJava/kotlinAgainstCompiledJavaWithKotlin/javaRefersToKotlin.kt");
|
||||||
|
|||||||
Generated
+5
@@ -5052,6 +5052,11 @@ public class LoadJavaUsingJavacTestGenerated extends AbstractLoadJavaUsingJavacT
|
|||||||
runTest("compiler/testData/loadJava/kotlinAgainstCompiledJavaWithKotlin/InheritParameterName.kt");
|
runTest("compiler/testData/loadJava/kotlinAgainstCompiledJavaWithKotlin/InheritParameterName.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaGetterImplementsKotlinProperty.kt")
|
||||||
|
public void testJavaGetterImplementsKotlinProperty() throws Exception {
|
||||||
|
runTest("compiler/testData/loadJava/kotlinAgainstCompiledJavaWithKotlin/javaGetterImplementsKotlinProperty.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("javaRefersToKotlin.kt")
|
@TestMetadata("javaRefersToKotlin.kt")
|
||||||
public void testJavaRefersToKotlin() throws Exception {
|
public void testJavaRefersToKotlin() throws Exception {
|
||||||
runTest("compiler/testData/loadJava/kotlinAgainstCompiledJavaWithKotlin/javaRefersToKotlin.kt");
|
runTest("compiler/testData/loadJava/kotlinAgainstCompiledJavaWithKotlin/javaRefersToKotlin.kt");
|
||||||
|
|||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.load.java.descriptors
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
|
||||||
|
class JavaForKotlinOverridePropertyDescriptor(
|
||||||
|
ownerDescriptor: ClassDescriptor,
|
||||||
|
getterMethod: SimpleFunctionDescriptor,
|
||||||
|
setterMethod: SimpleFunctionDescriptor?,
|
||||||
|
overriddenProperty: PropertyDescriptor
|
||||||
|
) : JavaPropertyDescriptor(
|
||||||
|
ownerDescriptor,
|
||||||
|
Annotations.EMPTY,
|
||||||
|
getterMethod.modality,
|
||||||
|
getterMethod.visibility,
|
||||||
|
setterMethod != null,
|
||||||
|
overriddenProperty.name,
|
||||||
|
getterMethod.source,
|
||||||
|
null,
|
||||||
|
CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
)
|
||||||
+1
-1
@@ -37,7 +37,7 @@ public class JavaPropertyDescriptor extends PropertyDescriptorImpl implements Ja
|
|||||||
@Nullable
|
@Nullable
|
||||||
private final Pair<UserDataKey<?>, ?> singleUserData;
|
private final Pair<UserDataKey<?>, ?> singleUserData;
|
||||||
|
|
||||||
private JavaPropertyDescriptor(
|
protected JavaPropertyDescriptor(
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
@NotNull Annotations annotations,
|
@NotNull Annotations annotations,
|
||||||
@NotNull Modality modality,
|
@NotNull Modality modality,
|
||||||
|
|||||||
+1
-5
@@ -514,11 +514,7 @@ class LazyJavaClassMemberScope(
|
|||||||
"for getter is ${getterMethod.modality}, but for setter is ${setterMethod?.modality}"
|
"for getter is ${getterMethod.modality}, but for setter is ${setterMethod?.modality}"
|
||||||
}
|
}
|
||||||
|
|
||||||
val propertyDescriptor = JavaPropertyDescriptor.create(
|
val propertyDescriptor = JavaForKotlinOverridePropertyDescriptor(ownerDescriptor, getterMethod, setterMethod, overriddenProperty)
|
||||||
ownerDescriptor, Annotations.EMPTY, getterMethod.modality, getterMethod.visibility,
|
|
||||||
/* isVar = */ setterMethod != null, overriddenProperty.name, getterMethod.source,
|
|
||||||
/* isStaticFinal = */ false
|
|
||||||
)
|
|
||||||
|
|
||||||
propertyDescriptor.setType(getterMethod.returnType!!, listOf(), getDispatchReceiverParameter(), null)
|
propertyDescriptor.setType(getterMethod.returnType!!, listOf(), getDispatchReceiverParameter(), null)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user