diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FieldInfo.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FieldInfo.java index 363f313d07f..adc32f8b538 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FieldInfo.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FieldInfo.java @@ -34,7 +34,7 @@ public class FieldInfo { } if (isNonCompanionObject(classDescriptor) || CompanionObjectMapping.INSTANCE.isMappedIntrinsicCompanionObject(classDescriptor)) { - return createSingletonViaInstance(classDescriptor, typeMapper); + return createSingletonViaInstance(classDescriptor, typeMapper, JvmAbi.INSTANCE_FIELD); } ClassDescriptor ownerDescriptor = DescriptorUtils.getParentOfType(classDescriptor, ClassDescriptor.class); @@ -46,10 +46,11 @@ public class FieldInfo { @NotNull public static FieldInfo createSingletonViaInstance( @NotNull ClassDescriptor classDescriptor, - @NotNull KotlinTypeMapper typeMapper + @NotNull KotlinTypeMapper typeMapper, + @NotNull String name ) { Type type = typeMapper.mapType(classDescriptor); - return new FieldInfo(type, type, JvmAbi.INSTANCE_FIELD, true); + return new FieldInfo(type, type, name, true); } @NotNull diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index e1cb8cf1f11..9fcc02e1c16 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -39,7 +39,6 @@ import org.jetbrains.kotlin.config.LanguageFeature; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.incremental.components.NoLookupLocation; import org.jetbrains.kotlin.lexer.KtTokens; -import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor; import org.jetbrains.kotlin.load.kotlin.TypeMappingMode; import org.jetbrains.kotlin.name.ClassId; @@ -77,6 +76,7 @@ import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isNonGenericToArray; import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*; import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass; import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtils2Kt.initDefaultSourceMappingIfNeeded; +import static org.jetbrains.kotlin.load.java.JvmAbi.*; import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall; import static org.jetbrains.kotlin.resolve.BindingContextUtils.getNotNull; import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration; @@ -354,6 +354,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { protected void generateSyntheticPartsAfterBody() { generateFieldForSingleton(); + initializeObjects(); + generateCompanionObjectBackingFieldCopies(); generateTraitMethods(); @@ -811,21 +813,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } private void generateFieldForSingleton() { + if (isCompanionObjectInInterfaceNotIntrinsic(descriptor)) { + StackValue.Field field = StackValue.createSingletonViaInstance(descriptor, typeMapper, HIDDEN_INSTANCE_FIELD); + //hidden instance in interface companion + v.newField(JvmDeclarationOriginKt.OtherOrigin(descriptor), + ACC_SYNTHETIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null); + } + if (isEnumEntry(descriptor) || isCompanionObject(descriptor)) return; if (isNonCompanionObject(descriptor)) { - StackValue.Field field = StackValue.singletonViaInstance(descriptor, typeMapper); + StackValue.Field field = StackValue.createSingletonViaInstance(descriptor, typeMapper, INSTANCE_FIELD); v.newField(JvmDeclarationOriginKt.OtherOriginFromPure(myClass), ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null); - if (!state.getClassBuilderMode().generateBodies) return; - // Invoke the object constructor but ignore the result because INSTANCE will be initialized in the first line of - InstructionAdapter v = createOrGetClInitCodegen().v; - markLineNumberForElement(element.getPsiOrParent(), v); - v.anew(classAsmType); - v.invokespecial(classAsmType.getInternalName(), "", "()V", false); - return; } @@ -853,6 +855,60 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } + private void initializeObjects() { + if (!DescriptorUtils.isObject(descriptor)) return; + if (!state.getClassBuilderMode().generateBodies) return; + + boolean isNonCompanionObject = isNonCompanionObject(descriptor); + boolean isInterfaceCompanion = isCompanionObjectInInterfaceNotIntrinsic(descriptor); + boolean isMappedIntrinsicCompanionObject = isMappedIntrinsicCompanionObject(descriptor); + if (isNonCompanionObject || isInterfaceCompanion || isMappedIntrinsicCompanionObject) { + ExpressionCodegen clInitCodegen = createOrGetClInitCodegen(); + InstructionAdapter v = clInitCodegen.v; + markLineNumberForElement(element.getPsiOrParent(), v); + v.anew(classAsmType); + v.dup(); + v.invokespecial(classAsmType.getInternalName(), "", "()V", false); + + //local0 emulates this in object constructor + int local0Index = clInitCodegen.getFrameMap().enterTemp(classAsmType); + assert local0Index == 0 : "Local variable with index 0 in clInit should be used only for singleton instance keeping"; + StackValue.Local local0 = StackValue.local(0, classAsmType); + local0.store(StackValue.onStack(classAsmType), clInitCodegen.v); + StackValue.Field singleton = + StackValue.createSingletonViaInstance( + descriptor, typeMapper, isInterfaceCompanion ? HIDDEN_INSTANCE_FIELD : INSTANCE_FIELD + ); + singleton.store(local0, clInitCodegen.v); + + generateInitializers(clInitCodegen); + + if (isInterfaceCompanion) { + //initialize singleton instance in outer by hidden instance + StackValue.singleton(descriptor, typeMapper).store( + singleton, getParentCodegen().createOrGetClInitCodegen().v, true + ); + } + } + else if (isCompanionObjectWithBackingFieldsInOuter(descriptor)) { + ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen(); + ExpressionCodegen parentClInitCodegen = parentCodegen.createOrGetClInitCodegen(); + InstructionAdapter parentVisitor = parentClInitCodegen.v; + + FunctionDescriptor constructor = (FunctionDescriptor) parentCodegen.context.accessibleDescriptor( + CollectionsKt.single(descriptor.getConstructors()), /* superCallExpression = */ null + ); + parentCodegen.generateMethodCallTo(constructor, null, parentVisitor); + StackValue instance = StackValue.onStack(parentCodegen.typeMapper.mapClass(descriptor)); + StackValue.singleton(descriptor, parentCodegen.typeMapper).store(instance, parentVisitor, true); + + generateInitializers(parentClInitCodegen); + } + else { + assert false : "Unknown object type: " + descriptor; + } + } + private void generateCompanionObjectBackingFieldCopies() { if (companionObjectPropertiesToCopy == null) return; @@ -900,17 +956,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { field.store(property, codegen.v); } - private void generateCompanionObjectInitializer(@NotNull ClassDescriptor companionObject) { - ExpressionCodegen codegen = createOrGetClInitCodegen(); - - FunctionDescriptor constructor = (FunctionDescriptor) context.accessibleDescriptor( - CollectionsKt.single(companionObject.getConstructors()), /* superCallExpression = */ null - ); - generateMethodCallTo(constructor, null, codegen.v); - StackValue instance = StackValue.onStack(typeMapper.mapClass(companionObject)); - StackValue.singleton(companionObject, typeMapper).store(instance, codegen.v, true); - } - private void generatePrimaryConstructor(DelegationFieldsInfo delegationFieldsInfo) { if (isInterface(descriptor) || isAnnotationClass(descriptor)) return; @@ -978,10 +1023,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor, getDelegationConstructorCall(bindingContext, constructorDescriptor)); - if (isNonCompanionObject(descriptor)) { - StackValue.singletonViaInstance(descriptor, typeMapper).store(StackValue.LOCAL_0, iv); - } - for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) { if (specifier instanceof KtDelegatedSuperTypeEntry) { genCallToDelegatorByExpressionSpecifier(iv, codegen, (KtDelegatedSuperTypeEntry) specifier, fieldsInfo); @@ -1003,18 +1044,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { curParam++; } - if (isCompanionObject(descriptor)) { - ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen(); - parentCodegen.generateCompanionObjectInitializer(descriptor); - } - - if (JvmAbi.isCompanionObjectWithBackingFieldsInOuter(descriptor)) { - generateInitializers(((ImplementationBodyCodegen) getParentCodegen())::createOrGetClInitCodegen); - } - else { + //object initialization was moved to initializeObjects() + if (!isObject(descriptor)) { generateInitializers(codegen); } - iv.visitInsn(RETURN); } @@ -1159,7 +1192,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (asmType == null) continue; - result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, JvmAbi.DELEGATE_SUPER_FIELD_PREFIX + n); + result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, DELEGATE_SUPER_FIELD_PREFIX + n); } n++; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index 7fbb9ed385c..11193c5aaf4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -621,8 +621,8 @@ public abstract class StackValue { return field(FieldInfo.createForSingleton(classDescriptor, typeMapper), none()); } - public static Field singletonViaInstance(ClassDescriptor classDescriptor, KotlinTypeMapper typeMapper) { - return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper), none()); + public static Field createSingletonViaInstance(@NotNull ClassDescriptor classDescriptor, @NotNull KotlinTypeMapper typeMapper, @NotNull String name) { + return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper, name), none()); } public static StackValue operation(Type type, Function1 lambda) { diff --git a/compiler/testData/codegen/box/objects/classCompanion.kt b/compiler/testData/codegen/box/objects/classCompanion.kt new file mode 100644 index 00000000000..66d6d588238 --- /dev/null +++ b/compiler/testData/codegen/box/objects/classCompanion.kt @@ -0,0 +1,19 @@ +var result = "" + +class A { + + companion object { + + val prop = test() + + fun test(): String { + result += "OK" + return result + } + } +} + +fun box(): String { + if (A.prop != "OK") return "fail ${A.prop}" + return result +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/objects/interfaceCompanion.kt b/compiler/testData/codegen/box/objects/interfaceCompanion.kt new file mode 100644 index 00000000000..924329d3b37 --- /dev/null +++ b/compiler/testData/codegen/box/objects/interfaceCompanion.kt @@ -0,0 +1,19 @@ +var result = "" + +interface A { + + companion object { + + val prop = test() + + fun test(): String { + result += "OK" + return result + } + } +} + +fun box(): String { + if (A.prop != "OK") return "fail ${A.prop}" + return result +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/objects/object.kt b/compiler/testData/codegen/box/objects/object.kt new file mode 100644 index 00000000000..8ce9ee1c9ba --- /dev/null +++ b/compiler/testData/codegen/box/objects/object.kt @@ -0,0 +1,15 @@ +var result = "" + +object A { + val prop = test() + + fun test(): String { + result += "OK" + return result + } +} + +fun box(): String { + if (A.prop != "OK") return "fail ${A.prop}" + return result +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/reflection/enclosing/lambdaInObjectDeclaration.kt b/compiler/testData/codegen/box/reflection/enclosing/lambdaInObjectDeclaration.kt index de061c4090a..9025828aa11 100644 --- a/compiler/testData/codegen/box/reflection/enclosing/lambdaInObjectDeclaration.kt +++ b/compiler/testData/codegen/box/reflection/enclosing/lambdaInObjectDeclaration.kt @@ -14,7 +14,7 @@ fun box(): String { if (enclosingMethod != null) return "method: $enclosingMethod" val enclosingConstructor = javaClass.getEnclosingConstructor() - if (enclosingConstructor == null) return "no enclosing constructor" + if (enclosingConstructor != null) return "field should be initialized in clInit" val enclosingClass = javaClass.getEnclosingClass() if (enclosingClass?.getName() != "O") return "enclosing class: $enclosingClass" diff --git a/compiler/testData/codegen/dumpDeclarations/interfaces.json b/compiler/testData/codegen/dumpDeclarations/interfaces.json index e4e86651b02..b9a10a0e879 100644 --- a/compiler/testData/codegen/dumpDeclarations/interfaces.json +++ b/compiler/testData/codegen/dumpDeclarations/interfaces.json @@ -49,7 +49,8 @@ "class": "PublicInterface$Companion", "members": [ {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "()V"}, - {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"} + {"visibility": "public", "declaration": "companion object", "name": "$$INSTANCE", "desc": "LPublicInterface$Companion;"}, + {"visibility": "public", "declaration": "companion object", "name": "", "desc": "()V"} ] }, { @@ -75,7 +76,8 @@ "class": "InternalInterface$Companion", "members": [ {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "()V"}, - {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"} + {"visibility": "public", "declaration": "companion object", "name": "$$INSTANCE", "desc": "LInternalInterface$Companion;"}, + {"visibility": "public", "declaration": "companion object", "name": "", "desc": "()V"} ] }, { @@ -101,7 +103,8 @@ "class": "InternalInterfacePrivateCompanion$Companion", "members": [ {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "()V"}, - {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"} + {"visibility": "private", "declaration": "companion object", "name": "$$INSTANCE", "desc": "LInternalInterfacePrivateCompanion$Companion;"}, + {"visibility": "private", "declaration": "companion object", "name": "", "desc": "()V"} ] }, { @@ -163,7 +166,8 @@ "class": "PrivateInterface$Companion", "members": [ {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "()V"}, - {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"} + {"visibility": "public", "declaration": "companion object", "name": "$$INSTANCE", "desc": "LPrivateInterface$Companion;"}, + {"visibility": "public", "declaration": "companion object", "name": "", "desc": "()V"} ] }, { @@ -189,7 +193,8 @@ "class": "PrivateInterfacePrivateCompanion$Companion", "members": [ {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "()V"}, - {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"} + {"visibility": "private", "declaration": "companion object", "name": "$$INSTANCE", "desc": "LPrivateInterfacePrivateCompanion$Companion;"}, + {"visibility": "private", "declaration": "companion object", "name": "", "desc": "()V"} ] }, { diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 47d623809e6..e7ce3771971 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -11993,6 +11993,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("classCompanion.kt") + public void testClassCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/classCompanion.kt"); + doTest(fileName); + } + @TestMetadata("flist.kt") public void testFlist() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt"); @@ -12011,6 +12017,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("interfaceCompanion.kt") + public void testInterfaceCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/interfaceCompanion.kt"); + doTest(fileName); + } + @TestMetadata("kt1047.kt") public void testKt1047() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/kt1047.kt"); @@ -12149,6 +12161,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("object.kt") + public void testObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/object.kt"); + doTest(fileName); + } + @TestMetadata("objectExtendsInnerAndReferencesOuterMember.kt") public void testObjectExtendsInnerAndReferencesOuterMember() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/objectExtendsInnerAndReferencesOuterMember.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 63f0e74f49e..bbc03016e9d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -11993,6 +11993,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("classCompanion.kt") + public void testClassCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/classCompanion.kt"); + doTest(fileName); + } + @TestMetadata("flist.kt") public void testFlist() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt"); @@ -12011,6 +12017,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("interfaceCompanion.kt") + public void testInterfaceCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/interfaceCompanion.kt"); + doTest(fileName); + } + @TestMetadata("kt1047.kt") public void testKt1047() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/kt1047.kt"); @@ -12149,6 +12161,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("object.kt") + public void testObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/object.kt"); + doTest(fileName); + } + @TestMetadata("objectExtendsInnerAndReferencesOuterMember.kt") public void testObjectExtendsInnerAndReferencesOuterMember() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/objectExtendsInnerAndReferencesOuterMember.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 2620fb623ba..c26d042e53c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -11993,6 +11993,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("classCompanion.kt") + public void testClassCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/classCompanion.kt"); + doTest(fileName); + } + @TestMetadata("flist.kt") public void testFlist() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt"); @@ -12011,6 +12017,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("interfaceCompanion.kt") + public void testInterfaceCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/interfaceCompanion.kt"); + doTest(fileName); + } + @TestMetadata("kt1047.kt") public void testKt1047() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/kt1047.kt"); @@ -12149,6 +12161,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("object.kt") + public void testObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/object.kt"); + doTest(fileName); + } + @TestMetadata("objectExtendsInnerAndReferencesOuterMember.kt") public void testObjectExtendsInnerAndReferencesOuterMember() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/objectExtendsInnerAndReferencesOuterMember.kt"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java index ab3913eff31..0d2b6746927 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.util.capitalizeDecapitalize.CapitalizeDecapitalizeKt import static org.jetbrains.kotlin.resolve.DescriptorUtils.isClassOrEnumClass; import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject; +import static org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface; public final class JvmAbi { public static final String DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls"; @@ -54,6 +55,7 @@ public final class JvmAbi { private static final String ANNOTATED_TYPEALIAS_METHOD_NAME_SUFFIX = ANNOTATIONS_SUFFIX; public static final String INSTANCE_FIELD = "INSTANCE"; + public static final String HIDDEN_INSTANCE_FIELD = "$$" + INSTANCE_FIELD; public static final String DEFAULT_MODULE_NAME = "main"; public static final ClassId REFLECTION_FACTORY_IMPL = ClassId.topLevel(new FqName("kotlin.reflect.jvm.internal.ReflectionFactoryImpl")); @@ -110,6 +112,16 @@ public final class JvmAbi { public static boolean isCompanionObjectWithBackingFieldsInOuter(@NotNull DeclarationDescriptor companionObject) { return isCompanionObject(companionObject) && isClassOrEnumClass(companionObject.getContainingDeclaration()) && - !CompanionObjectMapping.INSTANCE.isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject); + !isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject); + } + + public static boolean isMappedIntrinsicCompanionObject(@NotNull ClassDescriptor companionObject) { + return CompanionObjectMapping.INSTANCE.isMappedIntrinsicCompanionObject(companionObject); + } + + public static boolean isCompanionObjectInInterfaceNotIntrinsic(@NotNull DeclarationDescriptor companionObject) { + return isCompanionObject(companionObject) && + isInterface(companionObject.getContainingDeclaration()) && + !isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject); } } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 9ac66809cee..03ff4053da0 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -13163,6 +13163,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("classCompanion.kt") + public void testClassCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/classCompanion.kt"); + doTest(fileName); + } + @TestMetadata("flist.kt") public void testFlist() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt"); @@ -13181,6 +13187,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("interfaceCompanion.kt") + public void testInterfaceCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/interfaceCompanion.kt"); + doTest(fileName); + } + @TestMetadata("kt1047.kt") public void testKt1047() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/kt1047.kt"); @@ -13349,6 +13361,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("object.kt") + public void testObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/object.kt"); + doTest(fileName); + } + @TestMetadata("objectExtendsInnerAndReferencesOuterMember.kt") public void testObjectExtendsInnerAndReferencesOuterMember() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/objectExtendsInnerAndReferencesOuterMember.kt");