[IR] Support MFVC-typed properties and interfaces delegates
Signed-off-by: Evgeniy.Zhelenskiy <Evgeniy.Zhelenskiy@jetbrains.com> #KT-1179
This commit is contained in:
committed by
Space Team
parent
4d426fc4cd
commit
38c80192f9
+26
-16
@@ -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(
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+47
-26
@@ -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<IrProperty>) =
|
||||
LinkedHashMap<IrProperty, IntermediateMfvcNode>().apply {
|
||||
for (property in properties) {
|
||||
val node = replacements.getRegularClassMfvcPropertyNode(property) ?: continue
|
||||
put(property, node)
|
||||
private fun collectRegularClassMfvcPropertiesOrFieldsReplacement(propertiesOrFields: LinkedHashSet<IrPropertyOrIrField>) =
|
||||
LinkedHashMap<IrPropertyOrIrField, IntermediateMfvcNode>().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<IrField>,
|
||||
propertiesReplacement: Map<IrProperty, IntermediateMfvcNode>,
|
||||
propertiesOrFieldsReplacement: Map<IrPropertyOrIrField, IntermediateMfvcNode>,
|
||||
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}" }
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -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
|
||||
|
||||
@@ -122,8 +122,9 @@ class NameableMfvcNodeImpl(
|
||||
|
||||
@JvmStatic
|
||||
fun makeFullFieldName(rootPropertyName: String?, nameParts: List<IndexedNamePart>): 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<IrProperty>().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<IrProperty> =
|
||||
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<IrPropertyOrIrField> =
|
||||
LinkedHashSet<IrPropertyOrIrField>().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<LeafMfvcNode>
|
||||
leaves: List<LeafMfvcNode>,
|
||||
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 }
|
||||
|
||||
@@ -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 <init>(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.<init>(IILA;)V
|
||||
public final static field INSTANCE: B$a$2
|
||||
inner (anonymous) class B$a$2
|
||||
static method <clinit>(): void
|
||||
method <init>(): 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 <clinit>(): void
|
||||
private method <init>(p0: int, p1: int, p2: A): void
|
||||
public synthetic method <init>(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 <init>(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
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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 <init>(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.<init>(IILA;)V
|
||||
public final static field INSTANCE: B$a$2
|
||||
inner (anonymous) class B$a$2
|
||||
static method <clinit>(): void
|
||||
method <init>(): 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 <clinit>(): void
|
||||
private method <init>(p0: int, p1: int, p2: A): void
|
||||
public synthetic method <init>(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 <init>(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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 <init>(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 <init>(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.<init>(IILA;)V
|
||||
public final static field INSTANCE: C$z$2
|
||||
inner (anonymous) class C$z$2
|
||||
static method <clinit>(): void
|
||||
method <init>(): 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 <clinit>(): void
|
||||
public synthetic @Ann method <init>(p0: int, p1: int, @Ann$Container(value=[Ann, Ann, Ann, Ann]) p2: A, p3: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
private method <init>(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
|
||||
}
|
||||
@@ -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:[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>]
|
||||
@delegate:[Ann Ann]
|
||||
@property:[Ann Ann]
|
||||
@get:[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>]
|
||||
val z by lazy { A(-100, -200) }
|
||||
@delegate:[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>]
|
||||
@property:[Ann Ann]
|
||||
@get:[Ann Ann]
|
||||
val c by A(-100, -200)
|
||||
@delegate:[Ann Ann]
|
||||
@property:[Ann Ann]
|
||||
@get:[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>]
|
||||
val d by ::z
|
||||
|
||||
<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET, INAPPLICABLE_JVM_FIELD!>@JvmField<!>
|
||||
val e = x
|
||||
@@ -91,7 +107,7 @@ class C @Ann constructor(
|
||||
|
||||
|
||||
@[Ann Ann]
|
||||
fun @receiver:[Ann Ann] A.t(@[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>] a: A, @[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>] b: B, @[Ann Ann] c: C) {
|
||||
fun @receiver:[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>] A.t(@[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>] a: A, @[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>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(@[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TY
|
||||
|
||||
@[Ann Ann]
|
||||
fun @receiver:[Ann Ann] C.t(@[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>] a: A, @[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>] b: B, @[Ann Ann] c: C) = 4
|
||||
|
||||
@[Ann Ann]
|
||||
var @receiver:[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>] A.t
|
||||
@[Ann Ann]
|
||||
get() = A(1, 2)
|
||||
@[Ann Ann]
|
||||
set(@[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>] _) = Unit
|
||||
|
||||
@[Ann Ann]
|
||||
var @receiver:[Ann Ann] C.t
|
||||
@[Ann Ann]
|
||||
get() = A(1, 2)
|
||||
@[Ann Ann]
|
||||
set(@[<!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!> <!ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET!>Ann<!>] _) = Unit
|
||||
|
||||
+11
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+17
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user