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.ClassDescriptor
|
||||
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.jvm.annotations.hasJvmDefaultAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.hasPlatformDependentAnnotation
|
||||
@@ -42,18 +44,27 @@ class DescriptorBasedFunctionHandleForJvm(
|
||||
override val mightBeIncorrectCode: Boolean
|
||||
get() = state.classBuilderMode.mightBeIncorrectCode
|
||||
|
||||
override fun hashCode(): Int = descriptor.containerEntityForEqualityAndHashCode().hashCode() + 31 * asmMethod.hashCode()
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is DescriptorBasedFunctionHandleForJvm) return false
|
||||
override fun hashCode(): Int =
|
||||
(descriptor.containerEntityForEqualityAndHashCode().hashCode() * 31 +
|
||||
descriptor.isJavaForKotlinOverrideProperty.hashCode()) * 31 +
|
||||
asmMethod.hashCode()
|
||||
|
||||
return asmMethod == other.asmMethod &&
|
||||
descriptor.containerEntityForEqualityAndHashCode() == other.descriptor.containerEntityForEqualityAndHashCode()
|
||||
override fun equals(other: Any?): Boolean {
|
||||
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 =
|
||||
(containingDeclaration as? ClassDescriptor)?.typeConstructor ?: containingDeclaration
|
||||
|
||||
private val FunctionDescriptor.isJavaForKotlinOverrideProperty: Boolean
|
||||
get() = this is PropertyAccessorDescriptor && correspondingProperty is JavaForKotlinOverridePropertyDescriptor
|
||||
|
||||
private fun CallableMemberDescriptor.isJvmDefaultOrPlatformDependent() =
|
||||
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.TopDownAnalyzerFacadeForJVM;
|
||||
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.config.*;
|
||||
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.resolve.BindingContext;
|
||||
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.test.*;
|
||||
import org.jetbrains.kotlin.test.util.DescriptorValidator;
|
||||
@@ -237,7 +237,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
|
||||
configureEnvironment(environment);
|
||||
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);
|
||||
assertFalse(packageView.isEmpty());
|
||||
|
||||
|
||||
@@ -5052,6 +5052,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
||||
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")
|
||||
public void testJavaRefersToKotlin() throws Exception {
|
||||
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");
|
||||
}
|
||||
|
||||
@TestMetadata("javaGetterImplementsKotlinProperty.kt")
|
||||
public void testJavaGetterImplementsKotlinProperty() throws Exception {
|
||||
runTest("compiler/testData/loadJava/kotlinAgainstCompiledJavaWithKotlin/javaGetterImplementsKotlinProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaRefersToKotlin.kt")
|
||||
public void testJavaRefersToKotlin() throws Exception {
|
||||
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
|
||||
private final Pair<UserDataKey<?>, ?> singleUserData;
|
||||
|
||||
private JavaPropertyDescriptor(
|
||||
protected JavaPropertyDescriptor(
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@NotNull Annotations annotations,
|
||||
@NotNull Modality modality,
|
||||
|
||||
+1
-5
@@ -514,11 +514,7 @@ class LazyJavaClassMemberScope(
|
||||
"for getter is ${getterMethod.modality}, but for setter is ${setterMethod?.modality}"
|
||||
}
|
||||
|
||||
val propertyDescriptor = JavaPropertyDescriptor.create(
|
||||
ownerDescriptor, Annotations.EMPTY, getterMethod.modality, getterMethod.visibility,
|
||||
/* isVar = */ setterMethod != null, overriddenProperty.name, getterMethod.source,
|
||||
/* isStaticFinal = */ false
|
||||
)
|
||||
val propertyDescriptor = JavaForKotlinOverridePropertyDescriptor(ownerDescriptor, getterMethod, setterMethod, overriddenProperty)
|
||||
|
||||
propertyDescriptor.setType(getterMethod.returnType!!, listOf(), getDispatchReceiverParameter(), null)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user