JVM: push down implicit coercion to Unit in IR

This is basically a workaround for a slightly different IR generated by
fir2ir vs psi2ir. Simplified, psi2ir generates something like this for
the sample from KT-59218:

  TRY type=Unit
    try: BLOCK type=Unit
      VAR methodHandle [...]
      TYPE_OP type=Unit origin=IMPLICIT_COERCION_TO_UNIT
        CALL invokeExact [...]

While fir2ir generates the following:

  TYPE_OP type=Unit origin=IMPLICIT_COERCION_TO_UNIT
    TRY type=Any?
      try: BLOCK type=Any?
        VAR methodHandle [...]
        CALL invokeExact [...]

The lowering relies on the fact that a polymorphic call (`invokeExact`
in this case) is a direct argument to the TYPE_OP, to determine the
correct return type (Unit in this case) to be generated in the bytecode.

The solution here is to push the type coercion "through" all the
block-like structures (`try`, `when`, container expression) so that if
the last statement in the block is a polymorphic call, it gets properly
converted even if the whole block is under a type coercion operation, as
it happens in fir2ir. We achieve that by using the "data" parameter of
the IR transformer: appropriate immediate children of
IrTypeOperatorCall/IrTry/IrWhen/IrContainerExpression get the type that
the expression needs to be coerced to, and all the other expressions
ignore that type and set it to null when transforming their children.

A proper solution would be to ensure fir2ir generates exactly the same
IR as psi2ir (KT-59781), but since PolymorphicSignatureLowering is the
only lowering affected so far, and polymorphic calls occur very rarely,
it seems safe to workaround it in the lowering for now.

 #KT-59218 Fixed
This commit is contained in:
Alexander Udalov
2023-06-15 16:04:19 +02:00
committed by Space Team
parent 69059362b8
commit 1cb1420e43
12 changed files with 323 additions and 17 deletions
@@ -30447,6 +30447,26 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/polymorphicSignature/anonymousSubclass.kt");
}
@TestMetadata("insideComplexExpression.kt")
public void testInsideComplexExpression() throws Exception {
runTest("compiler/testData/codegen/box/polymorphicSignature/insideComplexExpression.kt");
}
@TestMetadata("insideIf.kt")
public void testInsideIf() throws Exception {
runTest("compiler/testData/codegen/box/polymorphicSignature/insideIf.kt");
}
@TestMetadata("insideTry.kt")
public void testInsideTry() throws Exception {
runTest("compiler/testData/codegen/box/polymorphicSignature/insideTry.kt");
}
@TestMetadata("insideWhen.kt")
public void testInsideWhen() throws Exception {
runTest("compiler/testData/codegen/box/polymorphicSignature/insideWhen.kt");
}
@TestMetadata("invoke.kt")
public void testInvoke() throws Exception {
runTest("compiler/testData/codegen/box/polymorphicSignature/invoke.kt");