[FIR2IR] Get rid of IrSymbol.owner usages in generation of delegated bodies in DelegatedMemberGenerator

^KT-60924
This commit is contained in:
Dmitriy Novozhilov
2023-09-12 17:14:14 +03:00
committed by Space Team
parent 4164c0f7ef
commit 3a9567ad45
@@ -17,15 +17,15 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.lowerBoundIfFlexible
import org.jetbrains.kotlin.fir.types.resolvedType
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbolInternals import org.jetbrains.kotlin.ir.symbols.IrSymbolInternals
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
@@ -56,27 +56,37 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
private val bodiesInfo = mutableListOf<DeclarationBodyInfo>() private val bodiesInfo = mutableListOf<DeclarationBodyInfo>()
fun generateBodies() { fun generateBodies() {
for ((declaration, irField, delegateToSymbol, delegateToLookupTag) in bodiesInfo) { for ((declaration, irField, delegateToFirSymbol, delegateToLookupTag) in bodiesInfo) {
val callTypeCanBeNullable = Fir2IrImplicitCastInserter.typeCanBeEnhancedOrFlexibleNullable(delegateToSymbol.fir.returnTypeRef.coneType.fullyExpandedType(session)) val delegatedDeclarationType = delegateToFirSymbol.fir.returnTypeRef.coneType.fullyExpandedType(session)
val callTypeCanBeNullable = Fir2IrImplicitCastInserter.typeCanBeEnhancedOrFlexibleNullable(delegatedDeclarationType)
when (declaration) { when (declaration) {
is IrSimpleFunction -> { is IrSimpleFunction -> {
@OptIn(IrSymbolInternals::class) val delegateToIrFunctionSymbol = declarationStorage.getIrFunctionSymbol(
val member = declarationStorage.getIrFunctionSymbol( delegateToFirSymbol as FirNamedFunctionSymbol, delegateToLookupTag
delegateToSymbol as FirNamedFunctionSymbol, delegateToLookupTag ) as? IrSimpleFunctionSymbol ?: continue
).owner as? IrSimpleFunction ?: continue val body = createDelegateBody(
val body = createDelegateBody(irField, declaration, member, callTypeCanBeNullable) irField, declaration, delegateToFirSymbol.fir, delegateToIrFunctionSymbol,
callTypeCanBeNullable, isSetter = false
)
declaration.body = body declaration.body = body
} }
is IrProperty -> { is IrProperty -> {
@OptIn(IrSymbolInternals::class) val delegateToIrPropertySymbol = declarationStorage.getIrPropertySymbol(
val member = declarationStorage.getIrPropertySymbol( delegateToFirSymbol as FirPropertySymbol, delegateToLookupTag
delegateToSymbol as FirPropertySymbol, delegateToLookupTag ) as? IrPropertySymbol ?: continue
).owner as? IrProperty ?: continue val delegateToGetterSymbol = declarationStorage.findGetterOfProperty(delegateToIrPropertySymbol)!!
val getter = declaration.getter!! val getter = declaration.getter!!
getter.body = createDelegateBody(irField, getter, member.getter!!, callTypeCanBeNullable) getter.body = createDelegateBody(
irField, getter, delegateToFirSymbol.fir, delegateToGetterSymbol,
callTypeCanBeNullable, isSetter = false
)
if (declaration.isVar) { if (declaration.isVar) {
val delegateToSetterSymbol = declarationStorage.findSetterOfProperty(delegateToIrPropertySymbol)!!
val setter = declaration.setter!! val setter = declaration.setter!!
setter.body = createDelegateBody(irField, setter, member.setter!!, false) setter.body = createDelegateBody(
irField, setter, delegateToFirSymbol.fir, delegateToSetterSymbol,
callTypeCanBeNullable = false, isSetter = true
)
} }
} }
} }
@@ -222,22 +232,51 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
return delegateFunction return delegateFunction
} }
/**
* interface Base {
* fun foo(): String
* }
*
* class Impl : Base {
* override fun foo(): String { <-------------- [originalFirFunction], [originalFunctionSymbol]
* return "OK"
* }
* }
*
* class Delegated(impl: Impl) : Base by impl {
* private field delegate_xxx: Impl = impl <-------------- [irField]
* generated override fun foo(): String <-------------- [delegateFunction]
* }
*
*/
private fun createDelegateBody( private fun createDelegateBody(
irField: IrField, irField: IrField,
delegateFunction: IrSimpleFunction, delegateFunction: IrSimpleFunction,
superFunction: IrSimpleFunction, originalFirDeclaration: FirCallableDeclaration,
callTypeCanBeNullable: Boolean originalFunctionSymbol: IrSimpleFunctionSymbol,
callTypeCanBeNullable: Boolean,
isSetter: Boolean
): IrBlockBody { ): IrBlockBody {
val startOffset = SYNTHETIC_OFFSET val startOffset = SYNTHETIC_OFFSET
val endOffset = SYNTHETIC_OFFSET val endOffset = SYNTHETIC_OFFSET
val body = irFactory.createBlockBody(startOffset, endOffset) val body = irFactory.createBlockBody(startOffset, endOffset)
val typeOrigin = when {
originalFirDeclaration is FirPropertyAccessor && originalFirDeclaration.isSetter -> ConversionTypeOrigin.SETTER
else -> ConversionTypeOrigin.DEFAULT
}
val callReturnType = when (isSetter) {
false -> originalFirDeclaration.returnTypeRef.toIrType(typeOrigin)
true -> irBuiltIns.unitType
}
val irCall = IrCallImpl( val irCall = IrCallImpl(
startOffset, startOffset,
endOffset, endOffset,
superFunction.returnType, callReturnType,
superFunction.symbol, originalFunctionSymbol,
superFunction.typeParameters.size, originalFirDeclaration.typeParameters.size,
superFunction.valueParameters.size originalFirDeclaration.numberOfIrValueParameters(isSetter)
).apply { ).apply {
val getField = IrGetFieldImpl( val getField = IrGetFieldImpl(
startOffset, endOffset, startOffset, endOffset,
@@ -252,11 +291,13 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
// When the delegation expression has an intersection type, it is not guaranteed that the field will have the same type as the // When the delegation expression has an intersection type, it is not guaranteed that the field will have the same type as the
// dispatch receiver of the target method. Therefore, we need to check if a cast must be inserted. // dispatch receiver of the target method. Therefore, we need to check if a cast must be inserted.
val superFunctionParent = superFunction.parent as? IrClass val superFunctionDispatchReceiverType = originalFirDeclaration.dispatchReceiverType
dispatchReceiver = if (superFunctionParent == null || irField.type.isSubtypeOfClass(superFunctionParent.symbol)) { val superFunctionDispatchReceiverLookupTag = (superFunctionDispatchReceiverType as? ConeClassLikeType)?.lookupTag
val superFunctionParentSymbol = superFunctionDispatchReceiverLookupTag?.let { classifierStorage.findIrClass(it)?.symbol }
dispatchReceiver = if (superFunctionParentSymbol == null || irField.type.isSubtypeOfClass(superFunctionParentSymbol)) {
getField getField
} else { } else {
Fir2IrImplicitCastInserter.implicitCastOrExpression(getField, superFunction.dispatchReceiverParameter!!.type) Fir2IrImplicitCastInserter.implicitCastOrExpression(getField, superFunctionDispatchReceiverType.toIrType())
} }
extensionReceiver = extensionReceiver =
@@ -266,10 +307,10 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
delegateFunction.valueParameters.forEach { delegateFunction.valueParameters.forEach {
putValueArgument(it.index, IrGetValueImpl(startOffset, endOffset, it.type, it.symbol)) putValueArgument(it.index, IrGetValueImpl(startOffset, endOffset, it.type, it.symbol))
} }
superFunction.typeParameters.forEach { for (index in originalFirDeclaration.typeParameters.indices) {
putTypeArgument( putTypeArgument(
it.index, IrSimpleTypeImpl( index, IrSimpleTypeImpl(
delegateFunction.typeParameters[it.index].symbol, delegateFunction.typeParameters[index].symbol,
hasQuestionMark = false, hasQuestionMark = false,
arguments = emptyList(), arguments = emptyList(),
annotations = emptyList() annotations = emptyList()
@@ -282,7 +323,8 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
val irCastOrCall = val irCastOrCall =
if (callTypeCanBeNullable && !resultType.isNullable()) Fir2IrImplicitCastInserter.implicitNotNullCast(irCall) if (callTypeCanBeNullable && !resultType.isNullable()) Fir2IrImplicitCastInserter.implicitNotNullCast(irCall)
else irCall else irCall
if (superFunction.returnType.isUnit() || superFunction.returnType.isNothing()) { val originalDeclarationReturnType = originalFirDeclaration.returnTypeRef.coneType
if (isSetter || originalDeclarationReturnType.isUnit || originalDeclarationReturnType.isNothing) {
body.statements.add(irCastOrCall) body.statements.add(irCastOrCall)
} else { } else {
val irReturn = IrReturnImpl(startOffset, endOffset, irBuiltIns.nothingType, delegateFunction.symbol, irCastOrCall) val irReturn = IrReturnImpl(startOffset, endOffset, irBuiltIns.nothingType, delegateFunction.symbol, irCastOrCall)
@@ -291,6 +333,15 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
return body return body
} }
private fun FirCallableDeclaration.numberOfIrValueParameters(isSetter: Boolean): Int {
var result = contextReceivers.size
when {
this is FirFunction -> result += valueParameters.size
this is FirProperty && isSetter -> result += 1
}
return result
}
private fun generateDelegatedProperty( private fun generateDelegatedProperty(
subClass: IrClass, subClass: IrClass,
firSubClass: FirClass, firSubClass: FirClass,