From d988853c11cb612b798257cf6f8d7bee4180a6eb Mon Sep 17 00:00:00 2001 From: pyos Date: Fri, 2 Jul 2021 12:35:02 +0200 Subject: [PATCH] JVM_IR: optimize out redundant delegated property receiver fields Now this: class C { val x = something val y by x::property } is *exactly* the same as this: class C { val x = something val y get() = x.property } (plus a `getY$delegate` method) --- .../FirBlackBoxCodegenTestGenerated.java | 12 +++ .../PropertyReferenceDelegationLowering.kt | 76 ++++++++++++++----- .../delegateToAnotherWithSideEffects.kt | 16 ++++ .../delegateToOpenProperty.kt | 23 ++++++ .../delegateToAnother.kt | 1 + .../codegen/BlackBoxCodegenTestGenerated.java | 12 +++ .../IrBlackBoxCodegenTestGenerated.java | 12 +++ .../LightAnalysisModeTestGenerated.java | 10 +++ .../IrJsCodegenBoxES6TestGenerated.java | 10 +++ .../IrJsCodegenBoxTestGenerated.java | 10 +++ .../semantics/JsCodegenBoxTestGenerated.java | 10 +++ 11 files changed, 175 insertions(+), 17 deletions(-) create mode 100644 compiler/testData/codegen/box/delegatedProperty/delegateToAnotherWithSideEffects.kt create mode 100644 compiler/testData/codegen/box/delegatedProperty/delegateToOpenProperty.kt 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 bb9fb4558a8..1e9ca3a33c1 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 @@ -13216,12 +13216,24 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherReflection.kt"); } + @Test + @TestMetadata("delegateToAnotherWithSideEffects.kt") + public void testDelegateToAnotherWithSideEffects() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherWithSideEffects.kt"); + } + @Test @TestMetadata("delegateToGenericJavaProperty.kt") public void testDelegateToGenericJavaProperty() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/delegateToGenericJavaProperty.kt"); } + @Test + @TestMetadata("delegateToOpenProperty.kt") + public void testDelegateToOpenProperty() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToOpenProperty.kt"); + } + @Test @TestMetadata("delegateWithPrivateSet.kt") public void testDelegateWithPrivateSet() throws Exception { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceDelegationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceDelegationLowering.kt index 71ccdead6df..eede5cb8dd6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceDelegationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceDelegationLowering.kt @@ -9,20 +9,20 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.codegen.fileParent import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder import org.jetbrains.kotlin.backend.jvm.lower.JvmPropertiesLowering.Companion.createSyntheticMethodForPropertyDelegate import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.buildField import org.jetbrains.kotlin.ir.builders.declarations.buildVariable import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrPropertyReferenceImpl -import org.jetbrains.kotlin.ir.util.getPackageFragment -import org.jetbrains.kotlin.ir.util.render -import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.name.Name @@ -39,14 +39,15 @@ private class PropertyReferenceDelegationLowering(val context: JvmBackendContext } private class PropertyReferenceDelegationTransformer(val context: JvmBackendContext) : IrElementTransformerVoid() { - private fun IrSimpleFunction.accessorBody(delegate: IrPropertyReference, receiverField: IrDeclaration?) = + private fun IrSimpleFunction.accessorBody(delegate: IrPropertyReference, receiverFieldOrExpression: IrStatement?) = context.createIrBuilder(symbol, startOffset, endOffset).run { val value = valueParameters.singleOrNull()?.let(::irGet) - var boundReceiver = when (receiverField) { + var boundReceiver = when (receiverFieldOrExpression) { null -> null - is IrField -> irGetField(dispatchReceiverParameter?.let(::irGet), receiverField) - is IrValueDeclaration -> irGet(receiverField) - else -> throw AssertionError("not a field/variable: ${receiverField.render()}") + is IrField -> irGetField(dispatchReceiverParameter?.let(::irGet), receiverFieldOrExpression) + is IrValueDeclaration -> irGet(receiverFieldOrExpression) + is IrExpression -> receiverFieldOrExpression + else -> throw AssertionError("not a field/variable/expression: ${receiverFieldOrExpression.render()}") } val unboundReceiver = extensionReceiverParameter ?: dispatchReceiverParameter val field = delegate.field?.owner @@ -84,6 +85,35 @@ private class PropertyReferenceDelegationTransformer(val context: JvmBackendCont private val IrStatement.isStdlibCall: Boolean get() = this is IrCall && symbol.owner.getPackageFragment()?.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME + // Constants, object accesses, reads of immutable variables, and reads of immutable properties in the same file + // don't need to be cached in a field; reads of mutable properties have to be as we should ignore further assignments + // to those, and immutable properties in other files might become mutable without breaking ABI. + private fun IrExpression.canInline(currentFile: IrFile): Boolean = when (this) { + is IrGetValue -> !symbol.owner.let { it is IrVariable && it.isVar } + is IrGetField -> symbol.owner.let { it.isFinal && it.fileParent == currentFile } && receiver?.canInline(currentFile) != false + is IrCall -> symbol.owner.let { it.isFinalDefaultValGetter && it.fileParent == currentFile } && + dispatchReceiver?.canInline(currentFile) != false && extensionReceiver?.canInline(currentFile) != false + else -> isTrivial() + } + + private val IrSimpleFunction.isFinalDefaultValGetter: Boolean + get() = origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR && + correspondingPropertySymbol?.let { it.owner.getter == this && it.owner.setter == null } == true && + modality == Modality.FINAL + + private fun IrExpression.inline(oldReceiver: IrValueParameter?, newReceiver: IrValueParameter?): IrExpression = when (this) { + is IrGetField -> + IrGetFieldImpl(startOffset, endOffset, symbol, type, receiver?.inline(oldReceiver, newReceiver), origin, superQualifierSymbol) + is IrGetValue -> + IrGetValueImpl(startOffset, endOffset, type, newReceiver?.symbol.takeIf { symbol == oldReceiver?.symbol } ?: symbol, origin) + is IrCall -> + IrCallImpl(startOffset, endOffset, type, symbol, typeArgumentsCount, valueArgumentsCount, origin, superQualifierSymbol).apply { + dispatchReceiver = this@inline.dispatchReceiver?.inline(oldReceiver, newReceiver) + extensionReceiver = this@inline.extensionReceiver?.inline(oldReceiver, newReceiver) + } + else -> shallowCopy() + } + override fun visitClass(declaration: IrClass): IrStatement { declaration.transformChildren(this, null) declaration.transformDeclarationsFlat { @@ -102,23 +132,27 @@ private class PropertyReferenceDelegationTransformer(val context: JvmBackendCont setter?.returnsResultOfStdlibCall == false ) return null - backingField = (delegate.dispatchReceiver ?: delegate.extensionReceiver)?.let { receiver -> + val receiver = (delegate.dispatchReceiver ?: delegate.extensionReceiver) + ?.transform(this@PropertyReferenceDelegationTransformer, null) + backingField = receiver?.takeIf { !it.canInline(fileParent) }?.let { context.irFactory.buildField { updateFrom(oldField) name = Name.identifier("${this@transform.name}\$receiver") type = receiver.type }.apply { parent = oldField.parent - initializer = context.irFactory.createExpressionBody(receiver.transform(this@PropertyReferenceDelegationTransformer, null)) + initializer = context.irFactory.createExpressionBody(it) } } - getter?.apply { body = accessorBody(delegate, backingField) } - setter?.apply { body = accessorBody(delegate, backingField) } + val originalThis = parentAsClass.thisReceiver + getter?.apply { body = accessorBody(delegate, backingField ?: receiver?.inline(originalThis, dispatchReceiverParameter)) } + setter?.apply { body = accessorBody(delegate, backingField ?: receiver?.inline(originalThis, dispatchReceiverParameter)) } val delegateMethod = context.createSyntheticMethodForPropertyDelegate(this).apply { body = context.createJvmIrBuilder(symbol).run { - val propertyOwner = if (getter?.dispatchReceiverParameter != null) irGet(valueParameters[0]) else null - val boundReceiver = backingField?.let { irGetField(propertyOwner, it) } + val propertyOwner = if (getter?.dispatchReceiverParameter != null) valueParameters[0] else null + val boundReceiver = backingField?.let { irGetField(propertyOwner?.let(::irGet), it) } + ?: receiver?.inline(originalThis, propertyOwner) irExprBody(with(delegate) { val origin = PropertyReferenceLowering.REFLECTED_PROPERTY_REFERENCE IrPropertyReferenceImpl(startOffset, endOffset, type, symbol, typeArgumentsCount, field, getter, setter, origin) @@ -130,7 +164,14 @@ private class PropertyReferenceDelegationTransformer(val context: JvmBackendCont }) } } - return listOf(this, delegateMethod) + // When the receiver is inlined, it can have side effects in form of class initialization, so it should be evaluated here. + val receiverBlock = receiver.takeIf { backingField == null }?.let { + val symbol = IrAnonymousInitializerSymbolImpl(parentAsClass.symbol) + context.irFactory.createAnonymousInitializer(it.startOffset, it.endOffset, IrDeclarationOrigin.DEFINED, symbol).apply { + body = context.irFactory.createBlockBody(startOffset, endOffset, listOf(it.inline(null, null))) + } + } + return listOfNotNull(this, delegateMethod, receiverBlock) } override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty): IrStatement { @@ -140,6 +181,7 @@ private class PropertyReferenceDelegationTransformer(val context: JvmBackendCont declaration.setter?.returnsResultOfStdlibCall == false ) return super.visitLocalDelegatedProperty(declaration) + // Variables are cheap, so optimizing them out is not really necessary. val receiver = (delegate.dispatchReceiver ?: delegate.extensionReceiver)?.let { receiver -> with(declaration.delegate) { buildVariable(parent, startOffset, endOffset, origin, name, receiver.type) }.apply { initializer = receiver.transform(this@PropertyReferenceDelegationTransformer, null) diff --git a/compiler/testData/codegen/box/delegatedProperty/delegateToAnotherWithSideEffects.kt b/compiler/testData/codegen/box/delegatedProperty/delegateToAnotherWithSideEffects.kt new file mode 100644 index 00000000000..184cb247355 --- /dev/null +++ b/compiler/testData/codegen/box/delegatedProperty/delegateToAnotherWithSideEffects.kt @@ -0,0 +1,16 @@ +// WITH_RUNTIME +var result = "Fail" + +object O { + val z = 42 + init { result = "OK" } +} + +class A { + val x by O::z +} + +fun box(): String { + A() + return result +} diff --git a/compiler/testData/codegen/box/delegatedProperty/delegateToOpenProperty.kt b/compiler/testData/codegen/box/delegatedProperty/delegateToOpenProperty.kt new file mode 100644 index 00000000000..49737b89356 --- /dev/null +++ b/compiler/testData/codegen/box/delegatedProperty/delegateToOpenProperty.kt @@ -0,0 +1,23 @@ +// WITH_RUNTIME +val String.foo: String + get() = this + +abstract class A { + abstract val x: String + + val y by x::foo +} + +var storage = "OK" + +class B : A() { + override var x: String + get() = storage + set(value) { storage = value } +} + +fun box(): String { + val b = B() + b.x = "fail" + return b.y +} diff --git a/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/delegateToAnother.kt b/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/delegateToAnother.kt index 21ad37b2230..11c104aeaed 100644 --- a/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/delegateToAnother.kt +++ b/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/delegateToAnother.kt @@ -33,6 +33,7 @@ fun local() { // Optimized all to direct accesses, with `$delegate` methods generating reflected references on demand: // 0 extends kotlin/jvm/internal/MutablePropertyReference[0-2]Impl // 0 private final( static)? Lkotlin/reflect/KMutableProperty[0-2]; [xyz]m?\$delegate +// 2 private final( static)? LC; [xyz]m?\$receiver // 0 LOCALVARIABLE [xyz]m? Lkotlin/reflect/KMutableProperty[0-2]; // 12 static get[XYZ]m?\$delegate diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index a72666dfc4b..a5eec068c1d 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -13216,12 +13216,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherReflection.kt"); } + @Test + @TestMetadata("delegateToAnotherWithSideEffects.kt") + public void testDelegateToAnotherWithSideEffects() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherWithSideEffects.kt"); + } + @Test @TestMetadata("delegateToGenericJavaProperty.kt") public void testDelegateToGenericJavaProperty() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/delegateToGenericJavaProperty.kt"); } + @Test + @TestMetadata("delegateToOpenProperty.kt") + public void testDelegateToOpenProperty() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToOpenProperty.kt"); + } + @Test @TestMetadata("delegateWithPrivateSet.kt") public void testDelegateWithPrivateSet() throws Exception { 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 5f67feccf18..5fb7a71b7a6 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 @@ -13216,12 +13216,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherReflection.kt"); } + @Test + @TestMetadata("delegateToAnotherWithSideEffects.kt") + public void testDelegateToAnotherWithSideEffects() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherWithSideEffects.kt"); + } + @Test @TestMetadata("delegateToGenericJavaProperty.kt") public void testDelegateToGenericJavaProperty() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/delegateToGenericJavaProperty.kt"); } + @Test + @TestMetadata("delegateToOpenProperty.kt") + public void testDelegateToOpenProperty() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToOpenProperty.kt"); + } + @Test @TestMetadata("delegateWithPrivateSet.kt") public void testDelegateWithPrivateSet() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index f20c3ba613d..56250c06010 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -10737,11 +10737,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherReflection.kt"); } + @TestMetadata("delegateToAnotherWithSideEffects.kt") + public void testDelegateToAnotherWithSideEffects() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherWithSideEffects.kt"); + } + @TestMetadata("delegateToGenericJavaProperty.kt") public void testDelegateToGenericJavaProperty() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/delegateToGenericJavaProperty.kt"); } + @TestMetadata("delegateToOpenProperty.kt") + public void testDelegateToOpenProperty() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToOpenProperty.kt"); + } + @TestMetadata("delegateWithPrivateSet.kt") public void testDelegateWithPrivateSet() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/delegateWithPrivateSet.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 5c421a3ab7e..c229fd6f763 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -9551,6 +9551,16 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherMutable.kt"); } + @TestMetadata("delegateToAnotherWithSideEffects.kt") + public void testDelegateToAnotherWithSideEffects() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherWithSideEffects.kt"); + } + + @TestMetadata("delegateToOpenProperty.kt") + public void testDelegateToOpenProperty() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToOpenProperty.kt"); + } + @TestMetadata("delegateWithPrivateSet.kt") public void testDelegateWithPrivateSet() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/delegateWithPrivateSet.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index af47c377b62..429a34a0d68 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -8957,6 +8957,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherMutable.kt"); } + @TestMetadata("delegateToAnotherWithSideEffects.kt") + public void testDelegateToAnotherWithSideEffects() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherWithSideEffects.kt"); + } + + @TestMetadata("delegateToOpenProperty.kt") + public void testDelegateToOpenProperty() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToOpenProperty.kt"); + } + @TestMetadata("delegateWithPrivateSet.kt") public void testDelegateWithPrivateSet() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/delegateWithPrivateSet.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 5e75e99b256..feee7484ab1 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -8957,6 +8957,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherMutable.kt"); } + @TestMetadata("delegateToAnotherWithSideEffects.kt") + public void testDelegateToAnotherWithSideEffects() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToAnotherWithSideEffects.kt"); + } + + @TestMetadata("delegateToOpenProperty.kt") + public void testDelegateToOpenProperty() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/delegateToOpenProperty.kt"); + } + @TestMetadata("delegateWithPrivateSet.kt") public void testDelegateWithPrivateSet() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/delegateWithPrivateSet.kt");