diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponeArgumentsChecks.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponeArgumentsChecks.kt index 0991673e648..e5ba9375217 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponeArgumentsChecks.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponeArgumentsChecks.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition +import org.jetbrains.kotlin.resolve.calls.inference.model.LHSArgumentConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.types.UnwrappedType @@ -141,6 +142,14 @@ private fun preprocessCallableReference( val notCallableTypeConstructor = csBuilder.getProperSuperTypeConstructors(expectedType).firstOrNull { !ReflectionTypes.isPossibleExpectedCallableType(it) } + + argument.lhsResult.safeAs()?.let { + val lhsType = it.unboundDetailedReceiver.stableType + if (ReflectionTypes.isNumberedTypeWithOneOrMoreNumber(expectedType)) { + val lhsTypeVariable = expectedType.arguments.first().type.unwrap() + csBuilder.addSubtypeConstraint(lhsType, lhsTypeVariable, LHSArgumentConstraintPosition(it.qualifier)) + } + } if (notCallableTypeConstructor != null) { diagnosticsHolder.addDiagnostic(NotCallableExpectedType(argument, expectedType, notCallableTypeConstructor)) } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt index 0f2c7ceb68e..f8b67d04582 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.INAPPLICABLE import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER +import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.UnwrappedType @@ -55,6 +56,12 @@ class KnownTypeParameterConstraintPosition(val typeArgument: KotlinType) : Const override fun toString() = "TypeArgument $typeArgument" } +class LHSArgumentConstraintPosition(val receiver: QualifierReceiver) : ConstraintPosition() { + override fun toString(): String { + return "LHS receiver $receiver" + } +} + class LambdaArgumentConstraintPosition(val lambda: ResolvedLambdaAtom) : ConstraintPosition() { override fun toString(): String { return "LambdaArgument $lambda" diff --git a/compiler/testData/diagnostics/tests/callableReference/kt25433.kt b/compiler/testData/diagnostics/tests/callableReference/kt25433.kt new file mode 100644 index 00000000000..b9a172d117d --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/kt25433.kt @@ -0,0 +1,17 @@ +// !WITH_NEW_INFERENCE +// !DIAGNOSTICS: -UNUSED_PARAMETER +// Issue: KT-25433 + +import kotlin.reflect.* + +fun hidden(nameProp: KProperty1, value: R) {} +fun hiddenFun(nameFunc: KFunction1, value: R) {} + +class App(val nullable: String?) { + fun nullableFun(): String? = null +} + +fun test() { + hidden(App::nullable, "foo") + hiddenFun(App::nullableFun, "foo") +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/kt25433.txt b/compiler/testData/diagnostics/tests/callableReference/kt25433.txt new file mode 100644 index 00000000000..00803c03764 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/kt25433.txt @@ -0,0 +1,14 @@ +package + +public fun hidden(/*0*/ nameProp: kotlin.reflect.KProperty1, /*1*/ value: R): kotlin.Unit +public fun hiddenFun(/*0*/ nameFunc: kotlin.reflect.KFunction1, /*1*/ value: R): kotlin.Unit +public fun test(): kotlin.Unit + +public final class App { + public constructor App(/*0*/ nullable: kotlin.String?) + public final val nullable: kotlin.String? + 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 final fun nullableFun(): kotlin.String? + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 2bcd0bd3a65..40449e139b4 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -1681,6 +1681,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/callableReference/kt15439_completeCall.kt"); } + @TestMetadata("kt25433.kt") + public void testKt25433() throws Exception { + runTest("compiler/testData/diagnostics/tests/callableReference/kt25433.kt"); + } + @TestMetadata("kt7430_wrongClassOnLHS.kt") public void testKt7430_wrongClassOnLHS() throws Exception { runTest("compiler/testData/diagnostics/tests/callableReference/kt7430_wrongClassOnLHS.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 5e3e8741fa2..de1a76459dc 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -1676,6 +1676,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/callableReference/kt15439_completeCall.kt"); } + @TestMetadata("kt25433.kt") + public void testKt25433() throws Exception { + runTest("compiler/testData/diagnostics/tests/callableReference/kt25433.kt"); + } + @TestMetadata("kt7430_wrongClassOnLHS.kt") public void testKt7430_wrongClassOnLHS() throws Exception { runTest("compiler/testData/diagnostics/tests/callableReference/kt7430_wrongClassOnLHS.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/ReflectionTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/ReflectionTypes.kt index 07589fc778d..3f0c07dcc1c 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/ReflectionTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/ReflectionTypes.kt @@ -18,9 +18,13 @@ import org.jetbrains.kotlin.types.* import kotlin.reflect.KProperty val KOTLIN_REFLECT_FQ_NAME = FqName("kotlin.reflect") +val K_PROPERTY_PREFIX = "KProperty" +val K_MUTABLE_PROPERTY_PREFIX = "KMutableProperty" val K_FUNCTION_PREFIX = "KFunction" val K_SUSPEND_FUNCTION_PREFIX = "KSuspendFunction" +val PREFIXES = listOf(K_PROPERTY_PREFIX, K_MUTABLE_PROPERTY_PREFIX, K_FUNCTION_PREFIX, K_SUSPEND_FUNCTION_PREFIX) + class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: NotFoundClasses) { private val kotlinReflectScope: MemberScope by lazy(LazyThreadSafetyMode.PUBLICATION) { module.getPackage(KOTLIN_REFLECT_FQ_NAME).memberScope @@ -122,6 +126,20 @@ class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: Not hasFqName(descriptor, KotlinBuiltIns.FQ_NAMES.kMutableProperty2) } + fun isNumberedTypeWithOneOrMoreNumber(type: KotlinType): Boolean { + val descriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return false + if (DescriptorUtils.getFqName(descriptor).parent().toSafe() != KOTLIN_REFLECT_FQ_NAME) return false + val shortName = descriptor.name.asString() + + for (prefix in PREFIXES) { + if (shortName.startsWith(prefix)) { + val number = shortName.removePrefix(prefix) + return number.isNotEmpty() && number != "0" + } + } + return false + } + fun hasKPropertyTypeFqName(type: KotlinType): Boolean = hasFqName(type.constructor, KotlinBuiltIns.FQ_NAMES.kPropertyFqName)