jvm-abi-gen: Mark annotation implementation classes as public...

...if they are used from public inline functions in the same file.
This commit is contained in:
Steven Schäfer
2021-08-17 13:28:56 +02:00
committed by Alexander Udalov
parent 6756420725
commit 8de6a5224f
2 changed files with 31 additions and 6 deletions
@@ -258,13 +258,16 @@ class ClassCodegen private constructor(
extraFlags = extraFlags or JvmAnnotationNames.METADATA_SCRIPT_FLAG
}
// There are three kinds of classes which are regenerated during inlining.
// There are four 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
// 3) WhenMapping classes used from public inline functions. These are collected in
// `JvmBackendContext.publicAbiSymbols` in `MappedEnumWhenLowering`.
// 4) Annotation implementation classes used from public inline function. Similar to
// public WhenMapping classes, these are collected in `publicAbiSymbols` in
// `JvmAnnotationImplementationTransformer`.
val isPublicAbi = irClass.symbol in context.publicAbiSymbols || irClass.isInlineSamWrapper ||
type.isAnonymousClass && irClass.isInPublicInlineScope
@@ -11,18 +11,20 @@ import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationTransfo
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
import org.jetbrains.kotlin.backend.jvm.ir.isInPublicInlineScope
import org.jetbrains.kotlin.backend.jvm.lower.FunctionReferenceLowering.Companion.javaClassReference
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.findDeclaration
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal val annotationImplementationPhase = makeIrFilePhase<JvmBackendContext>(
{ ctxt -> AnnotationImplementationLowering { JvmAnnotationImplementationTransformer(ctxt, it) } },
@@ -32,6 +34,20 @@ internal val annotationImplementationPhase = makeIrFilePhase<JvmBackendContext>(
class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext, file: IrFile) :
AnnotationImplementationTransformer(jvmContext, file) {
private val publicAnnotationImplementationClasses = mutableSetOf<IrClassSymbol>()
// FIXME: Copied from JvmSingleAbstractMethodLowering
private val inInlineFunctionScope: Boolean
get() = allScopes.any { it.irElement.safeAs<IrDeclaration>()?.isInPublicInlineScope == true }
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
val constructedClass = expression.type.classOrNull
if (constructedClass?.owner?.isAnnotationClass == true && inInlineFunctionScope) {
publicAnnotationImplementationClasses += constructedClass
}
return super.visitConstructorCall(expression)
}
override fun IrType.kClassToJClassIfNeeded(): IrType = when {
this.isKClass() -> jvmContext.ir.symbols.javaLangClass.starProjectedType
this.isKClassArray() -> jvmContext.irBuiltIns.arrayClass.typeWith(
@@ -72,6 +88,12 @@ class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext,
}
override fun implementPlatformSpecificParts(annotationClass: IrClass, implClass: IrClass) {
// Mark the implClass as part of the public ABI if it was instantiated from a public
// inline function, since annotation implementation classes are regenerated during inlining.
if (annotationClass.symbol in publicAnnotationImplementationClasses) {
jvmContext.publicAbiSymbols += implClass.symbol
}
implClass.addFunction(
name = "annotationType",
returnType = jvmContext.ir.symbols.javaLangClass.starProjectedType,