[NI] Make callable references more robust to overloads of outer call

#KT-30676 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2019-04-04 12:03:15 +03:00
parent 20a7f387bf
commit c3bc6ef2fa
17 changed files with 147 additions and 17 deletions
@@ -2328,6 +2328,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/byValType.kt");
}
@TestMetadata("chooseOuterCallBySingleCallableReference.kt")
public void testChooseOuterCallBySingleCallableReference() throws Exception {
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/chooseOuterCallBySingleCallableReference.kt");
}
@TestMetadata("commonSupertypeFromReturnTypesOfCallableReference.kt")
public void testCommonSupertypeFromReturnTypesOfCallableReference() throws Exception {
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/commonSupertypeFromReturnTypesOfCallableReference.kt");
@@ -2398,6 +2403,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/moreSpecificSimple.kt");
}
@TestMetadata("multipleOutersAndMultipleCallableReferences.kt")
public void testMultipleOutersAndMultipleCallableReferences() throws Exception {
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/multipleOutersAndMultipleCallableReferences.kt");
}
@TestMetadata("noFakeDescriptorForObject.kt")
public void testNoFakeDescriptorForObject() throws Exception {
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/noFakeDescriptorForObject.kt");
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver
import org.jetbrains.kotlin.resolve.calls.components.InferenceSession
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
@@ -67,7 +68,8 @@ class PSICallResolver(
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
private val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter,
private val deprecationResolver: DeprecationResolver,
private val moduleDescriptor: ModuleDescriptor
private val moduleDescriptor: ModuleDescriptor,
private val callableReferenceResolver: CallableReferenceResolver
) {
private val givenCandidatesName = Name.special("<given candidates>")
@@ -389,7 +391,9 @@ class PSICallResolver(
override fun factoryForVariable(stripExplicitReceiver: Boolean): CandidateFactory<KotlinResolutionCandidate> {
val explicitReceiver = if (stripExplicitReceiver) null else kotlinCall.explicitReceiver
val variableCall = PSIKotlinCallForVariable(kotlinCall, explicitReceiver, kotlinCall.name)
return SimpleCandidateFactory(callComponents, scopeTower, variableCall, createResolutionCallbacks(context))
return SimpleCandidateFactory(
callComponents, scopeTower, variableCall, createResolutionCallbacks(context), callableReferenceResolver
)
}
override fun factoryForInvoke(variable: KotlinResolutionCandidate, useExplicitReceiver: Boolean):
@@ -410,7 +414,7 @@ class PSICallResolver(
}
return variableCallArgument.receiver to SimpleCandidateFactory(
callComponents, scopeTower, callForInvoke, createResolutionCallbacks(context)
callComponents, scopeTower, callForInvoke, createResolutionCallbacks(context), callableReferenceResolver
)
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.resolve.calls
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver
import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
import org.jetbrains.kotlin.resolve.calls.components.NewOverloadingConflictResolver
@@ -32,6 +33,7 @@ class KotlinCallResolver(
private val towerResolver: TowerResolver,
private val kotlinCallCompleter: KotlinCallCompleter,
private val overloadingConflictResolver: NewOverloadingConflictResolver,
private val callableReferenceResolver: CallableReferenceResolver,
private val callComponents: KotlinCallComponents
) {
@@ -45,7 +47,9 @@ class KotlinCallResolver(
): CallResolutionResult {
kotlinCall.checkCallInvariants()
val candidateFactory = SimpleCandidateFactory(callComponents, scopeTower, kotlinCall, resolutionCallbacks)
val candidateFactory = SimpleCandidateFactory(
callComponents, scopeTower, kotlinCall, resolutionCallbacks, callableReferenceResolver
)
val processor = when (kotlinCall.callKind) {
KotlinCallKind.VARIABLE -> {
createVariableAndObjectProcessor(scopeTower, kotlinCall.name, candidateFactory, kotlinCall.explicitReceiver?.receiver)
@@ -96,7 +100,9 @@ class KotlinCallResolver(
collectAllCandidates: Boolean
): CallResolutionResult {
kotlinCall.checkCallInvariants()
val candidateFactory = SimpleCandidateFactory(callComponents, scopeTower, kotlinCall, resolutionCallbacks)
val candidateFactory = SimpleCandidateFactory(
callComponents, scopeTower, kotlinCall, resolutionCallbacks, callableReferenceResolver
)
val resolutionCandidates = givenCandidates.map { candidateFactory.createCandidate(it).forceResolution() }
@@ -29,15 +29,24 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun resolveKtPrimitive(
csBuilder: ConstraintSystemBuilder,
callableReferenceResolver: CallableReferenceResolver,
argument: KotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder,
isReceiver: Boolean
): ResolvedAtom = when (argument) {
is SimpleKotlinCallArgument -> checkSimpleArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver)
is LambdaKotlinCallArgument -> preprocessLambdaArgument(csBuilder, argument, expectedType)
is CallableReferenceKotlinCallArgument -> preprocessCallableReference(csBuilder, argument, expectedType, diagnosticsHolder)
is CollectionLiteralKotlinCallArgument -> preprocessCollectionLiteralArgument(argument, expectedType)
is SimpleKotlinCallArgument ->
checkSimpleArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver)
is LambdaKotlinCallArgument ->
preprocessLambdaArgument(csBuilder, argument, expectedType)
is CallableReferenceKotlinCallArgument ->
preprocessCallableReference(csBuilder, callableReferenceResolver, argument, expectedType, diagnosticsHolder)
is CollectionLiteralKotlinCallArgument ->
preprocessCollectionLiteralArgument(argument, expectedType)
else -> unexpectedArgument(argument)
}
@@ -133,11 +142,14 @@ fun LambdaWithTypeVariableAsExpectedTypeAtom.transformToResolvedLambda(csBuilder
private fun preprocessCallableReference(
csBuilder: ConstraintSystemBuilder,
callableReferenceResolver: CallableReferenceResolver,
argument: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder
): ResolvedAtom {
val result = EagerCallableReferenceAtom(argument, expectedType)
callableReferenceResolver.processCallableReferenceArgument(csBuilder, result, diagnosticsHolder)
if (expectedType == null) return result
val notCallableTypeConstructor =
@@ -93,7 +93,9 @@ class PostponedArgumentsAnalyzer(
returnArguments.forEach { c.addSubsystemFromArgument(it) }
val subResolvedKtPrimitives = returnArguments.map {
resolveKtPrimitive(c.getBuilder(), it, lambda.returnType.let(::substitute), diagnosticHolder, isReceiver = false)
resolveKtPrimitive(
c.getBuilder(), callableReferenceResolver, it, lambda.returnType.let(::substitute), diagnosticHolder, isReceiver = false
)
}
if (returnArguments.isEmpty()) {
@@ -275,7 +275,9 @@ private fun KotlinResolutionCandidate.resolveKotlinArgument(
isReceiver: Boolean
) {
val expectedType = candidateParameter?.let { prepareExpectedType(argument, candidateParameter) }
addResolvedKtPrimitive(resolveKtPrimitive(csBuilder, argument, expectedType, this, isReceiver))
addResolvedKtPrimitive(
resolveKtPrimitive(csBuilder, callableReferenceResolver, argument, expectedType, this, isReceiver)
)
}
private fun KotlinResolutionCandidate.prepareExpectedType(
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.resolve.calls.components.*
import org.jetbrains.kotlin.resolve.calls.inference.addSubsystemFromArgument
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDynamicExtensionAnnotation
@@ -50,7 +49,8 @@ class SimpleCandidateFactory(
val callComponents: KotlinCallComponents,
val scopeTower: ImplicitScopeTower,
val kotlinCall: KotlinCall,
val resolutionCallbacks: KotlinResolutionCallbacks
val resolutionCallbacks: KotlinResolutionCallbacks,
val callableReferenceResolver: CallableReferenceResolver
) : CandidateFactory<KotlinResolutionCandidate> {
val inferenceSession: InferenceSession = resolutionCallbacks.inferenceSession
@@ -135,6 +135,7 @@ class SimpleCandidateFactory(
if (ErrorUtils.isError(descriptor)) {
return KotlinResolutionCandidate(
callComponents,
callableReferenceResolver,
scopeTower,
baseSystem,
resolvedKtCall,
@@ -143,7 +144,9 @@ class SimpleCandidateFactory(
)
}
val candidate = KotlinResolutionCandidate(callComponents, scopeTower, baseSystem, resolvedKtCall, knownSubstitutor)
val candidate = KotlinResolutionCandidate(
callComponents, callableReferenceResolver, scopeTower, baseSystem, resolvedKtCall, knownSubstitutor
)
initialDiagnostics.forEach(candidate::addDiagnostic)
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.model
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver
import org.jetbrains.kotlin.resolve.calls.components.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
@@ -64,6 +65,7 @@ fun KotlinDiagnosticsHolder.addDiagnosticIfNotNull(diagnostic: KotlinCallDiagnos
*/
class KotlinResolutionCandidate(
val callComponents: KotlinCallComponents,
val callableReferenceResolver: CallableReferenceResolver,
val scopeTower: ImplicitScopeTower,
private val baseSystem: ConstraintStorage,
val resolvedCall: MutableResolvedCallAtom,
@@ -15,5 +15,5 @@ fun take(f: () -> Unit) {}
fun test() {
B::foo checkType { _<KFunction1<B, Unit>>() }
<!NI;OVERLOAD_RESOLUTION_AMBIGUITY, OI;NONE_APPLICABLE!>take<!>(B::<!NI;DEBUG_INFO_MISSING_UNRESOLVED!>foo<!>)
<!NONE_APPLICABLE!>take<!>(B::<!NI;DEBUG_INFO_MISSING_UNRESOLVED!>foo<!>)
}
@@ -0,0 +1,18 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
import kotlin.reflect.KProperty1
class Inv<T>
fun <T, R : Number> foo(prop: KProperty1<T, R>, p: String = "") {}
fun <T, R> foo(prop: KProperty1<T, Inv<R>>, p: Int = 42) {}
class A {
val prop = 42
}
fun test() {
foo(A::prop)
}
@@ -0,0 +1,20 @@
package
public fun </*0*/ T, /*1*/ R> foo(/*0*/ prop: kotlin.reflect.KProperty1<T, Inv<R>>, /*1*/ p: kotlin.Int = ...): kotlin.Unit
public fun </*0*/ T, /*1*/ R : kotlin.Number> foo(/*0*/ prop: kotlin.reflect.KProperty1<T, R>, /*1*/ p: kotlin.String = ...): kotlin.Unit
public fun test(): kotlin.Unit
public final class A {
public constructor A()
public final val prop: kotlin.Int = 42
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 Inv</*0*/ T> {
public constructor Inv</*0*/ T>()
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
}
@@ -0,0 +1,16 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
interface Base
class Inv<K> : Base
fun foo(x: Int): Inv<Int> = TODO()
fun foo(y: String): Inv<String> = TODO()
fun <T, R : Number> bar(f: (T) -> Inv<R>, p: String = "") {}
fun <T, R : Base> bar(f: (T) -> Inv<R>, p: Int = 4) {}
fun test() {
<!OVERLOAD_RESOLUTION_AMBIGUITY!>bar<!>(::<!DEBUG_INFO_MISSING_UNRESOLVED!>foo<!>)
}
@@ -0,0 +1,20 @@
package
public fun </*0*/ T, /*1*/ R : Base> bar(/*0*/ f: (T) -> Inv<R>, /*1*/ p: kotlin.Int = ...): kotlin.Unit
public fun </*0*/ T, /*1*/ R : kotlin.Number> bar(/*0*/ f: (T) -> Inv<R>, /*1*/ p: kotlin.String = ...): kotlin.Unit
public fun foo(/*0*/ x: kotlin.Int): Inv<kotlin.Int>
public fun foo(/*0*/ y: kotlin.String): Inv<kotlin.String>
public fun test(): kotlin.Unit
public interface Base {
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 Inv</*0*/ K> : Base {
public constructor Inv</*0*/ K>()
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
}
@@ -21,7 +21,7 @@ fun fn3(i: Int, f: (Int, Int, Int) -> Int): Int = f(i, i, i)
val x1 = fn1(1, ::foo, ::foo)
val x2 = fn1(1, ::foo, ::bar)
val x3 = <!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>fn2<!>(::<!NI;DEBUG_INFO_MISSING_UNRESOLVED!>bar<!>, ::<!NI;DEBUG_INFO_MISSING_UNRESOLVED!>foo<!>)
val x3 = fn2(::bar, ::foo)
val x4 = <!OVERLOAD_RESOLUTION_AMBIGUITY!>fn2<!>(::<!NI;DEBUG_INFO_MISSING_UNRESOLVED, OI;OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>, ::<!NI;DEBUG_INFO_MISSING_UNRESOLVED!>bar<!>)
val x5 = <!OVERLOAD_RESOLUTION_AMBIGUITY!>fn2<!>(::<!NI;DEBUG_INFO_MISSING_UNRESOLVED, OI;OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>, ::<!NI;DEBUG_INFO_MISSING_UNRESOLVED, OI;OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>)
@@ -2,7 +2,7 @@ package
public val x1: kotlin.String
public val x2: kotlin.String
public val x3: [ERROR : Type for fn2(::bar, ::foo)]
public val x3: kotlin.String
public val x4: [ERROR : Type for fn2(::foo, ::bar)]
public val x5: [ERROR : Type for fn2(::foo, ::foo)]
public val x6: kotlin.Int
@@ -2410,6 +2410,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/moreSpecificSimple.kt");
}
@TestMetadata("multipleOutersAndMultipleCallableReferences.kt")
public void testMultipleOutersAndMultipleCallableReferences() throws Exception {
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/multipleOutersAndMultipleCallableReferences.kt");
}
@TestMetadata("noFakeDescriptorForObject.kt")
public void testNoFakeDescriptorForObject() throws Exception {
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/noFakeDescriptorForObject.kt");
@@ -2330,6 +2330,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/byValType.kt");
}
@TestMetadata("chooseOuterCallBySingleCallableReference.kt")
public void testChooseOuterCallBySingleCallableReference() throws Exception {
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/chooseOuterCallBySingleCallableReference.kt");
}
@TestMetadata("commonSupertypeFromReturnTypesOfCallableReference.kt")
public void testCommonSupertypeFromReturnTypesOfCallableReference() throws Exception {
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/commonSupertypeFromReturnTypesOfCallableReference.kt");
@@ -2400,6 +2405,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/moreSpecificSimple.kt");
}
@TestMetadata("multipleOutersAndMultipleCallableReferences.kt")
public void testMultipleOutersAndMultipleCallableReferences() throws Exception {
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/multipleOutersAndMultipleCallableReferences.kt");
}
@TestMetadata("noFakeDescriptorForObject.kt")
public void testNoFakeDescriptorForObject() throws Exception {
runTest("compiler/testData/diagnostics/tests/callableReference/resolve/noFakeDescriptorForObject.kt");