From 36cb869ac2c3a89c63bf4cdd4f1a487e1293ee37 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Fri, 1 Sep 2023 12:32:17 +0300 Subject: [PATCH] [FIR2IR] Create fake one-time use properties for callable reference to synthetic properies Previously fir2ir created real IR properties some getter and setter for such references, which lead to the situation that there might be a unbound fake override for synthetic property which wasn't stored in declaration storage (and code in FakeOverrideGenerator was a hack to cover this case) In the same time K1 creates fake property for such cases, which is stored in IrPropertyReference along with original get... and set... functions as getter and setter of reference. And in this commit K2 does the same thing ^KT-61637 --- .../kotlin/fir/backend/ConversionUtils.kt | 33 +-- .../generators/CallAndReferenceGenerator.kt | 208 +++++++++++------- .../generators/FakeOverrideGenerator.kt | 15 -- .../Fir2IrCallableDeclarationsGenerator.kt | 25 +++ .../fir/symbols/impl/FirFunctionSymbol.kt | 4 + .../provideDelegate/javaDelegate.fir.ir.txt | 4 +- 6 files changed, 173 insertions(+), 116 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index db18cbc85dd..0a8b3b64877 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -19,9 +19,7 @@ import org.jetbrains.kotlin.fir.builder.buildPackageDirective import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.buildFile import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty -import org.jetbrains.kotlin.fir.declarations.utils.isInline -import org.jetbrains.kotlin.fir.declarations.utils.isJava -import org.jetbrains.kotlin.fir.declarations.utils.isStatic +import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.extensions.FirExtensionApiInternals import org.jetbrains.kotlin.fir.extensions.declarationGenerators @@ -162,7 +160,7 @@ fun FirClassifierSymbol<*>.toSymbol( } context(Fir2IrComponents) -private fun FirBasedSymbol<*>.toSymbolForCall( +fun FirBasedSymbol<*>.toSymbolForCall( dispatchReceiver: FirExpression?, preferGetter: Boolean, explicitReceiver: FirExpression? = null, @@ -181,6 +179,19 @@ private fun FirBasedSymbol<*>.toSymbolForCall( else -> error("Unknown symbol: $this") } +fun FirReference.extractSymbolForCall(): FirBasedSymbol<*>? { + if (this !is FirResolvedNamedReference) { + return null + } + var symbol = resolvedSymbol + + if (symbol is FirCallableSymbol<*> && symbol.origin == FirDeclarationOrigin.SubstitutionOverride.CallSite) { + symbol = symbol.fir.unwrapUseSiteSubstitutionOverrides().symbol + } + + return symbol +} + context(Fir2IrComponents) @OptIn(ExperimentalContracts::class) fun FirReference.toSymbolForCall( @@ -193,16 +204,8 @@ fun FirReference.toSymbolForCall( contract { returnsNotNull() implies (this@toSymbolForCall is FirResolvedNamedReference) } - if (this !is FirResolvedNamedReference) { - return null - } - var symbol = resolvedSymbol - if (symbol is FirCallableSymbol<*> && symbol.origin == FirDeclarationOrigin.SubstitutionOverride.CallSite) { - symbol = symbol.fir.unwrapUseSiteSubstitutionOverrides().symbol - } - - return symbol.toSymbolForCall( + return extractSymbolForCall()?.toSymbolForCall( dispatchReceiver, preferGetter, explicitReceiver, @@ -219,9 +222,9 @@ private fun FirResolvedQualifier.toLookupTag(session: FirSession): ConeClassLike } context(Fir2IrComponents) -private fun FirCallableSymbol<*>.toSymbolForCall( +fun FirCallableSymbol<*>.toSymbolForCall( dispatchReceiver: FirExpression?, - preferGetter: Boolean, + preferGetter: Boolean = true, // Note: in fact LHS for callable references and explicit receiver for normal qualified accesses explicitReceiver: FirExpression? = null, isDelegate: Boolean = false, diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index 34922de03d0..de12513a2db 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall import org.jetbrains.kotlin.fir.references.* import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.* +import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol import org.jetbrains.kotlin.fir.resolve.calls.getExpectedType import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor @@ -71,24 +72,18 @@ class CallAndReferenceGenerator( ): IrExpression { val type = approximateFunctionReferenceType(callableReferenceAccess.resolvedType).toIrType() - val callableSymbol = callableReferenceAccess.calleeReference.toResolvedCallableSymbol() - if (callableSymbol?.origin == FirDeclarationOrigin.SamConstructor) { + val firSymbol = callableReferenceAccess.calleeReference.extractSymbolForCall() + if (firSymbol?.origin == FirDeclarationOrigin.SamConstructor) { assert(explicitReceiverExpression == null) { "Fun interface constructor reference should be unbound: ${explicitReceiverExpression?.dump()}" } return adapterGenerator.generateFunInterfaceConstructorReference( callableReferenceAccess, - callableSymbol as FirSyntheticFunctionSymbol, + firSymbol as FirSyntheticFunctionSymbol, type ) } - val symbol = callableReferenceAccess.calleeReference.toSymbolForCall( - callableReferenceAccess.dispatchReceiver, - explicitReceiver = callableReferenceAccess.explicitReceiver, - isDelegate = isDelegate, - isReference = true - ) // val x by y -> // val `x$delegate` = y // val x get() = `x$delegate`.getValue(this, ::x) @@ -96,90 +91,135 @@ class CallAndReferenceGenerator( val isForDelegate = callableReferenceAccess.source?.kind == KtFakeSourceElementKind.DelegatedPropertyAccessor val origin = if (isForDelegate) IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE else null return callableReferenceAccess.convertWithOffsets { startOffset, endOffset -> - when (symbol) { - is IrPropertySymbol -> { - val referencedPropertyGetterSymbol = declarationStorage.findGetterOfProperty(symbol) - val referencedPropertySetterSymbol = runIf(callableReferenceAccess.resolvedType.isKMutableProperty(session)) { - declarationStorage.findSetterOfProperty(symbol) - } - val backingFieldSymbol = when { - referencedPropertyGetterSymbol != null -> null - else -> declarationStorage.findBackingFieldOfProperty(symbol) - } - IrPropertyReferenceImpl( - startOffset, endOffset, type, symbol, - typeArgumentsCount = callableReferenceAccess.toResolvedCallableSymbol()?.fir?.typeParameters?.size ?: 0, - field = backingFieldSymbol, - getter = referencedPropertyGetterSymbol, - setter = referencedPropertySetterSymbol, - origin = origin - ).applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess, explicitReceiverExpression) - } - is IrLocalDelegatedPropertySymbol -> { - IrLocalDelegatedPropertyReferenceImpl( - startOffset, endOffset, type, symbol, - delegate = declarationStorage.findDelegateVariableOfProperty(symbol), - getter = declarationStorage.findGetterOfProperty(symbol), - setter = declarationStorage.findSetterOfProperty(symbol), - origin = origin - ) - } + fun FirCallableSymbol<*>.toSymbolForCall(): IrSymbol? { + return toSymbolForCall( + callableReferenceAccess.dispatchReceiver, + explicitReceiver = callableReferenceAccess.explicitReceiver, + isDelegate = isDelegate, + isReference = true + ) + } - is IrFieldSymbol -> { - val field = (callableSymbol as FirFieldSymbol).fir - val propertySymbol = declarationStorage.findPropertyForBackingField(symbol) - ?: run { - // In case of [IrField] without the corresponding property, we've created it directly from [FirField]. - // Since it's used as a field reference, we need a bogus property as a placeholder. - val firSymbol = - (callableReferenceAccess.calleeReference as FirResolvedNamedReference).resolvedSymbol as FirFieldSymbol - @OptIn(IrSymbolInternals::class) - declarationStorage.getOrCreateIrPropertyByPureField(firSymbol.fir, symbol.owner.parent).symbol - } - IrPropertyReferenceImpl( - startOffset, endOffset, type, - propertySymbol, - typeArgumentsCount = 0, - field = symbol, - getter = runIf(!field.isStatic) { declarationStorage.findGetterOfProperty(propertySymbol) }, - setter = runIf(!field.isStatic) { declarationStorage.findSetterOfProperty(propertySymbol) }, - origin - ).applyReceivers(callableReferenceAccess, explicitReceiverExpression) + fun convertReferenceToRegularProperty(propertySymbol: FirPropertySymbol): IrExpression? { + val irPropertySymbol = propertySymbol.toSymbolForCall() as? IrPropertySymbol ?: return null + val referencedPropertyGetterSymbol = declarationStorage.findGetterOfProperty(irPropertySymbol) + val referencedPropertySetterSymbol = runIf(callableReferenceAccess.resolvedType.isKMutableProperty(session)) { + declarationStorage.findSetterOfProperty(irPropertySymbol) } + val backingFieldSymbol = when { + referencedPropertyGetterSymbol != null -> null + else -> declarationStorage.findBackingFieldOfProperty(irPropertySymbol) + } + return IrPropertyReferenceImpl( + startOffset, endOffset, type, irPropertySymbol, + typeArgumentsCount = callableReferenceAccess.toResolvedCallableSymbol()?.fir?.typeParameters?.size ?: 0, + field = backingFieldSymbol, + getter = referencedPropertyGetterSymbol, + setter = referencedPropertySetterSymbol, + origin = origin + ).applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess, explicitReceiverExpression) + } - is IrFunctionSymbol -> { - require(type is IrSimpleType) - var function = callableReferenceAccess.calleeReference.toResolvedFunctionSymbol()!!.fir - if (function is FirConstructor) { - // The number of type parameters of typealias constructor may mismatch with that number in the original constructor. - // And for IR, we need to use the original constructor as a source of truth - function = function.originalConstructorIfTypeAlias ?: function - } - if (adapterGenerator.needToGenerateAdaptedCallableReference(callableReferenceAccess, type, function)) { - // Receivers are being applied inside - with(adapterGenerator) { - // TODO: Figure out why `adaptedType` is different from the `type`? - val adaptedType = callableReferenceAccess.resolvedType.toIrType() as IrSimpleType - generateAdaptedCallableReference(callableReferenceAccess, explicitReceiverExpression, symbol, adaptedType) - } - } else { - IrFunctionReferenceImpl( - startOffset, endOffset, type, symbol, - typeArgumentsCount = function.typeParameters.size, - valueArgumentsCount = function.valueParameters.size + function.contextReceivers.size, - reflectionTarget = symbol - ).applyTypeArguments(callableReferenceAccess) - .applyReceivers(callableReferenceAccess, explicitReceiverExpression) + fun convertReferenceToSyntheticProperty(propertySymbol: FirSimpleSyntheticPropertySymbol): IrExpression? { + val irPropertySymbol = callablesGenerator.generateIrPropertyForSyntheticPropertyReference( + propertySymbol, + conversionScope.parentFromStack() + ).symbol + val property = propertySymbol.syntheticProperty + val referencedPropertyGetterSymbol = declarationStorage.getIrFunctionSymbol(property.getter.delegate.unwrapUseSiteSubstitutionOverrides().symbol) as? IrSimpleFunctionSymbol ?: return null + val referencedPropertySetterSymbol = runIf(callableReferenceAccess.resolvedType.isKMutableProperty(session)) { + property.setter?.delegate?.unwrapUseSiteSubstitutionOverrides()?.symbol?.let { + declarationStorage.getIrFunctionSymbol(it) as? IrSimpleFunctionSymbol? ?: return null } } + return IrPropertyReferenceImpl( + startOffset, endOffset, type, irPropertySymbol, + typeArgumentsCount = callableReferenceAccess.toResolvedCallableSymbol()?.fir?.typeParameters?.size ?: 0, + field = null, + getter = referencedPropertyGetterSymbol, + setter = referencedPropertySetterSymbol, + origin = origin + ).applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess, explicitReceiverExpression) + } - else -> { - IrErrorCallExpressionImpl( - startOffset, endOffset, type, "Unsupported callable reference: ${callableReferenceAccess.render()}" - ) + fun convertReferenceToLocalDelegatedProperty(propertySymbol: FirPropertySymbol): IrExpression? { + val irPropertySymbol = propertySymbol.toSymbolForCall() as? IrLocalDelegatedPropertySymbol ?: return null + + return IrLocalDelegatedPropertyReferenceImpl( + startOffset, endOffset, type, irPropertySymbol, + delegate = declarationStorage.findDelegateVariableOfProperty(irPropertySymbol), + getter = declarationStorage.findGetterOfProperty(irPropertySymbol), + setter = declarationStorage.findSetterOfProperty(irPropertySymbol), + origin = origin + ) + } + + fun convertReferenceToField(fieldSymbol: FirFieldSymbol): IrExpression? { + val irFieldSymbol = fieldSymbol.toSymbolForCall() as? IrFieldSymbol ?: return null + + val field = fieldSymbol.fir + val propertySymbol = declarationStorage.findPropertyForBackingField(irFieldSymbol) + ?: run { + // In case of [IrField] without the corresponding property, we've created it directly from [FirField]. + // Since it's used as a field reference, we need a bogus property as a placeholder. + @OptIn(IrSymbolInternals::class) + declarationStorage.getOrCreateIrPropertyByPureField(fieldSymbol.fir, irFieldSymbol.owner.parent).symbol + } + return IrPropertyReferenceImpl( + startOffset, endOffset, type, + propertySymbol, + typeArgumentsCount = 0, + field = irFieldSymbol, + getter = runIf(!field.isStatic) { declarationStorage.findGetterOfProperty(propertySymbol) }, + setter = runIf(!field.isStatic) { declarationStorage.findSetterOfProperty(propertySymbol) }, + origin + ).applyReceivers(callableReferenceAccess, explicitReceiverExpression) + } + + fun convertReferenceToFunction(functionSymbol: FirFunctionSymbol<*>): IrExpression? { + val irFunctionSymbol = functionSymbol.toSymbolForCall() as? IrFunctionSymbol ?: return null + + require(type is IrSimpleType) + var function = callableReferenceAccess.calleeReference.toResolvedFunctionSymbol()!!.fir + if (function is FirConstructor) { + // The number of type parameters of typealias constructor may mismatch with that number in the original constructor. + // And for IR, we need to use the original constructor as a source of truth + function = function.originalConstructorIfTypeAlias ?: function + } + return if (adapterGenerator.needToGenerateAdaptedCallableReference(callableReferenceAccess, type, function)) { + // Receivers are being applied inside + with(adapterGenerator) { + // TODO: Figure out why `adaptedType` is different from the `type`? + val adaptedType = callableReferenceAccess.resolvedType.toIrType() as IrSimpleType + generateAdaptedCallableReference(callableReferenceAccess, explicitReceiverExpression, irFunctionSymbol, adaptedType) + } + } else { + IrFunctionReferenceImpl( + startOffset, endOffset, type, irFunctionSymbol, + typeArgumentsCount = function.typeParameters.size, + valueArgumentsCount = function.valueParameters.size + function.contextReceivers.size, + reflectionTarget = irFunctionSymbol + ).applyTypeArguments(callableReferenceAccess) + .applyReceivers(callableReferenceAccess, explicitReceiverExpression) } } + + when (firSymbol) { + is FirSimpleSyntheticPropertySymbol -> convertReferenceToSyntheticProperty(firSymbol) + is FirPropertySymbol -> when { + firSymbol.isLocal -> when { + firSymbol.hasDelegate -> convertReferenceToLocalDelegatedProperty(firSymbol) + else -> null + } + else -> convertReferenceToRegularProperty(firSymbol) + } + is FirFunctionSymbol<*> -> convertReferenceToFunction(firSymbol) + is FirFieldSymbol -> convertReferenceToField(firSymbol) + else -> null + } ?: IrErrorCallExpressionImpl( + startOffset, endOffset, type, "Unsupported callable reference: ${callableReferenceAccess.render()}" + ) } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt index fd1a5a6d80b..18b4a528173 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt @@ -84,21 +84,6 @@ class FakeOverrideGenerator( // This parameter is only needed for data-class methods that is irrelevant for lazy library classes realDeclarationSymbols = emptySet() ) - // Only add synthetic properties if no real properties were found. This can happen in a mixed hierarchy when a Java class - // inherits an @JvmField property. When a Kotlin class extends that Java class, CONFLICTING_INHERITED_JVM_DECLARATIONS will be - // reported otherwise. See KT-56538. - if (none { it is IrProperty }) { - FirSyntheticPropertiesScope.createIfSyntheticNamesProviderIsDefined(session, firClass.defaultType(), useSiteMemberScope)?.let { - generateFakeOverridesForName( - irClass, it, name, firClass, - // We pass result = null so that the IR declaration is not added to the class' list of declarations - // but is still cached in the declaration storage. - result = null, - // This parameter is only needed for data-class methods that is irrelevant for lazy library classes - realDeclarationSymbols = emptySet() - ) - } - } val staticScope = firClass.scopeProvider.getStaticMemberScopeForCallables(firClass, session, scopeSession) if (staticScope != null) { generateFakeOverridesForName( diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt index 07a75edad2a..fb4a40cf12c 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol +import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject import org.jetbrains.kotlin.fir.resolve.isKFunctionInvoke import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag @@ -386,6 +387,30 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi return initializer } + fun generateIrPropertyForSyntheticPropertyReference( + propertySymbol: FirSimpleSyntheticPropertySymbol, + parent: IrDeclarationParent, + ): IrProperty { + val property = propertySymbol.fir + return irFactory.createProperty( + startOffset = UNDEFINED_OFFSET, + endOffset = UNDEFINED_OFFSET, + origin = IrDeclarationOrigin.SYNTHETIC_JAVA_PROPERTY_DELEGATE, + name = property.name, + visibility = visibilityConverter.convertToDescriptorVisibility(property.visibility), + modality = property.modality ?: Modality.FINAL, + symbol = IrPropertySymbolImpl(), + isVar = property.isVar, + isConst = false, + isLateinit = property.isLateInit, + isDelegated = property.delegate != null, + isExternal = property.isExternal, + isExpect = property.isExpect + ).also { + it.parent = parent + } + } + // ------------------------------------ property accessors ------------------------------------ private fun createIrPropertyAccessor( diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirFunctionSymbol.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirFunctionSymbol.kt index 5f04d88c879..77d86c50ee6 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirFunctionSymbol.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirFunctionSymbol.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.symbols.impl import org.jetbrains.kotlin.fir.FirLabel import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.references.toResolvedConstructorSymbol @@ -81,6 +82,9 @@ class FirConstructorSymbol(callableId: CallableId) : FirFunctionSymbol visibility:private [final,static] EXPRESSION_BODY - PROPERTY_REFERENCE 'public open foo: @[FlexibleNullability] kotlin.String?' field=null getter='public open fun (): @[FlexibleNullability] kotlin.String? declared in .J' setter='public open fun (s: @[FlexibleNullability] kotlin.String?): kotlin.Unit declared in .J' type=kotlin.reflect.KMutableProperty0<@[FlexibleNullability] kotlin.String?> origin=null + PROPERTY_REFERENCE 'public open foo' field=null getter='public open fun getFoo (): @[FlexibleNullability] kotlin.String? declared in .J' setter='public open fun setFoo (s: @[FlexibleNullability] kotlin.String?): kotlin.Unit declared in .J' type=kotlin.reflect.KMutableProperty0<@[FlexibleNullability] kotlin.String?> origin=null $this: CONSTRUCTOR_CALL 'public constructor () declared in .J' type=.J origin=null FUN DELEGATED_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:@[FlexibleNullability] kotlin.String? correspondingProperty: PROPERTY name:p1 visibility:public modality:FINAL [delegated,var] @@ -27,7 +27,7 @@ FILE fqName:k fileName:/box.kt PROPERTY name:p2 visibility:public modality:FINAL [delegated,var] FIELD PROPERTY_DELEGATE name:p2$delegate type:kotlin.reflect.KMutableProperty0<@[FlexibleNullability] kotlin.String?> visibility:private [final,static] EXPRESSION_BODY - PROPERTY_REFERENCE 'public open foo: @[FlexibleNullability] kotlin.String?' field=null getter='public open fun (): @[FlexibleNullability] kotlin.String? declared in .J' setter='public open fun (s: @[FlexibleNullability] kotlin.String?): kotlin.Unit declared in .J' type=kotlin.reflect.KMutableProperty0<@[FlexibleNullability] kotlin.String?> origin=null + PROPERTY_REFERENCE 'public open foo' field=null getter='public open fun getFoo (): @[FlexibleNullability] kotlin.String? declared in .J' setter='public open fun setFoo (s: @[FlexibleNullability] kotlin.String?): kotlin.Unit declared in .J' type=kotlin.reflect.KMutableProperty0<@[FlexibleNullability] kotlin.String?> origin=null $this: CONSTRUCTOR_CALL 'public constructor () declared in .J' type=.J origin=null FUN DELEGATED_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:@[FlexibleNullability] kotlin.String? correspondingProperty: PROPERTY name:p2 visibility:public modality:FINAL [delegated,var]