From 138d558f6a684e804525d6624908135b4acb915b Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Thu, 17 Oct 2019 18:33:38 +0300 Subject: [PATCH] Fix compiler exception during resolution of ambiguous callable references Function return type can't and should not be used during overload resolution of callable references. Since it can be DeferredType, its substitution in CS caused exception. --- .../resolve/calls/results/FlatSignature.kt | 4 +-- .../inference/regressions/kt32862_both.kt | 16 ++++++++++ .../inference/regressions/kt32862_both.txt | 29 +++++++++++++++++++ .../inference/regressions/kt32862_none.kt | 12 ++++++++ .../inference/regressions/kt32862_none.txt | 6 ++++ .../kotlin/builtins/ReflectionTypes.kt | 2 +- .../kotlin/builtins/functionTypes.kt | 12 ++++++++ 7 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/regressions/kt32862_both.kt create mode 100644 compiler/testData/diagnostics/tests/inference/regressions/kt32862_both.txt create mode 100644 compiler/testData/diagnostics/tests/inference/regressions/kt32862_none.kt create mode 100644 compiler/testData/diagnostics/tests/inference/regressions/kt32862_none.txt diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignature.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignature.kt index 465d736d301..ae8f76170ee 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignature.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignature.kt @@ -16,8 +16,8 @@ package org.jetbrains.kotlin.resolve.calls.results +import org.jetbrains.kotlin.builtins.getAllParameterProjectionsFromCallableReflectionType import org.jetbrains.kotlin.container.DefaultImplementation -import org.jetbrains.kotlin.container.PlatformExtensionsClashResolver import org.jetbrains.kotlin.container.PlatformSpecificExtension import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.MemberDescriptor @@ -62,7 +62,7 @@ class FlatSignature constructor( return FlatSignature( origin, descriptor.typeParameters, - reflectionType.arguments.map { it.type }, // should we drop return type? + reflectionType.getAllParameterProjectionsFromCallableReflectionType().map { it.type }, hasExtensionReceiver = false, hasVarargs = descriptor.valueParameters.any { it.varargElementType != null }, numDefaults = numDefaults, diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt32862_both.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt32862_both.kt new file mode 100644 index 00000000000..1d379fe81fe --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt32862_both.kt @@ -0,0 +1,16 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE + +interface G { + fun build(): G +} +class V1(val value: V) +class V2(val value: V) +fun G.foo(vararg values: V1) = build() +fun G.foo(vararg values: V2) = build() + +fun forReference(ref: Any?) {} + +fun test() { + forReference(G::foo) +} diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt32862_both.txt b/compiler/testData/diagnostics/tests/inference/regressions/kt32862_both.txt new file mode 100644 index 00000000000..92b363fc213 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt32862_both.txt @@ -0,0 +1,29 @@ +package + +public fun forReference(/*0*/ ref: kotlin.Any?): kotlin.Unit +public fun test(): kotlin.Unit +public fun G.foo(/*0*/ vararg values: V1 /*kotlin.Array>*/): G +public fun G.foo(/*0*/ vararg values: V2 /*kotlin.Array>*/): G + +public interface G { + public abstract fun build(): G + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class V1 { + public constructor V1(/*0*/ value: V) + public final val value: V + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class V2 { + public constructor V2(/*0*/ value: V) + public final val value: V + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt32862_none.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt32862_none.kt new file mode 100644 index 00000000000..60c0635ac66 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt32862_none.kt @@ -0,0 +1,12 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !LANGUAGE: +NewInference +// !WITH_NEW_INFERENCE + +fun foo(s: String) {} +fun foo(i: Long) {} + +fun bar(f: (Boolean) -> Unit) {} + +fun test() { + bar(::foo) +} diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt32862_none.txt b/compiler/testData/diagnostics/tests/inference/regressions/kt32862_none.txt new file mode 100644 index 00000000000..e51ec98eafc --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt32862_none.txt @@ -0,0 +1,6 @@ +package + +public fun bar(/*0*/ f: (kotlin.Boolean) -> kotlin.Unit): kotlin.Unit +public fun foo(/*0*/ i: kotlin.Long): kotlin.Unit +public fun foo(/*0*/ s: kotlin.String): kotlin.Unit +public fun test(): kotlin.Unit diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/ReflectionTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/ReflectionTypes.kt index 67b0ddd8eeb..4f1d8ef10b2 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/ReflectionTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/ReflectionTypes.kt @@ -112,7 +112,7 @@ class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: Not fun isNumberedKPropertyOrKMutablePropertyType(type: KotlinType): Boolean = isNumberedKPropertyType(type) || isNumberedKMutablePropertyType(type) - private fun isKCallableType(type: KotlinType): Boolean = + fun isKCallableType(type: KotlinType): Boolean = hasKCallableTypeFqName(type) || type.constructor.supertypes.any { isKCallableType(it) } fun hasKCallableTypeFqName(type: KotlinType): Boolean = diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt index 558ed5a6a5b..bf5428e07cd 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlin.utils.addToStdlib.safeAs import java.util.* private fun KotlinType.isTypeOrSubtypeOf(predicate: (KotlinType) -> Boolean): Boolean = @@ -58,6 +59,9 @@ val KotlinType.isFunctionType: Boolean val KotlinType.isSuspendFunctionType: Boolean get() = constructor.declarationDescriptor?.getFunctionalClassKind() == FunctionClassDescriptor.Kind.SuspendFunction +val KotlinType.isCallableReflectionType: Boolean + get() = ReflectionTypes.isKCallableType(this) + val KotlinType.isKSuspendFunctionType: Boolean get() = constructor.declarationDescriptor?.getFunctionalClassKind() == FunctionClassDescriptor.Kind.KSuspendFunction @@ -139,6 +143,14 @@ fun KotlinType.getValueParameterTypesFromFunctionType(): List { return arguments.subList(first, last) } +fun KotlinType.getAllParameterProjectionsFromCallableReflectionType(): List { + assert(isCallableReflectionType) { "Not a callable reflection type: $this" } + val arguments = arguments + val last = arguments.size - 1 + assert(last >= 0) { "Unexpected number of type arguments in type: $this" } + return arguments.subList(0, last) +} + fun KotlinType.extractParameterNameFromFunctionTypeArgument(): Name? { val annotation = annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.parameterName) ?: return null val name = (annotation.allValueArguments.values.singleOrNull() as? StringValue)