[FIR2IR] Fix synthetic property reference in delegate expression

This commit is contained in:
Ivan Kochurkin
2022-01-25 21:06:18 +03:00
committed by teamcity
parent a398f7d6cb
commit 8a8bdc9ff4
7 changed files with 54 additions and 32 deletions
@@ -170,13 +170,15 @@ private fun FirBasedSymbol<*>.toSymbolForCall(
classifierStorage: Fir2IrClassifierStorage,
declarationStorage: Fir2IrDeclarationStorage,
preferGetter: Boolean,
explicitReceiver: FirExpression? = null
explicitReceiver: FirExpression? = null,
isDelegate: Boolean = false
) = when (this) {
is FirCallableSymbol<*> -> unwrapCallRepresentative().toSymbolForCall(
dispatchReceiver,
declarationStorage,
preferGetter,
explicitReceiver
explicitReceiver,
isDelegate
)
is FirClassifierSymbol<*> -> toSymbol(session, classifierStorage)
else -> error("Unknown symbol: $this")
@@ -189,11 +191,12 @@ fun FirReference.toSymbolForCall(
declarationStorage: Fir2IrDeclarationStorage,
conversionScope: Fir2IrConversionScope,
preferGetter: Boolean = true,
explicitReceiver: FirExpression? = null // Actual only for callable references
explicitReceiver: FirExpression? = null, // Actual only for callable references
isDelegate: Boolean = false
): IrSymbol? {
return when (this) {
is FirResolvedNamedReference ->
resolvedSymbol.toSymbolForCall(dispatchReceiver, session, classifierStorage, declarationStorage, preferGetter, explicitReceiver)
resolvedSymbol.toSymbolForCall(dispatchReceiver, session, classifierStorage, declarationStorage, preferGetter, explicitReceiver, isDelegate)
is FirErrorNamedReference ->
candidateSymbol?.toSymbolForCall(
dispatchReceiver,
@@ -201,7 +204,8 @@ fun FirReference.toSymbolForCall(
classifierStorage,
declarationStorage,
preferGetter,
explicitReceiver
explicitReceiver,
isDelegate
)
is FirThisReference -> {
when (val boundSymbol = boundSymbol) {
@@ -222,7 +226,8 @@ private fun FirCallableSymbol<*>.toSymbolForCall(
dispatchReceiver: FirExpression,
declarationStorage: Fir2IrDeclarationStorage,
preferGetter: Boolean,
explicitReceiver: FirExpression? = null
explicitReceiver: FirExpression? = null,
isDelegate: Boolean = false
): IrSymbol? {
val dispatchReceiverLookupTag = when (dispatchReceiver) {
is FirNoReceiverExpression -> {
@@ -242,15 +247,20 @@ private fun FirCallableSymbol<*>.toSymbolForCall(
}
return when (this) {
is FirSimpleSyntheticPropertySymbol -> {
(fir as? FirSyntheticProperty)?.let { syntheticProperty ->
val delegateSymbol = if (preferGetter) {
syntheticProperty.getter.delegate.symbol
} else {
syntheticProperty.setter?.delegate?.symbol
?: throw AssertionError("Written synthetic property must have a setter")
}
delegateSymbol.unwrapCallRepresentative().toSymbolForCall(dispatchReceiver, declarationStorage, preferGetter)
} ?: declarationStorage.getIrPropertySymbol(this)
if (isDelegate) {
declarationStorage.getIrPropertySymbol(this)
} else {
(fir as? FirSyntheticProperty)?.let { syntheticProperty ->
val delegateSymbol = if (preferGetter) {
syntheticProperty.getter.delegate.symbol
} else {
syntheticProperty.setter?.delegate?.symbol
?: throw AssertionError("Written synthetic property must have a setter")
}
delegateSymbol.unwrapCallRepresentative()
.toSymbolForCall(dispatchReceiver, declarationStorage, preferGetter, isDelegate = false)
} ?: declarationStorage.getIrPropertySymbol(this)
}
}
is FirFunctionSymbol<*> -> declarationStorage.getIrFunctionSymbol(this, dispatchReceiverLookupTag)
is FirPropertySymbol -> declarationStorage.getIrPropertySymbol(this, dispatchReceiverLookupTag)
@@ -270,7 +270,7 @@ class Fir2IrVisitor(
val delegate = variable.delegate
if (delegate != null) {
val irProperty = declarationStorage.createIrLocalDelegatedProperty(variable, conversionScope.parentFromStack())
irProperty.delegate.initializer = convertToIrExpression(delegate)
irProperty.delegate.initializer = convertToIrExpression(delegate, isDelegate = true)
conversionScope.withFunction(irProperty.getter) {
memberGenerator.convertFunctionContent(irProperty.getter, variable.getter, null)
}
@@ -456,7 +456,8 @@ class Fir2IrVisitor(
}
}
} else if (boundSymbol is FirCallableSymbol) {
val receiverSymbol = calleeReference.toSymbolForCall(FirNoReceiverExpression, session, classifierStorage, declarationStorage, conversionScope)
val receiverSymbol =
calleeReference.toSymbolForCall(FirNoReceiverExpression, session, classifierStorage, declarationStorage, conversionScope)
val receiver = (receiverSymbol?.owner as? IrSimpleFunction)?.extensionReceiverParameter
if (receiver != null) {
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
@@ -499,10 +500,18 @@ class Fir2IrVisitor(
}
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement {
return convertCallableReferenceAccess(callableReferenceAccess, false)
}
private fun convertCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, isDelegate: Boolean): IrElement {
val explicitReceiverExpression = convertToIrReceiverExpression(
callableReferenceAccess.explicitReceiver, callableReferenceAccess.calleeReference, callableReferenceAccess
)
return callGenerator.convertToIrCallableReference(callableReferenceAccess, explicitReceiverExpression)
return callGenerator.convertToIrCallableReference(
callableReferenceAccess,
explicitReceiverExpression,
isDelegate = isDelegate
)
}
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: Any?): IrElement {
@@ -525,7 +534,11 @@ class Fir2IrVisitor(
return accept(this@Fir2IrVisitor, null) as IrStatement
}
internal fun convertToIrExpression(expression: FirExpression, annotationMode: Boolean = false): IrExpression {
internal fun convertToIrExpression(
expression: FirExpression,
annotationMode: Boolean = false,
isDelegate: Boolean = false
): IrExpression {
return when (expression) {
is FirBlock -> expression.convertToIrExpressionOrBlock(
if (expression.source?.kind == KtFakeSourceElementKind.DesugaredForLoop) IrStatementOrigin.FOR_LOOP else null
@@ -541,10 +554,14 @@ class Fir2IrVisitor(
when (unwrappedExpression) {
is FirFunctionCall -> convertToIrCall(unwrappedExpression, annotationMode)
is FirArrayOfCall -> convertToArrayOfCall(unwrappedExpression, annotationMode)
is FirCallableReferenceAccess -> convertCallableReferenceAccess(unwrappedExpression, isDelegate)
else -> expression.accept(this, null) as IrExpression
}
} else {
expression.accept(this, null) as IrExpression
when (unwrappedExpression) {
is FirCallableReferenceAccess -> convertCallableReferenceAccess(unwrappedExpression, isDelegate)
else -> expression.accept(this, null) as IrExpression
}
}
}
}.let {
@@ -61,7 +61,8 @@ class CallAndReferenceGenerator(
fun convertToIrCallableReference(
callableReferenceAccess: FirCallableReferenceAccess,
explicitReceiverExpression: IrExpression?
explicitReceiverExpression: IrExpression?,
isDelegate: Boolean
): IrExpression {
val type = approximateFunctionReferenceType(callableReferenceAccess.typeRef.coneType).toIrType()
@@ -79,7 +80,7 @@ class CallAndReferenceGenerator(
val symbol = callableReferenceAccess.calleeReference.toSymbolForCall(
callableReferenceAccess.dispatchReceiver, session, classifierStorage, declarationStorage, conversionScope,
explicitReceiver = callableReferenceAccess.explicitReceiver
explicitReceiver = callableReferenceAccess.explicitReceiver, isDelegate = isDelegate
)
// val x by y ->
// val `x$delegate` = y
@@ -217,7 +217,7 @@ internal class ClassMemberGenerator(
if (initializer == null && initializerExpression != null) {
initializer = irFactory.createExpressionBody(
run {
val irExpression = visitor.convertToIrExpression(initializerExpression)
val irExpression = visitor.convertToIrExpression(initializerExpression, isDelegate = property.delegate != null)
if (property.delegate == null) {
with(visitor.implicitCastInserter) {
irExpression.cast(initializerExpression, initializerExpression.typeRef, property.returnTypeRef)
@@ -1,6 +1,4 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// FIR status: REPEATED_ANNOTATION at val y9; fir2ir produces an IrFunctionReference of type KProperty0 instead of an IrPropertyReference
// WITH_REFLECT
// WITH_STDLIB
// FILE: J.java
@@ -34,6 +32,6 @@ fun box(): String {
val y6 by @Anno() (((j2)::value))
val y7 by (@Anno() ((j2)::value))
val y8 by ((@Anno() (j2)::value))
val y9 by @Anno() ((@Anno() (j2)::value))
val y9 by @Anno() (j2)::value
return x + y
}
@@ -1,8 +1,4 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// FIR status: V
// Caused by: java.lang.AssertionError: Unexpected IR element found during code generation. Either code generation for it is not implemented, or it should have been lowered:
// FUNCTION_REFERENCE 'public open fun getFoo (): @[FlexibleNullability] kotlin.String? declared in <root>.J' type=kotlin.reflect.KMutableProperty0<@[FlexibleNullability] kotlin.String?> origin=null reflectionTarget=<same>
// WITH_STDLIB
// MODULE: jjj
@@ -2,7 +2,7 @@ FILE fqName:k fileName:/box.kt
PROPERTY name:p1 visibility:public modality:FINAL [delegated,var]
FIELD PROPERTY_DELEGATE name:p1$delegate type:kotlin.reflect.KMutableProperty0<@[FlexibleNullability] kotlin.String?> visibility:private [final,static]
EXPRESSION_BODY
FUNCTION_REFERENCE 'public open fun getFoo (): @[FlexibleNullability] kotlin.String? declared in <root>.J' type=kotlin.reflect.KMutableProperty0<@[FlexibleNullability] kotlin.String?> origin=null reflectionTarget=<same>
PROPERTY_REFERENCE 'public open foo: @[FlexibleNullability] kotlin.String? [var]' field=null getter='public open fun <get-foo> (): @[FlexibleNullability] kotlin.String? declared in <root>.J' setter='public open fun <set-foo> (<set-?>: @[FlexibleNullability] kotlin.String?): kotlin.Unit declared in <root>.J' type=kotlin.reflect.KMutableProperty0<@[FlexibleNullability] kotlin.String?> origin=null
$this: CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.J' type=<root>.J origin=null
FUN DELEGATED_PROPERTY_ACCESSOR name:<get-p1> visibility:public modality:FINAL <> () returnType:@[FlexibleNullability] kotlin.String?
correspondingProperty: PROPERTY name:p1 visibility:public modality:FINAL [delegated,var]
@@ -26,7 +26,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
FUNCTION_REFERENCE 'public open fun getFoo (): @[FlexibleNullability] kotlin.String? declared in <root>.J' type=kotlin.reflect.KMutableProperty0<@[FlexibleNullability] kotlin.String?> origin=null reflectionTarget=<same>
PROPERTY_REFERENCE 'public open foo: @[FlexibleNullability] kotlin.String? [var]' field=null getter='public open fun <get-foo> (): @[FlexibleNullability] kotlin.String? declared in <root>.J' setter='public open fun <set-foo> (<set-?>: @[FlexibleNullability] kotlin.String?): kotlin.Unit declared in <root>.J' type=kotlin.reflect.KMutableProperty0<@[FlexibleNullability] kotlin.String?> origin=null
$this: CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.J' type=<root>.J origin=null
FUN DELEGATED_PROPERTY_ACCESSOR name:<get-p2> visibility:public modality:FINAL <> () returnType:@[FlexibleNullability] kotlin.String?
correspondingProperty: PROPERTY name:p2 visibility:public modality:FINAL [delegated,var]