From de9d2919a882918d2be876084ca667e7726d85d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Sch=C3=A4fer?= Date: Thu, 22 Oct 2020 14:07:56 +0200 Subject: [PATCH] JVM Metadata: Add a bit to mark anonymous objects in inline functions Anonymous objects in the scope of an inline functions are copied to all call-sites. This makes them part of the public ABI of a Kotlin library. We introduce a flag to mark all classes in the scope of an inline function. When compiling with assertions enabled, we check that this flag is set whenever we inline an anonymous object from another module. --- .../kotlin/codegen/ClosureCodegen.java | 5 +- .../kotlin/codegen/CodeFragmentCodegen.kt | 2 +- .../codegen/ImplementationBodyCodegen.java | 5 +- .../codegen/InterfaceImplBodyCodegen.kt | 2 +- .../kotlin/codegen/MultifileClassCodegen.kt | 2 +- .../codegen/MultifileClassPartCodegen.kt | 2 +- .../kotlin/codegen/PackagePartCodegen.java | 2 +- .../codegen/PropertyReferenceCodegen.kt | 3 +- .../kotlin/codegen/SamWrapperCodegen.java | 2 +- .../jetbrains/kotlin/codegen/ScriptCodegen.kt | 2 +- .../binding/CodegenAnnotatingVisitor.java | 10 +++- .../jetbrains/kotlin/codegen/codegenUtil.kt | 2 +- .../codegen/coroutines/CoroutineCodegen.kt | 4 +- .../inline/AnonymousObjectTransformer.kt | 16 +++++- .../inline/PsiSourceCompilerForInline.kt | 9 ++- .../codegen/inline/SourceCompilerForInline.kt | 12 +++- .../MappingClassesForWhenByEnumCodegen.java | 3 +- .../codegen/when/WhenByEnumsMapping.java | 9 ++- .../kotlin/codegen/writeAnnotationUtil.kt | 8 ++- .../kotlin/resolve/inline/InlineUtil.java | 11 ++++ .../kotlin/backend/jvm/JvmBackendContext.kt | 2 + .../backend/jvm/codegen/ClassCodegen.kt | 20 ++++++- .../jvm/codegen/IrSourceCompilerForInline.kt | 14 ++--- .../kotlin/backend/jvm/ir/IrUtils.kt | 24 ++++++++ .../jvm/lower/MappedEnumWhenLowering.kt | 55 +++++++++++++------ .../kotlin/load/java/JvmAnnotationNames.java | 1 + .../stdlib/jvm/runtime/kotlin/Metadata.kt | 2 + .../parcel/ParcelableCodegenExtension.kt | 5 +- .../compiler/backend/jvm/JVMCodegenUtil.kt | 2 +- .../parcelize/ParcelizeCodegenExtension.kt | 3 +- 30 files changed, 181 insertions(+), 58 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java index bba4150b6de..a8d0438151a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.psi.KtElement; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; +import org.jetbrains.kotlin.resolve.inline.InlineUtil; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; import org.jetbrains.kotlin.resolve.scopes.MemberScope; import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver; @@ -287,7 +288,9 @@ public class ClosureCodegen extends MemberCodegen { if (builder == null) return; ProtoBuf.Function functionProto = builder.build(); - WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0, av -> { + boolean publicAbi = InlineUtil.isInPublicInlineScope(frontendFunDescriptor); + + WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, publicAbi, 0, av -> { writeAnnotationData(av, serializer, functionProto); return Unit.INSTANCE; }); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CodeFragmentCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CodeFragmentCodegen.kt index 67696d79764..8fd3e239b3c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CodeFragmentCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CodeFragmentCodegen.kt @@ -79,7 +79,7 @@ class CodeFragmentCodegen private constructor( } override fun generateKotlinMetadataAnnotation() { - writeSyntheticClassMetadata(v, state) + writeSyntheticClassMetadata(v, state, false) } private fun genConstructor() { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 9c6afccca8a..75b3bd06ad7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -43,6 +43,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; +import org.jetbrains.kotlin.resolve.inline.InlineUtil; import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; @@ -304,7 +305,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { protected void generateKotlinMetadataAnnotation() { ProtoBuf.Class classProto = serializer.classProto(descriptor).build(); - WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.CLASS, 0, av -> { + boolean publicAbi = InlineUtil.isInPublicInlineScope(descriptor); + + WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.CLASS, publicAbi, 0, av -> { writeAnnotationData(av, serializer, classProto); return Unit.INSTANCE; }); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt index 16255dec118..36389ed7fc3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt @@ -141,7 +141,7 @@ class InterfaceImplBodyCodegen( override fun generateKotlinMetadataAnnotation() { (v as InterfaceImplClassBuilder).stopCounting() - writeSyntheticClassMetadata(v, state) + writeSyntheticClassMetadata(v, state, false) } override fun done() { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassCodegen.kt index 8becdf49b50..67c2112a274 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassCodegen.kt @@ -391,7 +391,7 @@ class MultifileClassCodegenImpl( facadeClassType: Type, kotlinPackageFqName: FqName ) { - writeKotlinMetadata(classBuilder, state, KotlinClassHeader.Kind.MULTIFILE_CLASS, flags) { av -> + writeKotlinMetadata(classBuilder, state, KotlinClassHeader.Kind.MULTIFILE_CLASS, false, flags) { av -> val arv = av.visitArray(JvmAnnotationNames.METADATA_DATA_FIELD_NAME) for (internalName in partInternalNames) { arv.visit(null, internalName) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt index 5a87cb1cb3d..d097dcec827 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt @@ -96,7 +96,7 @@ class MultifileClassPartCodegen( val extraFlags = if (shouldGeneratePartHierarchy) JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG else 0 - writeKotlinMetadata(v, state, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART, extraFlags) { av -> + writeKotlinMetadata(v, state, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART, false, extraFlags) { av -> DescriptorAsmUtil.writeAnnotationData(av, serializer, packageProto) av.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME, facadeClassType.internalName) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java index 0cd60d0c0fb..34315fb3f4c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java @@ -107,7 +107,7 @@ public class PackagePartCodegen extends MemberCodegen { protected void generateKotlinMetadataAnnotation() { Pair serializedPart = serializePackagePartMembers(this, packagePartType); - WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.FILE_FACADE, 0, av -> { + WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.FILE_FACADE, false, 0, av -> { writeAnnotationData(av, serializedPart.getFirst(), serializedPart.getSecond()); FqName kotlinPackageFqName = element.getPackageFqName(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt index ffab7bde6f3..28b94c2973a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.PropertyImportedFromObject import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny +import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.isUnderlyingPropertyOfInlineClass import org.jetbrains.kotlin.resolve.jvm.AsmTypes.* import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin @@ -209,7 +210,7 @@ class PropertyReferenceCodegen( } override fun generateKotlinMetadataAnnotation() { - writeSyntheticClassMetadata(v, state) + writeSyntheticClassMetadata(v, state, InlineUtil.isInPublicInlineScope(classDescriptor)) } fun putInstanceOnStack(receiverValue: StackValue?): StackValue { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/SamWrapperCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/SamWrapperCodegen.java index c56570165b5..737e57091ff 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/SamWrapperCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/SamWrapperCodegen.java @@ -138,7 +138,7 @@ public class SamWrapperCodegen { ); cv.visitSource(file.getName(), null); - WriteAnnotationUtilKt.writeSyntheticClassMetadata(cv, state); + WriteAnnotationUtilKt.writeSyntheticClassMetadata(cv, state, isInsideInline); generateInnerClassInformation(file, asmType, cv); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.kt index 4f471562b69..3e27b2dcdfc 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.kt @@ -69,7 +69,7 @@ class ScriptCodegen private constructor( override fun generateKotlinMetadataAnnotation() { val serializer = DescriptorSerializer.create(scriptDescriptor, JvmSerializerExtension(v.serializationBindings, state), null) val classProto = serializer.classProto(scriptDescriptor).build() - writeKotlinMetadata(v, state, KotlinClassHeader.Kind.CLASS, JvmAnnotationNames.METADATA_SCRIPT_FLAG) { av -> + writeKotlinMetadata(v, state, KotlinClassHeader.Kind.CLASS, false, JvmAnnotationNames.METADATA_SCRIPT_FLAG) { av -> DescriptorAsmUtil.writeAnnotationData(av, serializer, classProto) } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java index 109c5f2162e..5cde95d370e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java @@ -1012,7 +1012,15 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { ClassDescriptor classDescriptor = (ClassDescriptor) type.getConstructor().getDeclarationDescriptor(); assert classDescriptor != null : "because it's enum"; - WhenByEnumsMapping mapping = new WhenByEnumsMapping(classDescriptor, currentClassName, fieldNumber); + boolean isPublicAbi = false; + for (FunctionDescriptor descriptor : functionsStack) { + if (descriptor.isInline()) { + isPublicAbi = !DescriptorVisibilities.isPrivate(descriptor.getVisibility()); + break; + } + } + + WhenByEnumsMapping mapping = new WhenByEnumsMapping(classDescriptor, currentClassName, fieldNumber, isPublicAbi); for (ConstantValue constant : switchCodegenProvider.getAllConstants(expression)) { if (constant instanceof NullValue) continue; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt index f3b22692860..c45c182dec8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt @@ -654,7 +654,7 @@ private fun generateLambdaForRunSuspend( visitEnd() } - writeSyntheticClassMetadata(lambdaBuilder, state) + writeSyntheticClassMetadata(lambdaBuilder, state, false) lambdaBuilder.done() return lambdaBuilder.thisName diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt index a1eb4e62e66..121e7715d68 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.indexOrMinusOne +import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.isInlineClassType import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm @@ -742,7 +743,8 @@ class CoroutineCodegenForNamedFunction private constructor( } override fun generateKotlinMetadataAnnotation() { - writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0) { av -> + val publicAbi = InlineUtil.isInPublicInlineScope(classDescriptor) + writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, publicAbi, 0) { av -> val serializer = DescriptorSerializer.createForLambda(JvmSerializerExtension(v.serializationBindings, state)) val functionProto = serializer.functionProto( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt index 9149c06488e..ef88393b311 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt @@ -118,6 +118,10 @@ class AnonymousObjectTransformer( override fun visitEnd() {} }, ClassReader.SKIP_FRAMES) + val header = metadataReader.createHeader() + assert(isSameModule || (header != null && isPublicAbi(header))) { + "Trying to inline an anonymous object which is not part of the public ABI: ${oldObjectType.className}" + } // When regenerating objects in inline lambdas, keep the old SMAP and don't remap the line numbers to // save time. The result is effectively the same anyway. @@ -198,7 +202,6 @@ class AnonymousObjectTransformer( visitor.visitInnerClass(node.name, node.outerName, node.innerName, node.access) } - val header = metadataReader.createHeader() if (header != null) { writeTransformedMetadata(header, classBuilder) } @@ -229,7 +232,9 @@ class AnonymousObjectTransformer( } private fun writeTransformedMetadata(header: KotlinClassHeader, classBuilder: ClassBuilder) { - writeKotlinMetadata(classBuilder, state, header.kind, header.extraInt) action@{ av -> + // The transformed anonymous object becomes part of the public ABI if it is inside of a public inline function. + val publicAbi = inliningContext.callSiteInfo.isInPublicInlineScope + writeKotlinMetadata(classBuilder, state, header.kind, publicAbi, header.extraInt and JvmAnnotationNames.METADATA_PUBLIC_ABI_FLAG.inv()) action@{ av -> val (newProto, newStringTable) = transformMetadata(header) ?: run { val data = header.data val strings = header.strings @@ -242,6 +247,11 @@ class AnonymousObjectTransformer( } } + private fun isPublicAbi(header: KotlinClassHeader): Boolean = + // The public abi flag was only introduced in metadata version 1.6.0, before then we have to skip this check. + !header.metadataVersion.isAtLeast(1, 6, 0) || + header.extraInt and JvmAnnotationNames.METADATA_PUBLIC_ABI_FLAG != 0 + private fun transformMetadata(header: KotlinClassHeader): Pair? { val data = header.data ?: return null val strings = header.strings ?: return null @@ -317,7 +327,7 @@ class AnonymousObjectTransformer( InlineCallSiteInfo( transformationInfo.oldClassName, Method(sourceNode.name, if (isConstructor) transformationInfo.newConstructorDescriptor else sourceNode.desc), - inliningContext.callSiteInfo.isInlineOrInsideInline, + inliningContext.callSiteInfo.inlineScopeVisibility, inliningContext.callSiteInfo.file, inliningContext.callSiteInfo.lineNumber ), diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiSourceCompilerForInline.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiSourceCompilerForInline.kt index 47f83068ca7..cd45da13b82 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiSourceCompilerForInline.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiSourceCompilerForInline.kt @@ -74,7 +74,7 @@ class PsiSourceCompilerForInline( return InlineCallSiteInfo( parentCodegen.className, signature.asmMethod, - context.functionDescriptor.isInlineOrInsideInline(), + context.functionDescriptor.getInlineCallSiteVisibility(), callElement.containingFile, CodegenUtil.getLineNumberForElement(callElement, false) ?: 0 ) @@ -416,8 +416,11 @@ class PsiSourceCompilerForInline( } fun DeclarationDescriptor.isInlineOrInsideInline(): Boolean = - if (this is FunctionDescriptor && isInline) true - else containingDeclaration?.isInlineOrInsideInline() == true + getInlineCallSiteVisibility() != null + +fun DeclarationDescriptor.getInlineCallSiteVisibility(): DescriptorVisibility? = + if (this is FunctionDescriptor && isInline) visibility + else containingDeclaration?.getInlineCallSiteVisibility() fun getDeclarationLabels(lambdaOrFun: PsiElement?, descriptor: DeclarationDescriptor): Set { val result = HashSet() diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt index 01714c89330..248d89b749b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt @@ -10,6 +10,8 @@ import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.incremental.components.LocationInfo import org.jetbrains.kotlin.incremental.components.Position import org.jetbrains.kotlin.incremental.components.ScopeKind @@ -24,10 +26,16 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode class InlineCallSiteInfo( val ownerClassName: String, val method: Method, - val isInlineOrInsideInline: Boolean, + val inlineScopeVisibility: DescriptorVisibility?, val file: PsiFile?, val lineNumber: Int -) +) { + val isInlineOrInsideInline: Boolean + get() = inlineScopeVisibility != null + + val isInPublicInlineScope: Boolean + get() = inlineScopeVisibility != null && !DescriptorVisibilities.isPrivate(inlineScopeVisibility) +} interface SourceCompilerForInline { val state: GenerationState diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/when/MappingClassesForWhenByEnumCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/when/MappingClassesForWhenByEnumCodegen.java index 5448f2a68c2..800775b98c0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/when/MappingClassesForWhenByEnumCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/when/MappingClassesForWhenByEnumCodegen.java @@ -57,7 +57,8 @@ public class MappingClassesForWhenByEnumCodegen { generateFields(cb, mappings); generateInitialization(cb, mappings); - WriteAnnotationUtilKt.writeSyntheticClassMetadata(cb, state); + boolean publicAbi = mappings.stream().anyMatch(WhenByEnumsMapping::isPublicAbi); + WriteAnnotationUtilKt.writeSyntheticClassMetadata(cb, state, publicAbi); cb.done(); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/when/WhenByEnumsMapping.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/when/WhenByEnumsMapping.java index 9b92224d004..a723bd1f7be 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/when/WhenByEnumsMapping.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/when/WhenByEnumsMapping.java @@ -32,16 +32,19 @@ public class WhenByEnumsMapping { private final String outerClassInternalNameForExpression; private final String mappingsClassInternalName; private final int fieldNumber; + private final boolean isPublicAbi; public WhenByEnumsMapping( @NotNull ClassDescriptor enumClassDescriptor, @NotNull String outerClassInternalNameForExpression, - int fieldNumber + int fieldNumber, + boolean isPublicAbi ) { this.enumClassDescriptor = enumClassDescriptor; this.outerClassInternalNameForExpression = outerClassInternalNameForExpression; this.mappingsClassInternalName = outerClassInternalNameForExpression + MAPPINGS_CLASS_NAME_POSTFIX; this.fieldNumber = fieldNumber; + this.isPublicAbi = isPublicAbi; } public int getIndexByEntry(@NotNull EnumValue value) { @@ -80,6 +83,10 @@ public class WhenByEnumsMapping { return mappingsClassInternalName; } + public boolean isPublicAbi() { + return isPublicAbi; + } + @NotNull public Iterable> enumValuesToIntMapping() { return map.entrySet(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/writeAnnotationUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/writeAnnotationUtil.kt index c33ddbc0573..351a6e6772d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/writeAnnotationUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/writeAnnotationUtil.kt @@ -27,6 +27,7 @@ fun writeKotlinMetadata( cb: ClassBuilder, state: GenerationState, kind: KotlinClassHeader.Kind, + publicAbi: Boolean, extraFlags: Int, action: (AnnotationVisitor) -> Unit ) { @@ -43,6 +44,9 @@ fun writeKotlinMetadata( if (state.languageVersionSettings.getFlag(JvmAnalysisFlags.strictMetadataVersionSemantics)) { flags = flags or JvmAnnotationNames.METADATA_STRICT_VERSION_SEMANTICS_FLAG } + if (publicAbi) { + flags = flags or JvmAnnotationNames.METADATA_PUBLIC_ABI_FLAG + } if (flags != 0) { av.visit(JvmAnnotationNames.METADATA_EXTRA_INT_FIELD_NAME, flags) } @@ -50,8 +54,8 @@ fun writeKotlinMetadata( av.visitEnd() } -fun writeSyntheticClassMetadata(cb: ClassBuilder, state: GenerationState) { - writeKotlinMetadata(cb, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0) { _ -> +fun writeSyntheticClassMetadata(cb: ClassBuilder, state: GenerationState, publicAbi: Boolean) { + writeKotlinMetadata(cb, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, publicAbi, 0) { _ -> // Do nothing } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineUtil.java index 4d151d00a59..9365dd7e263 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineUtil.java @@ -74,6 +74,17 @@ public class InlineUtil { return isInlineOrContainingInline(descriptor.getContainingDeclaration()); } + public static boolean isInPublicInlineScope(@Nullable DeclarationDescriptor descriptor) { + if (descriptor == null) return false; + if (isInline(descriptor)) { + if (!(descriptor instanceof DeclarationDescriptorWithVisibility)) + return false; + DescriptorVisibility visibility = ((DeclarationDescriptorWithVisibility) descriptor).getVisibility(); + return !DescriptorVisibilities.isPrivate(visibility); + } + return isInPublicInlineScope(descriptor.getContainingDeclaration()); + } + public static boolean checkNonLocalReturnUsage( @NotNull DeclarationDescriptor fromFunction, @NotNull KtExpression startExpression, diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index d0702ea45eb..92036164571 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -136,6 +136,8 @@ class JvmBackendContext( val directInvokedLambdas = mutableListOf() + val publicAbiSymbols = mutableSetOf() + init { state.mapInlineClass = { descriptor -> typeMapper.mapType(referenceClass(descriptor).defaultType) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 85fc839337a..5933fab5b97 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen import org.jetbrains.kotlin.backend.common.psi.PsiSourceManager import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.backend.jvm.ir.isInPublicInlineScope import org.jetbrains.kotlin.backend.jvm.ir.isSyntheticSingleton import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry import org.jetbrains.kotlin.backend.jvm.lower.buildAssertionsDisabledField @@ -258,7 +259,17 @@ class ClassCodegen private constructor( extraFlags = extraFlags or JvmAnnotationNames.METADATA_SCRIPT_FLAG } - writeKotlinMetadata(visitor, state, kind, extraFlags) { av -> + // There are three kinds of classes which are regenerated during inlining. + // 1) Anonymous classes which are in the scope of an inline function. + // 2) SAM wrappers used in an inline function. These are identified by name, since they + // can be reused in different functions and are thus generated in the enclosing top-level + // class instead of inside of an inline function. + // 3) WhenMapping classes used from inline functions. These are collected in + // `JvmBackendContext.publicAbiSymbols` in `MappedEnumWhenLowering`. + val isPublicAbi = irClass.symbol in context.publicAbiSymbols || irClass.isInlineSamWrapper || + type.isAnonymousClass && irClass.isInPublicInlineScope + + writeKotlinMetadata(visitor, state, kind, isPublicAbi, extraFlags) { av -> if (metadata != null) { metadataSerializer.serialize(metadata)?.let { (proto, stringTable) -> DescriptorAsmUtil.writeAnnotationData(av, proto, stringTable) @@ -454,6 +465,9 @@ class ClassCodegen private constructor( private val IrClass.isAnonymousInnerClass: Boolean get() = isSamWrapper || name.isSpecial // NB '' is treated as anonymous inner class here + private val IrClass.isInlineSamWrapper: Boolean + get() = isSamWrapper && visibility == DescriptorVisibilities.PUBLIC + private val IrClass.isSamWrapper: Boolean get() = origin == IrDeclarationOrigin.GENERATED_SAM_IMPLEMENTATION @@ -579,3 +593,7 @@ private fun storeSerializedIr(av: AnnotationVisitor, serializedIr: ByteArray) { } partsVisitor.visitEnd() } + +// From `isAnonymousClass` in inlineCodegenUtils.kt +private val Type.isAnonymousClass: Boolean + get() = internalName.substringAfterLast("$", "").toIntOrNull() != null diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt index ae3d9c07841..4407e236821 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.util.TextRange import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.jvm.ir.getKtFile +import org.jetbrains.kotlin.backend.jvm.ir.inlineScopeVisibility import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.hasMangledReturnType import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.state.GenerationState @@ -16,7 +17,8 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticUtils import org.jetbrains.kotlin.incremental.components.LocationInfo import org.jetbrains.kotlin.incremental.components.Position import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI -import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrLoop @@ -48,7 +50,7 @@ class IrSourceCompilerForInline( return InlineCallSiteInfo( root.classCodegen.type.internalName, root.signature.asmMethod, - root.irFunction.isInlineOrInsideInline(), + root.irFunction.inlineScopeVisibility, root.irFunction.fileParent.getKtFile(), callElement.psiElement?.let { CodegenUtil.getLineNumberForElement(it, false) } ?: 0 ) @@ -131,12 +133,4 @@ class IrSourceCompilerForInline( } } -private tailrec fun IrDeclaration.isInlineOrInsideInline(): Boolean { - val original = (this as? IrAttributeContainer)?.attributeOwnerId as? IrDeclaration ?: this - if (original is IrSimpleFunction && original.isInline) return true - val parent = original.parent - if (parent !is IrDeclaration) return false - return parent.isInlineOrInsideInline() -} - internal fun IrLoop.nonLocalReturnLabel(forBreak: Boolean): String = "${label!!}\$${if (forBreak) "break" else "continue"}" diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt index b382e6828d0..dfc53348106 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.ir.IrBuiltIns @@ -48,6 +49,7 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_DEFAULT_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_DEFAULT_NO_COMPATIBILITY_FQ_NAME +import org.jetbrains.kotlin.utils.addToStdlib.safeAs /** * Perform as much type erasure as is significant for JVM signature generation. @@ -419,3 +421,25 @@ val IrClass.isSyntheticSingleton: Boolean || origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL || origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE) && primaryConstructor!!.valueParameters.isEmpty() + +// Map declarations to original declarations before lowering. +private val IrDeclaration.original: IrDeclaration + get() = (this as? IrAttributeContainer)?.attributeOwnerId as? IrDeclaration ?: this + +// Declarations in the scope of an externally visible inline function are implicitly part of the +// public ABI of a Kotlin module. This function returns the visibility of a containing inline function +// (determined *before* lowering), or null if the given declaration is not in the scope of an inline function. +val IrDeclaration.inlineScopeVisibility: DescriptorVisibility? + get() { + var owner = original + while (true) { + if (owner is IrFunction && owner.isInline) { + return owner.visibility + } + owner = owner.parent.safeAs()?.original ?: return null + } + } + +// True for declarations which are in the scope of an externally visible inline function. +val IrDeclaration.isInPublicInlineScope: Boolean + get() = inlineScopeVisibility?.let(DescriptorVisibilities::isPrivate) == false diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MappedEnumWhenLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MappedEnumWhenLowering.kt index 6b3be5319cd..bbbc402ea92 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MappedEnumWhenLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MappedEnumWhenLowering.kt @@ -5,18 +5,20 @@ package org.jetbrains.kotlin.backend.jvm.lower -import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.lower.EnumWhenLowering import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.backend.jvm.ir.isInPublicInlineScope import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.addField import org.jetbrains.kotlin.ir.builders.declarations.buildClass import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrEnumEntry import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -25,6 +27,7 @@ import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.addToStdlib.safeAs internal val enumWhenPhase = makeIrFilePhase( ::MappedEnumWhenLowering, @@ -57,7 +60,7 @@ internal val enumWhenPhase = makeIrFilePhase( // The latter would not need to be recompiled if new entries were added before `X` // at the negligible cost of an additional initializer per run + one array read per call. // -private class MappedEnumWhenLowering(context: CommonBackendContext) : EnumWhenLowering(context) { +private class MappedEnumWhenLowering(context: JvmBackendContext) : EnumWhenLowering(context) { private val intArray = context.irBuiltIns.primitiveArrayForType.getValue(context.irBuiltIns.intType) private val intArrayConstructor = intArray.constructors.single { it.owner.valueParameters.size == 1 } private val intArrayGet = intArray.functions.single { it.owner.name == OperatorNameConventions.GET } @@ -68,8 +71,14 @@ private class MappedEnumWhenLowering(context: CommonBackendContext) : EnumWhenLo // of the classes in which they are used. This field tracks which container is the innermost one. private var state: EnumMappingState? = null + private class EnumMappingClass( + val field: IrField, + val ordinals: MutableMap = mutableMapOf(), + var isPublicAbi: Boolean = false, + ) + private inner class EnumMappingState { - val mappings = mutableMapOf, IrField>>() + val mappings = mutableMapOf() val mappingsClass by lazy { context.irFactory.buildClass { name = Name.identifier("WhenMappings") @@ -79,39 +88,46 @@ private class MappedEnumWhenLowering(context: CommonBackendContext) : EnumWhenLo } } - fun getMappingForClass(enumClass: IrClass): Pair, IrField> = + fun getMappingForClass(enumClass: IrClass): EnumMappingClass = mappings.getOrPut(enumClass) { - mutableMapOf() to mappingsClass.addField { + EnumMappingClass(mappingsClass.addField { name = Name.identifier("\$EnumSwitchMapping\$${mappings.size}") type = intArray.defaultType origin = JvmLoweredDeclarationOrigin.ENUM_MAPPINGS_FOR_WHEN isFinal = true isStatic = true - } + }) } + + val isPublicAbi: Boolean + get() = mappings.values.any { it.isPublicAbi } } override fun mapConstEnumEntry(entry: IrEnumEntry): Int { - val (mapping) = state!!.getMappingForClass(entry.parentAsClass) + val mapping = state!!.getMappingForClass(entry.parentAsClass).ordinals // Index 0 (default value for integers) is reserved for unknown ordinals. return mapping.getOrPut(entry) { mapping.size + 1 } } override fun mapRuntimeEnumEntry(builder: IrBuilderWithScope, subject: IrExpression): IrExpression = builder.irCall(intArrayGet).apply { - val (_, field) = state!!.getMappingForClass(subject.type.getClass()!!) - dispatchReceiver = builder.irGetField(null, field) + val mapping = state!!.getMappingForClass(subject.type.getClass()!!) + + mapping.isPublicAbi = mapping.isPublicAbi || + (builder.scope.scopeOwnerSymbol.owner.safeAs()?.isInPublicInlineScope ?: false) + + dispatchReceiver = builder.irGetField(null, mapping.field) putValueArgument(0, super.mapRuntimeEnumEntry(builder, subject)) } override fun visitClassNew(declaration: IrClass): IrStatement { val oldState = state - state = EnumMappingState() + val mappingState = EnumMappingState() + state = mappingState super.visitClassNew(declaration) - for ((enum, mappingAndField) in state!!.mappings) { - val (mapping, field) = mappingAndField - val builder = context.createIrBuilder(state!!.mappingsClass.symbol) + for ((enum, mapping) in mappingState.mappings) { + val builder = context.createIrBuilder(mappingState.mappingsClass.symbol) val enumValues = enum.functions.single { it.name.toString() == "values" && it.dispatchReceiverParameter == null @@ -120,10 +136,10 @@ private class MappedEnumWhenLowering(context: CommonBackendContext) : EnumWhenLo && it.returnType.isBoxedArray && it.returnType.getArrayElementType(context.irBuiltIns).classOrNull == enum.symbol } - field.initializer = builder.irExprBody(builder.irBlock { + mapping.field.initializer = builder.irExprBody(builder.irBlock { val enumSize = irCall(refArraySize).apply { dispatchReceiver = irCall(enumValues) } val result = irTemporary(irCall(intArrayConstructor).apply { putValueArgument(0, enumSize) }) - for ((entry, index) in mapping) { + for ((entry, index) in mapping.ordinals) { val runtimeEntry = IrGetEnumValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, enum.defaultType, entry.symbol) +irCall(intArraySet).apply { dispatchReceiver = irGet(result) @@ -135,8 +151,13 @@ private class MappedEnumWhenLowering(context: CommonBackendContext) : EnumWhenLo }) } - if (state!!.mappings.isNotEmpty()) { - declaration.declarations += state!!.mappingsClass.apply { parent = declaration } + if (mappingState.mappings.isNotEmpty()) { + declaration.declarations += mappingState.mappingsClass.apply { + parent = declaration + if (mappingState.isPublicAbi) { + (context as JvmBackendContext).publicAbiSymbols += symbol + } + } } state = oldState return declaration diff --git a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java index 93a6db73d4f..3f3e759d250 100644 --- a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java +++ b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java @@ -44,6 +44,7 @@ public final class JvmAnnotationNames { public static final int METADATA_JVM_IR_FLAG = 1 << 4; public static final int METADATA_JVM_IR_STABLE_ABI_FLAG = 1 << 5; public static final int METADATA_FIR_FLAG = 1 << 6; + public static final int METADATA_PUBLIC_ABI_FLAG = 1 << 7; public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value"); diff --git a/libraries/stdlib/jvm/runtime/kotlin/Metadata.kt b/libraries/stdlib/jvm/runtime/kotlin/Metadata.kt index 1bac9414ddd..dfe79ab9a1f 100644 --- a/libraries/stdlib/jvm/runtime/kotlin/Metadata.kt +++ b/libraries/stdlib/jvm/runtime/kotlin/Metadata.kt @@ -76,6 +76,8 @@ public annotation class Metadata( * * 5 - this class file has stable metadata and ABI. This is used only for class files compiled with JVM IR (see flag #4) or FIR (#6), * and prevents metadata incompatibility diagnostics from being reported where the class is used. * * 6 - this class file is compiled with the new Kotlin compiler frontend (FIR). + * * 7 - this class is used in the scope of an inline function and implicitly part of the public ABI. Only valid from + * metadata version 1.6.0. */ @SinceKotlin("1.1") @get:JvmName("xi") diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt index 1a269af41ab..f10d3f81998 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt @@ -28,12 +28,12 @@ import org.jetbrains.kotlin.codegen.writeSyntheticClassMetadata import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.incremental.components.NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.storage.LockBasedStorageManager @@ -42,7 +42,6 @@ import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.Variance import org.jetbrains.org.objectweb.asm.Opcodes.* import org.jetbrains.org.objectweb.asm.Type -import java.io.FileDescriptor open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodegenExtension { @Deprecated( @@ -315,7 +314,7 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg codegen.v.visitInnerClass(creatorAsmType.internalName, containerAsmType.internalName, "Creator", ACC_PUBLIC or ACC_STATIC) codegenForCreator.v.visitInnerClass(creatorAsmType.internalName, containerAsmType.internalName, "Creator", ACC_PUBLIC or ACC_STATIC) - writeSyntheticClassMetadata(classBuilderForCreator, codegen.state) + writeSyntheticClassMetadata(classBuilderForCreator, codegen.state, InlineUtil.isInPublicInlineScope(parcelableClass)) writeCreatorConstructor(codegenForCreator, creatorClass, creatorAsmType) writeNewArrayMethod(codegenForCreator, parcelableClass, parcelableCreatorClassType, creatorClass, parcelerObject) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt index d4f0aed0797..30c023253ae 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt @@ -658,7 +658,7 @@ internal fun createSingletonLambda( areturn(kSerializerType) } - writeSyntheticClassMetadata(lambdaClassBuilder, lambdaCodegen.state) + writeSyntheticClassMetadata(lambdaClassBuilder, lambdaCodegen.state, false) lambdaClassBuilder.done() return lambdaType diff --git a/plugins/parcelize/parcelize-compiler/src/org/jetbrains/kotlin/parcelize/ParcelizeCodegenExtension.kt b/plugins/parcelize/parcelize-compiler/src/org/jetbrains/kotlin/parcelize/ParcelizeCodegenExtension.kt index 4f65535c98f..33d54c3c65c 100644 --- a/plugins/parcelize/parcelize-compiler/src/org/jetbrains/kotlin/parcelize/ParcelizeCodegenExtension.kt +++ b/plugins/parcelize/parcelize-compiler/src/org/jetbrains/kotlin/parcelize/ParcelizeCodegenExtension.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature @@ -329,7 +330,7 @@ open class ParcelizeCodegenExtension : ParcelizeExtensionBase, ExpressionCodegen codegen.v.visitInnerClass(creatorAsmType.internalName, containerAsmType.internalName, "Creator", ACC_PUBLIC or ACC_STATIC) codegenForCreator.v.visitInnerClass(creatorAsmType.internalName, containerAsmType.internalName, "Creator", ACC_PUBLIC or ACC_STATIC) - writeSyntheticClassMetadata(classBuilderForCreator, codegen.state) + writeSyntheticClassMetadata(classBuilderForCreator, codegen.state, InlineUtil.isInPublicInlineScope(parcelableClass)) writeCreatorConstructor(codegenForCreator, creatorClass, creatorAsmType) writeNewArrayMethod(codegenForCreator, parcelableClass, parcelableCreatorClassType, creatorClass, parcelerObject)