diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationChecker.kt index 5957d41ff8e..b67cbf216d5 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationChecker.kt @@ -26,10 +26,7 @@ import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.packageFqName import org.jetbrains.kotlin.fir.resolve.fqName import org.jetbrains.kotlin.fir.resolve.fullyExpandedType -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.coneType -import org.jetbrains.kotlin.fir.types.coneTypeSafe -import org.jetbrains.kotlin.fir.types.customAnnotations +import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.StandardClassIds @@ -55,6 +52,16 @@ object FirAnnotationChecker : FirBasicDeclarationChecker() { checkAnnotationTarget(declaration, annotation, context, reporter) } + + if (declaration is FirCallableDeclaration) { + val receiverParameter = declaration.receiverParameter + if (receiverParameter != null) { + for (receiverAnnotation in receiverParameter.annotations) { + reportIfMfvc(context, reporter, receiverAnnotation, "receivers", receiverParameter.typeRef) + } + } + } + if (deprecatedSinceKotlin != null) { checkDeprecatedCalls(deprecatedSinceKotlin, deprecated, context, reporter) } @@ -72,19 +79,26 @@ object FirAnnotationChecker : FirBasicDeclarationChecker() { } } + private fun reportIfMfvc(context: CheckerContext, reporter: DiagnosticReporter, annotation: FirAnnotation, hint: String, type: FirTypeRef) { + if (type.needsMultiFieldValueClassFlattening(context.session)) { + reporter.reportOn(annotation.source, FirErrors.ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET, hint, context) + } + } + private fun checkMultiFieldValueClassAnnotationRestrictions( declaration: FirDeclaration, annotation: FirAnnotation, context: CheckerContext, reporter: DiagnosticReporter ) { + fun FirPropertyAccessor.hasNoReceivers() = contextReceivers.isEmpty() && receiverParameter?.typeRef == null && + propertySymbol.resolvedReceiverTypeRef == null && propertySymbol.resolvedContextReceivers.isEmpty() + val (hint, type) = when (annotation.useSiteTarget) { - FIELD, PROPERTY_DELEGATE_FIELD -> "fields" to ((declaration as? FirProperty)?.backingField?.returnTypeRef ?: return) - FILE, PROPERTY, PROPERTY_SETTER -> return - PROPERTY_GETTER -> "getters" to ((declaration as? FirPropertyAccessor)?.returnTypeRef ?: return) - RECEIVER -> "receivers" to ((declaration as? FirCallableDeclaration)?.receiverTypeRef ?: return) - CONSTRUCTOR_PARAMETER, SETTER_PARAMETER -> "parameters" to (declaration as? FirValueParameter ?: return).returnTypeRef - null -> when { + FIELD -> "fields" to ((declaration as? FirProperty)?.backingField?.returnTypeRef ?: return) + PROPERTY_DELEGATE_FIELD -> "delegate fields" to ((declaration as? FirProperty)?.delegate?.typeRef ?: return) + RECEIVER -> "receivers" to ((declaration as? FirCallableDeclaration)?.receiverParameter?.typeRef ?: return) + FILE, PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, CONSTRUCTOR_PARAMETER, SETTER_PARAMETER, null -> when { declaration is FirProperty && !declaration.isLocal -> { val allowedAnnotationTargets = annotation.getAllowedAnnotationTargets(context.session) when { @@ -97,17 +111,13 @@ object FirAnnotationChecker : FirBasicDeclarationChecker() { declaration is FirField -> "fields" to declaration.returnTypeRef declaration is FirValueParameter -> "parameters" to declaration.returnTypeRef declaration is FirVariable -> "variables" to declaration.returnTypeRef - declaration is FirPropertyAccessor && declaration.isGetter && - declaration.receiverTypeRef == null && - declaration.contextReceivers.isEmpty() -> + declaration is FirPropertyAccessor && declaration.isGetter && declaration.hasNoReceivers() -> "getters" to declaration.returnTypeRef else -> return } } - if (type.needsMfvcFlattening(context.session)) { - reporter.reportOn(annotation.source, FirErrors.ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET, hint, context) - } + reportIfMfvc(context, reporter, annotation, hint, type) } private fun checkAnnotationTarget( diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index a98a2c05b28..54574cd2cac 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -50447,6 +50447,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/valueClasses/defaultParameters.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("delegating.kt") + public void testDelegating() throws Exception { + runTest("compiler/testData/codegen/box/valueClasses/delegating.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); + } + @Test @TestMetadata("equality.kt") public void testEquality() throws Exception { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt index b6c688b6713..043e9c1013a 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt @@ -138,9 +138,9 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV get() = this.symbol.owner fun IrBlockBuilder.addReplacement(expression: IrGetField): IrExpression? { - val property = expression.field.property ?: return null - expression.receiver?.get(this, property.name)?.let { +it; return it } - val node = replacements.getMfvcPropertyNode(property) ?: return null + val field = expression.field + expression.receiver?.get(this, field.name)?.let { +it; return it } + val node = replacements.getMfvcFieldNode(field) ?: return null val typeArguments = makeTypeArgumentsFromField(expression) val instance: ReceiverBasedMfvcNodeInstance = node.createInstanceFromBox(this, typeArguments, expression.receiver, AccessType.AlwaysPrivate, ::variablesSaver) @@ -151,9 +151,9 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV } fun IrBlockBuilder.addReplacement(expression: IrSetField, safe: Boolean): IrExpression? { - val property = expression.field.property ?: return null - expression.receiver?.get(this, property.name)?.let { +it; return it } - val node = replacements.getMfvcPropertyNode(property) ?: return null + val field = expression.field + expression.receiver?.get(this, field.name)?.let { +it; return it } + val node = replacements.getMfvcFieldNode(field) ?: return null val typeArguments = makeTypeArgumentsFromField(expression) val instance: ReceiverBasedMfvcNodeInstance = node.createInstanceFromBox(this, typeArguments, expression.receiver, AccessType.AlwaysPrivate, ::variablesSaver) @@ -317,44 +317,62 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV irClass.primaryConstructor?.let { replacements.getReplacementForRegularClassConstructor(it)?.let { replacement -> addBindingsFor(it, replacement) } } - val properties = collectPropertiesAfterLowering(irClass) - val oldBackingFields = properties.mapNotNull { property -> property.backingField?.let { property to it } }.toMap() - val propertiesReplacement = collectRegularClassMfvcPropertiesReplacement(properties) // resets backing fields + val propertiesOrFields = collectPropertiesOrFieldsAfterLowering(irClass) + val oldBackingFields = propertiesOrFields.mapNotNull { propertyOrField -> + val property = (propertyOrField as? IrPropertyOrIrField.Property)?.property ?: return@mapNotNull null + property.backingField?.let { property to it } + }.toMap() + val propertiesOrFieldsReplacement = collectRegularClassMfvcPropertiesOrFieldsReplacement(propertiesOrFields) // resets backing fields - val fieldsToRemove = propertiesReplacement.keys.mapNotNull { oldBackingFields[it] }.toSet() + val fieldsToRemove = propertiesOrFieldsReplacement.keys.mapNotNull { + when (it) { + is IrPropertyOrIrField.Field -> it.field + is IrPropertyOrIrField.Property -> oldBackingFields[it.property] + } + }.toSet() - if (fieldsToRemove.isNotEmpty() || propertiesReplacement.isNotEmpty()) { - val newDeclarations = makeNewDeclarationsForRegularClass(fieldsToRemove, propertiesReplacement, irClass) + if (fieldsToRemove.isNotEmpty() || propertiesOrFieldsReplacement.isNotEmpty()) { + val newDeclarations = makeNewDeclarationsForRegularClass(fieldsToRemove, propertiesOrFieldsReplacement, irClass) irClass.declarations.replaceAll(newDeclarations) } } - private fun collectRegularClassMfvcPropertiesReplacement(properties: LinkedHashSet) = - LinkedHashMap().apply { - for (property in properties) { - val node = replacements.getRegularClassMfvcPropertyNode(property) ?: continue - put(property, node) + private fun collectRegularClassMfvcPropertiesOrFieldsReplacement(propertiesOrFields: LinkedHashSet) = + LinkedHashMap().apply { + for (propertyOrField in propertiesOrFields) { + val node = when (propertyOrField) { + is IrPropertyOrIrField.Field -> replacements.getMfvcFieldNode(propertyOrField.field) + is IrPropertyOrIrField.Property -> replacements.getMfvcPropertyNode(propertyOrField.property) + } ?: continue + put(propertyOrField, node as IntermediateMfvcNode) } } private fun makeNewDeclarationsForRegularClass( fieldsToRemove: Set, - propertiesReplacement: Map, + propertiesOrFieldsReplacement: Map, irClass: IrClass, ) = buildList { for (element in irClass.declarations) { when (element) { !is IrField, !in fieldsToRemove -> add(element) else -> { - val replacement = propertiesReplacement[element.property!!]!! - addAll(replacement.fields!!) - element.initializer?.let { initializer -> add(makeInitializerReplacement(irClass, element, initializer)) } + val fields = element.property?.let { propertiesOrFieldsReplacement[IrPropertyOrIrField.Property(it)] }?.fields + ?: propertiesOrFieldsReplacement[IrPropertyOrIrField.Field(element)]?.fields + if (fields != null) { + addAll(fields) + element.initializer?.let { initializer -> add(makeInitializerReplacement(irClass, element, initializer)) } + } else { + add(element) + } } } } - for (node in propertiesReplacement.values) { - addAll(node.allInnerUnboxMethods.filter { it.parent == irClass }) + for ((propertyOrField, node) in propertiesOrFieldsReplacement.entries) { + if (propertyOrField is IrPropertyOrIrField.Property) { // they are not used, only boxes are used for them + addAll(node.allInnerUnboxMethods.filter { it.parent == irClass }) + } } } @@ -928,9 +946,12 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV oldArgument == null -> List(parametersCount) { null } parametersCount == 1 -> listOf(oldArgument.transform(this@JvmMultiFieldValueClassLowering, null)) else -> { - val type = oldArgument.type as IrSimpleType - require(type.needsMfvcFlattening()) { "Unexpected type: ${type.render()}" } - flattenExpression(oldArgument).also { + val castedIfNeeded = when { + oldArgument.type.needsMfvcFlattening() -> oldArgument + oldArgument.type.makeNotNull().needsMfvcFlattening() -> irImplicitCast(oldArgument, oldArgument.type.makeNotNull()) + else -> error("Unexpected type: ${oldArgument.type.render()}") + } + flattenExpression(castedIfNeeded).also { require(it.size == parametersCount) { "Expected $parametersCount arguments but got ${it.size}" } } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt index 5b4f16e7d8d..ac221455bd9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt @@ -302,10 +302,27 @@ class MemoizedMultiFieldValueClassReplacements( createIntermediateNodeForMfvcPropertyOfRegularClass(parent, context, property) } - fun getRegularClassMfvcPropertyNode(property: IrProperty): IntermediateMfvcNode? { - val parent = property.parent + fun getMfvcFieldNode(field: IrField): NameableMfvcNode? { + val parent = field.parent + val property = field.correspondingPropertySymbol?.owner return when { - property.run { backingField?.type ?: getter?.returnType }?.needsMfvcFlattening() != true -> null + property?.isDelegated == false -> getMfvcPropertyNode(property) + parent !is IrClass -> null + !field.type.needsMfvcFlattening() -> null + else -> getMfvcStandaloneFieldNodeImpl(field) + } + } + + private val getMfvcStandaloneFieldNodeImpl: (IrField) -> NameableMfvcNode = storageManager.createMemoizedFunction { field -> + val parent = field.parentAsClass + createIntermediateNodeForStandaloneMfvcField(parent, context, field) + } + + private fun getRegularClassMfvcPropertyNode(property: IrProperty): IntermediateMfvcNode? { + val parent = property.parent + val types = listOfNotNull(property.backingField?.takeUnless { property.isDelegated }?.type, property.getter?.returnType) + return when { + types.isEmpty() || types.any { !it.needsMfvcFlattening() } -> null parent !is IrClass -> null property.isFakeOverride -> null property.getter.let { it != null && (it.contextReceiverParametersCount > 0 || it.extensionReceiverParameter != null) } -> null diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNode.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNode.kt index 85801ce13fd..9487cc1f503 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNode.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNode.kt @@ -122,8 +122,9 @@ class NameableMfvcNodeImpl( @JvmStatic fun makeFullFieldName(rootPropertyName: String?, nameParts: List): Name { - val joined = (listOf(rootPropertyName ?: "field") + nameParts.map { it.index.toString() }).joinToString("-") - return Name.identifier(joined) + val name = Name.guessByFirstCharacter(rootPropertyName ?: "field") + val joined = (listOf(name.asStringStripSpecialMarkers()) + nameParts.map { it.index.toString() }).joinToString("-") + return if (name.isSpecial) Name.special("<$joined>") else Name.identifier(joined) } } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt index d30933bad07..74e163e7a9b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt @@ -8,6 +8,8 @@ package org.jetbrains.kotlin.backend.jvm import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.backend.common.lower.parents +import org.jetbrains.kotlin.backend.jvm.IrPropertyOrIrField.Field +import org.jetbrains.kotlin.backend.jvm.IrPropertyOrIrField.Property import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound import org.jetbrains.kotlin.backend.jvm.ir.upperBound @@ -191,7 +193,7 @@ fun createIntermediateMfvcNode( val replacements = context.multiFieldValueClassReplacements val rootNode = replacements.getRootMfvcNode(valueClass) - val oldField = oldGetter?.correspondingPropertySymbol?.owner?.backingField + val oldField = oldGetter?.correspondingPropertySymbol?.owner?.backingFieldIfNotDelegate val shadowBackingFieldProperty = if (oldField == null) oldGetter?.getGetterField()?.correspondingPropertySymbol?.owner else null val useOldGetter = oldGetter != null && (oldField == null || !oldGetter.isDefaultGetter(oldField)) @@ -243,18 +245,29 @@ fun createIntermediateMfvcNode( ) } -fun collectPropertiesAfterLowering(irClass: IrClass) = LinkedHashSet().apply { - for (element in irClass.declarations) { - if (element is IrField) { - element.correspondingPropertySymbol?.owner?.let { add(it) } - } else if (element is IrSimpleFunction && element.extensionReceiverParameter == null && element.contextReceiverParametersCount == 0) { - element.correspondingPropertySymbol?.owner?.let { add(it) } - } - } +fun collectPropertiesAfterLowering(irClass: IrClass): LinkedHashSet = + LinkedHashSet(collectPropertiesOrFieldsAfterLowering(irClass).map { (it as Property).property }) + +sealed class IrPropertyOrIrField { + data class Property(val property: IrProperty) : IrPropertyOrIrField() + data class Field(val field: IrField) : IrPropertyOrIrField() } +fun collectPropertiesOrFieldsAfterLowering(irClass: IrClass): LinkedHashSet = + LinkedHashSet().apply { + for (element in irClass.declarations) { + if (element is IrField) { + element.correspondingPropertySymbol?.owner?.takeUnless { it.isDelegated }?.let { add(Property(it)) } ?: add(Field(element)) + } else if (element is IrSimpleFunction && element.extensionReceiverParameter == null && element.contextReceiverParametersCount == 0) { + element.correspondingPropertySymbol?.owner?.let { add(Property(it)) } + } + } + } + private fun IrProperty.isStatic(currentContainer: IrDeclarationContainer) = - getterIfDeclared(currentContainer)?.isStatic ?: backingField?.isStatic ?: error("Property without both getter and backing field") + getterIfDeclared(currentContainer)?.isStatic + ?: backingFieldIfNotDelegate?.isStatic + ?: error("Property without both getter and backing field") fun getRootNode(context: JvmBackendContext, mfvc: IrClass): RootMfvcNode { require(mfvc.isMultiFieldValueClass) { "${mfvc.defaultType.render()} does not require flattening" } @@ -270,7 +283,7 @@ fun getRootNode(context: JvmBackendContext, mfvc: IrClass): RootMfvcNode { val fields = mfvcNodeWithSubnodesImpl.fields!! val newPrimaryConstructor = makeMfvcPrimaryConstructor(context, oldPrimaryConstructor, mfvc, leaves, fields) - val primaryConstructorImpl = makePrimaryConstructorImpl(context, oldPrimaryConstructor, mfvc, leaves) + val primaryConstructorImpl = makePrimaryConstructorImpl(context, oldPrimaryConstructor, mfvc, leaves, mfvcNodeWithSubnodesImpl) val boxMethod = makeBoxMethod(context, mfvc, leaves, newPrimaryConstructor) val customEqualsAny = mfvc.functions.singleOrNull { @@ -358,7 +371,8 @@ private fun makePrimaryConstructorImpl( context: JvmBackendContext, oldPrimaryConstructor: IrConstructor, mfvc: IrClass, - leaves: List + leaves: List, + subnodesImpl: MfvcNodeWithSubnodesImpl, ) = context.irFactory.buildFun { name = InlineClassAbi.mangledNameFor(oldPrimaryConstructor, false, false) visibility = oldPrimaryConstructor.visibility @@ -371,6 +385,14 @@ private fun makePrimaryConstructorImpl( for (leaf in leaves) { addValueParameter(leaf.fullFieldName, leaf.type.substitute(mfvc.typeParameters, typeParameters.map { it.defaultType })) } + for ((index, oldParameter) in oldPrimaryConstructor.valueParameters.withIndex()) { + val node = subnodesImpl.subnodes[index] + if (node is LeafMfvcNode) { + val newIndex = subnodesImpl.subnodeIndices[node]!!.first + valueParameters[newIndex].annotations = oldParameter.annotations + } + } + annotations = oldPrimaryConstructor.annotations // body is added in the Lowering file as it needs to be lowered } @@ -406,7 +428,7 @@ private fun makeRootMfvcNodeSubnodes( ) = representation.underlyingPropertyNamesToTypes.mapIndexed { index, (name, type) -> val typeArguments = makeTypeArgumentsFromType(type) val oldProperty = properties[false to name]!! - val oldBackingField = oldProperty.backingField + val oldBackingField = oldProperty.backingFieldIfNotDelegate val oldGetter = oldProperty.getterIfDeclared(mfvc) val overriddenNode = oldGetter?.let { getOverriddenNode(context.multiFieldValueClassReplacements, it) as IntermediateMfvcNode? } val static = oldProperty.isStatic(mfvc) @@ -448,7 +470,7 @@ fun createIntermediateNodeForMfvcPropertyOfRegularClass( oldProperty: IrProperty, ): IntermediateMfvcNode { val oldGetter = oldProperty.getterIfDeclared(parent) - val oldField = oldProperty.backingField + val oldField = oldProperty.backingFieldIfNotDelegate val type = oldProperty.getter?.returnType ?: oldField?.type ?: error("Either getter or field must exist") require(type is IrSimpleType && type.needsMfvcFlattening()) { "Expected MFVC but got ${type.render()}" } val fieldAnnotations = oldField?.annotations ?: listOf() @@ -463,6 +485,19 @@ fun createIntermediateNodeForMfvcPropertyOfRegularClass( } } +fun createIntermediateNodeForStandaloneMfvcField( + parent: IrDeclarationContainer, + context: JvmBackendContext, + oldField: IrField, +): IntermediateMfvcNode { + val type = oldField.type + require(type is IrSimpleType && type.needsMfvcFlattening()) { "Expected MFVC but got ${type.render()}" } + return createIntermediateMfvcNode( + parent, context, type, makeTypeArgumentsFromType(type), oldField.name.asString(), listOf(), + oldField.annotations, oldField.isStatic, null, null, null, Modality.FINAL, oldField + ) +} + private fun getOverriddenNode(replacements: MemoizedMultiFieldValueClassReplacements, getter: IrSimpleFunction): NameableMfvcNode? = getter.overriddenSymbols .firstOrNull { !it.owner.isFakeOverride } @@ -482,3 +517,5 @@ fun getOptimizedPublicAccess(currentElement: IrElement?, parent: IrClass): Acces } private fun IrProperty.getterIfDeclared(parent: IrDeclarationContainer): IrSimpleFunction? = getter?.takeIf { it in parent.declarations } + +private val IrProperty.backingFieldIfNotDelegate get() = backingField?.takeUnless { isDelegated } diff --git a/compiler/testData/codegen/box/valueClasses/delegating.fir.txt b/compiler/testData/codegen/box/valueClasses/delegating.fir.txt new file mode 100644 index 00000000000..8cb44c5905a --- /dev/null +++ b/compiler/testData/codegen/box/valueClasses/delegating.fir.txt @@ -0,0 +1,84 @@ +@kotlin.jvm.JvmInline +@kotlin.Metadata +public final class A { + // source: 'delegating.kt' + private final field field-0: int + private final field field-1: int + private synthetic method (p0: int, p1: int): void + public synthetic final static method box-impl(p0: int, p1: int): A + public final static method constructor-impl(p0: int, p1: int): void + public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean + public static method equals-impl(p0: int, p1: int, p2: java.lang.Object): boolean + public final static method equals-sUp7gFk(p0: int, p1: int, p2: int, p3: int): boolean + public final static method getValue-impl(p0: int, p1: int, @org.jetbrains.annotations.Nullable p2: java.lang.Object, @org.jetbrains.annotations.NotNull p3: kotlin.reflect.KProperty): int + public final method getX(): int + public method hashCode(): int + public static method hashCode-impl(p0: int, p1: int): int + public @org.jetbrains.annotations.NotNull method toString(): java.lang.String + public static method toString-impl(p0: int, p1: int): java.lang.String + public synthetic final method unbox-impl-0(): int + public synthetic final method unbox-impl-1(): int +} + +@kotlin.Metadata +public interface Abstract { + // source: 'delegating.kt' + public abstract method getX(): int +} + +@kotlin.Metadata +final class B$a$2 { + // source: 'delegating.kt' + enclosing method B.(IILA;)V + public final static field INSTANCE: B$a$2 + inner (anonymous) class B$a$2 + static method (): void + method (): void + public final @org.jetbrains.annotations.NotNull method invoke(): A + public synthetic bridge method invoke(): java.lang.Object +} + +@kotlin.Metadata +public final class B { + // source: 'delegating.kt' + synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final @org.jetbrains.annotations.NotNull field a$delegate: kotlin.Lazy + private final field b$delegate-0: int + private final field b$delegate-1: int + private field x-0: int + private field x-1: int + private @org.jetbrains.annotations.Nullable field y: A + inner (anonymous) class B$a$2 + static method (): void + private method (p0: int, p1: int, p2: A): void + public synthetic method (p0: int, p1: int, p2: A, p3: kotlin.jvm.internal.DefaultConstructorMarker): void + public final @org.jetbrains.annotations.NotNull method getA(): A + public synthetic final method getA-0(): int + public synthetic final method getA-1(): int + public final method getB(): int + private static method getC$delegate(p0: B): java.lang.Object + public final @org.jetbrains.annotations.NotNull method getC(): A + public synthetic final method getC-0(): int + public synthetic final method getC-1(): int + public final @org.jetbrains.annotations.NotNull method getX(): A + public synthetic final method getX-0(): int + public synthetic final method getX-1(): int + public final @org.jetbrains.annotations.Nullable method getY(): A + public final method setX-sUp7gFk(p0: int, p1: int): void + public final method setY(@org.jetbrains.annotations.Nullable p0: A): void +} + +@kotlin.Metadata +public final class C { + // source: 'delegating.kt' + private synthetic final field <$$delegate_0-0>: int + private synthetic final field <$$delegate_0-1>: int + public method (p0: int, p1: int): void + public method getX(): int +} + +@kotlin.Metadata +public final class DelegatingKt { + // source: 'delegating.kt' + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} diff --git a/compiler/testData/codegen/box/valueClasses/delegating.kt b/compiler/testData/codegen/box/valueClasses/delegating.kt new file mode 100644 index 00000000000..1642d382694 --- /dev/null +++ b/compiler/testData/codegen/box/valueClasses/delegating.kt @@ -0,0 +1,48 @@ +// !LANGUAGE: +ValueClasses +// WITH_STDLIB +// WORKS_WHEN_VALUE_CLASS +// TARGET_BACKEND: JVM_IR +// CHECK_BYTECODE_LISTING + +import kotlin.reflect.KProperty + +interface Abstract { + val x: Int +} + +@JvmInline +value class A(override val x: Int, val y: Int): Abstract { + operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { + return x + y + } +} + +class B(var x: A, var y: A?) { + val a by lazy { A(-100, -200) } + val b by A(-100, -200) + val c by ::a +} + +class C(a: A): Abstract by a + +fun box(): String { + val a = A(1, 2) + val b = B(a, a) + + require(b.x == b.y) + require(b.x.x == b.y?.x) + require(b.x.y == b.y?.y) + require(b.x.hashCode() == b.y.hashCode()) + + require(b.a == A(-100, -200)) + require(b.a.x == -100) + require(b.a.y == -200) + require(b.b == -300) + require(b.c == A(-100, -200)) + require(b.c.x == -100) + require(b.c.y == -200) + + require(C(a).x == 1) + + return "OK" +} diff --git a/compiler/testData/codegen/box/valueClasses/delegating.txt b/compiler/testData/codegen/box/valueClasses/delegating.txt new file mode 100644 index 00000000000..f6254bfe576 --- /dev/null +++ b/compiler/testData/codegen/box/valueClasses/delegating.txt @@ -0,0 +1,84 @@ +@kotlin.jvm.JvmInline +@kotlin.Metadata +public final class A { + // source: 'delegating.kt' + private final field field-0: int + private final field field-1: int + private synthetic method (p0: int, p1: int): void + public synthetic final static method box-impl(p0: int, p1: int): A + public final static method constructor-impl(p0: int, p1: int): void + public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean + public static method equals-impl(p0: int, p1: int, p2: java.lang.Object): boolean + public final static method equals-sUp7gFk(p0: int, p1: int, p2: int, p3: int): boolean + public final static method getValue-impl(p0: int, p1: int, @org.jetbrains.annotations.Nullable p2: java.lang.Object, @org.jetbrains.annotations.NotNull p3: kotlin.reflect.KProperty): int + public method getX(): int + public method hashCode(): int + public static method hashCode-impl(p0: int, p1: int): int + public @org.jetbrains.annotations.NotNull method toString(): java.lang.String + public static method toString-impl(p0: int, p1: int): java.lang.String + public synthetic final method unbox-impl-0(): int + public synthetic final method unbox-impl-1(): int +} + +@kotlin.Metadata +public interface Abstract { + // source: 'delegating.kt' + public abstract method getX(): int +} + +@kotlin.Metadata +final class B$a$2 { + // source: 'delegating.kt' + enclosing method B.(IILA;)V + public final static field INSTANCE: B$a$2 + inner (anonymous) class B$a$2 + static method (): void + method (): void + public final @org.jetbrains.annotations.NotNull method invoke(): A + public synthetic bridge method invoke(): java.lang.Object +} + +@kotlin.Metadata +public final class B { + // source: 'delegating.kt' + synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final @org.jetbrains.annotations.NotNull field a$delegate: kotlin.Lazy + private final field b$delegate-0: int + private final field b$delegate-1: int + private field x-0: int + private field x-1: int + private @org.jetbrains.annotations.Nullable field y: A + inner (anonymous) class B$a$2 + static method (): void + private method (p0: int, p1: int, p2: A): void + public synthetic method (p0: int, p1: int, p2: A, p3: kotlin.jvm.internal.DefaultConstructorMarker): void + public final @org.jetbrains.annotations.NotNull method getA(): A + public synthetic final method getA-0(): int + public synthetic final method getA-1(): int + public final method getB(): int + private static method getC$delegate(p0: B): java.lang.Object + public final @org.jetbrains.annotations.NotNull method getC(): A + public synthetic final method getC-0(): int + public synthetic final method getC-1(): int + public final @org.jetbrains.annotations.NotNull method getX(): A + public synthetic final method getX-0(): int + public synthetic final method getX-1(): int + public final @org.jetbrains.annotations.Nullable method getY(): A + public final method setX-sUp7gFk(p0: int, p1: int): void + public final method setY(@org.jetbrains.annotations.Nullable p0: A): void +} + +@kotlin.Metadata +public final class C { + // source: 'delegating.kt' + private synthetic final field $$delegate_0-0: int + private synthetic final field $$delegate_0-1: int + public method (p0: int, p1: int): void + public method getX(): int +} + +@kotlin.Metadata +public final class DelegatingKt { + // source: 'delegating.kt' + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} diff --git a/compiler/testData/codegen/bytecodeListing/valueClasses/annotations.kt b/compiler/testData/codegen/bytecodeListing/valueClasses/annotations.kt new file mode 100644 index 00000000000..59124bfcae2 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/valueClasses/annotations.kt @@ -0,0 +1,120 @@ +// !LANGUAGE: +ValueClasses +// WITH_STDLIB +// WORKS_WHEN_VALUE_CLASS +// FIR_IDENTICAL +// TARGET_BACKEND: JVM_IR +import kotlin.reflect.KProperty + + +@Repeatable +annotation class Ann + +@[Ann Ann] +@JvmInline +value class A @Ann constructor( + @[Ann Ann] + @param:[Ann Ann] + @property:[Ann Ann] + @field:[Ann Ann] + @get:[Ann Ann] + val x: Int, + @[Ann Ann] + @param:[Ann Ann] + @property:[Ann Ann] + @field:[Ann Ann] + @get:[Ann Ann] + val y: Int, +) { + operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { + return 0 + } +} + +@[Ann Ann] +@JvmInline +value class B @Ann constructor( + @property:[Ann Ann] + val x: A, + @[Ann Ann] + @param:[Ann Ann] + @property:[Ann Ann] + @field:[Ann Ann] + @get:[Ann Ann] + val y: A?, +) + +@[Ann Ann] +class C @Ann constructor( + @property:[Ann Ann] + @set:[Ann Ann] + var x: A, + @[Ann Ann] + @param:[Ann Ann] + @property:[Ann Ann] + @field:[Ann Ann] + @get:[Ann Ann] + @set:[Ann Ann] + @setparam:[Ann Ann] + var y: A?, +) { + @delegate:[Ann Ann] + @property:[Ann Ann] + val z by lazy { A(-100, -200) } + @property:[Ann Ann] + @get:[Ann Ann] + val t by A(-100, -200) + @property:[Ann Ann] + val d by ::z + + init { + if (2 + 2 == 4) { + @[Ann Ann] + val x = 4 + val y = A(1, 2) + } + + + fun f() { + if (2 + 2 == 4) { + @[Ann Ann] + val x = 4 + val y = A(1, 2) + } + } + } +} + + +@[Ann Ann] +fun A.t(a: A, b: B, @[Ann Ann] c: C) { + if (2 + 2 == 4) { + @[Ann Ann] + val x = 4 + val y = A(1, 2) + } + + fun f() { + if (2 + 2 == 4) { + @[Ann Ann] + val x1 = 4 + val y1 = A(1, 2) + } + } +} + +@[Ann Ann] +fun @receiver:[Ann Ann] C.t(a: A, b: B, @[Ann Ann] c: C) = 4 + +@[Ann Ann] +var A.t + @[Ann Ann] + get() = A(1, 2) + @[Ann Ann] + set(_) = Unit + +@[Ann Ann] +var @receiver:[Ann Ann] C.t + @[Ann Ann] + get() = A(1, 2) + @[Ann Ann] + set(_) = Unit diff --git a/compiler/testData/codegen/bytecodeListing/valueClasses/annotations.txt b/compiler/testData/codegen/bytecodeListing/valueClasses/annotations.txt new file mode 100644 index 00000000000..573eb9cd59c --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/valueClasses/annotations.txt @@ -0,0 +1,134 @@ +@Ann$Container(value=[Ann, Ann]) +@kotlin.jvm.JvmInline +@kotlin.Metadata +public final class A { + // source: 'annotations.kt' + private final @Ann$Container(value=[Ann, Ann]) field field-0: int + private final @Ann$Container(value=[Ann, Ann]) field field-1: int + private synthetic method (p0: int, p1: int): void + public synthetic final static method box-impl(p0: int, p1: int): A + public final static @Ann method constructor-impl(@Ann$Container(value=[Ann, Ann, Ann, Ann]) p0: int, @Ann$Container(value=[Ann, Ann, Ann, Ann]) p1: int): void + public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean + public static method equals-impl(p0: int, p1: int, p2: java.lang.Object): boolean + public final static method equals-sUp7gFk(p0: int, p1: int, p2: int, p3: int): boolean + public final static method getValue-impl(p0: int, p1: int, @org.jetbrains.annotations.Nullable p2: java.lang.Object, @org.jetbrains.annotations.NotNull p3: kotlin.reflect.KProperty): int + public synthetic deprecated static @Ann$Container(value=[Ann, Ann]) method getX$annotations(): void + public synthetic deprecated static @Ann$Container(value=[Ann, Ann]) method getY$annotations(): void + public method hashCode(): int + public static method hashCode-impl(p0: int, p1: int): int + public @org.jetbrains.annotations.NotNull method toString(): java.lang.String + public static method toString-impl(p0: int, p1: int): java.lang.String + public synthetic final method unbox-impl-0(): int + public synthetic final method unbox-impl-1(): int + public inner class Ann$Container +} + +@kotlin.jvm.internal.RepeatableContainer +@java.lang.annotation.Retention(value=RUNTIME) +@kotlin.Metadata +public annotation class Ann$Container { + // source: 'annotations.kt' + public abstract method value(): Ann[] + public inner class Ann$Container +} + +@kotlin.annotation.Repeatable +@java.lang.annotation.Retention(value=RUNTIME) +@java.lang.annotation.Repeatable(value=Ann$Container::class) +@kotlin.Metadata +public annotation class Ann { + // source: 'annotations.kt' + public inner class Ann$Container +} + +@kotlin.Metadata +public final class AnnotationsKt { + // source: 'annotations.kt' + public synthetic deprecated static @Ann$Container(value=[Ann, Ann]) method getT$annotations(p0: A): void + public synthetic deprecated static @Ann$Container(value=[Ann, Ann]) method getT$annotations(p0: C): void + public final static @Ann$Container(value=[Ann, Ann]) @org.jetbrains.annotations.NotNull method getT(@Ann$Container(value=[Ann, Ann]) @org.jetbrains.annotations.NotNull p0: C): A + public final static @Ann$Container(value=[Ann, Ann]) @org.jetbrains.annotations.NotNull method getT-sUp7gFk(p0: int, p1: int): A + public final static @Ann$Container(value=[Ann, Ann]) method setT-GPBa7dw(@Ann$Container(value=[Ann, Ann]) @org.jetbrains.annotations.NotNull p0: C, p1: int, p2: int): void + public final static @Ann$Container(value=[Ann, Ann]) method setT-GPBa7dw(p0: int, p1: int, p2: int, p3: int): void + public final static @Ann$Container(value=[Ann, Ann]) method t-552ch2I(@Ann$Container(value=[Ann, Ann]) @org.jetbrains.annotations.NotNull p0: C, p1: int, p2: int, p3: int, p4: int, @org.jetbrains.annotations.Nullable p5: A, @Ann$Container(value=[Ann, Ann]) @org.jetbrains.annotations.NotNull p6: C): int + public final static @Ann$Container(value=[Ann, Ann]) method t-552ch2I(p0: int, p1: int, p2: int, p3: int, p4: int, p5: int, @org.jetbrains.annotations.Nullable p6: A, @Ann$Container(value=[Ann, Ann]) @org.jetbrains.annotations.NotNull p7: C): void + private final static method t_552ch2I$f(): void + public inner class Ann$Container +} + +@Ann$Container(value=[Ann, Ann]) +@kotlin.jvm.JvmInline +@kotlin.Metadata +public final class B { + // source: 'annotations.kt' + private final field field-0-0: int + private final field field-0-1: int + private final @Ann$Container(value=[Ann, Ann]) @org.jetbrains.annotations.Nullable field field-1: A + private synthetic method (p0: int, p1: int, p2: A): void + public synthetic final static method box-impl(p0: int, p1: int, p2: A): B + public final static @Ann method constructor-impl(p0: int, p1: int, @Ann$Container(value=[Ann, Ann, Ann, Ann]) @org.jetbrains.annotations.Nullable p2: A): void + public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean + public static method equals-impl(p0: int, p1: int, p2: A, p3: java.lang.Object): boolean + public final static method equals-sUp7gFk(p0: int, p1: int, p2: A, p3: int, p4: int, p5: A): boolean + public synthetic deprecated static @Ann$Container(value=[Ann, Ann]) method getX$annotations(): void + public synthetic deprecated static @Ann$Container(value=[Ann, Ann]) method getY$annotations(): void + public method hashCode(): int + public static method hashCode-impl(p0: int, p1: int, p2: A): int + public @org.jetbrains.annotations.NotNull method toString(): java.lang.String + public static method toString-impl(p0: int, p1: int, p2: A): java.lang.String + public synthetic final method unbox-impl-0(): A + public synthetic final method unbox-impl-0-0(): int + public synthetic final method unbox-impl-0-1(): int + public synthetic final method unbox-impl-1(): A + public inner class Ann$Container +} + +@kotlin.Metadata +final class C$z$2 { + // source: 'annotations.kt' + enclosing method C.(IILA;)V + public final static field INSTANCE: C$z$2 + inner (anonymous) class C$z$2 + static method (): void + method (): void + public final @org.jetbrains.annotations.NotNull method invoke(): A + public synthetic bridge method invoke(): java.lang.Object +} + +@Ann$Container(value=[Ann, Ann]) +@kotlin.Metadata +public final class C { + // source: 'annotations.kt' + synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final field t$delegate-0: int + private final field t$delegate-1: int + private field x-0: int + private field x-1: int + private @Ann$Container(value=[Ann, Ann]) @org.jetbrains.annotations.Nullable field y: A + private final @Ann$Container(value=[Ann, Ann]) @org.jetbrains.annotations.NotNull field z$delegate: kotlin.Lazy + inner (anonymous) class C$z$2 + static method (): void + public synthetic @Ann method (p0: int, p1: int, @Ann$Container(value=[Ann, Ann, Ann, Ann]) p2: A, p3: kotlin.jvm.internal.DefaultConstructorMarker): void + private method (p0: int, p1: int, p2: A): void + private final static method _init_$f(): void + public synthetic deprecated static @Ann$Container(value=[Ann, Ann]) method getD$annotations(): void + private static method getD$delegate(p0: C): java.lang.Object + public final @org.jetbrains.annotations.NotNull method getD(): A + public synthetic final method getD-0(): int + public synthetic final method getD-1(): int + public synthetic deprecated static @Ann$Container(value=[Ann, Ann]) method getT$annotations(): void + public final @Ann$Container(value=[Ann, Ann]) method getT(): int + public synthetic deprecated static @Ann$Container(value=[Ann, Ann]) method getX$annotations(): void + public final @org.jetbrains.annotations.NotNull method getX(): A + public synthetic final method getX-0(): int + public synthetic final method getX-1(): int + public synthetic deprecated static @Ann$Container(value=[Ann, Ann]) method getY$annotations(): void + public final @Ann$Container(value=[Ann, Ann]) @org.jetbrains.annotations.Nullable method getY(): A + public synthetic deprecated static @Ann$Container(value=[Ann, Ann]) method getZ$annotations(): void + public final @org.jetbrains.annotations.NotNull method getZ(): A + public synthetic final method getZ-0(): int + public synthetic final method getZ-1(): int + public final @Ann$Container(value=[Ann, Ann]) method setX-sUp7gFk(p0: int, p1: int): void + public final @Ann$Container(value=[Ann, Ann]) method setY(@Ann$Container(value=[Ann, Ann]) @org.jetbrains.annotations.Nullable p0: A): void + public inner class Ann$Container +} diff --git a/compiler/testData/diagnostics/tests/valueClasses/annotations.kt b/compiler/testData/diagnostics/tests/valueClasses/annotations.kt index d7711682432..eeb5759e158 100644 --- a/compiler/testData/diagnostics/tests/valueClasses/annotations.kt +++ b/compiler/testData/diagnostics/tests/valueClasses/annotations.kt @@ -4,6 +4,8 @@ // WORKS_WHEN_VALUE_CLASS // FIR_IDENTICAL +import kotlin.reflect.KProperty + @Repeatable annotation class Ann @@ -22,7 +24,11 @@ value class A @Ann constructor( @field:[Ann Ann] @get:[Ann Ann] val y: Int, -) +) { + operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { + return 0 + } +} @[Ann Ann] @JvmInline @@ -63,8 +69,18 @@ class C @Ann constructor( @setparam:[Ann Ann] var y: A?, ) { - @delegate:[Ann Ann] + @delegate:[Ann Ann] + @property:[Ann Ann] + @get:[Ann Ann] val z by lazy { A(-100, -200) } + @delegate:[Ann Ann] + @property:[Ann Ann] + @get:[Ann Ann] + val c by A(-100, -200) + @delegate:[Ann Ann] + @property:[Ann Ann] + @get:[Ann Ann] + val d by ::z @JvmField val e = x @@ -91,7 +107,7 @@ class C @Ann constructor( @[Ann Ann] -fun @receiver:[Ann Ann] A.t(@[Ann Ann] a: A, @[Ann Ann] b: B, @[Ann Ann] c: C) { +fun @receiver:[Ann Ann] A.t(@[Ann Ann] a: A, @[Ann Ann] b: B, @[Ann Ann] c: C) { if (2 + 2 == 4) { @[Ann Ann] val x = 4 @@ -111,3 +127,17 @@ fun @receiver:[Ann Ann] A.t(@[Ann Ann] a: A, @[Ann Ann] b: B, @[Ann Ann] c: C) = 4 + +@[Ann Ann] +var @receiver:[Ann Ann] A.t + @[Ann Ann] + get() = A(1, 2) + @[Ann Ann] + set(@[Ann Ann] _) = Unit + +@[Ann Ann] +var @receiver:[Ann Ann] C.t + @[Ann Ann] + get() = A(1, 2) + @[Ann Ann] + set(@[Ann Ann] _) = Unit 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 e537a14fda3..c52bb5574e9 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 @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.test.runners.codegen; import com.intellij.testFramework.TestDataPath; import org.jetbrains.kotlin.test.util.KtTestUtil; import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.utils.TransformersFunctions; import org.jetbrains.kotlin.test.TestMetadata; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -2410,4 +2411,14 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { } } } + + @Nested + @TestMetadata("compiler/testData/codegen/bytecodeListing/valueClasses") + @TestDataPath("$PROJECT_ROOT") + public class ValueClasses { + @Test + public void testAllFilesPresentInValueClasses() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + } } diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 6a511179142..b8accecf370 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -50447,6 +50447,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/valueClasses/defaultParameters.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("delegating.kt") + public void testDelegating() throws Exception { + runTest("compiler/testData/codegen/box/valueClasses/delegating.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); + } + @Test @TestMetadata("equality.kt") public void testEquality() 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 989dd298ca0..8583d4a288f 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 @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.test.runners.codegen; import com.intellij.testFramework.TestDataPath; import org.jetbrains.kotlin.test.util.KtTestUtil; import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.utils.TransformersFunctions; import org.jetbrains.kotlin.test.TestMetadata; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -2512,4 +2513,20 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes } } } + + @Nested + @TestMetadata("compiler/testData/codegen/bytecodeListing/valueClasses") + @TestDataPath("$PROJECT_ROOT") + public class ValueClasses { + @Test + public void testAllFilesPresentInValueClasses() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("annotations.kt") + public void testAnnotations() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/valueClasses/annotations.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); + } + } }