Inline (wrapper) class IC extends erased inline class IC$Erased

This commit is contained in:
Dmitry Petrov
2018-08-29 17:57:38 +03:00
parent a46b28718e
commit 3080b65f7d
18 changed files with 143 additions and 22 deletions
@@ -14,11 +14,14 @@ import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErasedInlineClassOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class ErasedInlineClassBodyCodegen(
aClass: KtClass,
@@ -28,9 +31,8 @@ class ErasedInlineClassBodyCodegen(
parentCodegen: MemberCodegen<*>?
) : ClassBodyCodegen(aClass, context, v, state, parentCodegen) {
private val superClassAsmType: Type by lazy {
SuperClassInfo.getSuperClassInfo(descriptor, typeMapper).type
}
private val wrapperSuperClassAsmType = AsmTypes.OBJECT_TYPE
private val erasedSuperClassAsmType = AsmTypes.OBJECT_TYPE
private val classAsmType = typeMapper.mapErasedInlineClass(descriptor)
@@ -40,7 +42,7 @@ class ErasedInlineClassBodyCodegen(
override fun generateDeclaration() {
v.defineClass(
myClass.psiOrParent, state.classFileVersion, Opcodes.ACC_FINAL or Opcodes.ACC_STATIC or Opcodes.ACC_PUBLIC,
myClass.psiOrParent, state.classFileVersion, Opcodes.ACC_STATIC or Opcodes.ACC_PUBLIC,
classAsmType.internalName, null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
)
v.visitSource(myClass.containingKtFile.name, null)
@@ -49,15 +51,30 @@ class ErasedInlineClassBodyCodegen(
override fun generateConstructors() {
val delegationFieldsInfo = DelegationFieldsInfo(classAsmType, descriptor, state, bindingContext)
constructorCodegen.generatePrimaryConstructor(
delegationFieldsInfo.getDelegationFieldsInfo(myClass.superTypeListEntries), superClassAsmType
)
generateDefaultConstructorForErasedInlineClass()
constructorCodegen.generatePrimaryConstructor(delegationFieldsInfo, wrapperSuperClassAsmType)
for (secondaryConstructor in descriptor.secondaryConstructors) {
constructorCodegen.generateSecondaryConstructor(secondaryConstructor, superClassAsmType)
constructorCodegen.generateSecondaryConstructor(secondaryConstructor, wrapperSuperClassAsmType)
}
}
private fun generateDefaultConstructorForErasedInlineClass() {
val mv = v.newMethod(
ErasedInlineClassOrigin(myClass.psiOrParent, descriptor), 0,
"<init>", "()V", null, ArrayUtil.EMPTY_STRING_ARRAY
)
mv.visitCode()
InstructionAdapter(mv).apply {
load(0, AsmTypes.OBJECT_TYPE)
invokespecial(erasedSuperClassAsmType.internalName, "<init>", "()V", false)
areturn(Type.VOID_TYPE)
}
mv.visitMaxs(1, 1)
mv.visitEnd()
}
override fun generateSyntheticPartsAfterBody() {
super.generateSyntheticPartsAfterBody()
@@ -131,7 +131,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateDeclaration() {
getSuperClass();
superClassInfo = SuperClassInfo.getSuperClassInfo(descriptor, typeMapper);
superClassAsmType = superClassInfo.getType();
JvmClassSignature signature = signature();
@@ -404,11 +405,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
new ArrayList<>(superInterfaces), sw.makeJavaGenericSignature());
}
private void getSuperClass() {
superClassInfo = SuperClassInfo.getSuperClassInfo(descriptor, typeMapper);
superClassAsmType = superClassInfo.getType();
}
@Override
protected void generateSyntheticPartsBeforeBody() {
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
@@ -25,9 +25,9 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
class SuperClassInfo(
val type: Type,
// null means java/lang/Object
val kotlinType: KotlinType?
val type: Type,
// null means java/lang/Object or irrelevant
val kotlinType: KotlinType?
) {
companion object {
@@ -37,6 +37,10 @@ class SuperClassInfo(
return SuperClassInfo(OBJECT_TYPE, null)
}
if (descriptor.isInline) {
return SuperClassInfo(typeMapper.mapErasedInlineClass(descriptor), null)
}
for (supertype in descriptor.typeConstructor.supertypes) {
val superClass = supertype.constructor.declarationDescriptor
if (superClass != null && !isJvmInterface(superClass)) {
@@ -0,0 +1,16 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
interface IFoo {
fun foo(): String
}
inline class IC(val x: String) : IFoo {
private fun privateFun() = x
override fun foo() = privateFun()
}
fun box(): String {
val x: IFoo = IC("OK")
return x.foo()
}
@@ -0,0 +1,12 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class IC(val x: String) {
private fun privateFun() = x
override fun toString() = privateFun()
}
fun box(): String {
val x: Any = IC("OK")
return x.toString()
}
@@ -14,6 +14,8 @@ inline class A(val x: Int) {
inline fun stub() {}
// FILE: 2.kt
// NO_CHECK_LAMBDA_INLINING
// ^ TODO
import test.*
@@ -7,7 +7,8 @@ public final class Foo$Companion {
}
@kotlin.Metadata
public final static class Foo$Erased {
public static class Foo$Erased {
method <init>(): void
public final static @org.jetbrains.annotations.NotNull method box(p0: int): Foo
public static method constructor(p0: int): int
public static method equals(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
@@ -1,5 +1,6 @@
@kotlin.Metadata
public final static class Foo$Erased {
public static class Foo$Erased {
method <init>(): void
public final static @org.jetbrains.annotations.NotNull method box(p0: int): Foo
public static method constructor(p0: int): int
public static method equals(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
@@ -4,7 +4,8 @@ public interface A {
}
@kotlin.Metadata
public final static class Foo$Erased {
public static class Foo$Erased {
method <init>(): void
public final static @org.jetbrains.annotations.NotNull method box(p0: long): Foo
public static method constructor(p0: long): long
public static method equals(p0: long, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
@@ -1,5 +1,6 @@
@kotlin.Metadata
public final static class Foo$Erased {
public static class Foo$Erased {
method <init>(): void
public final static @org.jetbrains.annotations.NotNull method box(p0: long): Foo
public static method constructor(p0: long): long
public final static method empty(p0: long): void
@@ -0,0 +1,15 @@
// !LANGUAGE: +InlineClasses
inline class Z(val x: Int)
interface IFoo
interface IBar
inline class FooBar(val x: Int) : IFoo, IBar
// 1 public final class Z extends Z\$Erased
// 1 static class Z\$Erased
// 0 public static class Z\$Erased
// 1 public final class FooBar extends FooBar\$Erased implements IFoo IBar
// 1 static class FooBar\$Erased
// 0 public static class FooBar\$Erased
@@ -11731,6 +11731,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/nullableEqeqNonNull.kt");
}
@TestMetadata("overridingFunCallingPrivateFun.kt")
public void testOverridingFunCallingPrivateFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/overridingFunCallingPrivateFun.kt");
}
@TestMetadata("passInlineClassAsVararg.kt")
public void testPassInlineClassAsVararg() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/passInlineClassAsVararg.kt");
@@ -11761,6 +11766,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorsInsideInlineClass.kt");
}
@TestMetadata("toStringCallingPrivateFun.kt")
public void testToStringCallingPrivateFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/toStringCallingPrivateFun.kt");
}
@TestMetadata("typeChecksForInlineClasses.kt")
public void testTypeChecksForInlineClasses() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/typeChecksForInlineClasses.kt");
@@ -2088,6 +2088,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/inlineClassBoxingUnboxingInsideInlinedLambda.kt");
}
@TestMetadata("inlineClassExtendsErasedClass.kt")
public void testInlineClassExtendsErasedClass() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/inlineClassExtendsErasedClass.kt");
}
@TestMetadata("inlineClassesUnboxingAfterAssertionOperator.kt")
public void testInlineClassesUnboxingAfterAssertionOperator() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/inlineClassesUnboxingAfterAssertionOperator.kt");
@@ -11731,6 +11731,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/nullableEqeqNonNull.kt");
}
@TestMetadata("overridingFunCallingPrivateFun.kt")
public void testOverridingFunCallingPrivateFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/overridingFunCallingPrivateFun.kt");
}
@TestMetadata("passInlineClassAsVararg.kt")
public void testPassInlineClassAsVararg() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/passInlineClassAsVararg.kt");
@@ -11761,6 +11766,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorsInsideInlineClass.kt");
}
@TestMetadata("toStringCallingPrivateFun.kt")
public void testToStringCallingPrivateFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/toStringCallingPrivateFun.kt");
}
@TestMetadata("typeChecksForInlineClasses.kt")
public void testTypeChecksForInlineClasses() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/typeChecksForInlineClasses.kt");
@@ -11731,6 +11731,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/nullableEqeqNonNull.kt");
}
@TestMetadata("overridingFunCallingPrivateFun.kt")
public void testOverridingFunCallingPrivateFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/overridingFunCallingPrivateFun.kt");
}
@TestMetadata("passInlineClassAsVararg.kt")
public void testPassInlineClassAsVararg() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/passInlineClassAsVararg.kt");
@@ -11761,6 +11766,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorsInsideInlineClass.kt");
}
@TestMetadata("toStringCallingPrivateFun.kt")
public void testToStringCallingPrivateFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/toStringCallingPrivateFun.kt");
}
@TestMetadata("typeChecksForInlineClasses.kt")
public void testTypeChecksForInlineClasses() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/typeChecksForInlineClasses.kt");
@@ -26,7 +26,6 @@ import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
public final class JvmAbi {
public static final String DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls";
public static final String ERASED_INLINE_CONSTRUCTOR_NAME = "constructor";
private static final String ERASED_INLINE_CLASS_NAME = "Erased";
public static final FqName JVM_FIELD_ANNOTATION_FQ_NAME = new FqName("kotlin.jvm.JvmField");
/**
@@ -58,6 +57,7 @@ public final class JvmAbi {
public static final String LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT = "$i$a$";
public static final String LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION = "$i$f$";
private static final String ERASED_INLINE_CLASS_NAME = "Erased";
public static final String ERASED_INLINE_CLASS_SUFFIX = "$" + ERASED_INLINE_CLASS_NAME;
@NotNull
@@ -10266,6 +10266,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/nullableEqeqNonNull.kt");
}
@TestMetadata("overridingFunCallingPrivateFun.kt")
public void testOverridingFunCallingPrivateFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/overridingFunCallingPrivateFun.kt");
}
@TestMetadata("passInlineClassAsVararg.kt")
public void testPassInlineClassAsVararg() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/passInlineClassAsVararg.kt");
@@ -10296,6 +10301,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorsInsideInlineClass.kt");
}
@TestMetadata("toStringCallingPrivateFun.kt")
public void testToStringCallingPrivateFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/toStringCallingPrivateFun.kt");
}
@TestMetadata("typeChecksForInlineClasses.kt")
public void testTypeChecksForInlineClasses() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/typeChecksForInlineClasses.kt");
@@ -11331,6 +11331,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/nullableEqeqNonNull.kt");
}
@TestMetadata("overridingFunCallingPrivateFun.kt")
public void testOverridingFunCallingPrivateFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/overridingFunCallingPrivateFun.kt");
}
@TestMetadata("passInlineClassAsVararg.kt")
public void testPassInlineClassAsVararg() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/passInlineClassAsVararg.kt");
@@ -11361,6 +11366,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorsInsideInlineClass.kt");
}
@TestMetadata("toStringCallingPrivateFun.kt")
public void testToStringCallingPrivateFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/toStringCallingPrivateFun.kt");
}
@TestMetadata("typeChecksForInlineClasses.kt")
public void testTypeChecksForInlineClasses() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/typeChecksForInlineClasses.kt");