JVM_IR: No nullability annotations on static lambda instances

This commit is contained in:
Dmitry Petrov
2020-06-29 14:25:06 +03:00
parent eefa621c56
commit e4198466b8
5 changed files with 34 additions and 8 deletions
@@ -50,4 +50,5 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
object FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE : IrDeclarationOriginImpl("FOR_INLINE_TEMPLATE_CROSSINLINE") object FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE : IrDeclarationOriginImpl("FOR_INLINE_TEMPLATE_CROSSINLINE")
object CONTINUATION_CLASS_RESULT_FIELD: IrDeclarationOriginImpl("CONTINUATION_CLASS_RESULT_FIELD", isSynthetic = true) object CONTINUATION_CLASS_RESULT_FIELD: IrDeclarationOriginImpl("CONTINUATION_CLASS_RESULT_FIELD", isSynthetic = true)
object COMPANION_PROPERTY_BACKING_FIELD : IrDeclarationOriginImpl("COMPANION_MOVED_PROPERTY_BACKING_FIELD") object COMPANION_PROPERTY_BACKING_FIELD : IrDeclarationOriginImpl("COMPANION_MOVED_PROPERTY_BACKING_FIELD")
object FIELD_FOR_STATIC_LAMBDA_INSTANCE : IrDeclarationOriginImpl("FIELD_FOR_STATIC_LAMBDA_INSTANCE")
} }
@@ -235,21 +235,25 @@ abstract class ClassCodegen protected constructor(
if (field.origin == IrDeclarationOrigin.PROPERTY_DELEGATE) null if (field.origin == IrDeclarationOrigin.PROPERTY_DELEGATE) null
else context.methodSignatureMapper.mapFieldSignature(field) else context.methodSignatureMapper.mapFieldSignature(field)
val fieldName = field.name.asString() val fieldName = field.name.asString()
val flags = field.flags
val fv = visitor.newField( val fv = visitor.newField(
field.OtherOrigin, field.flags, fieldName, fieldType.descriptor, field.OtherOrigin, flags, fieldName, fieldType.descriptor,
fieldSignature, (field.initializer?.expression as? IrConst<*>)?.value fieldSignature, (field.initializer?.expression as? IrConst<*>)?.value
) )
jvmSignatureClashDetector.trackField(field, RawSignature(fieldName, fieldType.descriptor, MemberKind.FIELD)) jvmSignatureClashDetector.trackField(field, RawSignature(fieldName, fieldType.descriptor, MemberKind.FIELD))
if (field.origin != JvmLoweredDeclarationOrigin.CONTINUATION_CLASS_RESULT_FIELD) { if (field.origin != JvmLoweredDeclarationOrigin.CONTINUATION_CLASS_RESULT_FIELD) {
object : AnnotationCodegen(this@ClassCodegen, context) { val skipNullabilityAnnotations =
flags and Opcodes.ACC_SYNTHETIC != 0 || flags and Opcodes.ACC_PRIVATE != 0 ||
field.origin == JvmLoweredDeclarationOrigin.FIELD_FOR_STATIC_LAMBDA_INSTANCE
object : AnnotationCodegen(this@ClassCodegen, context, skipNullabilityAnnotations) {
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor { override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
return fv.visitAnnotation(descr, visible) return fv.visitAnnotation(descr, visible)
} }
override fun visitTypeAnnotation(descr: String?, path: TypePath?, visible: Boolean): AnnotationVisitor { override fun visitTypeAnnotation(descr: String?, path: TypePath?, visible: Boolean): AnnotationVisitor {
return fv.visitTypeAnnotation(TypeReference.newTypeReference(TypeReference.FIELD).value,path, descr, visible) return fv.visitTypeAnnotation(TypeReference.newTypeReference(TypeReference.FIELD).value, path, descr, visible)
} }
}.genAnnotations(field, fieldType, field.type) }.genAnnotations(field, fieldType, field.type)
} }
@@ -10,24 +10,30 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.irCall import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irExprBody import org.jetbrains.kotlin.ir.builders.irExprBody
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.util.constructedClass import org.jetbrains.kotlin.ir.util.constructedClass
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.primaryConstructor import org.jetbrains.kotlin.ir.util.primaryConstructor
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.util.*
internal val staticLambdaPhase = makeIrFilePhase( internal val staticLambdaPhase = makeIrFilePhase(
::StaticLambdaLowering, ::StaticLambdaLowering,
@@ -36,12 +42,14 @@ internal val staticLambdaPhase = makeIrFilePhase(
) )
class StaticLambdaLowering(val backendContext: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoid() { class StaticLambdaLowering(val backendContext: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoid() {
private val staticLambdaFields = HashMap<IrClass, IrField>()
override fun lower(irFile: IrFile) = irFile.transformChildrenVoid() override fun lower(irFile: IrFile) = irFile.transformChildrenVoid()
override fun visitClass(declaration: IrClass): IrStatement { override fun visitClass(declaration: IrClass): IrStatement {
declaration.transformChildrenVoid() declaration.transformChildrenVoid()
if (declaration.isSyntheticSingleton) { if (declaration.isSyntheticSingleton) {
declaration.declarations += backendContext.declarationFactory.getFieldForObjectInstance(declaration).also { field -> declaration.declarations += getFieldForStaticLambdaInstance(declaration).also { field ->
field.initializer = backendContext.createIrBuilder(field.symbol).run { field.initializer = backendContext.createIrBuilder(field.symbol).run {
irExprBody(irCall(declaration.primaryConstructor!!)) irExprBody(irCall(declaration.primaryConstructor!!))
} }
@@ -50,12 +58,26 @@ class StaticLambdaLowering(val backendContext: JvmBackendContext) : FileLowering
return declaration return declaration
} }
private fun getFieldForStaticLambdaInstance(lambdaClass: IrClass): IrField =
staticLambdaFields.getOrPut(lambdaClass) {
buildField {
name = Name.identifier(JvmAbi.INSTANCE_FIELD)
type = lambdaClass.defaultType
origin = JvmLoweredDeclarationOrigin.FIELD_FOR_STATIC_LAMBDA_INSTANCE
isFinal = true
isStatic = true
visibility = Visibilities.PUBLIC
}.apply {
parent = lambdaClass
}
}
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
val constructor = expression.symbol.owner val constructor = expression.symbol.owner
if (!constructor.constructedClass.isSyntheticSingleton) if (!constructor.constructedClass.isSyntheticSingleton)
return super.visitConstructorCall(expression) return super.visitConstructorCall(expression)
val instanceField = backendContext.declarationFactory.getFieldForObjectInstance(constructor.constructedClass) val instanceField = getFieldForStaticLambdaInstance(constructor.constructedClass)
return IrGetFieldImpl(expression.startOffset, expression.endOffset, instanceField.symbol, expression.type) return IrGetFieldImpl(expression.startOffset, expression.endOffset, instanceField.symbol, expression.type)
} }
@@ -37,7 +37,7 @@ public final class Override5Kt$inlineMe$1$generic$1 {
@kotlin.Metadata @kotlin.Metadata
public final class Override5Kt$inlineMe$1$generic$2 { public final class Override5Kt$inlineMe$1$generic$2 {
public final static @org.jetbrains.annotations.NotNull field INSTANCE: Override5Kt$inlineMe$1$generic$2 public final static field INSTANCE: Override5Kt$inlineMe$1$generic$2
inner (anonymous) class Override5Kt$inlineMe$1 inner (anonymous) class Override5Kt$inlineMe$1
inner (anonymous) class Override5Kt$inlineMe$1$generic$2 inner (anonymous) class Override5Kt$inlineMe$1$generic$2
static method <clinit>(): void static method <clinit>(): void
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
annotation class Ann annotation class Ann
@Ann open class My @Ann open class My