[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
@@ -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,