From 146f0f4904cdd52bf173959aad4889845d4d1b96 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Fri, 8 Oct 2021 09:57:05 +0300 Subject: [PATCH] JVM_IR KT-41214 emit PermittedSubclasses on JDK17+ --- .../kotlin/fir/lazy/Fir2IrLazyClass.kt | 5 + .../kotlin/backend/jvm/JvmIrCodegenFactory.kt | 7 +- .../kotlin/backend/jvm/JvmBackendContext.kt | 2 +- .../backend/jvm/codegen/ClassCodegen.kt | 18 ++ .../psi2ir/generators/ClassGenerator.kt | 4 + .../psi2ir/generators/GeneratorContext.kt | 4 +- .../ir/declarations/impl/IrClassImpl.kt | 4 +- .../persistent/PersistentIrClass.kt | 30 ++- .../persistent/carriers/ClassCarrier.kt | 8 +- .../ir/serialization/IrCarrierDeserializer.kt | 5 +- .../ir/serialization/IrCarrierSerializer.kt | 3 + .../kotlin/ir/persistentIrGenerator/Class.kt | 4 + .../PersistentIrGenerator.kt | 2 + .../IrCarrierDeserializerImpl.kt | 5 +- .../serialization/IrCarrierSerializerImpl.kt | 4 + .../kotlin/ir/declarations/IrClass.kt | 2 + .../ir/declarations/lazy/IrLazyClass.kt | 19 +- .../ir/util/DeepCopyIrTreeWithSymbols.kt | 3 + .../jetbrains/kotlin/ir/util/DumpIrTree.kt | 1 + .../serialization.common/src/KotlinIr.proto | 1 + .../src/KotlinPirCarriers.proto | 3 +- .../IrDeclarationDeserializer.kt | 2 + .../common/serialization/IrFileSerializer.kt | 4 + .../common/serialization/proto/IrClass.java | 152 +++++++++++++++ .../serialization/proto/IrClassOrBuilder.java | 13 ++ .../serialization/proto/PirClassCarrier.java | 178 ++++++++++++++++-- .../proto/PirClassCarrierOrBuilder.java | 17 +- .../javaExhaustiveWhenOnKotlinSealedClass.kt | 21 +++ .../permittedSubclassesOfSealedKotlinClass.kt | 29 +++ .../sealed/permittedSubclasses_1_7.kt | 26 +++ .../sealed/permittedSubclasses_1_7.txt | 104 ++++++++++ .../ir/irText/classes/sealedClasses.txt | 4 + .../multiplatform/expectedSealedClass.txt | 4 + .../ir/irText/firProblems/ArrayMap.txt | 5 + .../ir/irText/regressions/kt45236.txt | 2 + ...BlackBoxModernJdkCodegenTestGenerated.java | 12 ++ .../codegen/BytecodeListingTestGenerated.java | 6 + ...BlackBoxModernJdkCodegenTestGenerated.java | 12 ++ .../IrBytecodeListingTestGenerated.java | 6 + .../BytecodeListingTextCollectingVisitor.kt | 6 + .../kotlin/config/LanguageVersionSettings.kt | 1 + 41 files changed, 695 insertions(+), 43 deletions(-) create mode 100644 compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/javaExhaustiveWhenOnKotlinSealedClass.kt create mode 100644 compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/permittedSubclassesOfSealedKotlinClass.kt create mode 100644 compiler/testData/codegen/bytecodeListing/sealed/permittedSubclasses_1_7.kt create mode 100644 compiler/testData/codegen/bytecodeListing/sealed/permittedSubclasses_1_7.txt diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt index 02c5fa5ce94..c110f236377 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.lazy.IrMaybeDeserializedClass import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl @@ -102,6 +103,10 @@ class Fir2IrLazyClass( fir.superTypeRefs.map { it.toIrType(typeConverter) } } + override var sealedSubclasses: List by lazyVar(lock) { + TODO() + } + override var thisReceiver: IrValueParameter? by lazyVar(lock) { symbolTable.enterScope(this) val typeArguments = fir.typeParameters.map { diff --git a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt index 13ac0e81e79..28360927106 100644 --- a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt +++ b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt @@ -55,7 +55,7 @@ open class JvmIrCodegenFactory( val irProviders: List, val extensions: JvmGeneratorExtensionsImpl, val backendExtension: JvmBackendExtension, - val notifyCodegenStart: () -> Unit, + val notifyCodegenStart: () -> Unit ) : CodegenFactory.BackendInput override fun convertToIr(input: CodegenFactory.IrConversionInput): JvmIrBackendInput { @@ -215,7 +215,7 @@ open class JvmIrCodegenFactory( val phaseConfig = customPhaseConfig ?: PhaseConfig(jvmPhases) val context = JvmBackendContext( state, irModuleFragment.irBuiltins, irModuleFragment, symbolTable, phaseConfig, extensions, backendExtension, irSerializer, - notifyCodegenStart + notifyCodegenStart, ) /* JvmBackendContext creates new unbound symbols, have to resolve them. */ ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies() @@ -241,7 +241,8 @@ open class JvmIrCodegenFactory( generateModule( state, JvmIrBackendInput( - irModuleFragment, symbolTable, phaseConfig, irProviders, extensions, backendExtension, notifyCodegenStart + irModuleFragment, symbolTable, phaseConfig, irProviders, extensions, backendExtension, + notifyCodegenStart ) ) } 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 bcbdad0d563..7aed65485b8 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 @@ -48,7 +48,7 @@ class JvmBackendContext( val generatorExtensions: JvmGeneratorExtensions, val backendExtension: JvmBackendExtension, val irSerializer: JvmIrSerializer?, - val notifyCodegenStart: () -> Unit, + val notifyCodegenStart: () -> Unit ) : CommonBackendContext { // If the JVM fqname of a class differs from what is implied by its parent, e.g. if it's a file class // annotated with @JvmPackageName, the correct name is recorded here. 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 e44212cf8f4..70d336485cd 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 @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.codegen.addRecordComponent import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.writeKotlinMetadata import org.jetbrains.kotlin.config.JvmAnalysisFlags +import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.DescriptorVisibilities @@ -130,6 +131,14 @@ class ClassCodegen private constructor( if (generated) return generated = true + // Generate PermittedSubclasses attribute for sealed class. + if (state.languageVersionSettings.supportsFeature(LanguageFeature.JvmPermittedSubclassesAttributeForSealed) && + irClass.modality == Modality.SEALED && + state.target >= JvmTarget.JVM_17 + ) { + generatePermittedSubclasses() + } + // Generating a method node may cause the addition of a field with an initializer if an inline function // call uses `assert` and the JVM assertions mode is enabled. To avoid concurrent modification errors, // there is a very specific generation order. @@ -188,6 +197,15 @@ class ClassCodegen private constructor( jvmSignatureClashDetector.reportErrors(classOrigin) } + private fun generatePermittedSubclasses() { + val sealedSubclasses = irClass.sealedSubclasses + if (sealedSubclasses.isEmpty()) return + val classVisitor = visitor.visitor + for (sealedSubclassSymbol in sealedSubclasses) { + classVisitor.visitPermittedSubclass(typeMapper.mapClass(sealedSubclassSymbol.owner).internalName) + } + } + private fun addReifiedParametersFromSignature() { for (type in irClass.superTypes) { processTypeParameters(type) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt index 7ff08078e06..548f92c8c7c 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.IrImplementingDelegateDescriptorImpl import org.jetbrains.kotlin.ir.expressions.IrBlockBody @@ -56,6 +57,7 @@ import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize +@ObsoleteDescriptorBasedAPI class ClassGenerator( declarationGenerator: DeclarationGenerator ) : DeclarationGeneratorExtension(declarationGenerator) { @@ -115,6 +117,8 @@ class ClassGenerator( if (DescriptorUtils.isEnumClass(classDescriptor)) { generateAdditionalMembersForEnumClass(irClass) } + + irClass.sealedSubclasses = classDescriptor.sealedSubclasses.map { context.symbolTable.referenceClass(it) } } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt index d3d3c232fb5..4bf12d2c818 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt @@ -14,7 +14,9 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.NotFoundClasses import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.builders.IrGeneratorContext +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.expressions.IrDeclarationReference +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.TypeTranslator @@ -46,7 +48,7 @@ class GeneratorContext private constructor( extensions: GeneratorExtensions, typeTranslator: TypeTranslator, irBuiltIns: IrBuiltIns, - fragmentContext: FragmentContext? = null + fragmentContext: FragmentContext? = null, ) : this( configuration, moduleDescriptor, diff --git a/compiler/ir/ir.tree.impl/src/org/jetbrains/kotlin/ir/declarations/impl/IrClassImpl.kt b/compiler/ir/ir.tree.impl/src/org/jetbrains/kotlin/ir/declarations/impl/IrClassImpl.kt index 91384a17777..84ea9f5a727 100644 --- a/compiler/ir/ir.tree.impl/src/org/jetbrains/kotlin/ir/declarations/impl/IrClassImpl.kt +++ b/compiler/ir/ir.tree.impl/src/org/jetbrains/kotlin/ir/declarations/impl/IrClassImpl.kt @@ -29,7 +29,7 @@ open class IrClassImpl( override val startOffset: Int, override val endOffset: Int, override var origin: IrDeclarationOrigin, - override val symbol: IrClassSymbol, + final override val symbol: IrClassSymbol, override val name: Name, override val kind: ClassKind, override var visibility: DescriptorVisibility, @@ -70,4 +70,6 @@ open class IrClassImpl( override var metadata: MetadataSource? = null override var attributeOwnerId: IrAttributeContainer = this + + override var sealedSubclasses: List = emptyList() } diff --git a/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/declarations/persistent/PersistentIrClass.kt b/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/declarations/persistent/PersistentIrClass.kt index a58a7794c60..fe9fe826e76 100644 --- a/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/declarations/persistent/PersistentIrClass.kt +++ b/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/declarations/persistent/PersistentIrClass.kt @@ -5,9 +5,23 @@ package org.jetbrains.kotlin.ir.declarations.persistent -import org.jetbrains.kotlin.descriptors.* +import java.util.ArrayList +import java.util.Collections +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DescriptorVisibility +import org.jetbrains.kotlin.descriptors.InlineClassRepresentation +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI -import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.declarations.MetadataSource import org.jetbrains.kotlin.ir.declarations.persistent.carriers.Carrier import org.jetbrains.kotlin.ir.declarations.persistent.carriers.ClassCarrier import org.jetbrains.kotlin.ir.expressions.IrConstructorCall @@ -18,7 +32,6 @@ import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.name.Name -import java.util.* // Auto-generated by compiler/ir/ir.tree.persistent/generator/src/org/jetbrains/kotlin/ir/persistentIrGenerator/Main.kt. DO NOT EDIT! @@ -164,4 +177,15 @@ internal class PersistentIrClass( } override var attributeOwnerId: IrAttributeContainer = this + + override var sealedSubclassesField: List = emptyList() + + override var sealedSubclasses: List + get() = getCarrier().sealedSubclassesField + set(v) { + if (sealedSubclasses !== v) { + setCarrier() + sealedSubclassesField = v + } + } } diff --git a/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/declarations/persistent/carriers/ClassCarrier.kt b/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/declarations/persistent/carriers/ClassCarrier.kt index f438aa4edb0..31f93279556 100644 --- a/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/declarations/persistent/carriers/ClassCarrier.kt +++ b/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/declarations/persistent/carriers/ClassCarrier.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrTypeParameter import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol @@ -29,6 +30,7 @@ internal interface ClassCarrier : DeclarationCarrier{ val typeParametersSymbolField: List val superTypesField: List val inlineClassRepresentationField: InlineClassRepresentation? + val sealedSubclassesField: List override fun clone(): ClassCarrier { return ClassCarrierImpl( @@ -41,7 +43,8 @@ internal interface ClassCarrier : DeclarationCarrier{ modalityField, typeParametersSymbolField, superTypesField, - inlineClassRepresentationField + inlineClassRepresentationField, + sealedSubclassesField ) } } @@ -56,7 +59,8 @@ internal class ClassCarrierImpl( override val modalityField: Modality, override val typeParametersSymbolField: List, override val superTypesField: List, - override val inlineClassRepresentationField: InlineClassRepresentation? + override val inlineClassRepresentationField: InlineClassRepresentation?, + override val sealedSubclassesField: List ) : ClassCarrier { override val thisReceiverField: IrValueParameter? diff --git a/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/serialization/IrCarrierDeserializer.kt b/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/serialization/IrCarrierDeserializer.kt index 7ac0f06af71..b06efce4fa2 100644 --- a/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/serialization/IrCarrierDeserializer.kt +++ b/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/serialization/IrCarrierDeserializer.kt @@ -87,6 +87,8 @@ internal abstract class IrCarrierDeserializer { abstract fun deserializeSuperType(proto: Int): IrType + abstract fun deserializeSealedSubclass(proto: Long): IrClassSymbol + abstract fun deserializeType(proto: Int): IrType abstract fun deserializeClass(proto: Long): IrClassSymbol @@ -138,7 +140,8 @@ internal abstract class IrCarrierDeserializer { deserializeModality(proto.flags), proto.typeParametersList.map { deserializeTypeParameter(it) }, proto.superTypesList.map { deserializeSuperType(it) }, - if (proto.hasInlineClassRepresentation()) deserializeInlineClassRepresentation(proto.inlineClassRepresentation) else null + if (proto.hasInlineClassRepresentation()) deserializeInlineClassRepresentation(proto.inlineClassRepresentation) else null, + proto.sealedSubclassesList.map { deserializeSealedSubclass(it) } ) } diff --git a/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/serialization/IrCarrierSerializer.kt b/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/serialization/IrCarrierSerializer.kt index 9b86fb683d6..5d5fe464d6a 100644 --- a/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/serialization/IrCarrierSerializer.kt +++ b/compiler/ir/ir.tree.persistent/gen/org/jetbrains/kotlin/ir/serialization/IrCarrierSerializer.kt @@ -73,6 +73,8 @@ internal abstract class IrCarrierSerializer { abstract fun serializeSuperType(value: IrType): Int + abstract fun serializeSealedSubclass(value: IrClassSymbol): Long + abstract fun serializeType(value: IrType): Int abstract fun serializeClass(value: IrClassSymbol): Long @@ -122,6 +124,7 @@ internal abstract class IrCarrierSerializer { proto.addAllTypeParameters(carrier.typeParametersSymbolField.map { serializeTypeParameter(it) }) proto.addAllSuperTypes(carrier.superTypesField.map { serializeSuperType(it) }) carrier.inlineClassRepresentationField?.let { proto.setInlineClassRepresentation(serializeInlineClassRepresentation(it)) } + proto.addAllSealedSubclasses(carrier.sealedSubclassesField.map { serializeSealedSubclass(it) }) return proto.build().toByteArray() } diff --git a/compiler/ir/ir.tree.persistent/generator/src/org/jetbrains/kotlin/ir/persistentIrGenerator/Class.kt b/compiler/ir/ir.tree.persistent/generator/src/org/jetbrains/kotlin/ir/persistentIrGenerator/Class.kt index b5d007aa466..8f8cb636a21 100644 --- a/compiler/ir/ir.tree.persistent/generator/src/org/jetbrains/kotlin/ir/persistentIrGenerator/Class.kt +++ b/compiler/ir/ir.tree.persistent/generator/src/org/jetbrains/kotlin/ir/persistentIrGenerator/Class.kt @@ -22,6 +22,7 @@ internal fun PersistentIrGenerator.generateClass() { descriptorType("InlineClassRepresentation") + "<" + import("IrSimpleType", "org.jetbrains.kotlin.ir.types") + ">?", inlineClassRepresentationProto ) + val sealedSubclassesField = Field("sealedSubclasses", +"List<" + irSymbol("IrClassSymbol") + ">", sealedSubclassListProto) writeFile("PersistentIrClass.kt", renderFile("org.jetbrains.kotlin.ir.declarations.persistent") { lines( @@ -79,6 +80,7 @@ internal fun PersistentIrGenerator.generateClass() { modalityField.toPersistentField(+"modality"), inlineClassRepresentationField.toPersistentField(+"null"), +"override var attributeOwnerId: " + IrAttributeContainer + " = this", + sealedSubclassesField.toPersistentField(+"emptyList()"), ), id, )() @@ -93,6 +95,7 @@ internal fun PersistentIrGenerator.generateClass() { typeParametersField, superTypesField, inlineClassRepresentationField, + sealedSubclassesField, )() }) @@ -104,5 +107,6 @@ internal fun PersistentIrGenerator.generateClass() { typeParametersField, superTypesField, inlineClassRepresentationField, + sealedSubclassesField, ) } diff --git a/compiler/ir/ir.tree.persistent/generator/src/org/jetbrains/kotlin/ir/persistentIrGenerator/PersistentIrGenerator.kt b/compiler/ir/ir.tree.persistent/generator/src/org/jetbrains/kotlin/ir/persistentIrGenerator/PersistentIrGenerator.kt index 80165e567d7..f4e696e730b 100644 --- a/compiler/ir/ir.tree.persistent/generator/src/org/jetbrains/kotlin/ir/persistentIrGenerator/PersistentIrGenerator.kt +++ b/compiler/ir/ir.tree.persistent/generator/src/org/jetbrains/kotlin/ir/persistentIrGenerator/PersistentIrGenerator.kt @@ -152,6 +152,7 @@ internal object PersistentIrGenerator { val valueParameterListProto = Proto("int64", "valueParameter", +"Long", IrValueParameterSymbol, fieldKind = FieldKind.REPEATED) val typeParameterListProto = Proto("int64", "typeParameter", +"Long", IrTypeParameterSymbol, fieldKind = FieldKind.REPEATED) val superTypeListProto = Proto("int32", "superType", +"Int", IrType, fieldKind = FieldKind.REPEATED) + val sealedSubclassListProto = Proto("int64", "sealedSubclass", +"Long", IrClassSymbol, fieldKind = FieldKind.REPEATED) val typeProto = Proto("int32", "type", +"Int", IrType, fieldKind = FieldKind.REQUIRED) val optionalTypeProto = Proto("int32", "type", +"Int", IrType, fieldKind = FieldKind.OPTIONAL) val variableProto = Proto("IrVariable", "variable", protoVariable, IrVariable) @@ -187,6 +188,7 @@ internal object PersistentIrGenerator { valueParameterListProto, typeParameterListProto, superTypeListProto, + sealedSubclassListProto, typeProto, optionalTypeProto, classProto, diff --git a/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/serialization/IrCarrierDeserializerImpl.kt b/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/serialization/IrCarrierDeserializerImpl.kt index d118522c215..b8a5d4681db 100644 --- a/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/serialization/IrCarrierDeserializerImpl.kt +++ b/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/serialization/IrCarrierDeserializerImpl.kt @@ -30,7 +30,6 @@ internal class IrCarrierDeserializerImpl( val indexToBody: (Int) -> IrBody, val indexToExpressionBody: (Int) -> IrExpressionBody ) : IrCarrierDeserializer() { - override fun deserializeParentSymbol(proto: Long): IrSymbol { return declarationDeserializer.symbolDeserializer.deserializeIrSymbol(proto) } @@ -67,6 +66,10 @@ internal class IrCarrierDeserializerImpl( return declarationDeserializer.deserializeIrType(proto) } + override fun deserializeSealedSubclass(proto: Long): IrClassSymbol { + return declarationDeserializer.symbolDeserializer.deserializeIrSymbol(proto) as IrClassSymbol + } + override fun deserializeType(proto: Int): IrType { return declarationDeserializer.deserializeIrType(proto) } diff --git a/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/serialization/IrCarrierSerializerImpl.kt b/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/serialization/IrCarrierSerializerImpl.kt index df4df65bc44..c57e2dcc16c 100644 --- a/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/serialization/IrCarrierSerializerImpl.kt +++ b/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/serialization/IrCarrierSerializerImpl.kt @@ -63,6 +63,10 @@ internal class IrCarrierSerializerImpl(val fileSerializer: IrFileSerializer, val return fileSerializer.serializeIrType(value) } + override fun serializeSealedSubclass(value: IrClassSymbol): Long { + return fileSerializer.serializeIrSymbol(value) + } + override fun serializeType(value: IrType): Int { return fileSerializer.serializeIrType(value) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt index bf36b4eff3b..b4ec0a8de03 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt @@ -51,6 +51,8 @@ abstract class IrClass : abstract var inlineClassRepresentation: InlineClassRepresentation? + abstract var sealedSubclasses: List + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitClass(this, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt index a87968c7516..118466da694 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt @@ -12,11 +12,7 @@ import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator -import org.jetbrains.kotlin.ir.util.DeserializableClass -import org.jetbrains.kotlin.ir.util.TypeTranslator -import org.jetbrains.kotlin.ir.util.isObject -import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.NameResolver import org.jetbrains.kotlin.name.Name @@ -65,10 +61,8 @@ class IrLazyClass( generateChildStubs(descriptor.defaultType.memberScope.getContributedDescriptors(), it) generateChildStubs(descriptor.staticScope.getContributedDescriptors(), it) } - }.also { - it.forEach { - it.parent = this //initialize parent for non lazy cases - } + }.onEach { + it.parent = this //initialize parent for non lazy cases } } @@ -98,6 +92,13 @@ class IrLazyClass( } } + override var sealedSubclasses: List by lazyVar(stubGenerator.lock) { + descriptor.sealedSubclasses.map { sealedSubclassDescriptor -> + // NB 'generateClassStub' would return an existing class if it's already present in symbol table + stubGenerator.generateClassStub(sealedSubclassDescriptor).symbol + } + } + override var inlineClassRepresentation: InlineClassRepresentation? by lazyVar(stubGenerator.lock) { descriptor.inlineClassRepresentation?.mapUnderlyingType { it.toIrType() as? IrSimpleType ?: error("Inline class underlying type is not a simple type: ${render()}") diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt index c0ec3ed85c9..479a10e87ad 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt @@ -156,6 +156,9 @@ open class DeepCopyIrTreeWithSymbols( superTypes = declaration.superTypes.map { it.remapType() } + sealedSubclasses = declaration.sealedSubclasses.map { + symbolRemapper.getReferencedClass(it) + } thisReceiver = declaration.thisReceiver?.transform() inlineClassRepresentation = declaration.inlineClassRepresentation?.mapUnderlyingType { it.remapType() as IrSimpleType } declaration.transformDeclarationsTo(this) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt index 626e7dd136f..6f4350e0b0d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt @@ -111,6 +111,7 @@ class DumpIrTreeVisitor( override fun visitClass(declaration: IrClass, data: String) { declaration.dumpLabeledElementWith(data) { dumpAnnotations(declaration) + declaration.sealedSubclasses.dumpItems("sealedSubclasses") { it.dump() } declaration.thisReceiver?.accept(this, "\$this") declaration.typeParameters.dumpElements() declaration.declarations.ordered().dumpElements() diff --git a/compiler/ir/serialization.common/src/KotlinIr.proto b/compiler/ir/serialization.common/src/KotlinIr.proto index 71c91bbb8fc..5e82ca32257 100644 --- a/compiler/ir/serialization.common/src/KotlinIr.proto +++ b/compiler/ir/serialization.common/src/KotlinIr.proto @@ -558,6 +558,7 @@ message IrClass { repeated IrDeclaration declaration = 5; repeated int32 super_type = 6 [packed=true]; optional IrInlineClassRepresentation inline_class_representation = 7; + repeated int64 sealed_subclass = 8 [packed=true]; } message IrTypeAlias { diff --git a/compiler/ir/serialization.common/src/KotlinPirCarriers.proto b/compiler/ir/serialization.common/src/KotlinPirCarriers.proto index faa5f04b714..390649b74ac 100644 --- a/compiler/ir/serialization.common/src/KotlinPirCarriers.proto +++ b/compiler/ir/serialization.common/src/KotlinPirCarriers.proto @@ -26,7 +26,8 @@ message PirClassCarrier { repeated int64 typeParameters = 6; repeated int32 superTypes = 7; optional IrInlineClassRepresentation inlineClassRepresentation = 8; - optional int64 flags = 9 [default = 0]; + repeated int64 sealedSubclasses = 9; + optional int64 flags = 10 [default = 0]; } message PirConstructorCarrier { diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrDeclarationDeserializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrDeclarationDeserializer.kt index e67e611bd8d..4fee3f7cfc1 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrDeclarationDeserializer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrDeclarationDeserializer.kt @@ -348,6 +348,8 @@ class IrDeclarationDeserializer( else -> computeMissingInlineClassRepresentationForCompatibility(this) } + sealedSubclasses = proto.sealedSubclassList.map { deserializeIrSymbol(it) as IrClassSymbol } + fakeOverrideBuilder.enqueueClass(this, signature, compatibilityMode) } } diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt index 738eee50476..de422b2339f 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt @@ -1327,6 +1327,10 @@ open class IrFileSerializer( clazz.superTypes.forEach { proto.addSuperType(serializeIrType(it)) } + + clazz.sealedSubclasses.forEach { + proto.addSealedSubclass(serializeIrSymbol(it)) + } } return proto.build() diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/IrClass.java b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/IrClass.java index 0d1b53545a4..05d0cb04f3b 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/IrClass.java +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/IrClass.java @@ -134,6 +134,27 @@ public final class IrClass extends bitField0_ |= 0x00000008; break; } + case 64: { + if (!((mutable_bitField0_ & 0x00000080) == 0x00000080)) { + sealedSubclass_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000080; + } + sealedSubclass_.add(input.readInt64()); + break; + } + case 66: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + if (!((mutable_bitField0_ & 0x00000080) == 0x00000080) && input.getBytesUntilLimit() > 0) { + sealedSubclass_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000080; + } + while (input.getBytesUntilLimit() > 0) { + sealedSubclass_.add(input.readInt64()); + } + input.popLimit(limit); + break; + } } } } catch (org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException e) { @@ -151,6 +172,9 @@ public final class IrClass extends if (((mutable_bitField0_ & 0x00000020) == 0x00000020)) { superType_ = java.util.Collections.unmodifiableList(superType_); } + if (((mutable_bitField0_ & 0x00000080) == 0x00000080)) { + sealedSubclass_ = java.util.Collections.unmodifiableList(sealedSubclass_); + } try { unknownFieldsCodedOutput.flush(); } catch (java.io.IOException e) { @@ -330,6 +354,29 @@ public final class IrClass extends return inlineClassRepresentation_; } + public static final int SEALED_SUBCLASS_FIELD_NUMBER = 8; + private java.util.List sealedSubclass_; + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + public java.util.List + getSealedSubclassList() { + return sealedSubclass_; + } + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + public int getSealedSubclassCount() { + return sealedSubclass_.size(); + } + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + public long getSealedSubclass(int index) { + return sealedSubclass_.get(index); + } + private int sealedSubclassMemoizedSerializedSize = -1; + private void initFields() { base_ = org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclarationBase.getDefaultInstance(); name_ = 0; @@ -338,6 +385,7 @@ public final class IrClass extends declaration_ = java.util.Collections.emptyList(); superType_ = java.util.Collections.emptyList(); inlineClassRepresentation_ = org.jetbrains.kotlin.backend.common.serialization.proto.IrInlineClassRepresentation.getDefaultInstance(); + sealedSubclass_ = java.util.Collections.emptyList(); } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -413,6 +461,13 @@ public final class IrClass extends if (((bitField0_ & 0x00000008) == 0x00000008)) { output.writeMessage(7, inlineClassRepresentation_); } + if (getSealedSubclassList().size() > 0) { + output.writeRawVarint32(66); + output.writeRawVarint32(sealedSubclassMemoizedSerializedSize); + } + for (int i = 0; i < sealedSubclass_.size(); i++) { + output.writeInt64NoTag(sealedSubclass_.get(i)); + } output.writeRawBytes(unknownFields); } @@ -460,6 +515,20 @@ public final class IrClass extends size += org.jetbrains.kotlin.protobuf.CodedOutputStream .computeMessageSize(7, inlineClassRepresentation_); } + { + int dataSize = 0; + for (int i = 0; i < sealedSubclass_.size(); i++) { + dataSize += org.jetbrains.kotlin.protobuf.CodedOutputStream + .computeInt64SizeNoTag(sealedSubclass_.get(i)); + } + size += dataSize; + if (!getSealedSubclassList().isEmpty()) { + size += 1; + size += org.jetbrains.kotlin.protobuf.CodedOutputStream + .computeInt32SizeNoTag(dataSize); + } + sealedSubclassMemoizedSerializedSize = dataSize; + } size += unknownFields.size(); memoizedSerializedSize = size; return size; @@ -568,6 +637,8 @@ public final class IrClass extends bitField0_ = (bitField0_ & ~0x00000020); inlineClassRepresentation_ = org.jetbrains.kotlin.backend.common.serialization.proto.IrInlineClassRepresentation.getDefaultInstance(); bitField0_ = (bitField0_ & ~0x00000040); + sealedSubclass_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000080); return this; } @@ -622,6 +693,11 @@ public final class IrClass extends to_bitField0_ |= 0x00000008; } result.inlineClassRepresentation_ = inlineClassRepresentation_; + if (((bitField0_ & 0x00000080) == 0x00000080)) { + sealedSubclass_ = java.util.Collections.unmodifiableList(sealedSubclass_); + bitField0_ = (bitField0_ & ~0x00000080); + } + result.sealedSubclass_ = sealedSubclass_; result.bitField0_ = to_bitField0_; return result; } @@ -670,6 +746,16 @@ public final class IrClass extends if (other.hasInlineClassRepresentation()) { mergeInlineClassRepresentation(other.getInlineClassRepresentation()); } + if (!other.sealedSubclass_.isEmpty()) { + if (sealedSubclass_.isEmpty()) { + sealedSubclass_ = other.sealedSubclass_; + bitField0_ = (bitField0_ & ~0x00000080); + } else { + ensureSealedSubclassIsMutable(); + sealedSubclass_.addAll(other.sealedSubclass_); + } + + } setUnknownFields( getUnknownFields().concat(other.unknownFields)); return this; @@ -1262,6 +1348,72 @@ public final class IrClass extends return this; } + private java.util.List sealedSubclass_ = java.util.Collections.emptyList(); + private void ensureSealedSubclassIsMutable() { + if (!((bitField0_ & 0x00000080) == 0x00000080)) { + sealedSubclass_ = new java.util.ArrayList(sealedSubclass_); + bitField0_ |= 0x00000080; + } + } + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + public java.util.List + getSealedSubclassList() { + return java.util.Collections.unmodifiableList(sealedSubclass_); + } + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + public int getSealedSubclassCount() { + return sealedSubclass_.size(); + } + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + public long getSealedSubclass(int index) { + return sealedSubclass_.get(index); + } + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + public Builder setSealedSubclass( + int index, long value) { + ensureSealedSubclassIsMutable(); + sealedSubclass_.set(index, value); + + return this; + } + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + public Builder addSealedSubclass(long value) { + ensureSealedSubclassIsMutable(); + sealedSubclass_.add(value); + + return this; + } + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + public Builder addAllSealedSubclass( + java.lang.Iterable values) { + ensureSealedSubclassIsMutable(); + org.jetbrains.kotlin.protobuf.AbstractMessageLite.Builder.addAll( + values, sealedSubclass_); + + return this; + } + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + public Builder clearSealedSubclass() { + sealedSubclass_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000080); + + return this; + } + // @@protoc_insertion_point(builder_scope:org.jetbrains.kotlin.backend.common.serialization.proto.IrClass) } diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/IrClassOrBuilder.java b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/IrClassOrBuilder.java index 72773ae0142..ab8d84564e7 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/IrClassOrBuilder.java +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/IrClassOrBuilder.java @@ -83,4 +83,17 @@ public interface IrClassOrBuilder extends * optional .org.jetbrains.kotlin.backend.common.serialization.proto.IrInlineClassRepresentation inline_class_representation = 7; */ org.jetbrains.kotlin.backend.common.serialization.proto.IrInlineClassRepresentation getInlineClassRepresentation(); + + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + java.util.List getSealedSubclassList(); + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + int getSealedSubclassCount(); + /** + * repeated int64 sealed_subclass = 8 [packed = true]; + */ + long getSealedSubclass(int index); } \ No newline at end of file diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/PirClassCarrier.java b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/PirClassCarrier.java index 7139206d517..f266602b930 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/PirClassCarrier.java +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/PirClassCarrier.java @@ -137,6 +137,27 @@ public final class PirClassCarrier extends break; } case 72: { + if (!((mutable_bitField0_ & 0x00000100) == 0x00000100)) { + sealedSubclasses_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000100; + } + sealedSubclasses_.add(input.readInt64()); + break; + } + case 74: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + if (!((mutable_bitField0_ & 0x00000100) == 0x00000100) && input.getBytesUntilLimit() > 0) { + sealedSubclasses_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000100; + } + while (input.getBytesUntilLimit() > 0) { + sealedSubclasses_.add(input.readInt64()); + } + input.popLimit(limit); + break; + } + case 80: { bitField0_ |= 0x00000020; flags_ = input.readInt64(); break; @@ -158,6 +179,9 @@ public final class PirClassCarrier extends if (((mutable_bitField0_ & 0x00000040) == 0x00000040)) { superTypes_ = java.util.Collections.unmodifiableList(superTypes_); } + if (((mutable_bitField0_ & 0x00000100) == 0x00000100)) { + sealedSubclasses_ = java.util.Collections.unmodifiableList(sealedSubclasses_); + } try { unknownFieldsCodedOutput.flush(); } catch (java.io.IOException e) { @@ -338,16 +362,38 @@ public final class PirClassCarrier extends return inlineClassRepresentation_; } - public static final int FLAGS_FIELD_NUMBER = 9; + public static final int SEALEDSUBCLASSES_FIELD_NUMBER = 9; + private java.util.List sealedSubclasses_; + /** + * repeated int64 sealedSubclasses = 9; + */ + public java.util.List + getSealedSubclassesList() { + return sealedSubclasses_; + } + /** + * repeated int64 sealedSubclasses = 9; + */ + public int getSealedSubclassesCount() { + return sealedSubclasses_.size(); + } + /** + * repeated int64 sealedSubclasses = 9; + */ + public long getSealedSubclasses(int index) { + return sealedSubclasses_.get(index); + } + + public static final int FLAGS_FIELD_NUMBER = 10; private long flags_; /** - * optional int64 flags = 9 [default = 0]; + * optional int64 flags = 10 [default = 0]; */ public boolean hasFlags() { return ((bitField0_ & 0x00000020) == 0x00000020); } /** - * optional int64 flags = 9 [default = 0]; + * optional int64 flags = 10 [default = 0]; */ public long getFlags() { return flags_; @@ -362,6 +408,7 @@ public final class PirClassCarrier extends typeParameters_ = java.util.Collections.emptyList(); superTypes_ = java.util.Collections.emptyList(); inlineClassRepresentation_ = org.jetbrains.kotlin.backend.common.serialization.proto.IrInlineClassRepresentation.getDefaultInstance(); + sealedSubclasses_ = java.util.Collections.emptyList(); flags_ = 0L; } private byte memoizedIsInitialized = -1; @@ -417,8 +464,11 @@ public final class PirClassCarrier extends if (((bitField0_ & 0x00000010) == 0x00000010)) { output.writeMessage(8, inlineClassRepresentation_); } + for (int i = 0; i < sealedSubclasses_.size(); i++) { + output.writeInt64(9, sealedSubclasses_.get(i)); + } if (((bitField0_ & 0x00000020) == 0x00000020)) { - output.writeInt64(9, flags_); + output.writeInt64(10, flags_); } output.writeRawBytes(unknownFields); } @@ -471,9 +521,18 @@ public final class PirClassCarrier extends size += org.jetbrains.kotlin.protobuf.CodedOutputStream .computeMessageSize(8, inlineClassRepresentation_); } + { + int dataSize = 0; + for (int i = 0; i < sealedSubclasses_.size(); i++) { + dataSize += org.jetbrains.kotlin.protobuf.CodedOutputStream + .computeInt64SizeNoTag(sealedSubclasses_.get(i)); + } + size += dataSize; + size += 1 * getSealedSubclassesList().size(); + } if (((bitField0_ & 0x00000020) == 0x00000020)) { size += org.jetbrains.kotlin.protobuf.CodedOutputStream - .computeInt64Size(9, flags_); + .computeInt64Size(10, flags_); } size += unknownFields.size(); memoizedSerializedSize = size; @@ -585,8 +644,10 @@ public final class PirClassCarrier extends bitField0_ = (bitField0_ & ~0x00000040); inlineClassRepresentation_ = org.jetbrains.kotlin.backend.common.serialization.proto.IrInlineClassRepresentation.getDefaultInstance(); bitField0_ = (bitField0_ & ~0x00000080); - flags_ = 0L; + sealedSubclasses_ = java.util.Collections.emptyList(); bitField0_ = (bitField0_ & ~0x00000100); + flags_ = 0L; + bitField0_ = (bitField0_ & ~0x00000200); return this; } @@ -645,7 +706,12 @@ public final class PirClassCarrier extends to_bitField0_ |= 0x00000010; } result.inlineClassRepresentation_ = inlineClassRepresentation_; - if (((from_bitField0_ & 0x00000100) == 0x00000100)) { + if (((bitField0_ & 0x00000100) == 0x00000100)) { + sealedSubclasses_ = java.util.Collections.unmodifiableList(sealedSubclasses_); + bitField0_ = (bitField0_ & ~0x00000100); + } + result.sealedSubclasses_ = sealedSubclasses_; + if (((from_bitField0_ & 0x00000200) == 0x00000200)) { to_bitField0_ |= 0x00000020; } result.flags_ = flags_; @@ -700,6 +766,16 @@ public final class PirClassCarrier extends if (other.hasInlineClassRepresentation()) { mergeInlineClassRepresentation(other.getInlineClassRepresentation()); } + if (!other.sealedSubclasses_.isEmpty()) { + if (sealedSubclasses_.isEmpty()) { + sealedSubclasses_ = other.sealedSubclasses_; + bitField0_ = (bitField0_ & ~0x00000100); + } else { + ensureSealedSubclassesIsMutable(); + sealedSubclasses_.addAll(other.sealedSubclasses_); + } + + } if (other.hasFlags()) { setFlags(other.getFlags()); } @@ -1192,33 +1268,99 @@ public final class PirClassCarrier extends return this; } - private long flags_ ; - /** - * optional int64 flags = 9 [default = 0]; - */ - public boolean hasFlags() { - return ((bitField0_ & 0x00000100) == 0x00000100); + private java.util.List sealedSubclasses_ = java.util.Collections.emptyList(); + private void ensureSealedSubclassesIsMutable() { + if (!((bitField0_ & 0x00000100) == 0x00000100)) { + sealedSubclasses_ = new java.util.ArrayList(sealedSubclasses_); + bitField0_ |= 0x00000100; + } } /** - * optional int64 flags = 9 [default = 0]; + * repeated int64 sealedSubclasses = 9; + */ + public java.util.List + getSealedSubclassesList() { + return java.util.Collections.unmodifiableList(sealedSubclasses_); + } + /** + * repeated int64 sealedSubclasses = 9; + */ + public int getSealedSubclassesCount() { + return sealedSubclasses_.size(); + } + /** + * repeated int64 sealedSubclasses = 9; + */ + public long getSealedSubclasses(int index) { + return sealedSubclasses_.get(index); + } + /** + * repeated int64 sealedSubclasses = 9; + */ + public Builder setSealedSubclasses( + int index, long value) { + ensureSealedSubclassesIsMutable(); + sealedSubclasses_.set(index, value); + + return this; + } + /** + * repeated int64 sealedSubclasses = 9; + */ + public Builder addSealedSubclasses(long value) { + ensureSealedSubclassesIsMutable(); + sealedSubclasses_.add(value); + + return this; + } + /** + * repeated int64 sealedSubclasses = 9; + */ + public Builder addAllSealedSubclasses( + java.lang.Iterable values) { + ensureSealedSubclassesIsMutable(); + org.jetbrains.kotlin.protobuf.AbstractMessageLite.Builder.addAll( + values, sealedSubclasses_); + + return this; + } + /** + * repeated int64 sealedSubclasses = 9; + */ + public Builder clearSealedSubclasses() { + sealedSubclasses_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000100); + + return this; + } + + private long flags_ ; + /** + * optional int64 flags = 10 [default = 0]; + */ + public boolean hasFlags() { + return ((bitField0_ & 0x00000200) == 0x00000200); + } + /** + * optional int64 flags = 10 [default = 0]; */ public long getFlags() { return flags_; } /** - * optional int64 flags = 9 [default = 0]; + * optional int64 flags = 10 [default = 0]; */ public Builder setFlags(long value) { - bitField0_ |= 0x00000100; + bitField0_ |= 0x00000200; flags_ = value; return this; } /** - * optional int64 flags = 9 [default = 0]; + * optional int64 flags = 10 [default = 0]; */ public Builder clearFlags() { - bitField0_ = (bitField0_ & ~0x00000100); + bitField0_ = (bitField0_ & ~0x00000200); flags_ = 0L; return this; diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/PirClassCarrierOrBuilder.java b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/PirClassCarrierOrBuilder.java index b6c1f133467..0836a7ee571 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/PirClassCarrierOrBuilder.java +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/proto/PirClassCarrierOrBuilder.java @@ -93,11 +93,24 @@ public interface PirClassCarrierOrBuilder extends org.jetbrains.kotlin.backend.common.serialization.proto.IrInlineClassRepresentation getInlineClassRepresentation(); /** - * optional int64 flags = 9 [default = 0]; + * repeated int64 sealedSubclasses = 9; + */ + java.util.List getSealedSubclassesList(); + /** + * repeated int64 sealedSubclasses = 9; + */ + int getSealedSubclassesCount(); + /** + * repeated int64 sealedSubclasses = 9; + */ + long getSealedSubclasses(int index); + + /** + * optional int64 flags = 10 [default = 0]; */ boolean hasFlags(); /** - * optional int64 flags = 9 [default = 0]; + * optional int64 flags = 10 [default = 0]; */ long getFlags(); } \ No newline at end of file diff --git a/compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/javaExhaustiveWhenOnKotlinSealedClass.kt b/compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/javaExhaustiveWhenOnKotlinSealedClass.kt new file mode 100644 index 00000000000..8a67e084062 --- /dev/null +++ b/compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/javaExhaustiveWhenOnKotlinSealedClass.kt @@ -0,0 +1,21 @@ +// IGNORE_BACKEND: JVM +// !LANGUAGE: +JvmPermittedSubclassesAttributeForSealed +// ENABLE_JVM_PREVIEW + +// FILE: javaExhaustiveWhenOnKotlinSealedClass.kt +sealed class KS +class KO : KS() +class KK : KS() + +fun box(): String = + J.test(KO()) + J.test(KK()) + +// FILE: J.java +public class J { + public static String test(KS ks) { + return switch (ks) { + case KO ko -> "O"; + case KK kk -> "K"; + }; + } +} diff --git a/compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/permittedSubclassesOfSealedKotlinClass.kt b/compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/permittedSubclassesOfSealedKotlinClass.kt new file mode 100644 index 00000000000..f7e96cb8987 --- /dev/null +++ b/compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/permittedSubclassesOfSealedKotlinClass.kt @@ -0,0 +1,29 @@ +// IGNORE_BACKEND: JVM +// WITH_REFLECT +// !LANGUAGE: +JvmPermittedSubclassesAttributeForSealed + +sealed class Base +class O : Base() +class K : Base() + +sealed interface IBase +class X : IBase +class Y : IBase + +fun box(): String { + val cBase = Base::class.java + if (!cBase.isSealed) return "Error: Base is not sealed" + val pBase = cBase.permittedSubclasses.mapTo(HashSet()) { it.simpleName ?: "???" } + if (pBase != setOf("O", "K")) { + return "Failed: $pBase" + } + + val cIBase = IBase::class.java + if (!cIBase.isSealed) return "Error: IBase is not sealed" + val pIBase = cIBase.permittedSubclasses.mapTo(HashSet()) { it.simpleName ?: "???" } + if (pIBase != setOf("X", "Y")) { + return "Failed: $pIBase" + } + + return "OK" +} diff --git a/compiler/testData/codegen/bytecodeListing/sealed/permittedSubclasses_1_7.kt b/compiler/testData/codegen/bytecodeListing/sealed/permittedSubclasses_1_7.kt new file mode 100644 index 00000000000..78c0a0489f5 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/sealed/permittedSubclasses_1_7.kt @@ -0,0 +1,26 @@ +// IGNORE_BACKEND: JVM +// IGNORE_DEXING +// JVM_TARGET: 17 +// !LANGUAGE: +JvmPermittedSubclassesAttributeForSealed + +// FILE: Expr.kt +sealed interface Expr + +class VarExpr(val name: String) : Expr +class ParensExpr(val arg: Expr) : Expr + +// FILE: Literals.kt +class IntExpr(val value: Int) : Expr +class DoubleExpr(val value: Double) : Expr + +// FILE: UnaryOperators.kt +sealed class UnaryExpr(val arg: Expr) : Expr +class UnaryPlusExpr(arg: Expr) : UnaryExpr(arg) +class UnaryMinusExpr(arg: Expr) : UnaryExpr(arg) + +// FILE: BinaryOperators.kt +sealed class BinaryExpr(val arg1: Expr, val arg2: Expr) : Expr +class BinaryPlusExpr(arg1: Expr, arg2: Expr) : BinaryExpr(arg1, arg2) +class BinaryMinusExpr(arg1: Expr, arg2: Expr) : BinaryExpr(arg1, arg2) +class BinaryMulExpr(arg1: Expr, arg2: Expr) : BinaryExpr(arg1, arg2) +class BinaryDivExpr(arg1: Expr, arg2: Expr) : BinaryExpr(arg1, arg2) \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/sealed/permittedSubclasses_1_7.txt b/compiler/testData/codegen/bytecodeListing/sealed/permittedSubclasses_1_7.txt new file mode 100644 index 00000000000..9d0b0385727 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/sealed/permittedSubclasses_1_7.txt @@ -0,0 +1,104 @@ +@kotlin.Metadata +public final class BinaryDivExpr { + // source: 'BinaryOperators.kt' + public method (@org.jetbrains.annotations.NotNull p0: Expr, @org.jetbrains.annotations.NotNull p1: Expr): void +} + +@kotlin.Metadata +public abstract class BinaryExpr { + // source: 'BinaryOperators.kt' + private final @org.jetbrains.annotations.NotNull field arg1: Expr + private final @org.jetbrains.annotations.NotNull field arg2: Expr + private method (p0: Expr, p1: Expr): void + public synthetic method (p0: Expr, p1: Expr, p2: kotlin.jvm.internal.DefaultConstructorMarker): void + public final @org.jetbrains.annotations.NotNull method getArg1(): Expr + public final @org.jetbrains.annotations.NotNull method getArg2(): Expr + permittedSubclass: BinaryDivExpr + permittedSubclass: BinaryMinusExpr + permittedSubclass: BinaryMulExpr + permittedSubclass: BinaryPlusExpr +} + +@kotlin.Metadata +public final class BinaryMinusExpr { + // source: 'BinaryOperators.kt' + public method (@org.jetbrains.annotations.NotNull p0: Expr, @org.jetbrains.annotations.NotNull p1: Expr): void +} + +@kotlin.Metadata +public final class BinaryMulExpr { + // source: 'BinaryOperators.kt' + public method (@org.jetbrains.annotations.NotNull p0: Expr, @org.jetbrains.annotations.NotNull p1: Expr): void +} + +@kotlin.Metadata +public final class BinaryPlusExpr { + // source: 'BinaryOperators.kt' + public method (@org.jetbrains.annotations.NotNull p0: Expr, @org.jetbrains.annotations.NotNull p1: Expr): void +} + +@kotlin.Metadata +public final class DoubleExpr { + // source: 'Literals.kt' + private final field value: double + public method (p0: double): void + public final method getValue(): double +} + +@kotlin.Metadata +public interface Expr { + // source: 'Expr.kt' + permittedSubclass: BinaryExpr + permittedSubclass: DoubleExpr + permittedSubclass: IntExpr + permittedSubclass: ParensExpr + permittedSubclass: UnaryExpr + permittedSubclass: VarExpr +} + +@kotlin.Metadata +public final class IntExpr { + // source: 'Literals.kt' + private final field value: int + public method (p0: int): void + public final method getValue(): int +} + +@kotlin.Metadata +public final class ParensExpr { + // source: 'Expr.kt' + private final @org.jetbrains.annotations.NotNull field arg: Expr + public method (@org.jetbrains.annotations.NotNull p0: Expr): void + public final @org.jetbrains.annotations.NotNull method getArg(): Expr +} + +@kotlin.Metadata +public abstract class UnaryExpr { + // source: 'UnaryOperators.kt' + private final @org.jetbrains.annotations.NotNull field arg: Expr + private method (p0: Expr): void + public synthetic method (p0: Expr, p1: kotlin.jvm.internal.DefaultConstructorMarker): void + public final @org.jetbrains.annotations.NotNull method getArg(): Expr + permittedSubclass: UnaryMinusExpr + permittedSubclass: UnaryPlusExpr +} + +@kotlin.Metadata +public final class UnaryMinusExpr { + // source: 'UnaryOperators.kt' + public method (@org.jetbrains.annotations.NotNull p0: Expr): void +} + +@kotlin.Metadata +public final class UnaryPlusExpr { + // source: 'UnaryOperators.kt' + public method (@org.jetbrains.annotations.NotNull p0: Expr): void +} + +@kotlin.Metadata +public final class VarExpr { + // source: 'Expr.kt' + private final @org.jetbrains.annotations.NotNull field name: java.lang.String + public method (@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final @org.jetbrains.annotations.NotNull method getName(): java.lang.String +} diff --git a/compiler/testData/ir/irText/classes/sealedClasses.txt b/compiler/testData/ir/irText/classes/sealedClasses.txt index b4d45345d9a..3a2b290b94f 100644 --- a/compiler/testData/ir/irText/classes/sealedClasses.txt +++ b/compiler/testData/ir/irText/classes/sealedClasses.txt @@ -1,5 +1,9 @@ FILE fqName: fileName:/sealedClasses.kt CLASS CLASS name:Expr modality:SEALED visibility:public superTypes:[kotlin.Any] + sealedSubclasses: + CLASS CLASS name:Const modality:FINAL visibility:public superTypes:[.Expr] + CLASS CLASS name:Sum modality:FINAL visibility:public superTypes:[.Expr] + CLASS OBJECT name:NotANumber modality:FINAL visibility:public superTypes:[.Expr] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Expr CONSTRUCTOR visibility:protected <> () returnType:.Expr [primary] BLOCK_BODY diff --git a/compiler/testData/ir/irText/declarations/multiplatform/expectedSealedClass.txt b/compiler/testData/ir/irText/declarations/multiplatform/expectedSealedClass.txt index 6fc0053b071..c7adc2ee451 100644 --- a/compiler/testData/ir/irText/declarations/multiplatform/expectedSealedClass.txt +++ b/compiler/testData/ir/irText/declarations/multiplatform/expectedSealedClass.txt @@ -1,5 +1,7 @@ FILE fqName: fileName:/expectedSealedClass.kt CLASS CLASS name:Ops modality:SEALED visibility:public [expect] superTypes:[kotlin.Any] + sealedSubclasses: + CLASS CLASS name:Add modality:FINAL visibility:public superTypes:[.Ops] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Ops CONSTRUCTOR visibility:protected <> () returnType:.Ops [primary,expect] FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] @@ -32,6 +34,8 @@ FILE fqName: fileName:/expectedSealedClass.kt public open fun toString (): kotlin.String [fake_override] declared in .Ops $this: VALUE_PARAMETER name: type:kotlin.Any CLASS CLASS name:Ops modality:SEALED visibility:public superTypes:[kotlin.Any] + sealedSubclasses: + CLASS CLASS name:Add modality:FINAL visibility:public superTypes:[.Ops] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Ops CONSTRUCTOR visibility:protected <> () returnType:.Ops [primary] BLOCK_BODY diff --git a/compiler/testData/ir/irText/firProblems/ArrayMap.txt b/compiler/testData/ir/irText/firProblems/ArrayMap.txt index 4585c1d3825..430ea7ef36f 100644 --- a/compiler/testData/ir/irText/firProblems/ArrayMap.txt +++ b/compiler/testData/ir/irText/firProblems/ArrayMap.txt @@ -1,5 +1,9 @@ FILE fqName: fileName:/ArrayMap.kt CLASS CLASS name:ArrayMap modality:SEALED visibility:public superTypes:[kotlin.collections.Iterable.ArrayMap>] + sealedSubclasses: + CLASS OBJECT name:EmptyArrayMap modality:FINAL visibility:internal superTypes:[.ArrayMap] + CLASS CLASS name:OneElementArrayMap modality:FINAL visibility:internal superTypes:[.ArrayMap.OneElementArrayMap>] + CLASS CLASS name:ArrayMapImpl modality:FINAL visibility:internal superTypes:[.ArrayMap.ArrayMapImpl>] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.ArrayMap.ArrayMap> TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any] CONSTRUCTOR visibility:protected <> () returnType:.ArrayMap.ArrayMap> [primary] @@ -859,3 +863,4 @@ FILE fqName: fileName:/ArrayMap.kt overridden: public open fun toString (): kotlin.String [fake_override] declared in .ArrayMap $this: VALUE_PARAMETER name: type:kotlin.Any + diff --git a/compiler/testData/ir/irText/regressions/kt45236.txt b/compiler/testData/ir/irText/regressions/kt45236.txt index 2ee0d3ed126..5270c9c2792 100644 --- a/compiler/testData/ir/irText/regressions/kt45236.txt +++ b/compiler/testData/ir/irText/regressions/kt45236.txt @@ -1,5 +1,7 @@ FILE fqName: fileName:/kt45236.kt CLASS CLASS name:NetRequestStatus modality:SEALED visibility:public superTypes:[kotlin.Any] + sealedSubclasses: + CLASS CLASS name:Error modality:FINAL visibility:public [data] superTypes:[.NetRequestStatus.NetRequestStatus.Error>] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.NetRequestStatus.NetRequestStatus> TYPE_PARAMETER name:T index:0 variance:out superTypes:[kotlin.Any] CONSTRUCTOR visibility:protected <> () returnType:.NetRequestStatus.NetRequestStatus> [primary] diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxModernJdkCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxModernJdkCodegenTestGenerated.java index 096e284d5e4..46f25d4a04e 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxModernJdkCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxModernJdkCodegenTestGenerated.java @@ -228,6 +228,12 @@ public class BlackBoxModernJdkCodegenTestGenerated extends AbstractBlackBoxCodeg runTest("compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/compiledJavaSealedInterface.kt"); } + @Test + @TestMetadata("javaExhaustiveWhenOnKotlinSealedClass.kt") + public void testJavaExhaustiveWhenOnKotlinSealedClass() throws Exception { + runTest("compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/javaExhaustiveWhenOnKotlinSealedClass.kt"); + } + @Test @TestMetadata("javaRecordsViaKotlinReflection.kt") public void testJavaRecordsViaKotlinReflection() throws Exception { @@ -246,6 +252,12 @@ public class BlackBoxModernJdkCodegenTestGenerated extends AbstractBlackBoxCodeg runTest("compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/javaSealedInterface.kt"); } + @Test + @TestMetadata("permittedSubclassesOfSealedKotlinClass.kt") + public void testPermittedSubclassesOfSealedKotlinClass() throws Exception { + runTest("compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/permittedSubclassesOfSealedKotlinClass.kt"); + } + @Test @TestMetadata("sealedJavaClassViaJavaReflection.kt") public void testSealedJavaClassViaJavaReflection() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeListingTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeListingTestGenerated.java index 7f361ba957d..41c1bae5336 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeListingTestGenerated.java @@ -2142,6 +2142,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { runTest("compiler/testData/codegen/bytecodeListing/sealed/annotationsOnSealedConstructor.kt"); } + @Test + @TestMetadata("permittedSubclasses_1_7.kt") + public void testPermittedSubclasses_1_7() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/sealed/permittedSubclasses_1_7.kt"); + } + @Test @TestMetadata("sealedClassConstructor_1_4.kt") public void testSealedClassConstructor_1_4() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxModernJdkCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxModernJdkCodegenTestGenerated.java index 9379e2c57d9..371d4e0bc4b 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxModernJdkCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxModernJdkCodegenTestGenerated.java @@ -246,6 +246,12 @@ public class IrBlackBoxModernJdkCodegenTestGenerated extends AbstractIrBlackBoxC runTest("compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/compiledJavaSealedInterface.kt"); } + @Test + @TestMetadata("javaExhaustiveWhenOnKotlinSealedClass.kt") + public void testJavaExhaustiveWhenOnKotlinSealedClass() throws Exception { + runTest("compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/javaExhaustiveWhenOnKotlinSealedClass.kt"); + } + @Test @TestMetadata("javaRecordsViaKotlinReflection.kt") public void testJavaRecordsViaKotlinReflection() throws Exception { @@ -264,6 +270,12 @@ public class IrBlackBoxModernJdkCodegenTestGenerated extends AbstractIrBlackBoxC runTest("compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/javaSealedInterface.kt"); } + @Test + @TestMetadata("permittedSubclassesOfSealedKotlinClass.kt") + public void testPermittedSubclassesOfSealedKotlinClass() throws Exception { + runTest("compiler/testData/codegen/boxModernJdk/testsWithJava17/sealed/permittedSubclassesOfSealedKotlinClass.kt"); + } + @Test @TestMetadata("sealedJavaClassViaJavaReflection.kt") public void testSealedJavaClassViaJavaReflection() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeListingTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeListingTestGenerated.java index e4a95156f75..319f06f4445 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeListingTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeListingTestGenerated.java @@ -2190,6 +2190,12 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes runTest("compiler/testData/codegen/bytecodeListing/sealed/annotationsOnSealedConstructor.kt"); } + @Test + @TestMetadata("permittedSubclasses_1_7.kt") + public void testPermittedSubclasses_1_7() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/sealed/permittedSubclasses_1_7.kt"); + } + @Test @TestMetadata("sealedClassConstructor_1_4.kt") public void testSealedClassConstructor_1_4() throws Exception { diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/BytecodeListingTextCollectingVisitor.kt b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/BytecodeListingTextCollectingVisitor.kt index 24d5b74efc5..93255004e8e 100644 --- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/BytecodeListingTextCollectingVisitor.kt +++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/BytecodeListingTextCollectingVisitor.kt @@ -165,6 +165,12 @@ class BytecodeListingTextCollectingVisitor( } } + override fun visitPermittedSubclass(permittedSubclass: String?) { + if (permittedSubclass != null) { + declarationsInsideClass.add(Declaration("permittedSubclass: $permittedSubclass")) + } + } + override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor? { if (!filter.shouldWriteMethod(access, name, desc)) { return null diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index b5fdeab9764..e82f14b3bda 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -233,6 +233,7 @@ enum class LanguageFeature( StopPropagatingDeprecationThroughOverrides(KOTLIN_1_7), AbstractClassMemberNotImplementedWithIntermediateAbstractClass(KOTLIN_1_7, kind = BUG_FIX), RefineTypeCheckingOnAssignmentsToJavaFields(KOTLIN_1_7), + JvmPermittedSubclassesAttributeForSealed(KOTLIN_1_7), // Temporarily disabled, see KT-27084/KT-22379 SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX),