[NI] Check receivers for callable reference resolution.
This commit is contained in:
committed by
Mikhail Zarechenskiy
parent
a5dffafacd
commit
c752e1580e
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.diagnostics.Errors
|
|||||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.referenceExpression
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.ModifierCheckerCore
|
import org.jetbrains.kotlin.resolve.ModifierCheckerCore
|
||||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
||||||
@@ -561,7 +562,7 @@ class PSICallResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is DoubleColonLHS.Type -> {
|
is DoubleColonLHS.Type -> {
|
||||||
val qualifier = expressionTypingContext.trace.get(BindingContext.QUALIFIER, ktExpression.receiverExpression!!)
|
val qualifier = expressionTypingContext.trace.get(BindingContext.QUALIFIER, ktExpression.receiverExpression!!.referenceExpression())
|
||||||
if (qualifier is ClassQualifier) {
|
if (qualifier is ClassQualifier) {
|
||||||
LHSResult.Type(qualifier)
|
LHSResult.Type(qualifier)
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-1
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.builtins.isFunctionType
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||||
@@ -113,6 +114,7 @@ class CallableReferencesCandidateFactory(
|
|||||||
val compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit,
|
val compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit,
|
||||||
val expectedType: UnwrappedType?
|
val expectedType: UnwrappedType?
|
||||||
) : CandidateFactory<CallableReferenceCandidate> {
|
) : CandidateFactory<CallableReferenceCandidate> {
|
||||||
|
private val position = ArgumentConstraintPosition(argument)
|
||||||
|
|
||||||
fun createCallableProcessor(explicitReceiver: DetailedReceiver?) =
|
fun createCallableProcessor(explicitReceiver: DetailedReceiver?) =
|
||||||
createCallableReferenceProcessor(outerCallContext.scopeTower, argument.rhsName, this, explicitReceiver)
|
createCallableReferenceProcessor(outerCallContext.scopeTower, argument.rhsName, this, explicitReceiver)
|
||||||
@@ -152,8 +154,11 @@ class CallableReferencesCandidateFactory(
|
|||||||
|
|
||||||
val toFreshSubstitutor = CreateDescriptorWithFreshTypeVariables.createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, it, kotlinCall = null)
|
val toFreshSubstitutor = CreateDescriptorWithFreshTypeVariables.createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, it, kotlinCall = null)
|
||||||
val reflectionType = toFreshSubstitutor.safeSubstitute(reflectionCandidateType)
|
val reflectionType = toFreshSubstitutor.safeSubstitute(reflectionCandidateType)
|
||||||
|
it.addSubtypeConstraint(reflectionType, expectedType, position)
|
||||||
|
|
||||||
|
it.addUnboundConstraint(toFreshSubstitutor, dispatchCallableReceiver, candidateDescriptor.dispatchReceiverParameter)
|
||||||
|
it.addUnboundConstraint(toFreshSubstitutor, extensionCallableReceiver, candidateDescriptor.extensionReceiverParameter)
|
||||||
|
|
||||||
it.addSubtypeConstraint(reflectionType, expectedType, ArgumentConstraintPosition(argument))
|
|
||||||
if (it.hasContradiction) diagnostics.add(CallableReferenceNotCompatible(argument, candidateDescriptor, expectedType, reflectionType))
|
if (it.hasContradiction) diagnostics.add(CallableReferenceNotCompatible(argument, candidateDescriptor, expectedType, reflectionType))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,6 +166,16 @@ class CallableReferencesCandidateFactory(
|
|||||||
explicitReceiverKind, reflectionCandidateType, defaults, ResolutionCandidateStatus(diagnostics))
|
explicitReceiverKind, reflectionCandidateType, defaults, ResolutionCandidateStatus(diagnostics))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ConstraintSystemOperation.addUnboundConstraint(
|
||||||
|
toFreshSubstitutor: FreshVariableNewTypeSubstitutor,
|
||||||
|
receiver: CallableReceiver?,
|
||||||
|
candidateReceiver: ReceiverParameterDescriptor?
|
||||||
|
) {
|
||||||
|
val expectedType = toFreshSubstitutor.safeSubstitute(candidateReceiver?.value?.type?.unwrap() ?: return)
|
||||||
|
val receiverType = receiver?.receiver?.stableType ?: return
|
||||||
|
addSubtypeConstraint(receiverType, expectedType, position)
|
||||||
|
}
|
||||||
|
|
||||||
private fun getArgumentAndReturnTypeUseMappingByExpectedType(
|
private fun getArgumentAndReturnTypeUseMappingByExpectedType(
|
||||||
descriptor: FunctionDescriptor,
|
descriptor: FunctionDescriptor,
|
||||||
expectedType: UnwrappedType?,
|
expectedType: UnwrappedType?,
|
||||||
|
|||||||
+11
-10
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ReceiverConstraintPosi
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType
|
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
import org.jetbrains.kotlin.types.checker.captureFromExpression
|
import org.jetbrains.kotlin.types.checker.captureFromExpression
|
||||||
import org.jetbrains.kotlin.types.checker.hasSupertypeWithGivenTypeConstructor
|
import org.jetbrains.kotlin.types.checker.hasSupertypeWithGivenTypeConstructor
|
||||||
@@ -202,7 +203,7 @@ internal fun checkExpressionArgument(
|
|||||||
isReceiver: Boolean
|
isReceiver: Boolean
|
||||||
): KotlinCallDiagnostic? {
|
): KotlinCallDiagnostic? {
|
||||||
// todo run this approximation only once for call
|
// todo run this approximation only once for call
|
||||||
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(expressionArgument.stableType, expectedType)
|
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(expressionArgument.receiver.stableType, expectedType)
|
||||||
|
|
||||||
fun unstableSmartCastOrSubtypeError(
|
fun unstableSmartCastOrSubtypeError(
|
||||||
unstableType: UnwrappedType?, expectedType: UnwrappedType, position: ConstraintPosition
|
unstableType: UnwrappedType?, expectedType: UnwrappedType, position: ConstraintPosition
|
||||||
@@ -220,17 +221,17 @@ internal fun checkExpressionArgument(
|
|||||||
val position = if (isReceiver) ReceiverConstraintPosition(expressionArgument) else ArgumentConstraintPosition(expressionArgument)
|
val position = if (isReceiver) ReceiverConstraintPosition(expressionArgument) else ArgumentConstraintPosition(expressionArgument)
|
||||||
if (expressionArgument.isSafeCall) {
|
if (expressionArgument.isSafeCall) {
|
||||||
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
|
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
|
||||||
return unstableSmartCastOrSubtypeError(expressionArgument.unstableType, expectedNullableType, position)?.let { return it }
|
return unstableSmartCastOrSubtypeError(expressionArgument.receiver.unstableType, expectedNullableType, position)?.let { return it }
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedType, position)) {
|
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedType, position)) {
|
||||||
if (!isReceiver) {
|
if (!isReceiver) {
|
||||||
return unstableSmartCastOrSubtypeError(expressionArgument.unstableType, expectedType, position)?.let { return it }
|
return unstableSmartCastOrSubtypeError(expressionArgument.receiver.unstableType, expectedType, position)?.let { return it }
|
||||||
}
|
}
|
||||||
|
|
||||||
val unstableType = expressionArgument.unstableType
|
val unstableType = expressionArgument.receiver.unstableType
|
||||||
if (unstableType != null && csBuilder.addSubtypeConstraintIfCompatible(unstableType, expectedType, position)) {
|
if (unstableType != null && csBuilder.addSubtypeConstraintIfCompatible(unstableType, expectedType, position)) {
|
||||||
return UnstableSmartCast(expressionArgument, unstableType)
|
return UnstableSmartCast(expressionArgument, unstableType)
|
||||||
}
|
}
|
||||||
@@ -279,17 +280,17 @@ private fun captureFromTypeParameterUpperBoundIfNeeded(argumentType: UnwrappedTy
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if expression is not stable and has smart casts, then we create this type
|
// if expression is not stable and has smart casts, then we create this type
|
||||||
private val ExpressionKotlinCallArgument.unstableType: UnwrappedType?
|
private val ReceiverValueWithSmartCastInfo.unstableType: UnwrappedType?
|
||||||
get() {
|
get() {
|
||||||
if (receiver.isStable || receiver.possibleTypes.isEmpty()) return null
|
if (isStable || possibleTypes.isEmpty()) return null
|
||||||
return intersectWrappedTypes(receiver.possibleTypes + receiver.receiverValue.type)
|
return intersectWrappedTypes(possibleTypes + receiverValue.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
// with all smart casts if stable
|
// with all smart casts if stable
|
||||||
internal val ExpressionKotlinCallArgument.stableType: UnwrappedType
|
internal val ReceiverValueWithSmartCastInfo.stableType: UnwrappedType
|
||||||
get() {
|
get() {
|
||||||
if (!receiver.isStable || receiver.possibleTypes.isEmpty()) return receiver.receiverValue.type.unwrap()
|
if (!isStable || possibleTypes.isEmpty()) return receiverValue.type.unwrap()
|
||||||
return intersectWrappedTypes(receiver.possibleTypes + receiver.receiverValue.type)
|
return intersectWrappedTypes(possibleTypes + receiverValue.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -55,9 +55,9 @@ internal object CheckVisibility : ResolutionPart {
|
|||||||
val invisibleMember = Visibilities.findInvisibleMember(receiverValue, candidateDescriptor, containingDescriptor) ?: return emptyList()
|
val invisibleMember = Visibilities.findInvisibleMember(receiverValue, candidateDescriptor, containingDescriptor) ?: return emptyList()
|
||||||
|
|
||||||
if (dispatchReceiverArgument is ExpressionKotlinCallArgument) {
|
if (dispatchReceiverArgument is ExpressionKotlinCallArgument) {
|
||||||
val smartCastReceiver = getReceiverValueWithSmartCast(receiverValue, dispatchReceiverArgument.stableType)
|
val smartCastReceiver = getReceiverValueWithSmartCast(receiverValue, dispatchReceiverArgument.receiver.stableType)
|
||||||
if (Visibilities.findInvisibleMember(smartCastReceiver, candidateDescriptor, containingDescriptor) == null) {
|
if (Visibilities.findInvisibleMember(smartCastReceiver, candidateDescriptor, containingDescriptor) == null) {
|
||||||
return listOf(SmartCastDiagnostic(dispatchReceiverArgument, dispatchReceiverArgument.stableType))
|
return listOf(SmartCastDiagnostic(dispatchReceiverArgument, dispatchReceiverArgument.receiver.stableType))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user