JVM_IR: cast bound property receivers to original type

Because the receiver type is used for determining where to put
accessors, and the type of fake overrides' receivers is the same as for
the original declaration, casting to the type of the parameter leads to
assertion errors.

 #KT-44658 Fixed
This commit is contained in:
pyos
2021-03-17 13:23:39 +01:00
committed by Alexander Udalov
parent 1d96f810da
commit 85aa6383ad
11 changed files with 80 additions and 9 deletions
@@ -39269,6 +39269,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedInvokeVirtual.kt");
}
@Test
@TestMetadata("accessorForProtectedPropertyReference.kt")
public void testAccessorForProtectedPropertyReference() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedPropertyReference.kt");
}
@Test
public void testAllFilesPresentInSyntheticAccessors() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
@@ -342,6 +342,7 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
referenceClass.addOverride(getSignature) { computeSignatureString(expression) }
}
val boundReceiver = expression.getBoundReceiver()
val backingField = superClass.properties.single { it.name.asString() == "receiver" }.backingField!!
val get = superClass.functions.find { it.name.asString() == "get" }
val set = superClass.functions.find { it.name.asString() == "set" }
@@ -350,20 +351,20 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
val field = expression.field?.owner
if (field == null) {
fun IrBuilderWithScope.setCallArguments(call: IrCall, arguments: List<IrValueParameter>) {
var index = 1
val receiverFromField = boundReceiver?.let { irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type) }
call.copyTypeArgumentsFrom(expression)
val hasBoundReceiver = expression.getBoundReceiver() != null
call.dispatchReceiver = call.symbol.owner.dispatchReceiverParameter?.let {
if (hasBoundReceiver)
irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type)
else
irImplicitCast(irGet(arguments[index++]), it.type)
// TODO: 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).
// Since there is no information about `C` in `IrPropertyReference`, we rely on fake overrides here
// (expecting that the getter is `C.getX` and not `<some superclass>.getX`) and that does not work with FIR.
receiverFromField ?: irImplicitCast(irGet(arguments[1]), call.symbol.owner.parentAsClass.defaultType)
}
call.extensionReceiver = call.symbol.owner.extensionReceiverParameter?.let {
if (hasBoundReceiver)
irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type)
if (call.symbol.owner.dispatchReceiverParameter == null)
receiverFromField ?: irImplicitCast(irGet(arguments[1]), it.type)
else
irImplicitCast(irGet(arguments[index++]), it.type)
irImplicitCast(irGet(arguments[if (receiverFromField != null) 1 else 2]), it.type)
}
}
@@ -0,0 +1,21 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: WASM
// FILE: 1.kt
package a
open class A {
protected val v = "O"
protected var w = ""
}
// FILE: 2.kt
import a.*
class B : A() {
fun foo(): String {
B::w.set(this, "K")
return ::v.get() + B::w.get(this)
}
}
fun box() = B().foo()
@@ -39251,6 +39251,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedInvokeVirtual.kt");
}
@Test
@TestMetadata("accessorForProtectedPropertyReference.kt")
public void testAccessorForProtectedPropertyReference() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedPropertyReference.kt");
}
@Test
public void testAllFilesPresentInSyntheticAccessors() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
@@ -39269,6 +39269,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedInvokeVirtual.kt");
}
@Test
@TestMetadata("accessorForProtectedPropertyReference.kt")
public void testAccessorForProtectedPropertyReference() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedPropertyReference.kt");
}
@Test
public void testAllFilesPresentInSyntheticAccessors() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
@@ -31426,6 +31426,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedInvokeVirtual.kt");
}
@TestMetadata("accessorForProtectedPropertyReference.kt")
public void testAccessorForProtectedPropertyReference() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedPropertyReference.kt");
}
public void testAllFilesPresentInSyntheticAccessors() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@@ -39388,6 +39388,12 @@ public class VisualizerBlackBoxTestGenerated extends AbstractVisualizerBlackBoxT
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedInvokeVirtual.kt");
}
@Test
@TestMetadata("accessorForProtectedPropertyReference.kt")
public void testAccessorForProtectedPropertyReference() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedPropertyReference.kt");
}
@Test
public void testAllFilesPresentInSyntheticAccessors() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), null, true);
@@ -26561,6 +26561,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedInvokeVirtual.kt");
}
@TestMetadata("accessorForProtectedPropertyReference.kt")
public void testAccessorForProtectedPropertyReference() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedPropertyReference.kt");
}
public void testAllFilesPresentInSyntheticAccessors() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
@@ -25982,6 +25982,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedInvokeVirtual.kt");
}
@TestMetadata("accessorForProtectedPropertyReference.kt")
public void testAccessorForProtectedPropertyReference() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedPropertyReference.kt");
}
public void testAllFilesPresentInSyntheticAccessors() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@@ -25942,6 +25942,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedInvokeVirtual.kt");
}
@TestMetadata("accessorForProtectedPropertyReference.kt")
public void testAccessorForProtectedPropertyReference() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedPropertyReference.kt");
}
public void testAllFilesPresentInSyntheticAccessors() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@@ -14379,6 +14379,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedInvokeVirtual.kt");
}
@TestMetadata("accessorForProtectedPropertyReference.kt")
public void testAccessorForProtectedPropertyReference() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/accessorForProtectedPropertyReference.kt");
}
public void testAllFilesPresentInSyntheticAccessors() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}