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:
Alexander Udalov
2019-05-24 11:04:16 +02:00
parent d05e72dda8
commit 082c337faa
12 changed files with 100 additions and 13 deletions
@@ -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()
@@ -0,0 +1,3 @@
package test
class C : B(), I
@@ -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?
}
@@ -0,0 +1,7 @@
package test;
public abstract class A {
public String getValue() {
return null;
}
}
@@ -0,0 +1,4 @@
package test;
public class B extends A implements I {
}
@@ -0,0 +1,5 @@
package test
interface I {
val value: String?
}
@@ -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");
@@ -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");
@@ -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
)
@@ -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,
@@ -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)