[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.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.referenceExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.ModifierCheckerCore
|
||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
||||
@@ -561,7 +562,7 @@ class PSICallResolver(
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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.annotations.Annotations
|
||||
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.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
@@ -113,6 +114,7 @@ class CallableReferencesCandidateFactory(
|
||||
val compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit,
|
||||
val expectedType: UnwrappedType?
|
||||
) : CandidateFactory<CallableReferenceCandidate> {
|
||||
private val position = ArgumentConstraintPosition(argument)
|
||||
|
||||
fun createCallableProcessor(explicitReceiver: DetailedReceiver?) =
|
||||
createCallableReferenceProcessor(outerCallContext.scopeTower, argument.rhsName, this, explicitReceiver)
|
||||
@@ -152,8 +154,11 @@ class CallableReferencesCandidateFactory(
|
||||
|
||||
val toFreshSubstitutor = CreateDescriptorWithFreshTypeVariables.createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, it, kotlinCall = null)
|
||||
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))
|
||||
}
|
||||
|
||||
@@ -161,6 +166,16 @@ class CallableReferencesCandidateFactory(
|
||||
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(
|
||||
descriptor: FunctionDescriptor,
|
||||
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.model.*
|
||||
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.checker.captureFromExpression
|
||||
import org.jetbrains.kotlin.types.checker.hasSupertypeWithGivenTypeConstructor
|
||||
@@ -202,7 +203,7 @@ internal fun checkExpressionArgument(
|
||||
isReceiver: Boolean
|
||||
): KotlinCallDiagnostic? {
|
||||
// todo run this approximation only once for call
|
||||
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(expressionArgument.stableType, expectedType)
|
||||
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(expressionArgument.receiver.stableType, expectedType)
|
||||
|
||||
fun unstableSmartCastOrSubtypeError(
|
||||
unstableType: UnwrappedType?, expectedType: UnwrappedType, position: ConstraintPosition
|
||||
@@ -220,17 +221,17 @@ internal fun checkExpressionArgument(
|
||||
val position = if (isReceiver) ReceiverConstraintPosition(expressionArgument) else ArgumentConstraintPosition(expressionArgument)
|
||||
if (expressionArgument.isSafeCall) {
|
||||
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
|
||||
}
|
||||
|
||||
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedType, position)) {
|
||||
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)) {
|
||||
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
|
||||
private val ExpressionKotlinCallArgument.unstableType: UnwrappedType?
|
||||
private val ReceiverValueWithSmartCastInfo.unstableType: UnwrappedType?
|
||||
get() {
|
||||
if (receiver.isStable || receiver.possibleTypes.isEmpty()) return null
|
||||
return intersectWrappedTypes(receiver.possibleTypes + receiver.receiverValue.type)
|
||||
if (isStable || possibleTypes.isEmpty()) return null
|
||||
return intersectWrappedTypes(possibleTypes + receiverValue.type)
|
||||
}
|
||||
|
||||
// with all smart casts if stable
|
||||
internal val ExpressionKotlinCallArgument.stableType: UnwrappedType
|
||||
internal val ReceiverValueWithSmartCastInfo.stableType: UnwrappedType
|
||||
get() {
|
||||
if (!receiver.isStable || receiver.possibleTypes.isEmpty()) return receiver.receiverValue.type.unwrap()
|
||||
return intersectWrappedTypes(receiver.possibleTypes + receiver.receiverValue.type)
|
||||
if (!isStable || possibleTypes.isEmpty()) return receiverValue.type.unwrap()
|
||||
return intersectWrappedTypes(possibleTypes + receiverValue.type)
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -55,9 +55,9 @@ internal object CheckVisibility : ResolutionPart {
|
||||
val invisibleMember = Visibilities.findInvisibleMember(receiverValue, candidateDescriptor, containingDescriptor) ?: return emptyList()
|
||||
|
||||
if (dispatchReceiverArgument is ExpressionKotlinCallArgument) {
|
||||
val smartCastReceiver = getReceiverValueWithSmartCast(receiverValue, dispatchReceiverArgument.stableType)
|
||||
val smartCastReceiver = getReceiverValueWithSmartCast(receiverValue, dispatchReceiverArgument.receiver.stableType)
|
||||
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