FIR2IR: set dispatch receiver for companion member reference
#KT-42132 fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
01d852c006
commit
3151fc8577
@@ -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) {
|
||||
|
||||
+27
-6
@@ -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
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_REFLECT
|
||||
|
||||
Reference in New Issue
Block a user