FIR2IR KT-47939 callable references to fun interface constructors
This commit is contained in:
committed by
TeamCityServer
parent
f55f880726
commit
11daed8b01
+101
-12
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.fir.backend.generators
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
|
||||
import org.jetbrains.kotlin.fir.backend.Fir2IrConversionScope
|
||||
import org.jetbrains.kotlin.fir.backend.FirMetadataSource
|
||||
import org.jetbrains.kotlin.fir.backend.convertWithOffsets
|
||||
import org.jetbrains.kotlin.fir.backend.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
@@ -21,23 +18,18 @@ import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirFakeArgumentForCallableReference
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ResolvedCallArgument
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.types.typeOrNull
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -500,4 +492,101 @@ internal class AdapterGenerator(
|
||||
}
|
||||
return irCall
|
||||
}
|
||||
|
||||
fun generateFunInterfaceConstructorReference(
|
||||
callableReference: FirCallableReferenceAccess,
|
||||
callableSymbol: FirFunctionSymbol<*>,
|
||||
irReferenceType: IrType
|
||||
): IrExpression =
|
||||
callableReference.convertWithOffsets { startOffset: Int, endOffset: Int ->
|
||||
// {
|
||||
// fun <ADAPTER_FUN>(function: <FUN_TYPE>): <FUN_INTERFACE_TYPE> =
|
||||
// <FUN_INTERFACE_TYPE>(function)
|
||||
// ::<ADAPTER_FUN>
|
||||
// }
|
||||
|
||||
val irAdapterFun = generateFunInterfaceConstructorAdapter(startOffset, endOffset, callableSymbol, irReferenceType)
|
||||
|
||||
val irAdapterRef = IrFunctionReferenceImpl(
|
||||
startOffset, endOffset,
|
||||
type = irReferenceType,
|
||||
symbol = irAdapterFun.symbol,
|
||||
typeArgumentsCount = irAdapterFun.typeParameters.size,
|
||||
valueArgumentsCount = irAdapterFun.valueParameters.size,
|
||||
reflectionTarget = irAdapterFun.symbol,
|
||||
origin = IrStatementOrigin.FUN_INTERFACE_CONSTRUCTOR_REFERENCE
|
||||
)
|
||||
|
||||
IrBlockImpl(
|
||||
startOffset, endOffset,
|
||||
irReferenceType,
|
||||
IrStatementOrigin.FUN_INTERFACE_CONSTRUCTOR_REFERENCE,
|
||||
listOf(
|
||||
irAdapterFun,
|
||||
irAdapterRef
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun IrSimpleType.getArgumentTypeAt(index: Int): IrType {
|
||||
val irTypeArgument = this.arguments[index] as? IrTypeProjection
|
||||
?: throw AssertionError("Type projection expected at argument $index: ${this.render()}")
|
||||
return irTypeArgument.type
|
||||
}
|
||||
|
||||
private fun generateFunInterfaceConstructorAdapter(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
callableSymbol: FirFunctionSymbol<*>,
|
||||
irReferenceType: IrType
|
||||
): IrSimpleFunction {
|
||||
// Here irReferenceType is always kotlin.reflect.KFunction1<FUN_TYPE, FUN_INTERFACE_TYPE>
|
||||
val irSimpleReferenceType = irReferenceType as? IrSimpleType
|
||||
?: throw AssertionError("Class type expected: ${irReferenceType.render()}")
|
||||
val irSamType = irSimpleReferenceType.getArgumentTypeAt(1)
|
||||
val irFunctionType = irSimpleReferenceType.getArgumentTypeAt(0)
|
||||
|
||||
val functionParameter = callableSymbol.valueParameterSymbols.singleOrNull()
|
||||
?: throw AssertionError("Single value parameter expected: ${callableSymbol.valueParameterSymbols}")
|
||||
|
||||
return irFactory.createFunction(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR,
|
||||
IrSimpleFunctionSymbolImpl(),
|
||||
callableSymbol.name,
|
||||
DescriptorVisibilities.LOCAL,
|
||||
Modality.FINAL,
|
||||
irSamType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = true,
|
||||
isOperator = false,
|
||||
isInfix = false,
|
||||
isExpect = false,
|
||||
isFakeOverride = false
|
||||
).also { irAdapterFunction ->
|
||||
symbolTable.enterScope(irAdapterFunction)
|
||||
irAdapterFunction.dispatchReceiverParameter = null
|
||||
irAdapterFunction.extensionReceiverParameter = null
|
||||
val irFunctionParameter = createAdapterParameter(
|
||||
irAdapterFunction,
|
||||
functionParameter.name,
|
||||
0,
|
||||
irFunctionType,
|
||||
IrDeclarationOrigin.ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE
|
||||
)
|
||||
irAdapterFunction.valueParameters = listOf(irFunctionParameter)
|
||||
irAdapterFunction.body = irFactory.createExpressionBody(
|
||||
startOffset, endOffset,
|
||||
IrTypeOperatorCallImpl(
|
||||
startOffset, endOffset,
|
||||
irSamType, IrTypeOperator.SAM_CONVERSION, irSamType,
|
||||
IrGetValueImpl(startOffset, endOffset, irFunctionParameter.symbol)
|
||||
)
|
||||
)
|
||||
symbolTable.leaveScope(irAdapterFunction)
|
||||
irAdapterFunction.parent = conversionScope.parent()!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-1
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolvedAnnotations
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSamResolverImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.getExpectedType
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.isFunctional
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
@@ -43,6 +44,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.isFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
@@ -70,10 +72,22 @@ class CallAndReferenceGenerator(
|
||||
callableReferenceAccess: FirCallableReferenceAccess,
|
||||
explicitReceiverExpression: IrExpression?
|
||||
): IrExpression {
|
||||
val type = callableReferenceAccess.typeRef.toIrType()
|
||||
val callableSymbol = callableReferenceAccess.calleeReference.toResolvedCallableSymbol()
|
||||
if (callableSymbol?.origin == FirDeclarationOrigin.SamConstructor) {
|
||||
assert(explicitReceiverExpression == null) {
|
||||
"Fun interface constructor reference should be unbound: ${explicitReceiverExpression?.dump()}"
|
||||
}
|
||||
return adapterGenerator.generateFunInterfaceConstructorReference(
|
||||
callableReferenceAccess,
|
||||
callableSymbol as FirSyntheticFunctionSymbol,
|
||||
type
|
||||
)
|
||||
}
|
||||
|
||||
val symbol = callableReferenceAccess.calleeReference.toSymbolForCall(
|
||||
callableReferenceAccess.dispatchReceiver, session, classifierStorage, declarationStorage, conversionScope
|
||||
)
|
||||
val type = callableReferenceAccess.typeRef.toIrType()
|
||||
// val x by y ->
|
||||
// val `x$delegate` = y
|
||||
// val x get() = `x$delegate`.getValue(this, ::x)
|
||||
|
||||
Reference in New Issue
Block a user