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");
|
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
|
@Test
|
||||||
@TestMetadata("nested.kt")
|
@TestMetadata("nested.kt")
|
||||||
public void testNested() throws Exception {
|
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.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
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.types.IrTypeProjection
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
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 {
|
private fun expandInlineFunctionReferenceToLambda(expression: IrCallableReference<*>, referencedFunction: IrFunction): IrExpression {
|
||||||
val irBuilder = context.createJvmIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset)
|
val irBuilder = context.createJvmIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset)
|
||||||
return irBuilder.irBlock(expression, IrStatementOrigin.LAMBDA) {
|
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 argumentTypes = (expression.type as IrSimpleType).arguments.dropLast(1).map { (it as IrTypeProjection).type }
|
||||||
|
|
||||||
val function = context.irFactory.buildFun {
|
val function = context.irFactory.buildFun {
|
||||||
@@ -173,8 +139,8 @@ private class InlineCallableReferenceToLambdaTransformer(
|
|||||||
isSuspend = referencedFunction.isSuspend
|
isSuspend = referencedFunction.isSuspend
|
||||||
}.apply {
|
}.apply {
|
||||||
parent = currentDeclarationParent!!
|
parent = currentDeclarationParent!!
|
||||||
if (boundReceiver != null) {
|
if (receiverValue != null) {
|
||||||
addExtensionReceiver(boundReceiver.receiverType)
|
addExtensionReceiver(receiverValue.type)
|
||||||
}
|
}
|
||||||
for ((index, argumentType) in argumentTypes.withIndex()) {
|
for ((index, argumentType) in argumentTypes.withIndex()) {
|
||||||
addValueParameter {
|
addValueParameter {
|
||||||
@@ -196,7 +162,7 @@ private class InlineCallableReferenceToLambdaTransformer(
|
|||||||
var unboundIndex = 0
|
var unboundIndex = 0
|
||||||
for (parameter in referencedFunction.explicitParameters) {
|
for (parameter in referencedFunction.explicitParameters) {
|
||||||
when {
|
when {
|
||||||
boundReceiver?.receiverParameter == parameter ->
|
receiverParameter == parameter ->
|
||||||
irGet(extensionReceiverParameter!!)
|
irGet(extensionReceiverParameter!!)
|
||||||
parameter.isVararg && unboundIndex < argumentTypes.size && parameter.type == valueParameters[unboundIndex].type ->
|
parameter.isVararg && unboundIndex < argumentTypes.size && parameter.type == valueParameters[unboundIndex].type ->
|
||||||
irGet(valueParameters[unboundIndex++])
|
irGet(valueParameters[unboundIndex++])
|
||||||
@@ -225,7 +191,7 @@ private class InlineCallableReferenceToLambdaTransformer(
|
|||||||
origin = IrStatementOrigin.LAMBDA
|
origin = IrStatementOrigin.LAMBDA
|
||||||
).apply {
|
).apply {
|
||||||
copyAttributes(expression)
|
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) }
|
val receiverFromField = boundReceiver?.let { irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type) }
|
||||||
call.copyTypeArgumentsFrom(expression)
|
call.copyTypeArgumentsFrom(expression)
|
||||||
call.dispatchReceiver = call.symbol.owner.dispatchReceiverParameter?.let {
|
call.dispatchReceiver = call.symbol.owner.dispatchReceiverParameter?.let {
|
||||||
receiverFromField ?: irImplicitCast(
|
receiverFromField ?: irImplicitCast(irGet(arguments[1]), expression.receiverType)
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
call.extensionReceiver = call.symbol.owner.extensionReceiverParameter?.let {
|
call.extensionReceiver = call.symbol.owner.extensionReceiverParameter?.let {
|
||||||
if (call.symbol.owner.dispatchReceiverParameter == null)
|
if (call.symbol.owner.dispatchReceiverParameter == null)
|
||||||
@@ -393,9 +385,9 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
|
|||||||
field.isStatic ->
|
field.isStatic ->
|
||||||
null
|
null
|
||||||
expression.dispatchReceiver != null ->
|
expression.dispatchReceiver != null ->
|
||||||
irImplicitCast(irGetField(irGet(arguments[0]), backingField), field.parentAsClass.defaultType)
|
irImplicitCast(irGetField(irGet(arguments[0]), backingField), expression.receiverType)
|
||||||
else ->
|
else ->
|
||||||
irImplicitCast(irGet(arguments[1]), field.parentAsClass.defaultType)
|
irImplicitCast(irGet(arguments[1]), expression.receiverType)
|
||||||
}
|
}
|
||||||
|
|
||||||
referenceClass.addOverride(get!!) { arguments ->
|
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? {
|
private fun IrCallableReference<*>.getBoundReceiver(): IrExpression? {
|
||||||
val callee = symbol.owner
|
val callee = symbol.owner
|
||||||
return if (callee is IrDeclaration && callee.isJvmStaticInObject()) {
|
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
|
// TARGET_BACKEND: JVM
|
||||||
// WITH_RUNTIME
|
// 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
|
// FILE: kt46578_delegated.kt
|
||||||
import p.*
|
import p.*
|
||||||
|
|||||||
Vendored
-2
@@ -1,7 +1,5 @@
|
|||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// WITH_RUNTIME
|
// 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
|
// FILE: kt46578_propertyRef.kt
|
||||||
import p.*
|
import p.*
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|
||||||
// FILE: a.kt
|
// FILE: a.kt
|
||||||
|
|||||||
-2
@@ -1,5 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
// FILE: a.kt
|
// FILE: a.kt
|
||||||
package a
|
package a
|
||||||
|
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// IGNORE_BACKEND: WASM
|
// IGNORE_BACKEND: WASM
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
// FILE: a.kt
|
// FILE: a.kt
|
||||||
package a
|
package a
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
// FILE: a/Base.java
|
// FILE: a/Base.java
|
||||||
package a;
|
package a;
|
||||||
|
|||||||
+6
@@ -2542,6 +2542,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/callableReference/kt44483.kt");
|
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
|
@Test
|
||||||
@TestMetadata("nested.kt")
|
@TestMetadata("nested.kt")
|
||||||
public void testNested() throws Exception {
|
public void testNested() throws Exception {
|
||||||
|
|||||||
+6
@@ -2542,6 +2542,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/callableReference/kt44483.kt");
|
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
|
@Test
|
||||||
@TestMetadata("nested.kt")
|
@TestMetadata("nested.kt")
|
||||||
public void testNested() throws Exception {
|
public void testNested() throws Exception {
|
||||||
|
|||||||
+5
@@ -2230,6 +2230,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/callableReference/kt44483.kt");
|
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")
|
@TestMetadata("nested.kt")
|
||||||
public void testNested() throws Exception {
|
public void testNested() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/callableReference/nested.kt");
|
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");
|
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")
|
@TestMetadata("nested.kt")
|
||||||
public void testNested() throws Exception {
|
public void testNested() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/callableReference/nested.kt");
|
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");
|
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")
|
@TestMetadata("nested.kt")
|
||||||
public void testNested() throws Exception {
|
public void testNested() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/callableReference/nested.kt");
|
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");
|
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")
|
@TestMetadata("nested.kt")
|
||||||
public void testNested() throws Exception {
|
public void testNested() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/callableReference/nested.kt");
|
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");
|
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")
|
@TestMetadata("nested.kt")
|
||||||
public void testNested() throws Exception {
|
public void testNested() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/callableReference/nested.kt");
|
runTest("compiler/testData/codegen/box/callableReference/nested.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user