From 9017654b9d7f4a672f38218b99f41e6c9a73bfc5 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 19 Feb 2020 10:59:43 +0300 Subject: [PATCH] [FIR] Handle default parameters when checking callable reference type #KT-36759 Fixed --- .../kotlin/fir/resolve/calls/ResolverParts.kt | 21 +++++++++++++++---- .../callableReferencesAndDefaultParameters.kt | 2 +- ...callableReferencesAndDefaultParameters.txt | 2 +- .../simpleDefaultArgument.kt | 1 - .../box/defaultArguments/referenceAsArg.kt | 1 - ...WithDefaultValueAsOtherFunctionType.fir.kt | 2 +- ...ultValueAsOtherFunctionType_enabled.fir.kt | 2 +- .../resolve/overloads.fir.kt | 2 +- .../withAdaptedArguments.fir.txt | 10 ++++----- .../withVarargViewedAsArray.fir.txt | 4 ++-- 10 files changed, 29 insertions(+), 18 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt index 9e0a992f561..3d19bf1656d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt @@ -230,7 +230,10 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() { val returnTypeRef = candidate.bodyResolveComponents.returnTypeCalculator.tryCalculateReturnType(fir) val resultingType: ConeKotlinType = when (fir) { - is FirFunction -> createKFunctionType(fir, resultingReceiverType, returnTypeRef) + is FirFunction -> createKFunctionType( + fir, resultingReceiverType, returnTypeRef, + expectedParameterNumberWithReceiver = expectedType?.let { it.typeArguments.size - 1 } + ) is FirVariable<*> -> createKPropertyType(fir, resultingReceiverType, returnTypeRef) else -> ConeKotlinErrorType("Unknown callable kind: ${fir::class}") }.let(candidate.substitutor::substituteOrSelf) @@ -284,10 +287,20 @@ private fun createKPropertyType( private fun createKFunctionType( function: FirFunction<*>, receiverType: ConeKotlinType?, - returnTypeRef: FirResolvedTypeRef + returnTypeRef: FirResolvedTypeRef, + expectedParameterNumberWithReceiver: Int? ): ConeKotlinType { - val parameterTypes = function.valueParameters.map { - it.returnTypeRef.coneTypeSafe() ?: ConeKotlinErrorType("No type for parameter $it") + val parameterTypes = mutableListOf() + val expectedParameterNumber = when { + expectedParameterNumberWithReceiver == null -> null + receiverType != null -> expectedParameterNumberWithReceiver - 1 + else -> expectedParameterNumberWithReceiver + } + for ((index, valueParameter) in function.valueParameters.withIndex()) { + if (expectedParameterNumber == null || index < expectedParameterNumber || valueParameter.defaultValue == null) { + parameterTypes += valueParameter.returnTypeRef.coneTypeSafe() + ?: ConeKotlinErrorType("No type for parameter $valueParameter") + } } return createFunctionalType( diff --git a/compiler/fir/resolve/testData/resolve/problems/callableReferencesAndDefaultParameters.kt b/compiler/fir/resolve/testData/resolve/problems/callableReferencesAndDefaultParameters.kt index 019bb375e75..d42b9a85ddd 100644 --- a/compiler/fir/resolve/testData/resolve/problems/callableReferencesAndDefaultParameters.kt +++ b/compiler/fir/resolve/testData/resolve/problems/callableReferencesAndDefaultParameters.kt @@ -5,5 +5,5 @@ class A { inline fun T.myLet(block: (T) -> Unit) {} fun test(a: A, s: String) { - s.myLet(a::foo) + s.myLet(a::foo) } \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/problems/callableReferencesAndDefaultParameters.txt b/compiler/fir/resolve/testData/resolve/problems/callableReferencesAndDefaultParameters.txt index 354783b2404..a0c1fab80f3 100644 --- a/compiler/fir/resolve/testData/resolve/problems/callableReferencesAndDefaultParameters.txt +++ b/compiler/fir/resolve/testData/resolve/problems/callableReferencesAndDefaultParameters.txt @@ -11,5 +11,5 @@ FILE: callableReferencesAndDefaultParameters.kt public final inline fun R|T|.myLet(block: R|(T) -> kotlin/Unit|): R|kotlin/Unit| { } public final fun test(a: R|A|, s: R|kotlin/String|): R|kotlin/Unit| { - R|/s|.#(R|/a|::R|/A.foo|) + R|/s|.R|/myLet|(R|/a|::R|/A.foo|) } diff --git a/compiler/testData/codegen/box/callableReference/varargAndDefaults/simpleDefaultArgument.kt b/compiler/testData/codegen/box/callableReference/varargAndDefaults/simpleDefaultArgument.kt index ada3893e105..4e763bea348 100644 --- a/compiler/testData/codegen/box/callableReference/varargAndDefaults/simpleDefaultArgument.kt +++ b/compiler/testData/codegen/box/callableReference/varargAndDefaults/simpleDefaultArgument.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType -// IGNORE_BACKEND_FIR: JVM_IR fun foo(x: String, y: String = "K"): String = x + y diff --git a/compiler/testData/codegen/box/defaultArguments/referenceAsArg.kt b/compiler/testData/codegen/box/defaultArguments/referenceAsArg.kt index bbd647a9bf4..e3a5d011077 100644 --- a/compiler/testData/codegen/box/defaultArguments/referenceAsArg.kt +++ b/compiler/testData/codegen/box/defaultArguments/referenceAsArg.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType -// IGNORE_BACKEND_FIR: JVM_IR inline fun String.app(f: (String) -> String) = f(this) diff --git a/compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType.fir.kt b/compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType.fir.kt index ed924b0da86..f4823010880 100644 --- a/compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType.fir.kt +++ b/compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType.fir.kt @@ -13,6 +13,6 @@ fun bar2(body: (String, Int) -> String): String { } fun test() { - bar1(::foo) + bar1(::foo) bar2(::foo) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType_enabled.fir.kt b/compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType_enabled.fir.kt index f104ac67c15..a4caa63e3d4 100644 --- a/compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType_enabled.fir.kt +++ b/compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType_enabled.fir.kt @@ -13,6 +13,6 @@ fun bar2(body: (String, Int) -> String): String { } fun test() { - bar1(::foo) + bar1(::foo) bar2(::foo) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/overloads.fir.kt b/compiler/testData/diagnostics/tests/callableReference/resolve/overloads.fir.kt index 4d70f87fc21..60effb9908c 100644 --- a/compiler/testData/diagnostics/tests/callableReference/resolve/overloads.fir.kt +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/overloads.fir.kt @@ -26,5 +26,5 @@ fun test() { B::bas - ::fas + ::fas } \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/callableReferences/withAdaptedArguments.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/withAdaptedArguments.fir.txt index b81735563b2..b42e8c0e8ec 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/withAdaptedArguments.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/withAdaptedArguments.fir.txt @@ -47,11 +47,11 @@ FILE fqName: fileName:/withAdaptedArguments.kt overridden: public open fun toString (): kotlin.String declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any - FUN name:testDefault visibility:public modality:FINAL <> () returnType:IrErrorType + FUN name:testDefault visibility:public modality:FINAL <> () returnType:kotlin.String BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun testDefault (): IrErrorType declared in ' - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - FUNCTION_REFERENCE 'public final fun fnWithDefault (a: kotlin.Int, b: kotlin.Int): kotlin.String declared in ' type=kotlin.reflect.KFunction2 origin=null reflectionTarget= + RETURN type=kotlin.Nothing from='public final fun testDefault (): kotlin.String declared in ' + CALL 'public final fun use (fn: kotlin.Function1): kotlin.String declared in ' type=kotlin.String origin=null + fn: FUNCTION_REFERENCE 'public final fun fnWithDefault (a: kotlin.Int, b: kotlin.Int): kotlin.String declared in ' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= FUN name:testVararg visibility:public modality:FINAL <> () returnType:IrErrorType BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun testVararg (): IrErrorType declared in ' @@ -61,7 +61,7 @@ FILE fqName: fileName:/withAdaptedArguments.kt BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun testCoercionToUnit (): IrErrorType declared in ' ERROR_CALL 'Unresolved reference: #' type=IrErrorType - FUNCTION_REFERENCE 'public final fun fnWithDefault (a: kotlin.Int, b: kotlin.Int): kotlin.String declared in ' type=kotlin.reflect.KFunction2 origin=null reflectionTarget= + FUNCTION_REFERENCE 'public final fun fnWithDefault (a: kotlin.Int, b: kotlin.Int): kotlin.String declared in ' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= FUN name:testImportedObjectMember visibility:public modality:FINAL <> () returnType:IrErrorType BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun testImportedObjectMember (): IrErrorType declared in ' diff --git a/compiler/testData/ir/irText/expressions/callableReferences/withVarargViewedAsArray.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/withVarargViewedAsArray.fir.txt index b8d40cbba89..2d1bc68075f 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/withVarargViewedAsArray.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/withVarargViewedAsArray.fir.txt @@ -72,5 +72,5 @@ FILE fqName: fileName:/withVarargViewedAsArray.kt FUNCTION_REFERENCE 'public final fun nsum (vararg args: kotlin.Number): kotlin.Int declared in ' type=kotlin.reflect.KFunction1, kotlin.Int> origin=null reflectionTarget= FUN name:testArrayAndDefaults visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - FUNCTION_REFERENCE 'public final fun zap (vararg b: kotlin.String, k: kotlin.Int): kotlin.Unit declared in ' type=kotlin.reflect.KFunction2, kotlin.Int, kotlin.Unit> origin=null reflectionTarget= + CALL 'public final fun useStringArray (fn: kotlin.Function1, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null + fn: FUNCTION_REFERENCE 'public final fun zap (vararg b: kotlin.String, k: kotlin.Int): kotlin.Unit declared in ' type=kotlin.reflect.KFunction1, kotlin.Unit> origin=null reflectionTarget=