Fix compilation on mixed hierarchies in compatibility mode

This commit is contained in:
Mikhail Bogdanov
2020-06-19 15:54:23 +02:00
parent 41511898a1
commit af3bda51ec
6 changed files with 50 additions and 17 deletions
@@ -10,7 +10,6 @@ import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CodegenUtil; import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.backend.common.bridges.ImplKt;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.context.ClassContext; import org.jetbrains.kotlin.codegen.context.ClassContext;
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
@@ -39,7 +38,6 @@ import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedS
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration; import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE; import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL; import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL;
import static org.jetbrains.kotlin.util.DeclarationUtilKt.findImplementationFromInterface;
import static org.jetbrains.kotlin.util.DeclarationUtilKt.findInterfaceImplementation; import static org.jetbrains.kotlin.util.DeclarationUtilKt.findInterfaceImplementation;
public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject> { public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject> {
@@ -239,14 +237,8 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
boolean isErasedInlineClass boolean isErasedInlineClass
) { ) {
// Skip Java 8 default methods // Skip Java 8 default methods
if (CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun)) { if (CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) ||
return; JvmAnnotationUtilKt.checkIsImplementationCompiledToJvmDefault(interfaceFun, state.getJvmDefaultMode())) {
}
CallableMemberDescriptor actualImplementation =
interfaceFun.getKind().isReal() ? interfaceFun : findImplementationFromInterface(interfaceFun);
assert actualImplementation != null : "Can't find actual implementation for " + interfaceFun;
if (JvmAnnotationUtilKt.isCallableMemberCompiledToJvmDefault(actualImplementation, state.getJvmDefaultMode())) {
return; return;
} }
@@ -719,9 +719,8 @@ public class FunctionCodegen {
@NotNull JvmDefaultMode jvmDefaultMode @NotNull JvmDefaultMode jvmDefaultMode
) { ) {
return OwnerKind.DEFAULT_IMPLS == context.getContextKind() && return OwnerKind.DEFAULT_IMPLS == context.getContextKind() &&
jvmDefaultMode.isCompatibility() && jvmDefaultMode.isCompatibility() &&
JvmAnnotationUtilKt.isCompiledToJvmDefault(DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(functionDescriptor), JvmAnnotationUtilKt.checkIsImplementationCompiledToJvmDefault(functionDescriptor, jvmDefaultMode);
jvmDefaultMode);
} }
private static void generateLocalVariableTable( private static void generateLocalVariableTable(
@@ -6,10 +6,7 @@
package org.jetbrains.kotlin.resolve.jvm.annotations package org.jetbrains.kotlin.resolve.jvm.annotations
import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
@@ -18,6 +15,7 @@ import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
import org.jetbrains.kotlin.util.findImplementationFromInterface
val JVM_DEFAULT_FQ_NAME = FqName("kotlin.jvm.JvmDefault") val JVM_DEFAULT_FQ_NAME = FqName("kotlin.jvm.JvmDefault")
val JVM_DEFAULT_NO_COMPATIBILITY_FQ_NAME = FqName("kotlin.jvm.JvmDefaultWithoutCompatibility") val JVM_DEFAULT_NO_COMPATIBILITY_FQ_NAME = FqName("kotlin.jvm.JvmDefaultWithoutCompatibility")
@@ -63,6 +61,13 @@ fun CallableMemberDescriptor.isCompiledToJvmDefault(jvmDefault: JvmDefaultMode):
return JvmProtoBufUtil.isNewPlaceForBodyGeneration(clazz.classProto) return JvmProtoBufUtil.isNewPlaceForBodyGeneration(clazz.classProto)
} }
fun FunctionDescriptor.checkIsImplementationCompiledToJvmDefault(jvmDefaultMode: JvmDefaultMode): Boolean {
val actualImplementation =
(if (kind.isReal) this else findImplementationFromInterface(this))
?: error("Can't find actual implementation for $this")
return actualImplementation.isCallableMemberCompiledToJvmDefault(jvmDefaultMode)
}
fun CallableMemberDescriptor.hasJvmDefaultAnnotation(): Boolean = fun CallableMemberDescriptor.hasJvmDefaultAnnotation(): Boolean =
DescriptorUtils.getDirectMember(this).annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME) DescriptorUtils.getDirectMember(this).annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME)
@@ -0,0 +1,27 @@
// FILE: 1.kt
// !JVM_DEFAULT_MODE: disable
interface Foo<T> {
fun test(p: T) = "fail"
val T.prop: String
get() = "fail"
}
// FILE: main.kt
// !JVM_DEFAULT_MODE: all-compatibility
// JVM_TARGET: 1.8
interface Foo2: Foo<String> {
override fun test(p: String) : String = p
override val String.prop: String
get() = this
}
interface Foo3: Foo<String>, Foo2
class Base : Foo3
fun box(): String {
val base = Base()
return base.test("O") + with(base) { "K".prop }
}
@@ -520,6 +520,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes2.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes2.kt");
} }
@TestMetadata("newAndOldSchemes2Compatibility.kt")
public void testNewAndOldSchemes2Compatibility() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes2Compatibility.kt");
}
@TestMetadata("newSchemeWithJvmDefault.kt") @TestMetadata("newSchemeWithJvmDefault.kt")
public void testNewSchemeWithJvmDefault() throws Exception { public void testNewSchemeWithJvmDefault() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newSchemeWithJvmDefault.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newSchemeWithJvmDefault.kt");
@@ -515,6 +515,11 @@ public class IrCompileKotlinAgainstKotlinTestGenerated extends AbstractIrCompile
runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes2.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes2.kt");
} }
@TestMetadata("newAndOldSchemes2Compatibility.kt")
public void testNewAndOldSchemes2Compatibility() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes2Compatibility.kt");
}
@TestMetadata("newSchemeWithJvmDefault.kt") @TestMetadata("newSchemeWithJvmDefault.kt")
public void testNewSchemeWithJvmDefault() throws Exception { public void testNewSchemeWithJvmDefault() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newSchemeWithJvmDefault.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newSchemeWithJvmDefault.kt");