FIR2IR: set dispatch receiver for companion member reference

#KT-42132 fixed
This commit is contained in:
Jinseong Jeon
2020-09-24 23:13:33 -07:00
committed by Mikhail Glukhikh
parent 01d852c006
commit 3151fc8577
4 changed files with 39 additions and 10 deletions
@@ -495,7 +495,7 @@ class Fir2IrVisitor(
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement {
val explicitReceiverExpression = convertToIrReceiverExpression(
callableReferenceAccess.explicitReceiver, callableReferenceAccess.calleeReference, callableReferenceMode = true
callableReferenceAccess.explicitReceiver, callableReferenceAccess.calleeReference, callableReferenceAccess
)
return callGenerator.convertToIrCallableReference(callableReferenceAccess, explicitReceiverExpression)
}
@@ -547,11 +547,11 @@ class Fir2IrVisitor(
private fun convertToIrReceiverExpression(
expression: FirExpression?,
calleeReference: FirReference,
callableReferenceMode: Boolean = false
callableReferenceAccess: FirCallableReferenceAccess? = null
): IrExpression? {
return when (expression) {
null -> null
is FirResolvedQualifier -> callGenerator.convertToGetObject(expression, callableReferenceMode)
is FirResolvedQualifier -> callGenerator.convertToGetObject(expression, callableReferenceAccess)
is FirExpressionWithSmartcast -> convertToImplicitCastExpression(expression, calleeReference)
is FirFunctionCall, is FirThisReceiverExpression, is FirCallableReferenceAccess -> convertToIrExpression(expression)
else -> if (expression is FirQualifiedAccessExpression && expression.explicitReceiver == null) {
@@ -361,14 +361,35 @@ class CallAndReferenceGenerator(
}.applyCallArguments(annotationCall, annotationMode = true)
}
fun convertToGetObject(qualifier: FirResolvedQualifier): IrExpression {
return convertToGetObject(qualifier, callableReferenceMode = false)!!
internal fun convertToGetObject(qualifier: FirResolvedQualifier): IrExpression {
return convertToGetObject(qualifier, null)!!
}
internal fun convertToGetObject(qualifier: FirResolvedQualifier, callableReferenceMode: Boolean): IrExpression? {
internal fun convertToGetObject(
qualifier: FirResolvedQualifier,
callableReferenceAccess: FirCallableReferenceAccess? = null
): IrExpression? {
val classSymbol = (qualifier.typeRef.coneType as? ConeClassLikeType)?.lookupTag?.toSymbol(session)
if (callableReferenceMode && classSymbol is FirRegularClassSymbol) {
if (classSymbol.classId != qualifier.classId) {
if (callableReferenceAccess != null && classSymbol is FirRegularClassSymbol) {
val classIdMatched = classSymbol.classId == qualifier.classId
val companionClassIdMatched = classSymbol.fir.isCompanion && classSymbol.classId.outerClassId == qualifier.classId
val lastClassIfCompanion = conversionScope.lastClass()?.takeIf { it.isCompanion }
val callable =
((callableReferenceAccess.calleeReference as FirResolvedNamedReference).resolvedSymbol as FirCallableSymbol<*>)
val companionMemberReferenceThatNeedsDispatchReceiver = companionClassIdMatched &&
// TODO: this can't cover delegated members. See bb test kt38664.kt
// Make sure the reference indeed refers to a member of that companion
classSymbol.fir.declarations.contains(callable.fir) &&
// Built-in extensions are stored in the companion, e.g., String.Companion.
// Make sure this is not a reference to an extension function.
!callable.isExtension &&
// Dispatch receiver is not needed if we're converting a callable reference inside that companion, e.g.,
// class Foo {
// companion object {
// val cp = Foo::member
// } }
lastClassIfCompanion?.classId != classSymbol.classId
if (!classIdMatched && !companionMemberReferenceThatNeedsDispatchReceiver) {
return null
}
}
@@ -612,7 +633,7 @@ class CallAndReferenceGenerator(
return explicitReceiverExpression
}
if (firReceiver is FirResolvedQualifier) {
return convertToGetObject(firReceiver, callableReferenceMode = this is FirCallableReferenceAccess)
return convertToGetObject(firReceiver, this as? FirCallableReferenceAccess)
}
return firReceiver.takeIf { it !is FirNoReceiverExpression }?.let { visitor.convertToIrExpression(it) }
?: explicitReceiverExpression
@@ -6,7 +6,9 @@
package org.jetbrains.kotlin.fir.symbols.impl
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.CallableId
@@ -21,6 +23,13 @@ abstract class FirCallableSymbol<D : FirCallableDeclaration<D>> : AbstractFirBas
val FirCallableSymbol<*>.isStatic: Boolean get() = (fir as? FirMemberDeclaration)?.status?.isStatic == true
val FirCallableSymbol<*>.isExtension: Boolean
get() = when (fir) {
is FirFunction -> fir.receiverTypeRef != null
is FirProperty -> fir.receiverTypeRef != null
else -> false
}
inline fun <reified E : FirCallableSymbol<*>> E.unwrapSubstitutionOverrides(): E {
var current = this
while (current.overriddenSymbol != null) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_REFLECT