JVM_IR: use correct dispatch receiver type in more references
#KT-46902 Fixed
This commit is contained in:
+6
@@ -2542,6 +2542,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt44483.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt46902.kt")
|
||||
public void testKt46902() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt46902.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
|
||||
+5
-39
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
@@ -125,43 +124,10 @@ private class InlineCallableReferenceToLambdaTransformer(
|
||||
}
|
||||
}
|
||||
|
||||
private class BoundReceiver(
|
||||
val receiverParameter: IrValueParameter,
|
||||
val receiverValue: IrExpression,
|
||||
val receiverType: IrType
|
||||
)
|
||||
|
||||
private fun IrCallableReference<*>.getBoundReceiver(): BoundReceiver? {
|
||||
val irFunction = when (this) {
|
||||
is IrFunctionReference ->
|
||||
this.symbol.owner
|
||||
is IrPropertyReference ->
|
||||
this.getter!!.owner
|
||||
else ->
|
||||
throw AssertionError("Unexpected callable reference: ${this.render()}")
|
||||
}
|
||||
|
||||
this.dispatchReceiver?.let { dispatchReceiver ->
|
||||
val dispatchReceiverParameter = irFunction.dispatchReceiverParameter
|
||||
?: throw AssertionError("Referenced declaration '${this.symbol.owner.render()}' has no dispatch receiver: ${this.dump()}")
|
||||
// NB in case of fake override of Base::foo in Child::foo, dispatch receiver type is Base,
|
||||
// but we in fact need Child (because of accessor generation).
|
||||
return BoundReceiver(dispatchReceiverParameter, dispatchReceiver, irFunction.parentAsClass.defaultType)
|
||||
}
|
||||
|
||||
this.extensionReceiver?.let { extensionReceiver ->
|
||||
val extensionReceiverParameter = irFunction.extensionReceiverParameter
|
||||
?: throw AssertionError("Referenced declaration '${this.symbol.owner.render()}' has no extension receiver: ${this.dump()}")
|
||||
return BoundReceiver(extensionReceiverParameter, extensionReceiver, extensionReceiverParameter.type)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun expandInlineFunctionReferenceToLambda(expression: IrCallableReference<*>, referencedFunction: IrFunction): IrExpression {
|
||||
val irBuilder = context.createJvmIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset)
|
||||
return irBuilder.irBlock(expression, IrStatementOrigin.LAMBDA) {
|
||||
val boundReceiver = expression.getBoundReceiver()
|
||||
val (receiverParameter, receiverValue) = expression.getArgumentsWithIr().singleOrNull() ?: (null to null)
|
||||
val argumentTypes = (expression.type as IrSimpleType).arguments.dropLast(1).map { (it as IrTypeProjection).type }
|
||||
|
||||
val function = context.irFactory.buildFun {
|
||||
@@ -173,8 +139,8 @@ private class InlineCallableReferenceToLambdaTransformer(
|
||||
isSuspend = referencedFunction.isSuspend
|
||||
}.apply {
|
||||
parent = currentDeclarationParent!!
|
||||
if (boundReceiver != null) {
|
||||
addExtensionReceiver(boundReceiver.receiverType)
|
||||
if (receiverValue != null) {
|
||||
addExtensionReceiver(receiverValue.type)
|
||||
}
|
||||
for ((index, argumentType) in argumentTypes.withIndex()) {
|
||||
addValueParameter {
|
||||
@@ -196,7 +162,7 @@ private class InlineCallableReferenceToLambdaTransformer(
|
||||
var unboundIndex = 0
|
||||
for (parameter in referencedFunction.explicitParameters) {
|
||||
when {
|
||||
boundReceiver?.receiverParameter == parameter ->
|
||||
receiverParameter == parameter ->
|
||||
irGet(extensionReceiverParameter!!)
|
||||
parameter.isVararg && unboundIndex < argumentTypes.size && parameter.type == valueParameters[unboundIndex].type ->
|
||||
irGet(valueParameters[unboundIndex++])
|
||||
@@ -225,7 +191,7 @@ private class InlineCallableReferenceToLambdaTransformer(
|
||||
origin = IrStatementOrigin.LAMBDA
|
||||
).apply {
|
||||
copyAttributes(expression)
|
||||
extensionReceiver = boundReceiver?.receiverValue
|
||||
extensionReceiver = receiverValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-11
@@ -354,15 +354,7 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
|
||||
val receiverFromField = boundReceiver?.let { irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type) }
|
||||
call.copyTypeArgumentsFrom(expression)
|
||||
call.dispatchReceiver = call.symbol.owner.dispatchReceiverParameter?.let {
|
||||
receiverFromField ?: irImplicitCast(
|
||||
irGet(arguments[1]),
|
||||
// In `C::x`, the receiver must be cast to `C` in order to put accessors for protected
|
||||
// properties in the correct class (box/syntheticAccessors/accessorForProtectedPropertyReference.kt).
|
||||
// However, if `x` is a property of C's superclass, the type of `dispatchReceiverParameter` is not `C`.
|
||||
// Since the receiver is not bound, the type of the property must be `KProperty1<C, ReturnType>` or
|
||||
// `KProperty2<C, ExtensionReceiver, ReturnType>`.
|
||||
((expression.type as IrSimpleType).arguments.first() as IrTypeProjection).type
|
||||
)
|
||||
receiverFromField ?: irImplicitCast(irGet(arguments[1]), expression.receiverType)
|
||||
}
|
||||
call.extensionReceiver = call.symbol.owner.extensionReceiverParameter?.let {
|
||||
if (call.symbol.owner.dispatchReceiverParameter == null)
|
||||
@@ -393,9 +385,9 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
|
||||
field.isStatic ->
|
||||
null
|
||||
expression.dispatchReceiver != null ->
|
||||
irImplicitCast(irGetField(irGet(arguments[0]), backingField), field.parentAsClass.defaultType)
|
||||
irImplicitCast(irGetField(irGet(arguments[0]), backingField), expression.receiverType)
|
||||
else ->
|
||||
irImplicitCast(irGet(arguments[1]), field.parentAsClass.defaultType)
|
||||
irImplicitCast(irGet(arguments[1]), expression.receiverType)
|
||||
}
|
||||
|
||||
referenceClass.addOverride(get!!) { arguments ->
|
||||
@@ -449,6 +441,12 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
|
||||
}
|
||||
}
|
||||
|
||||
// In `value::x`, using `value`'s type is fine; but in `C::x`, the type of the receiver has to be `C`.
|
||||
// This is *not* the type of `x`'s dispatch receiver if `x` is declared in a superclass of `C`, so we
|
||||
// extract `C` from the reference's type, which is either `KProperty1<C, R>` or `KProperty2<C, Extension, R>`.
|
||||
private val IrCallableReference<*>.receiverType
|
||||
get() = dispatchReceiver?.type ?: ((type as IrSimpleType).arguments.first() as IrTypeProjection).type
|
||||
|
||||
private fun IrCallableReference<*>.getBoundReceiver(): IrExpression? {
|
||||
val callee = symbol.owner
|
||||
return if (callee is IrDeclaration && callee.isJvmStaticInObject()) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
class A {
|
||||
inner class C(val m: String) {
|
||||
fun test(): String {
|
||||
m.f(::C)
|
||||
return m
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline fun String.f(g: (String) -> A.C): A.C = g(this)
|
||||
|
||||
fun box(): String = A().C("OK").test()
|
||||
Vendored
-2
@@ -1,7 +1,5 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// ^ ::jpf is incorrectly represented as a reference to Base::jpf (should be: reference to fake override in Derived)
|
||||
|
||||
// FILE: kt46578_delegated.kt
|
||||
import p.*
|
||||
|
||||
Vendored
-2
@@ -1,7 +1,5 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// ^ ::jpf is incorrectly represented as a reference to Base::jpf (should be: reference to fake override in Derived)
|
||||
|
||||
// FILE: kt46578_propertyRef.kt
|
||||
import p.*
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
// FILE: a.kt
|
||||
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
// FILE: a.kt
|
||||
package a
|
||||
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// IGNORE_BACKEND: WASM
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
// FILE: a.kt
|
||||
package a
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
// FILE: a/Base.java
|
||||
package a;
|
||||
|
||||
+6
@@ -2542,6 +2542,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt44483.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt46902.kt")
|
||||
public void testKt46902() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt46902.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
|
||||
+6
@@ -2542,6 +2542,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt44483.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt46902.kt")
|
||||
public void testKt46902() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt46902.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
|
||||
+5
@@ -2230,6 +2230,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt44483.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt46902.kt")
|
||||
public void testKt46902() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt46902.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/nested.kt");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+5
@@ -1510,6 +1510,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt44483.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt46902.kt")
|
||||
public void testKt46902() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt46902.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/nested.kt");
|
||||
|
||||
Generated
+5
@@ -1510,6 +1510,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt44483.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt46902.kt")
|
||||
public void testKt46902() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt46902.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/nested.kt");
|
||||
|
||||
Generated
+5
@@ -1510,6 +1510,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt44483.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt46902.kt")
|
||||
public void testKt46902() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt46902.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/nested.kt");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+5
@@ -1290,6 +1290,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt37604.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt46902.kt")
|
||||
public void testKt46902() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/kt46902.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/nested.kt");
|
||||
|
||||
Reference in New Issue
Block a user