[FIR2IR] Convert explicit receiver in advance
This commit is contained in:
@@ -265,7 +265,8 @@ class Fir2IrVisitor(
|
||||
} else {
|
||||
functionCall
|
||||
}
|
||||
return callGenerator.convertToIrCall(convertibleCall, convertibleCall.typeRef)
|
||||
val explicitReceiverExpression = convertToIrReceiverExpression(functionCall.explicitReceiver)
|
||||
return callGenerator.convertToIrCall(convertibleCall, convertibleCall.typeRef, explicitReceiverExpression)
|
||||
}
|
||||
|
||||
private fun FirFunctionCall.resolvedNamedFunctionSymbol(): FirNamedFunctionSymbol? {
|
||||
@@ -278,7 +279,8 @@ class Fir2IrVisitor(
|
||||
}
|
||||
|
||||
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: Any?): IrElement {
|
||||
return callGenerator.convertToIrCall(qualifiedAccessExpression, qualifiedAccessExpression.typeRef)
|
||||
val explicitReceiverExpression = convertToIrReceiverExpression(qualifiedAccessExpression.explicitReceiver)
|
||||
return callGenerator.convertToIrCall(qualifiedAccessExpression, qualifiedAccessExpression.typeRef, explicitReceiverExpression)
|
||||
}
|
||||
|
||||
override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression, data: Any?): IrElement {
|
||||
@@ -333,11 +335,15 @@ class Fir2IrVisitor(
|
||||
}
|
||||
|
||||
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement {
|
||||
return callGenerator.convertToIrCallableReference(callableReferenceAccess)
|
||||
val explicitReceiverExpression = convertToIrReceiverExpression(
|
||||
callableReferenceAccess.explicitReceiver, callableReferenceMode = true
|
||||
)
|
||||
return callGenerator.convertToIrCallableReference(callableReferenceAccess, explicitReceiverExpression)
|
||||
}
|
||||
|
||||
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: Any?): IrElement {
|
||||
return callGenerator.convertToIrSetCall(variableAssignment)
|
||||
val explicitReceiverExpression = convertToIrReceiverExpression(variableAssignment.explicitReceiver)
|
||||
return callGenerator.convertToIrSetCall(variableAssignment, explicitReceiverExpression)
|
||||
}
|
||||
|
||||
override fun <T> visitConstExpression(constExpression: FirConstExpression<T>, data: Any?): IrElement =
|
||||
@@ -365,6 +371,14 @@ class Fir2IrVisitor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertToIrReceiverExpression(expression: FirExpression?, callableReferenceMode: Boolean = false): IrExpression? {
|
||||
return when (expression) {
|
||||
null -> null
|
||||
is FirResolvedQualifier -> callGenerator.convertToGetObject(expression, callableReferenceMode)
|
||||
else -> convertToIrExpression(expression)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirBlock.mapToIrStatements(): List<IrStatement?> {
|
||||
val irRawStatements = statements.map { it.toIrStatement() }
|
||||
val result = mutableListOf<IrStatement?>()
|
||||
|
||||
+40
-27
@@ -44,7 +44,10 @@ internal class CallAndReferenceGenerator(
|
||||
|
||||
private fun ConeKotlinType.toIrType(): IrType = with(typeConverter) { toIrType() }
|
||||
|
||||
fun convertToIrCallableReference(callableReferenceAccess: FirCallableReferenceAccess): IrExpression {
|
||||
fun convertToIrCallableReference(
|
||||
callableReferenceAccess: FirCallableReferenceAccess,
|
||||
explicitReceiverExpression: IrExpression?
|
||||
): IrExpression {
|
||||
val symbol = callableReferenceAccess.calleeReference.toSymbol(session, classifierStorage, declarationStorage, conversionScope)
|
||||
val type = callableReferenceAccess.typeRef.toIrType()
|
||||
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
|
||||
@@ -91,22 +94,27 @@ internal class CallAndReferenceGenerator(
|
||||
)
|
||||
}
|
||||
}
|
||||
}.applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess)
|
||||
}.applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess, explicitReceiverExpression)
|
||||
}
|
||||
|
||||
fun convertToIrCall(qualifiedAccess: FirQualifiedAccess, typeRef: FirTypeRef): IrExpression {
|
||||
fun convertToIrCall(
|
||||
qualifiedAccess: FirQualifiedAccess,
|
||||
typeRef: FirTypeRef,
|
||||
explicitReceiverExpression: IrExpression?
|
||||
): IrExpression {
|
||||
val explicitReceiver = qualifiedAccess.explicitReceiver
|
||||
if (!qualifiedAccess.safe || explicitReceiver == null) {
|
||||
return convertToUnsafeIrCall(qualifiedAccess, typeRef)
|
||||
return convertToUnsafeIrCall(qualifiedAccess, typeRef, explicitReceiverExpression)
|
||||
}
|
||||
return qualifiedAccess.convertWithOffsets { startOffset, endOffset ->
|
||||
val type = typeRef.toIrType()
|
||||
val callableSymbol = (qualifiedAccess.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirCallableSymbol<*>
|
||||
val typeShouldBeNotNull = callableSymbol?.fir?.returnTypeRef?.coneTypeSafe<ConeKotlinType>()?.isNullable == false
|
||||
val unsafeIrCall = convertToUnsafeIrCall(qualifiedAccess, typeRef, makeNotNull = typeShouldBeNotNull)
|
||||
val unsafeIrCall = convertToUnsafeIrCall(
|
||||
qualifiedAccess, typeRef, explicitReceiverExpression, makeNotNull = typeShouldBeNotNull
|
||||
)
|
||||
IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.SAFE_CALL).apply {
|
||||
val receiver = visitor.convertToIrExpression(explicitReceiver)
|
||||
val receiverVariable = declarationStorage.declareTemporaryVariable(receiver).apply {
|
||||
val receiverVariable = declarationStorage.declareTemporaryVariable(explicitReceiverExpression!!).apply {
|
||||
parent = conversionScope.parentFromStack()
|
||||
}
|
||||
statements += receiverVariable
|
||||
@@ -135,7 +143,7 @@ internal class CallAndReferenceGenerator(
|
||||
}
|
||||
|
||||
private fun convertToUnsafeIrCall(
|
||||
qualifiedAccess: FirQualifiedAccess, typeRef: FirTypeRef, makeNotNull: Boolean = false
|
||||
qualifiedAccess: FirQualifiedAccess, typeRef: FirTypeRef, explicitReceiverExpression: IrExpression?, makeNotNull: Boolean = false
|
||||
): IrExpression {
|
||||
val type = typeRef.toIrType().let { if (makeNotNull) it.makeNotNull() else it }
|
||||
val symbol = qualifiedAccess.calleeReference.toSymbol(
|
||||
@@ -181,10 +189,11 @@ internal class CallAndReferenceGenerator(
|
||||
is IrEnumEntrySymbol -> IrGetEnumValueImpl(startOffset, endOffset, type, symbol)
|
||||
else -> generateErrorCallExpression(startOffset, endOffset, qualifiedAccess.calleeReference, type)
|
||||
}
|
||||
}.applyCallArguments(qualifiedAccess as? FirCall).applyTypeArguments(qualifiedAccess).applyReceivers(qualifiedAccess)
|
||||
}.applyCallArguments(qualifiedAccess as? FirCall)
|
||||
.applyTypeArguments(qualifiedAccess).applyReceivers(qualifiedAccess, explicitReceiverExpression)
|
||||
}
|
||||
|
||||
fun convertToIrSetCall(variableAssignment: FirVariableAssignment): IrExpression {
|
||||
fun convertToIrSetCall(variableAssignment: FirVariableAssignment, explicitReceiverExpression: IrExpression?): IrExpression {
|
||||
val type = irBuiltIns.unitType
|
||||
val calleeReference = variableAssignment.calleeReference
|
||||
val symbol = calleeReference.toSymbol(session, classifierStorage, declarationStorage, conversionScope, preferGetter = false)
|
||||
@@ -218,7 +227,7 @@ internal class CallAndReferenceGenerator(
|
||||
is IrVariableSymbol -> IrSetVariableImpl(startOffset, endOffset, type, symbol, assignedValue, origin)
|
||||
else -> generateErrorCallExpression(startOffset, endOffset, calleeReference)
|
||||
}
|
||||
}.applyTypeArguments(variableAssignment).applyReceivers(variableAssignment)
|
||||
}.applyTypeArguments(variableAssignment).applyReceivers(variableAssignment, explicitReceiverExpression)
|
||||
}
|
||||
|
||||
fun convertToIrConstructorCall(annotationCall: FirAnnotationCall): IrExpression {
|
||||
@@ -257,7 +266,7 @@ internal class CallAndReferenceGenerator(
|
||||
return convertToGetObject(qualifier, callableReferenceMode = false)!!
|
||||
}
|
||||
|
||||
private fun convertToGetObject(qualifier: FirResolvedQualifier, callableReferenceMode: Boolean): IrExpression? {
|
||||
internal fun convertToGetObject(qualifier: FirResolvedQualifier, callableReferenceMode: Boolean): IrExpression? {
|
||||
val typeRef = qualifier.typeRef as? FirResolvedTypeRef
|
||||
val classSymbol = (typeRef?.type as? ConeClassLikeType)?.lookupTag?.toSymbol(session)
|
||||
if (callableReferenceMode && classSymbol is FirRegularClassSymbol) {
|
||||
@@ -351,22 +360,26 @@ internal class CallAndReferenceGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirQualifiedAccess.findIrDispatchReceiver(): IrExpression? = findIrReceiver(isDispatch = true)
|
||||
private fun FirQualifiedAccess.findIrDispatchReceiver(explicitReceiverExpression: IrExpression?): IrExpression? =
|
||||
findIrReceiver(explicitReceiverExpression, isDispatch = true)
|
||||
|
||||
private fun FirQualifiedAccess.findIrExtensionReceiver(): IrExpression? = findIrReceiver(isDispatch = false)
|
||||
private fun FirQualifiedAccess.findIrExtensionReceiver(explicitReceiverExpression: IrExpression?): IrExpression? =
|
||||
findIrReceiver(explicitReceiverExpression, isDispatch = false)
|
||||
|
||||
private fun FirQualifiedAccess.findIrReceiver(isDispatch: Boolean): IrExpression? {
|
||||
private fun FirQualifiedAccess.findIrReceiver(explicitReceiverExpression: IrExpression?, isDispatch: Boolean): IrExpression? {
|
||||
val firReceiver = if (isDispatch) dispatchReceiver else extensionReceiver
|
||||
if (firReceiver == explicitReceiver) {
|
||||
// TODO: remove after fix of KT-35730 (temporary hack to prevent receiver duplication)
|
||||
if (!isDispatch && dispatchReceiver is FirNoReceiverExpression) {
|
||||
return visitor.convertToIrExpression(firReceiver)
|
||||
}
|
||||
return explicitReceiverExpression
|
||||
}
|
||||
if (firReceiver is FirResolvedQualifier) {
|
||||
return convertToGetObject(firReceiver, callableReferenceMode = this is FirCallableReferenceAccess)
|
||||
}
|
||||
return firReceiver.takeIf { it !is FirNoReceiverExpression }?.let { visitor.convertToIrExpression(it) }
|
||||
?: explicitReceiver?.let {
|
||||
if (it is FirResolvedQualifier) {
|
||||
return convertToGetObject(it, callableReferenceMode = this is FirCallableReferenceAccess)
|
||||
}
|
||||
visitor.convertToIrExpression(it)
|
||||
}
|
||||
?: explicitReceiverExpression
|
||||
?: run {
|
||||
if (this is FirCallableReferenceAccess) return null
|
||||
val name = if (isDispatch) "Dispatch" else "Extension"
|
||||
@@ -376,32 +389,32 @@ internal class CallAndReferenceGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrExpression.applyReceivers(qualifiedAccess: FirQualifiedAccess): IrExpression {
|
||||
private fun IrExpression.applyReceivers(qualifiedAccess: FirQualifiedAccess, explicitReceiverExpression: IrExpression?): IrExpression {
|
||||
return when (this) {
|
||||
is IrCallWithIndexedArgumentsBase -> {
|
||||
val ownerFunction = symbol.owner as? IrFunction
|
||||
if (ownerFunction?.dispatchReceiverParameter != null) {
|
||||
dispatchReceiver = qualifiedAccess.findIrDispatchReceiver()
|
||||
dispatchReceiver = qualifiedAccess.findIrDispatchReceiver(explicitReceiverExpression)
|
||||
}
|
||||
if (ownerFunction?.extensionReceiverParameter != null) {
|
||||
extensionReceiver = qualifiedAccess.findIrExtensionReceiver()
|
||||
extensionReceiver = qualifiedAccess.findIrExtensionReceiver(explicitReceiverExpression)
|
||||
}
|
||||
this
|
||||
}
|
||||
is IrNoArgumentsCallableReferenceBase -> {
|
||||
val ownerPropertyGetter = (symbol.owner as? IrProperty)?.getter
|
||||
if (ownerPropertyGetter?.dispatchReceiverParameter != null) {
|
||||
dispatchReceiver = qualifiedAccess.findIrDispatchReceiver()
|
||||
dispatchReceiver = qualifiedAccess.findIrDispatchReceiver(explicitReceiverExpression)
|
||||
}
|
||||
if (ownerPropertyGetter?.extensionReceiverParameter != null) {
|
||||
extensionReceiver = qualifiedAccess.findIrExtensionReceiver()
|
||||
extensionReceiver = qualifiedAccess.findIrExtensionReceiver(explicitReceiverExpression)
|
||||
}
|
||||
this
|
||||
}
|
||||
is IrFieldExpressionBase -> {
|
||||
val ownerField = symbol.owner
|
||||
if (!ownerField.isStatic) {
|
||||
receiver = qualifiedAccess.findIrDispatchReceiver()
|
||||
receiver = qualifiedAccess.findIrDispatchReceiver(explicitReceiverExpression)
|
||||
}
|
||||
this
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun Array<String>.test1(): Array<String> {
|
||||
val func = { i:Int -> this}
|
||||
return func(1)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class C {
|
||||
private fun String.ext() : String = ""
|
||||
private fun f() {}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class C{
|
||||
private var v : Int = 0
|
||||
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
interface Callback {
|
||||
fun invoke(): String
|
||||
}
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// KOTLIN_CONFIGURATION_FLAGS: CONSTRUCTOR_CALL_NORMALIZATION_MODE=enable
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +NormalizeConstructorCalls
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
open class A(val s: String)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
//WITH_REFLECT
|
||||
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
inline class R(private val r: Int) {
|
||||
fun test() = object {
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
inline class R(private val r: Int) {
|
||||
fun test() =
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
val d = 42.0
|
||||
val c = 'C'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
return (object { val r = "OK" } ?: null)!!.r
|
||||
}
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// !JVM_DEFAULT_MODE: all-compatibility
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// !JVM_DEFAULT_MODE: all
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class A {
|
||||
var a: String = "Fail"
|
||||
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class A(
|
||||
val a: String = object {
|
||||
override fun toString(): String = "OK"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
open class A {
|
||||
fun foo() = "OK"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
package test
|
||||
|
||||
private val prop = "O"
|
||||
|
||||
Reference in New Issue
Block a user