Don't add LHS type constraint for callable references too early, before the resolution
The constraint depends on a resolution candidate, because it can be Java static or companion object's member (don't need add constraint in this case) ^KT-41978 Fixed
This commit is contained in:
committed by
TeamCityServer
parent
fd2929d2c5
commit
43a83dd07a
+36
@@ -7,16 +7,20 @@ package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.builtins.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
|
||||
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.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.captureFromExpression
|
||||
import org.jetbrains.kotlin.types.expressions.CoercionStrategy
|
||||
import org.jetbrains.kotlin.types.model.TypeVariance
|
||||
import org.jetbrains.kotlin.types.model.convertVariance
|
||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
|
||||
@@ -78,11 +82,21 @@ fun CallableReferenceResolutionCandidate.addConstraints(
|
||||
substitutor: FreshVariableNewTypeSubstitutor,
|
||||
callableReference: CallableReferenceResolutionAtom
|
||||
) {
|
||||
val lhsResult = callableReference.lhsResult
|
||||
val position = when (callableReference) {
|
||||
is CallableReferenceKotlinCallArgument -> ArgumentConstraintPositionImpl(callableReference)
|
||||
is CallableReferenceKotlinCall -> CallableReferenceConstraintPositionImpl(callableReference)
|
||||
}
|
||||
|
||||
if (lhsResult is LHSResult.Type && expectedType != null && !TypeUtils.noExpectedType(expectedType)) {
|
||||
// NB: regular objects have lhsResult of `LHSResult.Object` type and won't be proceeded here
|
||||
val isStaticOrCompanionMember =
|
||||
DescriptorUtils.isStaticDeclaration(candidate) || candidate.containingDeclaration.isCompanionObject()
|
||||
if (!isStaticOrCompanionMember) {
|
||||
constraintSystem.addLhsTypeConstraint(lhsResult.unboundDetailedReceiver.stableType, expectedType, position)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ErrorUtils.isError(candidate)) {
|
||||
constraintSystem.addReceiverConstraint(substitutor, dispatchReceiver, candidate.dispatchReceiverParameter, position)
|
||||
constraintSystem.addReceiverConstraint(substitutor, extensionReceiver, candidate.extensionReceiverParameter, position)
|
||||
@@ -93,6 +107,28 @@ fun CallableReferenceResolutionCandidate.addConstraints(
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConstraintSystemOperation.addLhsTypeConstraint(
|
||||
lhsType: KotlinType,
|
||||
expectedType: UnwrappedType,
|
||||
position: ConstraintPosition
|
||||
) {
|
||||
if (!ReflectionTypes.isNumberedTypeWithOneOrMoreNumber(expectedType)) return
|
||||
|
||||
val expectedTypeProjectionForLHS = expectedType.arguments.first()
|
||||
val expectedTypeForLHS = expectedTypeProjectionForLHS.type
|
||||
val expectedTypeVariance = expectedTypeProjectionForLHS.projectionKind.convertVariance()
|
||||
val effectiveVariance = AbstractTypeChecker.effectiveVariance(
|
||||
expectedType.constructor.parameters.first().variance.convertVariance(),
|
||||
expectedTypeVariance
|
||||
) ?: expectedTypeVariance
|
||||
|
||||
when (effectiveVariance) {
|
||||
TypeVariance.INV -> addEqualityConstraint(lhsType, expectedTypeForLHS, position)
|
||||
TypeVariance.IN -> addSubtypeConstraint(expectedTypeForLHS, lhsType, position)
|
||||
TypeVariance.OUT -> addSubtypeConstraint(lhsType, expectedTypeForLHS, position)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConstraintSystemOperation.addReceiverConstraint(
|
||||
toFreshSubstitutor: FreshVariableNewTypeSubstitutor,
|
||||
receiverArgument: CallableReceiver?,
|
||||
|
||||
-29
@@ -250,11 +250,6 @@ private fun preprocessCallableReference(
|
||||
|
||||
if (expectedType == null) return result
|
||||
|
||||
val lhsResult = argument.lhsResult
|
||||
if (lhsResult is LHSResult.Type) {
|
||||
csBuilder.addConstraintFromLHS(argument, lhsResult, expectedType)
|
||||
}
|
||||
|
||||
val notCallableTypeConstructor =
|
||||
csBuilder.getProperSuperTypeConstructors(expectedType)
|
||||
.firstOrNull { !ReflectionTypes.isPossibleExpectedCallableType(it.requireIs()) }
|
||||
@@ -271,30 +266,6 @@ private fun preprocessCallableReference(
|
||||
return result
|
||||
}
|
||||
|
||||
private fun ConstraintSystemBuilder.addConstraintFromLHS(
|
||||
argument: CallableReferenceKotlinCallArgument,
|
||||
lhsResult: LHSResult.Type,
|
||||
expectedType: UnwrappedType
|
||||
) {
|
||||
if (!ReflectionTypes.isNumberedTypeWithOneOrMoreNumber(expectedType)) return
|
||||
|
||||
val lhsType = lhsResult.unboundDetailedReceiver.stableType
|
||||
val expectedTypeProjectionForLHS = expectedType.arguments.first()
|
||||
val expectedTypeForLHS = expectedTypeProjectionForLHS.type
|
||||
val constraintPosition = LHSArgumentConstraintPositionImpl(argument, lhsResult.qualifier ?: lhsResult.unboundDetailedReceiver)
|
||||
val expectedTypeVariance = expectedTypeProjectionForLHS.projectionKind.convertVariance()
|
||||
val effectiveVariance = AbstractTypeChecker.effectiveVariance(
|
||||
expectedType.constructor.parameters.first().variance.convertVariance(),
|
||||
expectedTypeVariance
|
||||
) ?: expectedTypeVariance
|
||||
|
||||
when (effectiveVariance) {
|
||||
TypeVariance.INV -> addEqualityConstraint(lhsType, expectedTypeForLHS, constraintPosition)
|
||||
TypeVariance.IN -> addSubtypeConstraint(expectedTypeForLHS, lhsType, constraintPosition)
|
||||
TypeVariance.OUT -> addSubtypeConstraint(lhsType, expectedTypeForLHS, constraintPosition)
|
||||
}
|
||||
}
|
||||
|
||||
private fun preprocessCollectionLiteralArgument(
|
||||
collectionLiteralArgument: CollectionLiteralKotlinCallArgument,
|
||||
expectedType: UnwrappedType?
|
||||
|
||||
-5
@@ -46,11 +46,6 @@ class FixVariableConstraintPositionImpl(
|
||||
|
||||
class KnownTypeParameterConstraintPositionImpl(typeArgument: KotlinType) : KnownTypeParameterConstraintPosition<KotlinType>(typeArgument)
|
||||
|
||||
class LHSArgumentConstraintPositionImpl(
|
||||
argument: CallableReferenceKotlinCallArgument,
|
||||
receiver: DetailedReceiver
|
||||
) : LHSArgumentConstraintPosition<CallableReferenceKotlinCallArgument, DetailedReceiver>(argument, receiver)
|
||||
|
||||
class LambdaArgumentConstraintPositionImpl(lambda: ResolvedLambdaAtom) : LambdaArgumentConstraintPosition<ResolvedLambdaAtom>(lambda)
|
||||
|
||||
class DelegatedPropertyConstraintPositionImpl(topLevelCall: KotlinCall) : DelegatedPropertyConstraintPosition<KotlinCall>(topLevelCall)
|
||||
|
||||
Reference in New Issue
Block a user