FIR2IR: support adapted references for constructors

This commit is contained in:
Mikhail Glukhikh
2021-02-15 12:55:28 +03:00
parent 8bab208322
commit fa0f967c83
8 changed files with 74 additions and 32 deletions
@@ -112,7 +112,7 @@ internal class AdapterGenerator(
adapteeSymbol: IrFunctionSymbol,
type: IrSimpleType
): IrExpression {
val firAdaptee = callableReferenceAccess.toResolvedCallableReference()?.resolvedSymbol?.fir as? FirSimpleFunction
val firAdaptee = callableReferenceAccess.toResolvedCallableReference()?.resolvedSymbol?.fir as? FirFunction
val adaptee = adapteeSymbol.owner
val expectedReturnType = type.arguments.last().typeOrNull
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
@@ -164,7 +164,7 @@ internal class AdapterGenerator(
callableReferenceAccess: FirCallableReferenceAccess,
startOffset: Int,
endOffset: Int,
firAdaptee: FirSimpleFunction,
firAdaptee: FirFunction<*>,
adaptee: IrFunction,
type: IrSimpleType,
boundDispatchReceiver: IrExpression?,
@@ -172,6 +172,7 @@ internal class AdapterGenerator(
): IrSimpleFunction {
val returnType = type.arguments.last().typeOrNull!!
val parameterTypes = type.arguments.dropLast(1).map { it.typeOrNull!! }
val firMemberAdaptee = firAdaptee as FirMemberDeclaration
return irFactory.createFunction(
startOffset, endOffset,
IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE,
@@ -180,13 +181,13 @@ internal class AdapterGenerator(
DescriptorVisibilities.LOCAL,
Modality.FINAL,
returnType,
isInline = firAdaptee.isInline,
isExternal = firAdaptee.isExternal,
isTailrec = firAdaptee.isTailRec,
isSuspend = firAdaptee.isSuspend || type.isSuspendFunction(),
isOperator = firAdaptee.isOperator,
isInfix = firAdaptee.isInfix,
isExpect = firAdaptee.isExpect,
isInline = firMemberAdaptee.isInline,
isExternal = firMemberAdaptee.isExternal,
isTailrec = firMemberAdaptee.isTailRec,
isSuspend = firMemberAdaptee.isSuspend || type.isSuspendFunction(),
isOperator = firMemberAdaptee.isOperator,
isInfix = firMemberAdaptee.isInfix,
isExpect = firMemberAdaptee.isExpect,
isFakeOverride = false
).also { irAdapterFunction ->
irAdapterFunction.metadata = FirMetadataSource.Function(firAdaptee)
@@ -122,16 +122,6 @@ class CallAndReferenceGenerator(
origin
)
}
is IrConstructorSymbol -> {
val constructor = symbol.owner
val klass = constructor.parent as? IrClass
IrFunctionReferenceImpl(
startOffset, endOffset, type, symbol,
typeArgumentsCount = constructor.typeParameters.size + (klass?.typeParameters?.size ?: 0),
valueArgumentsCount = constructor.valueParameters.size,
reflectionTarget = symbol
)
}
is IrFunctionSymbol -> {
assert(type.isFunctionTypeOrSubtype()) {
"Callable reference whose symbol refers to a function should be of functional type."
@@ -144,9 +134,12 @@ class CallAndReferenceGenerator(
generateAdaptedCallableReference(callableReferenceAccess, explicitReceiverExpression, symbol, adaptedType)
}
} else {
val klass = function.parent as? IrClass
val typeArgumentCount = function.typeParameters.size +
if (function is IrConstructor) klass?.typeParameters?.size ?: 0 else 0
IrFunctionReferenceImpl(
startOffset, endOffset, type, symbol,
typeArgumentsCount = function.typeParameters.size,
typeArgumentsCount = typeArgumentCount,
valueArgumentsCount = function.valueParameters.size,
reflectionTarget = symbol
)
@@ -1,5 +1,4 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
import kotlin.reflect.KCallable
@@ -1,6 +1,5 @@
// !LANGUAGE: +SuspendConversion
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
import kotlin.reflect.KCallable
@@ -30,13 +30,29 @@ class Outer {
}
fun testConstructor(): Any {
return use(fn = C::<init>)
return use(fn = local fun <init>(p0: Int): C {
return C(xs = [p0])
}
)
}
fun testInnerClassConstructor(outer: Outer): Any {
return use(fn = outer::<init>)
return use(fn = { // BLOCK
local fun Outer.<init>(p0: Int): Inner {
return receiver.Inner(xs = [p0])
}
outer::<init>
})
}
fun testInnerClassConstructorCapturingOuter(): Any {
return use(fn = Outer()::<init>)
return use(fn = { // BLOCK
local fun Outer.<init>(p0: Int): Inner {
return receiver.Inner(xs = [p0])
}
Outer()::<init>
})
}
@@ -70,17 +70,44 @@ FILE fqName:<root> fileName:/constructorWithAdaptedArguments.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testConstructor (): 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: FUNCTION_REFERENCE 'public constructor <init> (vararg xs: kotlin.Int) [primary] declared in <root>.C' type=kotlin.reflect.KFunction1<kotlin.Int, <root>.C> origin=null reflectionTarget=<same>
fn: FUN_EXPR type=kotlin.Function1<kotlin.Int, <root>.C> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:<init> visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:<root>.C
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>.C declared in <root>.testConstructor'
CONSTRUCTOR_CALL 'public constructor <init> (vararg xs: kotlin.Int) [primary] declared in <root>.C' type=<root>.C origin=null
xs: VARARG type=kotlin.IntArray varargElementType=kotlin.Int
GET_VAR 'p0: kotlin.Int declared in <root>.testConstructor.<init>' type=kotlin.Int origin=null
FUN name:testInnerClassConstructor visibility:public modality:FINAL <> (outer:<root>.Outer) returnType:kotlin.Any
VALUE_PARAMETER name:outer index:0 type:<root>.Outer
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: FUNCTION_REFERENCE 'public constructor <init> (vararg xs: kotlin.Int) [primary] declared in <root>.Outer.Inner' type=kotlin.reflect.KFunction1<kotlin.Int, <root>.Outer.Inner> origin=null reflectionTarget=<same>
$this: GET_VAR 'outer: <root>.Outer declared in <root>.testInnerClassConstructor' type=<root>.Outer origin=null
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 '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: FUNCTION_REFERENCE 'public constructor <init> (vararg xs: kotlin.Int) [primary] declared in <root>.Outer.Inner' type=kotlin.reflect.KFunction1<kotlin.Int, <root>.Outer.Inner> origin=null reflectionTarget=<same>
$this: CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.Outer' type=<root>.Outer origin=null
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>.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: CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.Outer' type=<root>.Outer origin=null
@@ -27,5 +27,8 @@ fun testFn(): Any {
}
fun testCtor(): Any {
return use(fn = C::<init>)
return use(fn = local fun <init>(): C {
return C()
}
)
}
@@ -58,4 +58,8 @@ FILE fqName:<root> fileName:/kt37131.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testCtor (): kotlin.Any declared in <root>'
CALL 'public final fun use (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>' type=kotlin.Any origin=null
fn: FUNCTION_REFERENCE 'public constructor <init> (x: kotlin.String) [primary] declared in <root>.C' type=kotlin.reflect.KFunction0<<root>.C> origin=null reflectionTarget=<same>
fn: FUN_EXPR type=kotlin.Function0<<root>.C> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:<init> visibility:local modality:FINAL <> () returnType:<root>.C
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <init> (): <root>.C declared in <root>.testCtor'
CONSTRUCTOR_CALL 'public constructor <init> (x: kotlin.String) [primary] declared in <root>.C' type=<root>.C origin=null