[FIR2IR] Correct 'this' conversion when it points to non-closest class

This commit is contained in:
Mikhail Glukhikh
2020-03-27 19:16:53 +03:00
parent 4388b30f87
commit a0978a50e8
13 changed files with 26 additions and 19 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.parentClassOrNull
class Fir2IrConversionScope {
private val parentStack = mutableListOf<IrDeclarationParent>()
@@ -76,6 +77,15 @@ class Fir2IrConversionScope {
fun parent(): IrDeclarationParent? = parentStack.lastOrNull()
fun dispatchReceiverParameter(irClass: IrClass): IrValueParameter? {
for (function in functionStack.asReversed()) {
if (function.parentClassOrNull == irClass) {
function.dispatchReceiverParameter?.let { return it }
}
}
return irClass.thisReceiver
}
fun lastDispatchReceiverParameter(): IrValueParameter? {
// Use the dispatch receiver of the containing/enclosing functions (from the last to the first)
for (function in functionStack.asReversed()) {
@@ -285,21 +285,20 @@ class Fir2IrVisitor(
override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression, data: Any?): IrElement {
val calleeReference = thisReceiverExpression.calleeReference
if (calleeReference.labelName == null && calleeReference.boundSymbol is FirClassSymbol) {
val boundSymbol = calleeReference.boundSymbol
if (calleeReference.labelName == null && boundSymbol is FirClassSymbol) {
// Object case
val firObject = (calleeReference.boundSymbol?.fir as? FirClass)?.takeIf {
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
}
if (firObject != null) {
val irObject = classifierStorage.getCachedIrClass(firObject)!!
if (irObject != conversionScope.lastClass()) {
val firClass = boundSymbol.fir as FirClass
val irClass = classifierStorage.getCachedIrClass(firClass)!!
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.classKind == ClassKind.OBJECT) {
if (irClass != conversionScope.lastClass()) {
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
IrGetObjectValueImpl(startOffset, endOffset, irObject.defaultType, irObject.symbol)
IrGetObjectValueImpl(startOffset, endOffset, irClass.defaultType, irClass.symbol)
}
}
}
val dispatchReceiver = conversionScope.lastDispatchReceiverParameter()
val dispatchReceiver = conversionScope.dispatchReceiverParameter(irClass)
if (dispatchReceiver != null) {
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
IrGetValueImpl(startOffset, endOffset, dispatchReceiver.type, dispatchReceiver.symbol)