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 {
|
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement {
|
||||||
val explicitReceiverExpression = convertToIrReceiverExpression(
|
val explicitReceiverExpression = convertToIrReceiverExpression(
|
||||||
callableReferenceAccess.explicitReceiver, callableReferenceAccess.calleeReference, callableReferenceMode = true
|
callableReferenceAccess.explicitReceiver, callableReferenceAccess.calleeReference, callableReferenceAccess
|
||||||
)
|
)
|
||||||
return callGenerator.convertToIrCallableReference(callableReferenceAccess, explicitReceiverExpression)
|
return callGenerator.convertToIrCallableReference(callableReferenceAccess, explicitReceiverExpression)
|
||||||
}
|
}
|
||||||
@@ -547,11 +547,11 @@ class Fir2IrVisitor(
|
|||||||
private fun convertToIrReceiverExpression(
|
private fun convertToIrReceiverExpression(
|
||||||
expression: FirExpression?,
|
expression: FirExpression?,
|
||||||
calleeReference: FirReference,
|
calleeReference: FirReference,
|
||||||
callableReferenceMode: Boolean = false
|
callableReferenceAccess: FirCallableReferenceAccess? = null
|
||||||
): IrExpression? {
|
): IrExpression? {
|
||||||
return when (expression) {
|
return when (expression) {
|
||||||
null -> null
|
null -> null
|
||||||
is FirResolvedQualifier -> callGenerator.convertToGetObject(expression, callableReferenceMode)
|
is FirResolvedQualifier -> callGenerator.convertToGetObject(expression, callableReferenceAccess)
|
||||||
is FirExpressionWithSmartcast -> convertToImplicitCastExpression(expression, calleeReference)
|
is FirExpressionWithSmartcast -> convertToImplicitCastExpression(expression, calleeReference)
|
||||||
is FirFunctionCall, is FirThisReceiverExpression, is FirCallableReferenceAccess -> convertToIrExpression(expression)
|
is FirFunctionCall, is FirThisReceiverExpression, is FirCallableReferenceAccess -> convertToIrExpression(expression)
|
||||||
else -> if (expression is FirQualifiedAccessExpression && expression.explicitReceiver == null) {
|
else -> if (expression is FirQualifiedAccessExpression && expression.explicitReceiver == null) {
|
||||||
|
|||||||
+27
-6
@@ -361,14 +361,35 @@ class CallAndReferenceGenerator(
|
|||||||
}.applyCallArguments(annotationCall, annotationMode = true)
|
}.applyCallArguments(annotationCall, annotationMode = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun convertToGetObject(qualifier: FirResolvedQualifier): IrExpression {
|
internal fun convertToGetObject(qualifier: FirResolvedQualifier): IrExpression {
|
||||||
return convertToGetObject(qualifier, callableReferenceMode = false)!!
|
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)
|
val classSymbol = (qualifier.typeRef.coneType as? ConeClassLikeType)?.lookupTag?.toSymbol(session)
|
||||||
if (callableReferenceMode && classSymbol is FirRegularClassSymbol) {
|
if (callableReferenceAccess != null && classSymbol is FirRegularClassSymbol) {
|
||||||
if (classSymbol.classId != qualifier.classId) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -612,7 +633,7 @@ class CallAndReferenceGenerator(
|
|||||||
return explicitReceiverExpression
|
return explicitReceiverExpression
|
||||||
}
|
}
|
||||||
if (firReceiver is FirResolvedQualifier) {
|
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) }
|
return firReceiver.takeIf { it !is FirNoReceiverExpression }?.let { visitor.convertToIrExpression(it) }
|
||||||
?: explicitReceiverExpression
|
?: explicitReceiverExpression
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
package org.jetbrains.kotlin.fir.symbols.impl
|
package org.jetbrains.kotlin.fir.symbols.impl
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
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.FirMemberDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
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<*>.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 {
|
inline fun <reified E : FirCallableSymbol<*>> E.unwrapSubstitutionOverrides(): E {
|
||||||
var current = this
|
var current = this
|
||||||
while (current.overriddenSymbol != null) {
|
while (current.overriddenSymbol != null) {
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// JVM_TARGET: 1.8
|
// JVM_TARGET: 1.8
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
|
|||||||
Reference in New Issue
Block a user