JVM_IR KT-43051 no static inline class members for default Java methods

This commit is contained in:
Dmitry Petrov
2020-12-01 11:23:53 +03:00
parent 4c3ffc3451
commit 85b5948931
8 changed files with 262 additions and 1 deletions
@@ -12,10 +12,11 @@ import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.classFileContainsMethod
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
import org.jetbrains.kotlin.backend.jvm.ir.isFromJava
import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
@@ -70,6 +71,8 @@ class MemoizedInlineClassReplacements(
when {
it.isRemoveAtSpecialBuiltinStub() ->
null
it.isInlineClassMemberFakeOverriddenFromDefaultJavaInterfaceMethod() ->
null
it.origin == IrDeclarationOrigin.IR_BUILTINS_STUB ->
createMethodReplacement(it)
else ->
@@ -94,6 +97,16 @@ class MemoizedInlineClassReplacements(
valueParameters.size == 1 &&
valueParameters[0].type.isInt()
private fun IrFunction.isInlineClassMemberFakeOverriddenFromDefaultJavaInterfaceMethod(): Boolean {
if (this !is IrSimpleFunction) return false
if (!this.isFakeOverride) return false
val parentClass = parentClassOrNull ?: return false
if (!parentClass.isInline) return false
val overridden = resolveFakeOverride() ?: return false
return overridden.isFromJava() && overridden.modality != Modality.ABSTRACT && overridden.parentAsClass.isJvmInterface
}
/**
* Get the box function for an inline class. Concretely, this is a synthetic
* static function named "box-impl" which takes an unboxed value and returns
@@ -0,0 +1,12 @@
// FULL_JDK
inline class UInt(val x: Int)
inline class UIntArray(private val storage: IntArray) : Collection<UInt> {
public override val size: Int get() = storage.size
override operator fun iterator() = TODO()
override fun contains(element: UInt): Boolean = TODO()
override fun containsAll(elements: Collection<UInt>): Boolean = TODO()
override fun isEmpty(): Boolean = TODO()
}
@@ -0,0 +1,57 @@
@kotlin.Metadata
public final class UInt {
// source: 'UIntArrayWithFullJdk.kt'
private final field x: int
private synthetic method <init>(p0: int): void
public synthetic final static method box-impl(p0: int): UInt
public static method constructor-impl(p0: int): int
public method equals(p0: java.lang.Object): boolean
public static method equals-impl(p0: int, p1: java.lang.Object): boolean
public final static method equals-impl0(p0: int, p1: int): boolean
public final method getX(): int
public method hashCode(): int
public static method hashCode-impl(p0: int): int
public method toString(): java.lang.String
public static method toString-impl(p0: int): java.lang.String
public synthetic final method unbox-impl(): int
}
@kotlin.Metadata
public final class UIntArray {
// source: 'UIntArrayWithFullJdk.kt'
private final field storage: int[]
private synthetic method <init>(p0: int[]): void
public synthetic method add(p0: java.lang.Object): boolean
public method add-fLmw4x8(p0: int): boolean
public method addAll(p0: java.util.Collection): boolean
public synthetic final static method box-impl(p0: int[]): UIntArray
public method clear(): void
public static @org.jetbrains.annotations.NotNull method constructor-impl(@org.jetbrains.annotations.NotNull p0: int[]): int[]
public bridge final method contains(p0: java.lang.Object): boolean
public method contains-fLmw4x8(p0: int): boolean
public static method contains-fLmw4x8(p0: int[], p1: int): boolean
public method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean
public static method containsAll-impl(p0: int[], @org.jetbrains.annotations.NotNull p1: java.util.Collection): boolean
public method equals(p0: java.lang.Object): boolean
public static method equals-impl(p0: int[], p1: java.lang.Object): boolean
public final static method equals-impl0(p0: int[], p1: int[]): boolean
public method getSize(): int
public static method getSize-impl(p0: int[]): int
public method hashCode(): int
public static method hashCode-impl(p0: int[]): int
public method isEmpty(): boolean
public static method isEmpty-impl(p0: int[]): boolean
public @org.jetbrains.annotations.NotNull method iterator(): java.lang.Void
public synthetic bridge method iterator(): java.util.Iterator
public static @org.jetbrains.annotations.NotNull method iterator-impl(p0: int[]): java.lang.Void
public method remove(p0: java.lang.Object): boolean
public method removeAll(p0: java.util.Collection): boolean
public method removeIf(p0: java.util.function.Predicate): boolean
public method retainAll(p0: java.util.Collection): boolean
public bridge final method size(): int
public method toArray(): java.lang.Object[]
public method toArray(p0: java.lang.Object[]): java.lang.Object[]
public method toString(): java.lang.String
public static method toString-impl(p0: int[]): java.lang.String
public synthetic final method unbox-impl(): int[]
}
@@ -0,0 +1,57 @@
@kotlin.Metadata
public final class UInt {
// source: 'UIntArrayWithFullJdk.kt'
private final field x: int
private synthetic method <init>(p0: int): void
public synthetic final static method box-impl(p0: int): UInt
public static method constructor-impl(p0: int): int
public method equals(p0: java.lang.Object): boolean
public static method equals-impl(p0: int, p1: java.lang.Object): boolean
public final static method equals-impl0(p0: int, p1: int): boolean
public final method getX(): int
public method hashCode(): int
public static method hashCode-impl(p0: int): int
public method toString(): java.lang.String
public static method toString-impl(p0: int): java.lang.String
public synthetic final method unbox-impl(): int
}
@kotlin.Metadata
public final class UIntArray {
// source: 'UIntArrayWithFullJdk.kt'
private final @org.jetbrains.annotations.NotNull field storage: int[]
private synthetic method <init>(p0: int[]): void
public synthetic bridge method add(p0: java.lang.Object): boolean
public method add-fLmw4x8(p0: int): boolean
public method addAll(p0: java.util.Collection): boolean
public synthetic final static method box-impl(p0: int[]): UIntArray
public method clear(): void
public static @org.jetbrains.annotations.NotNull method constructor-impl(@org.jetbrains.annotations.NotNull p0: int[]): int[]
public synthetic bridge method contains(p0: java.lang.Object): boolean
public static method contains-fLmw4x8(@org.jetbrains.annotations.NotNull p0: int[], p1: int): boolean
public method contains-fLmw4x8(p0: int): boolean
public method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean
public static method containsAll-impl(@org.jetbrains.annotations.NotNull p0: int[], @org.jetbrains.annotations.NotNull p1: java.util.Collection): boolean
public method equals(p0: java.lang.Object): boolean
public static method equals-impl(p0: int[], p1: java.lang.Object): boolean
public final static method equals-impl0(p0: int[], p1: int[]): boolean
public method getSize(): int
public static method getSize-impl(@org.jetbrains.annotations.NotNull p0: int[]): int
public method hashCode(): int
public static method hashCode-impl(p0: int[]): int
public method isEmpty(): boolean
public static method isEmpty-impl(@org.jetbrains.annotations.NotNull p0: int[]): boolean
public @org.jetbrains.annotations.NotNull method iterator(): java.lang.Void
public synthetic bridge method iterator(): java.util.Iterator
public static @org.jetbrains.annotations.NotNull method iterator-impl(@org.jetbrains.annotations.NotNull p0: int[]): java.lang.Void
public method remove(p0: java.lang.Object): boolean
public method removeAll(p0: java.util.Collection): boolean
public method removeIf(p0: java.util.function.Predicate): boolean
public method retainAll(p0: java.util.Collection): boolean
public synthetic bridge method size(): int
public method toArray(): java.lang.Object[]
public method toArray(p0: java.lang.Object[]): java.lang.Object[]
public method toString(): java.lang.String
public static method toString-impl(p0: int[]): java.lang.String
public synthetic final method unbox-impl(): int[]
}
@@ -0,0 +1,22 @@
// JVM_TARGET: 1.8
// FILE: javaDefaultInterfaceMember.kt
interface KFoo2 : JIFoo
interface KFooUnrelated {
fun foo()
}
interface KFoo3 : KFoo2, KFooUnrelated {
override fun foo() {}
}
inline class Test1(val x: Int) : JIFoo
inline class Test2(val x: Int) : KFoo2
inline class Test3(val x: Int) : KFoo3
// FILE: JIFoo.java
public interface JIFoo {
default void foo() {}
}
@@ -0,0 +1,80 @@
@kotlin.Metadata
public interface KFoo2 {
// source: 'javaDefaultInterfaceMember.kt'
}
@kotlin.Metadata
public final class KFoo3$DefaultImpls {
// source: 'javaDefaultInterfaceMember.kt'
public static method foo(@org.jetbrains.annotations.NotNull p0: KFoo3): void
public final inner class KFoo3$DefaultImpls
}
@kotlin.Metadata
public interface KFoo3 {
// source: 'javaDefaultInterfaceMember.kt'
public abstract method foo(): void
public final inner class KFoo3$DefaultImpls
}
@kotlin.Metadata
public interface KFooUnrelated {
// source: 'javaDefaultInterfaceMember.kt'
public abstract method foo(): void
}
@kotlin.Metadata
public final class Test1 {
// source: 'javaDefaultInterfaceMember.kt'
private final field x: int
private synthetic method <init>(p0: int): void
public synthetic final static method box-impl(p0: int): Test1
public static method constructor-impl(p0: int): int
public method equals(p0: java.lang.Object): boolean
public static method equals-impl(p0: int, p1: java.lang.Object): boolean
public final static method equals-impl0(p0: int, p1: int): boolean
public final method getX(): int
public method hashCode(): int
public static method hashCode-impl(p0: int): int
public method toString(): java.lang.String
public static method toString-impl(p0: int): java.lang.String
public synthetic final method unbox-impl(): int
}
@kotlin.Metadata
public final class Test2 {
// source: 'javaDefaultInterfaceMember.kt'
private final field x: int
private synthetic method <init>(p0: int): void
public synthetic final static method box-impl(p0: int): Test2
public static method constructor-impl(p0: int): int
public method equals(p0: java.lang.Object): boolean
public static method equals-impl(p0: int, p1: java.lang.Object): boolean
public final static method equals-impl0(p0: int, p1: int): boolean
public final method getX(): int
public method hashCode(): int
public static method hashCode-impl(p0: int): int
public method toString(): java.lang.String
public static method toString-impl(p0: int): java.lang.String
public synthetic final method unbox-impl(): int
}
@kotlin.Metadata
public final class Test3 {
// source: 'javaDefaultInterfaceMember.kt'
private final field x: int
private synthetic method <init>(p0: int): void
public synthetic final static method box-impl(p0: int): Test3
public static method constructor-impl(p0: int): int
public method equals(p0: java.lang.Object): boolean
public static method equals-impl(p0: int, p1: java.lang.Object): boolean
public final static method equals-impl0(p0: int, p1: int): boolean
public method foo(): void
public static method foo-impl(p0: int): void
public final method getX(): int
public method hashCode(): int
public static method hashCode-impl(p0: int): int
public method toString(): java.lang.String
public static method toString-impl(p0: int): java.lang.String
public synthetic final method unbox-impl(): int
}
@@ -982,6 +982,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/inlineClassWithManyKindsOfMembers.kt");
}
@TestMetadata("javaDefaultInterfaceMember.kt")
public void testJavaDefaultInterfaceMember() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/javaDefaultInterfaceMember.kt");
}
@TestMetadata("jvmName.kt")
public void testJvmName() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/jvmName.kt");
@@ -1123,6 +1128,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
public void testSet() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCollection/set.kt");
}
@TestMetadata("UIntArrayWithFullJdk.kt")
public void testUIntArrayWithFullJdk() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCollection/UIntArrayWithFullJdk.kt");
}
}
@TestMetadata("compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCollectionOfInlineClass")
@@ -952,6 +952,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/inlineClassWithManyKindsOfMembers.kt");
}
@TestMetadata("javaDefaultInterfaceMember.kt")
public void testJavaDefaultInterfaceMember() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/javaDefaultInterfaceMember.kt");
}
@TestMetadata("jvmName.kt")
public void testJvmName() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/jvmName.kt");
@@ -1093,6 +1098,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
public void testSet() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCollection/set.kt");
}
@TestMetadata("UIntArrayWithFullJdk.kt")
public void testUIntArrayWithFullJdk() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCollection/UIntArrayWithFullJdk.kt");
}
}
@TestMetadata("compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCollectionOfInlineClass")