FIR: initial support of suspend conversion for function reference
This commit is contained in:
committed by
Mikhail Glukhikh
parent
b9243aad24
commit
5a3367e09c
+176
-11
@@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.backend.generators
|
package org.jetbrains.kotlin.fir.backend.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.fir.backend.*
|
import org.jetbrains.kotlin.fir.backend.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
@@ -18,22 +21,28 @@ import org.jetbrains.kotlin.fir.render
|
|||||||
import org.jetbrains.kotlin.fir.resolve.calls.isFunctional
|
import org.jetbrains.kotlin.fir.resolve.calls.isFunctional
|
||||||
import org.jetbrains.kotlin.fir.resolve.getCorrespondingConstructorReferenceOrNull
|
import org.jetbrains.kotlin.fir.resolve.getCorrespondingConstructorReferenceOrNull
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
|
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||||
import org.jetbrains.kotlin.ir.types.toArrayOrPrimitiveArrayType
|
import org.jetbrains.kotlin.ir.types.toArrayOrPrimitiveArrayType
|
||||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
import org.jetbrains.kotlin.ir.types.typeOrNull
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtPropertyDelegate
|
import org.jetbrains.kotlin.psi.KtPropertyDelegate
|
||||||
import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects
|
import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects
|
||||||
|
|
||||||
@@ -87,12 +96,18 @@ class CallAndReferenceGenerator(
|
|||||||
}
|
}
|
||||||
is IrFunctionSymbol -> {
|
is IrFunctionSymbol -> {
|
||||||
val function = symbol.owner
|
val function = symbol.owner
|
||||||
IrFunctionReferenceImpl(
|
// TODO: should refer to LanguageVersionSettings.SuspendConversion
|
||||||
startOffset, endOffset, type, symbol,
|
if (requiresSuspendConversion(type, function)) {
|
||||||
typeArgumentsCount = function.typeParameters.size,
|
val adaptedType = callableReferenceAccess.typeRef.coneType.kFunctionTypeToFunctionType()
|
||||||
valueArgumentsCount = function.valueParameters.size,
|
generateAdaptedCallableReference(callableReferenceAccess, symbol, adaptedType)
|
||||||
reflectionTarget = symbol
|
} else {
|
||||||
)
|
IrFunctionReferenceImpl(
|
||||||
|
startOffset, endOffset, type, symbol,
|
||||||
|
typeArgumentsCount = function.typeParameters.size,
|
||||||
|
valueArgumentsCount = function.valueParameters.size,
|
||||||
|
reflectionTarget = symbol
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
IrErrorCallExpressionImpl(
|
IrErrorCallExpressionImpl(
|
||||||
@@ -103,6 +118,156 @@ class CallAndReferenceGenerator(
|
|||||||
}.applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess, explicitReceiverExpression)
|
}.applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess, explicitReceiverExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun requiresSuspendConversion(type: IrType, function: IrFunction): Boolean =
|
||||||
|
type.isKSuspendFunction() && !function.isSuspend
|
||||||
|
|
||||||
|
private fun ConeKotlinType.kFunctionTypeToFunctionType(): IrSimpleType {
|
||||||
|
val kind =
|
||||||
|
if (isSuspendFunctionType(session)) FunctionClassDescriptor.Kind.SuspendFunction
|
||||||
|
else FunctionClassDescriptor.Kind.Function
|
||||||
|
val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size - 1))
|
||||||
|
val coneType = ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(functionalTypeId), typeArguments, isNullable = false)
|
||||||
|
return coneType.toIrType() as IrSimpleType
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateAdaptedCallableReference(
|
||||||
|
callableReferenceAccess: FirCallableReferenceAccess,
|
||||||
|
adapteeSymbol: IrFunctionSymbol,
|
||||||
|
type: IrSimpleType
|
||||||
|
): IrExpression {
|
||||||
|
val firAdaptee = callableReferenceAccess.toResolvedCallableReference()?.resolvedSymbol?.fir as? FirSimpleFunction
|
||||||
|
val adaptee = adapteeSymbol.owner
|
||||||
|
// TODO: handle bound receiver, e.g., c::foo
|
||||||
|
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
|
||||||
|
val irAdapterFunction = createAdapterFunctionForSuspendConversion(startOffset, endOffset, firAdaptee!!, adaptee, type)
|
||||||
|
val irCall = createAdapteeCall(callableReferenceAccess, adapteeSymbol, irAdapterFunction)
|
||||||
|
irAdapterFunction.body = irFactory.createBlockBody(startOffset, endOffset) {
|
||||||
|
if (firAdaptee.returnTypeRef.isUnit) {
|
||||||
|
statements.add(irCall)
|
||||||
|
} else {
|
||||||
|
statements.add(IrReturnImpl(startOffset, endOffset, irBuiltIns.nothingType, irAdapterFunction.symbol, irCall))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IrFunctionExpressionImpl(startOffset, endOffset, type, irAdapterFunction, IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createAdapterFunctionForSuspendConversion(
|
||||||
|
startOffset: Int,
|
||||||
|
endOffset: Int,
|
||||||
|
firAdaptee: FirSimpleFunction,
|
||||||
|
adaptee: IrFunction,
|
||||||
|
type: IrSimpleType,
|
||||||
|
): IrSimpleFunction {
|
||||||
|
val returnType = type.arguments.last().typeOrNull!!
|
||||||
|
val parameterTypes = type.arguments.dropLast(1).map { it.typeOrNull!! }
|
||||||
|
val adapterFunctionDescriptor = WrappedSimpleFunctionDescriptor()
|
||||||
|
return symbolTable.declareSimpleFunction(adapterFunctionDescriptor) { irAdapterSymbol ->
|
||||||
|
irFactory.createFunction(
|
||||||
|
startOffset, endOffset,
|
||||||
|
IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE,
|
||||||
|
irAdapterSymbol,
|
||||||
|
adaptee.name,
|
||||||
|
Visibilities.LOCAL,
|
||||||
|
Modality.FINAL,
|
||||||
|
returnType,
|
||||||
|
isInline = firAdaptee.isInline,
|
||||||
|
isExternal = firAdaptee.isExternal,
|
||||||
|
isTailrec = firAdaptee.isTailRec,
|
||||||
|
isSuspend = true,
|
||||||
|
isOperator = firAdaptee.isOperator,
|
||||||
|
isInfix = firAdaptee.isInfix,
|
||||||
|
isExpect = firAdaptee.isExpect,
|
||||||
|
isFakeOverride = false
|
||||||
|
).also { irAdapterFunction ->
|
||||||
|
adapterFunctionDescriptor.bind(irAdapterFunction)
|
||||||
|
irAdapterFunction.metadata = FirMetadataSource.Function(firAdaptee)
|
||||||
|
symbolTable.enterScope(irAdapterFunction)
|
||||||
|
irAdapterFunction.valueParameters += parameterTypes.mapIndexed { index, parameterType ->
|
||||||
|
createAdapterParameter(irAdapterFunction, Name.identifier("p$index"), index, parameterType)
|
||||||
|
}
|
||||||
|
symbolTable.leaveScope(irAdapterFunction)
|
||||||
|
irAdapterFunction.parent = conversionScope.parent()!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createAdapterParameter(
|
||||||
|
adapterFunction: IrFunction,
|
||||||
|
name: Name,
|
||||||
|
index: Int,
|
||||||
|
type: IrType
|
||||||
|
): IrValueParameter {
|
||||||
|
val startOffset = adapterFunction.startOffset
|
||||||
|
val endOffset = adapterFunction.endOffset
|
||||||
|
val descriptor = WrappedValueParameterDescriptor()
|
||||||
|
return symbolTable.declareValueParameter(
|
||||||
|
startOffset, endOffset, IrDeclarationOrigin.ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE, descriptor, type
|
||||||
|
) { irAdapterParameterSymbol ->
|
||||||
|
irFactory.createValueParameter(
|
||||||
|
startOffset, endOffset,
|
||||||
|
IrDeclarationOrigin.ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE,
|
||||||
|
irAdapterParameterSymbol,
|
||||||
|
name,
|
||||||
|
index,
|
||||||
|
type,
|
||||||
|
varargElementType = null,
|
||||||
|
isCrossinline = false,
|
||||||
|
isNoinline = false
|
||||||
|
).also { irAdapterValueParameter ->
|
||||||
|
descriptor.bind(irAdapterValueParameter)
|
||||||
|
irAdapterValueParameter.parent = adapterFunction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createAdapteeCall(
|
||||||
|
callableReferenceAccess: FirCallableReferenceAccess,
|
||||||
|
adapteeSymbol: IrFunctionSymbol,
|
||||||
|
adapterFunction: IrFunction
|
||||||
|
): IrExpression {
|
||||||
|
val adapteeFunction = adapteeSymbol.owner
|
||||||
|
val startOffset = adapteeFunction.startOffset
|
||||||
|
val endOffset = adapteeFunction.endOffset
|
||||||
|
val type = adapteeFunction.returnType
|
||||||
|
val irCall =
|
||||||
|
if (adapteeSymbol is IrConstructorSymbol) {
|
||||||
|
IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, type, adapteeSymbol)
|
||||||
|
} else {
|
||||||
|
IrCallImpl(
|
||||||
|
startOffset,
|
||||||
|
endOffset,
|
||||||
|
type,
|
||||||
|
adapteeSymbol,
|
||||||
|
callableReferenceAccess.typeArguments.size,
|
||||||
|
adapteeFunction.valueParameters.size,
|
||||||
|
origin = null,
|
||||||
|
superQualifierSymbol = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle non-transient, bound dispatch/extension receiver
|
||||||
|
|
||||||
|
adapteeFunction.valueParameters.mapIndexed { index, valueParameter ->
|
||||||
|
when {
|
||||||
|
valueParameter.hasDefaultValue() -> {
|
||||||
|
irCall.putValueArgument(index, null)
|
||||||
|
}
|
||||||
|
valueParameter.isVararg -> {
|
||||||
|
// TODO: handle vararg and spread
|
||||||
|
irCall.putValueArgument(index, null)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val irValueArgument = adapterFunction.valueParameters[index]
|
||||||
|
irCall.putValueArgument(index, IrGetValueImpl(startOffset, endOffset, irValueArgument.type, irValueArgument.symbol))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return irCall.applyTypeArguments(callableReferenceAccess)
|
||||||
|
}
|
||||||
|
|
||||||
private fun FirQualifiedAccess.tryConvertToSamConstructorCall(type: IrType): IrTypeOperatorCall? {
|
private fun FirQualifiedAccess.tryConvertToSamConstructorCall(type: IrType): IrTypeOperatorCall? {
|
||||||
val calleeReference = calleeReference as? FirResolvedNamedReference ?: return null
|
val calleeReference = calleeReference as? FirResolvedNamedReference ?: return null
|
||||||
val fir = calleeReference.resolvedSymbol.fir
|
val fir = calleeReference.resolvedSymbol.fir
|
||||||
|
|||||||
@@ -220,12 +220,18 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val returnTypeRef = candidate.bodyResolveComponents.returnTypeCalculator.tryCalculateReturnType(fir)
|
val returnTypeRef = candidate.bodyResolveComponents.returnTypeCalculator.tryCalculateReturnType(fir)
|
||||||
|
// If the expected type is a suspend function type and the current argument of interest is a function reference, we need to do
|
||||||
|
// "suspend conversion." Here, during resolution, we bypass constraint system by making resulting type be KSuspendFunction.
|
||||||
|
// Then, during conversion, we need to create an adapter function and replace the function reference created here with an adapted
|
||||||
|
// callable reference.
|
||||||
|
// TODO: should refer to LanguageVersionSettings.SuspendConversion
|
||||||
|
val requireSuspendConversion = expectedType?.isSuspendFunctionType(callInfo.session) == true
|
||||||
|
// TODO: handle callable reference with vararg
|
||||||
val resultingType: ConeKotlinType = when (fir) {
|
val resultingType: ConeKotlinType = when (fir) {
|
||||||
is FirFunction -> callInfo.session.createKFunctionType(
|
is FirFunction -> callInfo.session.createKFunctionType(
|
||||||
fir, resultingReceiverType, returnTypeRef,
|
fir, resultingReceiverType, returnTypeRef,
|
||||||
expectedParameterNumberWithReceiver = expectedType?.let { it.typeArguments.size - 1 },
|
expectedParameterNumberWithReceiver = expectedType?.let { it.typeArguments.size - 1 },
|
||||||
isSuspend = (fir as? FirSimpleFunction)?.isSuspend == true,
|
isSuspend = (fir as? FirSimpleFunction)?.isSuspend == true || requireSuspendConversion,
|
||||||
expectedReturnType = extractInputOutputTypesFromCallableReferenceExpectedType(expectedType, callInfo.session)?.outputType
|
expectedReturnType = extractInputOutputTypesFromCallableReferenceExpectedType(expectedType, callInfo.session)?.outputType
|
||||||
)
|
)
|
||||||
is FirVariable<*> -> createKPropertyType(fir, resultingReceiverType, returnTypeRef)
|
is FirVariable<*> -> createKPropertyType(fir, resultingReceiverType, returnTypeRef)
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
|
|||||||
Vendored
-1
@@ -1,7 +1,6 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
|
|||||||
Vendored
-1
@@ -1,7 +1,6 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
|
|||||||
Vendored
-1
@@ -1,7 +1,6 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
|
|||||||
+3
-3
@@ -9,10 +9,10 @@ fun bar2(x: Int) {}
|
|||||||
fun bar2(s: String) {}
|
fun bar2(s: String) {}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo1<!>(::bar1)
|
foo1(::bar1)
|
||||||
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo2<!>(42, <!UNRESOLVED_REFERENCE!>::bar2<!>)
|
foo2(42, ::bar2)
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo2<!>("str", <!UNRESOLVED_REFERENCE!>::bar2<!>)
|
foo2("str", ::bar2)
|
||||||
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo2<!>(42, ::bar1)
|
<!INAPPLICABLE_CANDIDATE!>foo2<!>(42, ::bar1)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -22,7 +22,7 @@ object Test2 {
|
|||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val result = foo(::bar)
|
val result = foo(::bar)
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>result<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>result<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -11,7 +11,7 @@ object Test1 {
|
|||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val result = foo(::bar)
|
val result = foo(::bar)
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>result<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>result<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ object Test2 {
|
|||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val result = foo(::bar)
|
val result = foo(::bar)
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Double")!>result<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>result<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ fun test(
|
|||||||
<!INAPPLICABLE_CANDIDATE!>foo2<!>(f2)
|
<!INAPPLICABLE_CANDIDATE!>foo2<!>(f2)
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo3<!>(f3)
|
<!INAPPLICABLE_CANDIDATE!>foo3<!>(f3)
|
||||||
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo1<!>(::bar)
|
foo1(::bar)
|
||||||
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo1<!>(f2)
|
<!INAPPLICABLE_CANDIDATE!>foo1<!>(f2)
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo1<!>(f3)
|
<!INAPPLICABLE_CANDIDATE!>foo1<!>(f3)
|
||||||
|
|||||||
Vendored
-21
@@ -1,21 +0,0 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
|
||||||
|
|
||||||
fun interface SuspendRunnable {
|
|
||||||
suspend fun invoke()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun foo1(s: SuspendRunnable) {}
|
|
||||||
fun bar1() {}
|
|
||||||
|
|
||||||
fun bar2(s: String = ""): Int = 0
|
|
||||||
|
|
||||||
fun bar3() {}
|
|
||||||
suspend fun bar3(s: String = ""): Int = 0
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo1<!>(::bar1)
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo1<!>(::bar2)
|
|
||||||
|
|
||||||
foo1(::bar3) // Should be ambiguity
|
|
||||||
}
|
|
||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -14,8 +14,8 @@ fun unitCoercionAndDefaults(f: suspend () -> Unit) {}
|
|||||||
fun all(s: String = ""): Int = 0
|
fun all(s: String = ""): Int = 0
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
<!INAPPLICABLE_CANDIDATE!>unitCoercion<!>(::foo)
|
unitCoercion(::foo)
|
||||||
<!INAPPLICABLE_CANDIDATE!>defaults<!>(::bar)
|
defaults(::bar)
|
||||||
<!INAPPLICABLE_CANDIDATE!>varargs<!>(::baz)
|
<!INAPPLICABLE_CANDIDATE!>varargs<!>(::baz)
|
||||||
<!INAPPLICABLE_CANDIDATE!>unitCoercionAndDefaults<!>(::all)
|
unitCoercionAndDefaults(::all)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -14,5 +14,5 @@ abstract class SubInt : () -> Int
|
|||||||
fun test(f: () -> String, s: SubInt) {
|
fun test(f: () -> String, s: SubInt) {
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(f)
|
<!INAPPLICABLE_CANDIDATE!>foo<!>(f)
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(s)
|
<!INAPPLICABLE_CANDIDATE!>foo<!>(s)
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(::bar)
|
foo(::bar)
|
||||||
}
|
}
|
||||||
+1
-1
@@ -8,7 +8,7 @@ fun bar(): String = ""
|
|||||||
abstract class SubInt : () -> Int
|
abstract class SubInt : () -> Int
|
||||||
|
|
||||||
fun test(g: () -> Double, s: SubInt) {
|
fun test(g: () -> Double, s: SubInt) {
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(::bar)
|
foo(::bar)
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(g)
|
<!INAPPLICABLE_CANDIDATE!>foo<!>(g)
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(s)
|
<!INAPPLICABLE_CANDIDATE!>foo<!>(s)
|
||||||
}
|
}
|
||||||
+33
-13
@@ -59,30 +59,50 @@ FILE fqName:<root> fileName:/suspendConversion.kt
|
|||||||
fn: FUNCTION_REFERENCE 'public final fun foo0 (): kotlin.Unit [suspend] declared in <root>' type=kotlin.reflect.KSuspendFunction0<kotlin.Unit> origin=null reflectionTarget=<same>
|
fn: FUNCTION_REFERENCE 'public final fun foo0 (): kotlin.Unit [suspend] declared in <root>' type=kotlin.reflect.KSuspendFunction0<kotlin.Unit> origin=null reflectionTarget=<same>
|
||||||
FUN name:testSuspendPlain visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
FUN name:testSuspendPlain visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [/useSuspend]>#' type=IrErrorType
|
CALL 'public final fun useSuspend (fn: kotlin.coroutines.SuspendFunction0<kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
FUNCTION_REFERENCE 'public final fun foo1 (): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction0<kotlin.Unit> origin=null reflectionTarget=<same>
|
fn: FUN_EXPR type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
|
||||||
|
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:foo1 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend]
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public final fun foo1 (): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
FUN name:testSuspendWithArgs visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
FUN name:testSuspendWithArgs visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [/useSuspendInt]>#' type=IrErrorType
|
CALL 'public final fun useSuspendInt (fn: kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
FUNCTION_REFERENCE 'public final fun fooInt (x: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit> origin=null reflectionTarget=<same>
|
fn: FUN_EXPR type=kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
|
||||||
|
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:fooInt visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit [suspend]
|
||||||
|
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public final fun fooInt (x: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
x: GET_VAR 'p0: kotlin.Int declared in <root>.testSuspendWithArgs.fooInt' type=kotlin.Int origin=null
|
||||||
FUN name:testWithVararg visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
FUN name:testWithVararg visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [/useSuspend]>#' type=IrErrorType
|
CALL 'public final fun useSuspend (fn: kotlin.coroutines.SuspendFunction0<kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
FUNCTION_REFERENCE 'public final fun foo2 (vararg xs: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Unit> origin=null reflectionTarget=<same>
|
fn: FUN_EXPR type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
|
||||||
|
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:foo2 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend]
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public final fun foo2 (vararg xs: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
FUN name:testWithVarargMapped visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
FUN name:testWithVarargMapped visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [/useSuspendInt]>#' type=IrErrorType
|
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [/useSuspendInt]>#' type=IrErrorType
|
||||||
FUNCTION_REFERENCE 'public final fun foo2 (vararg xs: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Unit> origin=null reflectionTarget=<same>
|
FUNCTION_REFERENCE 'public final fun foo2 (vararg xs: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Unit> origin=null reflectionTarget=<same>
|
||||||
FUN name:testWithCoercionToUnit visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
FUN name:testWithCoercionToUnit visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [/useSuspend]>#' type=IrErrorType
|
CALL 'public final fun useSuspend (fn: kotlin.coroutines.SuspendFunction0<kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
FUNCTION_REFERENCE 'public final fun foo3 (): kotlin.Int declared in <root>' type=kotlin.reflect.KFunction0<kotlin.Int> origin=null reflectionTarget=<same>
|
fn: FUN_EXPR type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
|
||||||
|
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:foo3 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend]
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='local final fun foo3 (): kotlin.Unit [suspend] declared in <root>.testWithCoercionToUnit'
|
||||||
|
CALL 'public final fun foo3 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||||
FUN name:testWithDefaults visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
FUN name:testWithDefaults visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [/useSuspend]>#' type=IrErrorType
|
CALL 'public final fun useSuspend (fn: kotlin.coroutines.SuspendFunction0<kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
FUNCTION_REFERENCE 'public final fun foo4 (i: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit> origin=null reflectionTarget=<same>
|
fn: FUN_EXPR type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
|
||||||
|
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:foo4 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend]
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public final fun foo4 (i: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
FUN name:testWithBoundReceiver visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
FUN name:testWithBoundReceiver visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [/useSuspend]>#' type=IrErrorType
|
CALL 'public final fun useSuspend (fn: kotlin.coroutines.SuspendFunction0<kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
FUNCTION_REFERENCE 'public final fun bar (): kotlin.Unit declared in <root>.C' type=kotlin.reflect.KFunction0<kotlin.Unit> origin=null reflectionTarget=<same>
|
fn: FUN_EXPR type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
|
||||||
$this: CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.C' type=<root>.C origin=null
|
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:bar visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend]
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public final fun bar (): kotlin.Unit declared in <root>.C' type=kotlin.Unit origin=null
|
||||||
|
|||||||
Reference in New Issue
Block a user