psi2ir: rework representation of bound adapted function references

This fixes the problem in JVM IR backend which didn't pass bound
receiver value of an adapted function reference to the superclass
(kotlin/jvm/internal/AdaptedFunctionReference), which caused equals to
work incorrectly on such references (see changes in box tests).

Previously, bound adapted function reference was represented as
IrFunctionExpression to an adapter function which calls the callee. The
value of the bound receiver in that case could only be found in the body
of that adapter function. This is not very convenient, so this change
makes psi2ir produce a block of the adapter function + reference to it.
The bound receiver value is then found in the reference. This is
basically similar to what ProvisionalFunctionExpressionLowering is doing
for all function expressions. And since this IR structure is already
supported in FunctionReferenceLowering, the problem in the JVM IR is
fixed without any additional modifications.

However, inliners do not support this IR structure yet, see KT-38535 and
KT-38536.
This commit is contained in:
Alexander Udalov
2020-04-22 17:45:11 +02:00
parent 22bf23025a
commit 025d1ca64d
20 changed files with 303 additions and 150 deletions
@@ -83,28 +83,33 @@ FILE fqName:<root> fileName:/constructorWithAdaptedArguments.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testInnerClassConstructor (outer: <root>.Outer): kotlin.Any declared in <root>'
CALL 'public final fun use (fn: kotlin.Function1<kotlin.Int, kotlin.Any>): kotlin.Any declared in <root>' type=kotlin.Any origin=null
fn: FUN_EXPR type=kotlin.Function1<kotlin.Int, <root>.Outer.Inner> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:<init> visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:<root>.Outer.Inner
fn: BLOCK type=kotlin.Function1<kotlin.Int, <root>.Outer.Inner> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:<init> visibility:local modality:FINAL <> ($receiver:<root>.Outer, p0:kotlin.Int) returnType:<root>.Outer.Inner
$receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:receiver type:<root>.Outer
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <init> (p0: kotlin.Int): <root>.Outer.Inner declared in <root>.testInnerClassConstructor'
CONSTRUCTOR_CALL 'public constructor <init> (vararg xs: kotlin.Int) [primary] declared in <root>.Outer.Inner' type=<root>.Outer.Inner origin=null
$outer: GET_VAR 'outer: <root>.Outer declared in <root>.testInnerClassConstructor' type=<root>.Outer origin=null
$outer: GET_VAR 'receiver: <root>.Outer declared in <root>.testInnerClassConstructor.<init>' type=<root>.Outer origin=ADAPTED_FUNCTION_REFERENCE
xs: VARARG type=kotlin.IntArray varargElementType=kotlin.Int
GET_VAR 'p0: kotlin.Int declared in <root>.testInnerClassConstructor.<init>' type=kotlin.Int origin=null
FUNCTION_REFERENCE 'local final fun <init> (p0: kotlin.Int): <root>.Outer.Inner declared in <root>.testInnerClassConstructor' type=kotlin.Function1<kotlin.Int, <root>.Outer.Inner> origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=null
$receiver: GET_VAR 'outer: <root>.Outer declared in <root>.testInnerClassConstructor' type=<root>.Outer origin=null
FUN name:testInnerClassConstructorCapturingOuter visibility:public modality:FINAL <> () returnType:kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testInnerClassConstructorCapturingOuter (): kotlin.Any declared in <root>'
CALL 'public final fun use (fn: kotlin.Function1<kotlin.Int, kotlin.Any>): kotlin.Any declared in <root>' type=kotlin.Any origin=null
fn: BLOCK type=kotlin.Function1<kotlin.Int, <root>.Outer.Inner> origin=null
fn: BLOCK type=kotlin.Function1<kotlin.Int, <root>.Outer.Inner> origin=ADAPTED_FUNCTION_REFERENCE
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.Outer [val]
CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.Outer' type=<root>.Outer origin=null
FUN_EXPR type=kotlin.Function1<kotlin.Int, <root>.Outer.Inner> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:<init> visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:<root>.Outer.Inner
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <init> (p0: kotlin.Int): <root>.Outer.Inner declared in <root>.testInnerClassConstructorCapturingOuter'
CONSTRUCTOR_CALL 'public constructor <init> (vararg xs: kotlin.Int) [primary] declared in <root>.Outer.Inner' type=<root>.Outer.Inner origin=null
$outer: GET_VAR 'val tmp_0: <root>.Outer [val] declared in <root>.testInnerClassConstructorCapturingOuter' type=<root>.Outer origin=null
xs: VARARG type=kotlin.IntArray varargElementType=kotlin.Int
GET_VAR 'p0: kotlin.Int declared in <root>.testInnerClassConstructorCapturingOuter.<init>' type=kotlin.Int origin=null
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:<init> visibility:local modality:FINAL <> ($receiver:<root>.Outer, p0:kotlin.Int) returnType:<root>.Outer.Inner
$receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:receiver type:<root>.Outer
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <init> (p0: kotlin.Int): <root>.Outer.Inner declared in <root>.testInnerClassConstructorCapturingOuter'
CONSTRUCTOR_CALL 'public constructor <init> (vararg xs: kotlin.Int) [primary] declared in <root>.Outer.Inner' type=<root>.Outer.Inner origin=null
$outer: GET_VAR 'receiver: <root>.Outer declared in <root>.testInnerClassConstructorCapturingOuter.<init>' type=<root>.Outer origin=ADAPTED_FUNCTION_REFERENCE
xs: VARARG type=kotlin.IntArray varargElementType=kotlin.Int
GET_VAR 'p0: kotlin.Int declared in <root>.testInnerClassConstructorCapturingOuter.<init>' type=kotlin.Int origin=null
FUNCTION_REFERENCE 'local final fun <init> (p0: kotlin.Int): <root>.Outer.Inner declared in <root>.testInnerClassConstructorCapturingOuter' type=kotlin.Function1<kotlin.Int, <root>.Outer.Inner> origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=null
$receiver: GET_VAR 'val tmp_0: <root>.Outer [val] declared in <root>.testInnerClassConstructorCapturingOuter' type=<root>.Outer origin=null