diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt index b031d0f8996..0b8094bde64 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.psi2ir.generators +import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.declarations.* @@ -25,6 +26,8 @@ import org.jetbrains.kotlin.ir.expressions.mapValueParameters import org.jetbrains.kotlin.ir.expressions.putTypeArguments import org.jetbrains.kotlin.ir.expressions.typeParametersCount import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides +import org.jetbrains.kotlin.ir.util.fields +import org.jetbrains.kotlin.ir.util.properties import org.jetbrains.kotlin.ir.util.referenceFunction import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry @@ -176,14 +179,21 @@ class ClassGenerator( val superClass = superTypeConstructorDescriptor as? ClassDescriptor ?: throw AssertionError("Unexpected supertype constructor for delegation: $superTypeConstructorDescriptor") - val delegateDescriptor = IrImplementingDelegateDescriptorImpl(irClass.descriptor, delegateType, superType, delegateNumber) - val irDelegateField = context.symbolTable.declareField( - ktDelegateExpression.startOffsetSkippingComments, ktDelegateExpression.endOffset, - IrDeclarationOrigin.DELEGATE, - delegateDescriptor, delegateDescriptor.type.toIrType(), - createBodyGenerator(irClass.symbol).generateExpressionBody(ktDelegateExpression) - ) - irClass.addMember(irDelegateField) + val propertyDescriptor = CodegenUtil.getDelegatePropertyIfAny(ktDelegateExpression, irClass.descriptor, context.bindingContext) + + val irDelegateField: IrField = if (CodegenUtil.isFinalPropertyWithBackingField(propertyDescriptor, context.bindingContext)) { + irClass.properties.first { it.descriptor == propertyDescriptor }.backingField!! + } else { + val delegateDescriptor = IrImplementingDelegateDescriptorImpl(irClass.descriptor, delegateType, superType, delegateNumber) + context.symbolTable.declareField( + ktDelegateExpression.startOffsetSkippingComments, ktDelegateExpression.endOffset, + IrDeclarationOrigin.DELEGATE, + delegateDescriptor, delegateDescriptor.type.toIrType(), + createBodyGenerator(irClass.symbol).generateExpressionBody(ktDelegateExpression) + ).apply { + irClass.addMember(this) + } + } val delegatesMap = DelegationResolver.getDelegates(irClass.descriptor, superClass, delegateType) val delegatedMembers = delegatesMap.keys.toList().sortedByRenderer() diff --git a/compiler/testData/codegen/box/delegation/delegationToVal.kt b/compiler/testData/codegen/box/delegation/delegationToVal.kt index e8b30ebfb54..8725b0767a0 100644 --- a/compiler/testData/codegen/box/delegation/delegationToVal.kt +++ b/compiler/testData/codegen/box/delegation/delegationToVal.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME @@ -37,7 +36,7 @@ fun box(): String { try { Test2::class.java.getDeclaredField("\$\$delegate_0") - return "\$\$delegate_0 field generated for class Test but should not" + return "\$\$delegate_0 field generated for class Test2 but should not" } catch (e: NoSuchFieldException) { // ok