[NI] Support callable reference resolution in NI.
Missing parts: - report results about callable references into trace
This commit is contained in:
committed by
Mikhail Zarechenskiy
parent
02f4558683
commit
55dc2c11f7
@@ -16,13 +16,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.tower
|
package org.jetbrains.kotlin.resolve.calls.tower
|
||||||
|
|
||||||
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
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.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument
|
import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
@@ -110,8 +110,8 @@ class CallableReferenceKotlinCallArgumentImpl(
|
|||||||
override val dataFlowInfoAfterThisArgument: DataFlowInfo,
|
override val dataFlowInfoAfterThisArgument: DataFlowInfo,
|
||||||
val ktCallableReferenceExpression: KtCallableReferenceExpression,
|
val ktCallableReferenceExpression: KtCallableReferenceExpression,
|
||||||
override val argumentName: Name?,
|
override val argumentName: Name?,
|
||||||
override val lhsType: UnwrappedType?,
|
override val lhsResult: LHSResult,
|
||||||
override val constraintStorage: ConstraintStorage
|
override val rhsName: Name
|
||||||
) : CallableReferenceKotlinCallArgument, PSIKotlinCallArgument()
|
) : CallableReferenceKotlinCallArgument, PSIKotlinCallArgument()
|
||||||
|
|
||||||
class SubKotlinCallArgumentImpl(
|
class SubKotlinCallArgumentImpl(
|
||||||
@@ -137,6 +137,16 @@ class ExpressionKotlinCallArgumentImpl(
|
|||||||
override val isSafeCall: Boolean get() = false
|
override val isSafeCall: Boolean get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FakeValueArgumentForLeftCallableReference(val ktExpression: KtCallableReferenceExpression): ValueArgument {
|
||||||
|
override fun getArgumentExpression() = ktExpression.receiverExpression
|
||||||
|
|
||||||
|
override fun getArgumentName(): ValueArgumentName? = null
|
||||||
|
override fun isNamed(): Boolean = false
|
||||||
|
override fun asElement(): KtElement = getArgumentExpression() ?: ktExpression
|
||||||
|
override fun getSpreadElement(): LeafPsiElement? = null
|
||||||
|
override fun isExternal(): Boolean = false
|
||||||
|
}
|
||||||
|
|
||||||
internal fun createSimplePSICallArgument(
|
internal fun createSimplePSICallArgument(
|
||||||
context: BasicCallResolutionContext,
|
context: BasicCallResolutionContext,
|
||||||
valueArgument: ValueArgument,
|
valueArgument: ValueArgument,
|
||||||
|
|||||||
@@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.tower
|
package org.jetbrains.kotlin.resolve.calls.tower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
@@ -28,9 +30,10 @@ 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
|
||||||
import org.jetbrains.kotlin.resolve.TypeResolver
|
import org.jetbrains.kotlin.resolve.TypeResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.*
|
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
|
import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation
|
import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.ArgumentsToParametersMapper
|
import org.jetbrains.kotlin.resolve.calls.components.ArgumentsToParametersMapper
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver
|
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver
|
||||||
@@ -40,7 +43,6 @@ import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
|||||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
|
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
|
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.*
|
import org.jetbrains.kotlin.resolve.calls.results.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
@@ -75,6 +77,7 @@ class PSICallResolver(
|
|||||||
val resultTypeResolver: ResultTypeResolver,
|
val resultTypeResolver: ResultTypeResolver,
|
||||||
val callableReferenceResolver: CallableReferenceResolver,
|
val callableReferenceResolver: CallableReferenceResolver,
|
||||||
val constraintInjector: ConstraintInjector,
|
val constraintInjector: ConstraintInjector,
|
||||||
|
val reflectionTypes: ReflectionTypes,
|
||||||
private val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer,
|
private val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer,
|
||||||
private val kotlinCallResolver: KotlinCallResolver,
|
private val kotlinCallResolver: KotlinCallResolver,
|
||||||
private val typeApproximator: TypeApproximator,
|
private val typeApproximator: TypeApproximator,
|
||||||
@@ -146,7 +149,7 @@ class PSICallResolver(
|
|||||||
|
|
||||||
private fun createCallContext(scopeTower: ASTScopeTower, resolutionCallbacks: KotlinResolutionCallbacks) =
|
private fun createCallContext(scopeTower: ASTScopeTower, resolutionCallbacks: KotlinResolutionCallbacks) =
|
||||||
KotlinCallContext(scopeTower, resolutionCallbacks, argumentsToParametersMapper, typeArgumentsToParametersMapper, resultTypeResolver,
|
KotlinCallContext(scopeTower, resolutionCallbacks, argumentsToParametersMapper, typeArgumentsToParametersMapper, resultTypeResolver,
|
||||||
callableReferenceResolver, constraintInjector)
|
callableReferenceResolver, constraintInjector, reflectionTypes)
|
||||||
|
|
||||||
private fun <D : CallableDescriptor> convertToOverloadResolutionResults(
|
private fun <D : CallableDescriptor> convertToOverloadResolutionResults(
|
||||||
context: BasicCallResolutionContext,
|
context: BasicCallResolutionContext,
|
||||||
@@ -456,17 +459,44 @@ class PSICallResolver(
|
|||||||
if (ktExpression is KtCallableReferenceExpression) {
|
if (ktExpression is KtCallableReferenceExpression) {
|
||||||
checkNoSpread(outerCallContext, valueArgument)
|
checkNoSpread(outerCallContext, valueArgument)
|
||||||
|
|
||||||
// todo analyze left expression and get constraint system
|
val expressionTypingContext = ExpressionTypingContext.newContext(context)
|
||||||
val (lhsResult, rightResults) = doubleColonExpressionResolver.resolveCallableReference(
|
val lhsResult = if (ktExpression.isEmptyLHS) null else doubleColonExpressionResolver.resolveDoubleColonLHS(ktExpression, expressionTypingContext)
|
||||||
ktExpression, ExpressionTypingContext.newContext(context), ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS)
|
|
||||||
|
|
||||||
val newDataFlowInfo = (lhsResult as? DoubleColonLHS.Expression)?.dataFlowInfo ?: startDataFlowInfo
|
val newDataFlowInfo = (lhsResult as? DoubleColonLHS.Expression)?.dataFlowInfo ?: startDataFlowInfo
|
||||||
|
val name = ktExpression.callableReference.getReferencedNameAsName()
|
||||||
|
|
||||||
// todo ChosenCallableReferenceDescriptor
|
val lhsNewResult = when (lhsResult) {
|
||||||
|
null -> LHSResult.Empty
|
||||||
|
is DoubleColonLHS.Expression -> {
|
||||||
|
if (lhsResult.isObjectQualifier) {
|
||||||
|
val classifier = lhsResult.type.constructor.declarationDescriptor
|
||||||
|
val calleeExpression = ktExpression.receiverExpression?.getCalleeExpressionIfAny()
|
||||||
|
if (calleeExpression is KtSimpleNameExpression && classifier is ClassDescriptor) {
|
||||||
|
LHSResult.Object(ClassQualifier(calleeExpression, classifier))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LHSResult.Empty // this is error case actually
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val fakeArgument = FakeValueArgumentForLeftCallableReference(ktExpression)
|
||||||
|
|
||||||
|
val kotlinCallArgument = createSimplePSICallArgument(context, fakeArgument, lhsResult.typeInfo)
|
||||||
|
kotlinCallArgument?.let { LHSResult.Expression(it as SimpleKotlinCallArgument) } ?: LHSResult.Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is DoubleColonLHS.Type -> {
|
||||||
|
val qualifier = expressionTypingContext.trace.get(BindingContext.QUALIFIER, ktExpression.receiverExpression!!)
|
||||||
|
if (qualifier is ClassQualifier) {
|
||||||
|
LHSResult.Type(qualifier)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LHSResult.Empty // this is error case actually
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return CallableReferenceKotlinCallArgumentImpl(valueArgument, startDataFlowInfo, newDataFlowInfo,
|
return CallableReferenceKotlinCallArgumentImpl(valueArgument, startDataFlowInfo, newDataFlowInfo,
|
||||||
ktExpression, argumentName, (lhsResult as? DoubleColonLHS.Type)?.type?.unwrap(),
|
ktExpression, argumentName, lhsNewResult, name)
|
||||||
ConstraintStorage.Empty)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// valueArgument.getArgumentExpression()!! instead of ktExpression is hack -- type info should be stored also for parenthesized expression
|
// valueArgument.getArgumentExpression()!! instead of ktExpression is hack -- type info should be stored also for parenthesized expression
|
||||||
|
|||||||
+1
-1
@@ -75,7 +75,7 @@ sealed class DoubleColonLHS(val type: KotlinType) {
|
|||||||
* (Obj)::class // not an object qualifier (can only be treated as an expression, not as a type)
|
* (Obj)::class // not an object qualifier (can only be treated as an expression, not as a type)
|
||||||
* { Obj }()::class // not an object qualifier
|
* { Obj }()::class // not an object qualifier
|
||||||
*/
|
*/
|
||||||
class Expression(typeInfo: KotlinTypeInfo, val isObjectQualifier: Boolean) : DoubleColonLHS(typeInfo.type!!) {
|
class Expression(val typeInfo: KotlinTypeInfo, val isObjectQualifier: Boolean) : DoubleColonLHS(typeInfo.type!!) {
|
||||||
val dataFlowInfo: DataFlowInfo = typeInfo.dataFlowInfo
|
val dataFlowInfo: DataFlowInfo = typeInfo.dataFlowInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+305
@@ -0,0 +1,305 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.calls.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||||
|
import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
|
||||||
|
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.model.ArgumentConstraintPosition
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tower.*
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
||||||
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
|
import org.jetbrains.kotlin.types.expressions.CoercionStrategy
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
import org.jetbrains.kotlin.types.upperIfFlexible
|
||||||
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
|
|
||||||
|
sealed class CallableReceiver {
|
||||||
|
class UnboundReference(val qualifier: QualifierReceiver) : CallableReceiver()
|
||||||
|
class BoundValueReference(val qualifier: QualifierReceiver) : CallableReceiver()
|
||||||
|
class ScopeReceiver(val receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver()
|
||||||
|
class ExplicitValueReceiver(val receiver: SimpleKotlinCallArgument) : CallableReceiver()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val CallableReceiver.asReceiverValueForVisibilityChecks: ReceiverValue
|
||||||
|
get() = when(this) {
|
||||||
|
is CallableReceiver.ScopeReceiver -> receiver.receiverValue
|
||||||
|
is CallableReceiver.ExplicitValueReceiver -> receiver.receiver.receiverValue
|
||||||
|
is CallableReceiver.BoundValueReference -> qualifier.classValueReceiver ?: Visibilities.ALWAYS_SUITABLE_RECEIVER
|
||||||
|
is CallableReceiver.UnboundReference -> (qualifier.descriptor as? ClassDescriptor)?.defaultType?.let(::TransientReceiver)
|
||||||
|
?: Visibilities.ALWAYS_SUITABLE_RECEIVER
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suppose we have class A with staticM, memberM, memberExtM.
|
||||||
|
* For A::staticM both receivers will be null
|
||||||
|
* For A::memberM dispatchReceiver = UnboundReceiver, extensionReceiver = null
|
||||||
|
* For a::memberExtM dispatchReceiver = ExplicitValueReceiver, extensionReceiver = ExplicitValueReceiver
|
||||||
|
*
|
||||||
|
* For class B with companion object B::companionM dispatchReceiver = BoundValueReference
|
||||||
|
*/
|
||||||
|
class CallableReferenceCandidate(
|
||||||
|
val candidate: CallableDescriptor,
|
||||||
|
val dispatchReceiver: CallableReceiver?,
|
||||||
|
val extensionReceiver: CallableReceiver?,
|
||||||
|
val reflectionCandidateType: UnwrappedType,
|
||||||
|
val numDefaults: Int,
|
||||||
|
override val status: ResolutionCandidateStatus
|
||||||
|
) : Candidate {
|
||||||
|
override val isSuccessful get() = status.resultingApplicability.isSuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cases: class A {}, class B { companion object }, object C, enum class D { E }
|
||||||
|
* A::foo <-> Type
|
||||||
|
* a::foo <-> Expression
|
||||||
|
* B::foo <-> Type
|
||||||
|
* C::foo <-> Object
|
||||||
|
* D.E::foo <-> Expression
|
||||||
|
*/
|
||||||
|
fun createCallableReferenceProcessor(factory: CallableReferencesCandidateFactory): ScopeTowerProcessor<CallableReferenceCandidate> {
|
||||||
|
val lhsResult = factory.argument.lhsResult
|
||||||
|
when (lhsResult) {
|
||||||
|
LHSResult.Empty, is LHSResult.Expression -> {
|
||||||
|
val explicitReceiver = (lhsResult as? LHSResult.Expression)?.lshCallArgument?.receiver
|
||||||
|
return factory.createCallableProcessor(explicitReceiver)
|
||||||
|
}
|
||||||
|
is LHSResult.Type -> {
|
||||||
|
val static = factory.createCallableProcessor(lhsResult.qualifier)
|
||||||
|
val unbound = factory.createCallableProcessor(lhsResult.unboundDetailedReceiver)
|
||||||
|
|
||||||
|
// note that if we use CompositeScopeTowerProcessor then static will win over unbound members
|
||||||
|
val staticOrUnbound = CompositeSimpleScopeTowerProcessor(static, unbound)
|
||||||
|
|
||||||
|
val asValue = lhsResult.qualifier.classValueReceiverWithSmartCastInfo ?: return staticOrUnbound
|
||||||
|
return CompositeScopeTowerProcessor(staticOrUnbound, factory.createCallableProcessor(asValue))
|
||||||
|
}
|
||||||
|
is LHSResult.Object -> {
|
||||||
|
// callable reference to nested class constructor
|
||||||
|
val static = factory.createCallableProcessor(lhsResult.qualifier)
|
||||||
|
val boundObjectReference = factory.createCallableProcessor(lhsResult.objectValueReceiver)
|
||||||
|
|
||||||
|
return CompositeSimpleScopeTowerProcessor(static, boundObjectReference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CallableReferencesCandidateFactory(
|
||||||
|
val argument: CallableReferenceKotlinCallArgument,
|
||||||
|
val outerCallContext: KotlinCallContext,
|
||||||
|
val compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit,
|
||||||
|
val expectedType: UnwrappedType?
|
||||||
|
) : CandidateFactory<CallableReferenceCandidate> {
|
||||||
|
|
||||||
|
fun createCallableProcessor(explicitReceiver: DetailedReceiver?) =
|
||||||
|
createCallableReferenceProcessor(outerCallContext.scopeTower, argument.rhsName, this, explicitReceiver)
|
||||||
|
|
||||||
|
override fun createCandidate(
|
||||||
|
towerCandidate: CandidateWithBoundDispatchReceiver,
|
||||||
|
explicitReceiverKind: ExplicitReceiverKind,
|
||||||
|
extensionReceiver: ReceiverValueWithSmartCastInfo?
|
||||||
|
): CallableReferenceCandidate {
|
||||||
|
|
||||||
|
val dispatchCallableReceiver = towerCandidate.dispatchReceiver?.let { toCallableReceiver(it, explicitReceiverKind == DISPATCH_RECEIVER) }
|
||||||
|
val extensionCallableReceiver = extensionReceiver?.let { toCallableReceiver(it, explicitReceiverKind == EXTENSION_RECEIVER) }
|
||||||
|
val candidateDescriptor = towerCandidate.descriptor
|
||||||
|
|
||||||
|
val (reflectionCandidateType, defaults) = buildReflectionType(candidateDescriptor,
|
||||||
|
dispatchCallableReceiver,
|
||||||
|
extensionCallableReceiver,
|
||||||
|
expectedType)
|
||||||
|
|
||||||
|
if (candidateDescriptor !is CallableMemberDescriptor) {
|
||||||
|
val status = ResolutionCandidateStatus(listOf(NotCallableMemberReference(argument, candidateDescriptor)))
|
||||||
|
return CallableReferenceCandidate(candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
|
||||||
|
reflectionCandidateType, defaults, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
val diagnostics = SmartList<KotlinCallDiagnostic>()
|
||||||
|
val invisibleMember = Visibilities.findInvisibleMember(dispatchCallableReceiver?.asReceiverValueForVisibilityChecks,
|
||||||
|
candidateDescriptor, outerCallContext.scopeTower.lexicalScope.ownerDescriptor)
|
||||||
|
if (invisibleMember != null) {
|
||||||
|
diagnostics.add(VisibilityError(invisibleMember))
|
||||||
|
}
|
||||||
|
// todo smartcast on receiver diagnostic and CheckInstantiationOfAbstractClass
|
||||||
|
|
||||||
|
compatibilityChecker {
|
||||||
|
if (it.hasContradiction || expectedType == null) return@compatibilityChecker
|
||||||
|
|
||||||
|
val toFreshSubstitutor = CreateDescriptorWithFreshTypeVariables.createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, it, kotlinCall = null)
|
||||||
|
val reflectionType = toFreshSubstitutor.safeSubstitute(reflectionCandidateType)
|
||||||
|
|
||||||
|
it.addSubtypeConstraint(reflectionType, expectedType, ArgumentConstraintPosition(argument))
|
||||||
|
if (it.hasContradiction) diagnostics.add(CallableReferenceNotCompatible(argument, candidateDescriptor, expectedType, reflectionType))
|
||||||
|
}
|
||||||
|
|
||||||
|
return CallableReferenceCandidate(candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
|
||||||
|
reflectionCandidateType, defaults, ResolutionCandidateStatus(diagnostics))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getArgumentAndReturnTypeUseMappingByExpectedType(
|
||||||
|
descriptor: FunctionDescriptor,
|
||||||
|
expectedType: UnwrappedType?,
|
||||||
|
unboundReceiverCount: Int
|
||||||
|
): Triple<Array<KotlinType>, CoercionStrategy, Int>? {
|
||||||
|
if (expectedType == null) return null
|
||||||
|
|
||||||
|
val functionType =
|
||||||
|
if (expectedType.isFunctionType) {
|
||||||
|
expectedType
|
||||||
|
}
|
||||||
|
else if (ReflectionTypes.isNumberedKFunction(expectedType)) {
|
||||||
|
expectedType.immediateSupertypes().first { it.isFunctionType }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val expectedArgumentCount = functionType.arguments.size - unboundReceiverCount - 1 // 1 -- return type
|
||||||
|
if (expectedArgumentCount < 0) return null
|
||||||
|
|
||||||
|
val fakeArguments = (0..(expectedArgumentCount - 1)).map { FakeKotlinCallArgumentForCallableReference(it) }
|
||||||
|
val argumentMapping = outerCallContext.argumentsToParametersMapper.mapArguments(fakeArguments, externalArgument = null, descriptor = descriptor)
|
||||||
|
if (argumentMapping.diagnostics.any { !it.candidateApplicability.isSuccess }) return null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (A, B, C) -> Unit
|
||||||
|
* fun foo(a: A, b: B = B(), vararg c: C)
|
||||||
|
*/
|
||||||
|
var defaults = 0
|
||||||
|
val mappedArguments = arrayOfNulls<KotlinType?>(fakeArguments.size)
|
||||||
|
for ((valueParameter, resolvedArgument) in argumentMapping.parameterToCallArgumentMap) {
|
||||||
|
for (fakeArgument in resolvedArgument.arguments) {
|
||||||
|
val index = (fakeArgument as FakeKotlinCallArgumentForCallableReference).index
|
||||||
|
val substitutedParameter = descriptor.valueParameters.getOrNull(valueParameter.index) ?: continue
|
||||||
|
|
||||||
|
mappedArguments[index] = substitutedParameter.varargElementType ?: substitutedParameter.type
|
||||||
|
}
|
||||||
|
if (resolvedArgument == ResolvedCallArgument.DefaultArgument) defaults++
|
||||||
|
}
|
||||||
|
if (mappedArguments.any { it == null }) return null
|
||||||
|
|
||||||
|
val unitExpectedType = functionType.let(KotlinType::getReturnTypeFromFunctionType).takeIf { it.upperIfFlexible().isUnit() }
|
||||||
|
val coercion = if (unitExpectedType != null) CoercionStrategy.COERCION_TO_UNIT else CoercionStrategy.NO_COERCION
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return Triple(mappedArguments as Array<KotlinType>, coercion, defaults)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildReflectionType(
|
||||||
|
descriptor: CallableDescriptor,
|
||||||
|
dispatchReceiver: CallableReceiver?,
|
||||||
|
extensionReceiver: CallableReceiver?,
|
||||||
|
expectedType: UnwrappedType?
|
||||||
|
): Pair<UnwrappedType, /*defaults*/ Int> {
|
||||||
|
val argumentsAndReceivers = ArrayList<KotlinType>(descriptor.valueParameters.size + 2)
|
||||||
|
|
||||||
|
if (dispatchReceiver is CallableReceiver.UnboundReference) {
|
||||||
|
argumentsAndReceivers.add(descriptor.dispatchReceiverParameter?.type
|
||||||
|
?: error("Dispatch receiver should be not null for descriptor: $descriptor"))
|
||||||
|
}
|
||||||
|
if (extensionReceiver is CallableReceiver.UnboundReference) {
|
||||||
|
argumentsAndReceivers.add(descriptor.extensionReceiverParameter?.type
|
||||||
|
?: error("Extension receiver should be not null for descriptor: $descriptor"))
|
||||||
|
}
|
||||||
|
|
||||||
|
val descriptorReturnType = descriptor.returnType
|
||||||
|
?: ErrorUtils.createErrorType("Error return type for descriptor: $descriptor")
|
||||||
|
|
||||||
|
when (descriptor) {
|
||||||
|
is PropertyDescriptor -> {
|
||||||
|
val mutable = descriptor.isVar && run {
|
||||||
|
val setter = descriptor.setter
|
||||||
|
setter == null || Visibilities.isVisible(dispatchReceiver?.asReceiverValueForVisibilityChecks, setter,
|
||||||
|
outerCallContext.scopeTower.lexicalScope.ownerDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
return outerCallContext.reflectionTypes.getKPropertyType(Annotations.EMPTY, argumentsAndReceivers, descriptorReturnType, mutable) to 0
|
||||||
|
}
|
||||||
|
is FunctionDescriptor -> {
|
||||||
|
val returnType: KotlinType
|
||||||
|
val defaults: Int
|
||||||
|
val argumentsAndExpectedTypeCoercion = getArgumentAndReturnTypeUseMappingByExpectedType(descriptor, expectedType,
|
||||||
|
unboundReceiverCount = argumentsAndReceivers.size)
|
||||||
|
|
||||||
|
if (argumentsAndExpectedTypeCoercion == null) {
|
||||||
|
descriptor.valueParameters.mapTo(argumentsAndReceivers) { it.type }
|
||||||
|
returnType = descriptorReturnType
|
||||||
|
defaults = 0
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val (arguments, coercion) = argumentsAndExpectedTypeCoercion
|
||||||
|
defaults = argumentsAndExpectedTypeCoercion.third
|
||||||
|
argumentsAndReceivers.addAll(arguments)
|
||||||
|
|
||||||
|
returnType = if (coercion == CoercionStrategy.COERCION_TO_UNIT) descriptor.builtIns.unitType else descriptorReturnType
|
||||||
|
}
|
||||||
|
|
||||||
|
return outerCallContext.reflectionTypes.getKFunctionType(Annotations.EMPTY, null, argumentsAndReceivers, null,
|
||||||
|
returnType, descriptor.builtIns) to defaults
|
||||||
|
}
|
||||||
|
else -> error("Unsupported descriptor type: $descriptor")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toCallableReceiver(receiver: ReceiverValueWithSmartCastInfo, isExplicit: Boolean): CallableReceiver {
|
||||||
|
if (!isExplicit) return CallableReceiver.ScopeReceiver(receiver)
|
||||||
|
|
||||||
|
val lhsResult = argument.lhsResult
|
||||||
|
return when (lhsResult) {
|
||||||
|
is LHSResult.Expression -> CallableReceiver.ExplicitValueReceiver(lhsResult.lshCallArgument)
|
||||||
|
is LHSResult.Type -> {
|
||||||
|
if (lhsResult.qualifier.classValueReceiver?.type == receiver.receiverValue.type) {
|
||||||
|
CallableReceiver.BoundValueReference(lhsResult.qualifier)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CallableReceiver.UnboundReference(lhsResult.qualifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is LHSResult.Object -> CallableReceiver.BoundValueReference(lhsResult.qualifier)
|
||||||
|
else -> throw IllegalStateException("Unsupported kind of lhsResult: $lhsResult")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CallableReferenceNotCompatible(
|
||||||
|
val argument: CallableReferenceKotlinCallArgument,
|
||||||
|
val candidate: CallableMemberDescriptor,
|
||||||
|
val expectedType: UnwrappedType,
|
||||||
|
val callableReverenceType: UnwrappedType
|
||||||
|
) : KotlinCallDiagnostic(ResolutionCandidateApplicability.INAPPLICABLE) {
|
||||||
|
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotCallableMemberReference(
|
||||||
|
val argument: CallableReferenceKotlinCallArgument,
|
||||||
|
val candidate: CallableDescriptor
|
||||||
|
) : KotlinCallDiagnostic(ResolutionCandidateApplicability.INAPPLICABLE) {
|
||||||
|
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
|
||||||
|
}
|
||||||
+55
-95
@@ -16,104 +16,64 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.components
|
package org.jetbrains.kotlin.resolve.calls.components
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
|
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.resolve.calls.inference.components.SimpleConstraintSystemImpl
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.CallableReferenceKotlinCallArgument
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.resolve.calls.results.OverloadingConflictResolver
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tower.TowerResolver
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
|
||||||
import org.jetbrains.kotlin.types.upperIfFlexible
|
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
class CallableReferenceResolver(
|
class CallableReferenceOverloadConflictResolver(
|
||||||
val reflectionTypes: ReflectionTypes,
|
builtIns: KotlinBuiltIns,
|
||||||
val argumentsToParametersMapper: ArgumentsToParametersMapper
|
specificityComparator: TypeSpecificityComparator,
|
||||||
) {
|
isDescriptorFromSourcePredicate: IsDescriptorFromSourcePredicate,
|
||||||
|
constraintInjector: ConstraintInjector,
|
||||||
fun resolvePropertyReference(
|
typeResolver: ResultTypeResolver
|
||||||
descriptor: PropertyDescriptor,
|
) : OverloadingConflictResolver<CallableReferenceCandidate>(
|
||||||
propertyReference: ChosenCallableReferenceDescriptor,
|
builtIns,
|
||||||
outerCall: KotlinCall,
|
specificityComparator,
|
||||||
scopeOwnerDescriptor: DeclarationDescriptor
|
{ it.candidate },
|
||||||
): ResolvedPropertyReference {
|
{ SimpleConstraintSystemImpl(constraintInjector, typeResolver) },
|
||||||
val mutable = descriptor.isVar && run {
|
Companion::createFlatSignature,
|
||||||
val setter = descriptor.setter
|
{ null },
|
||||||
setter == null || Visibilities.isVisible(propertyReference.candidate.dispatchReceiver?.receiverValue, setter, scopeOwnerDescriptor)
|
isDescriptorFromSourcePredicate
|
||||||
}
|
) {
|
||||||
|
companion object {
|
||||||
val reflectionType = reflectionTypes.getKPropertyType(Annotations.EMPTY, listOfNotNull(propertyReference.dispatchNotBoundReceiver,
|
private fun createFlatSignature(candidate: CallableReferenceCandidate) =
|
||||||
propertyReference.extensionNotBoundReceiver), descriptor.type.unwrap(), mutable)
|
FlatSignature.createFromReflectionType(candidate, candidate.candidate, candidate.numDefaults, candidate.reflectionCandidateType)
|
||||||
|
}
|
||||||
return ResolvedPropertyReference(outerCall, propertyReference, reflectionType)
|
}
|
||||||
}
|
|
||||||
|
class PostponeCallableReferenceArgument(
|
||||||
private fun createFakeArgumentsAndMapArguments(
|
val argument: CallableReferenceKotlinCallArgument,
|
||||||
functionReference: ChosenCallableReferenceDescriptor,
|
val expectedType: UnwrappedType
|
||||||
argumentCount: Int?
|
)
|
||||||
): Pair<List<UnwrappedType>, ArgumentsToParametersMapper.ArgumentMapping?> {
|
|
||||||
if (argumentCount == null) {
|
class CallableReferenceResolver(
|
||||||
return functionReference.candidate.descriptor.valueParameters.map { it.varargElementType?.unwrap() ?: it.type.unwrap() } to null
|
val towerResolver: TowerResolver,
|
||||||
}
|
val callableReferenceOverloadConflictResolver: CallableReferenceOverloadConflictResolver
|
||||||
|
) {
|
||||||
val fakeArguments = (0..(argumentCount - 1)).map { FakeKotlinCallArgumentForCallableReference(functionReference, it) }
|
|
||||||
|
fun runRLSResolution(
|
||||||
val argumentsToParametersMapping = argumentsToParametersMapper.mapArguments(fakeArguments, null, functionReference.candidate.descriptor)
|
outerCallContext: KotlinCallContext,
|
||||||
val parameters = Array<UnwrappedType?>(argumentCount) { null }
|
callableReference: CallableReferenceKotlinCallArgument,
|
||||||
|
expectedType: UnwrappedType?, // this type can have not fixed type variable inside
|
||||||
for ((parameter, resolvedArgument) in argumentsToParametersMapping.parameterToCallArgumentMap) {
|
compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit // you can run anything throw this operation and all this operation will be roll backed
|
||||||
for (argument in resolvedArgument.arguments) {
|
): Set<CallableReferenceCandidate> {
|
||||||
val index = (argument as FakeKotlinCallArgumentForCallableReference).index
|
val factory = CallableReferencesCandidateFactory(callableReference, outerCallContext, compatibilityChecker, expectedType)
|
||||||
parameters[index] = parameter.type.unwrap()
|
val processor = createCallableReferenceProcessor(factory)
|
||||||
}
|
val candidates = towerResolver.runResolve(outerCallContext.scopeTower, processor, useOrder = true)
|
||||||
}
|
return callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(candidates, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||||
|
discriminateGenerics = false,
|
||||||
return parameters.map { it ?: ErrorUtils.createErrorType("Wrong parameters mapping") } to argumentsToParametersMapping
|
isDebuggerContext = outerCallContext.scopeTower.isDebuggerContext)
|
||||||
}
|
|
||||||
|
|
||||||
fun resolveFunctionReference(
|
|
||||||
functionReference: ChosenCallableReferenceDescriptor,
|
|
||||||
outerCall: KotlinCall,
|
|
||||||
expectedType: UnwrappedType
|
|
||||||
): ResolvedFunctionReference {
|
|
||||||
val functionType =
|
|
||||||
if (expectedType.isFunctionType) {
|
|
||||||
expectedType
|
|
||||||
}
|
|
||||||
else if (ReflectionTypes.isNumberedKFunction(expectedType)) {
|
|
||||||
expectedType.immediateSupertypes().first { it.isFunctionType }
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
val parameterTypes = ArrayList<UnwrappedType>(functionType?.arguments?.size ?: 2)
|
|
||||||
parameterTypes.addIfNotNull(functionReference.dispatchNotBoundReceiver)
|
|
||||||
parameterTypes.addIfNotNull(functionReference.extensionNotBoundReceiver)
|
|
||||||
|
|
||||||
// (A, B, C) -> Int if A -- receiver, then B & C -- parameters
|
|
||||||
// here parameterTypes contains only receivers, all parameters will be added later
|
|
||||||
val argumentCount = functionType?.arguments?.let { it.size - parameterTypes.size - 1 }?.takeIf { it >= 0 }
|
|
||||||
val (parameters, mapping) = createFakeArgumentsAndMapArguments(functionReference, argumentCount)
|
|
||||||
parameterTypes.addAll(parameters)
|
|
||||||
|
|
||||||
val unitExpectedType = functionType?.let(KotlinType::getReturnTypeFromFunctionType)?.takeIf { it.upperIfFlexible().isUnit() }
|
|
||||||
// coercion to unit
|
|
||||||
val returnType = unitExpectedType ?: functionReference.candidate.descriptor.returnType
|
|
||||||
?: ErrorUtils.createErrorType("Error return type")
|
|
||||||
|
|
||||||
val kFunctionType = reflectionTypes.getKFunctionType(Annotations.EMPTY, null, parameterTypes, null, returnType, expectedType.builtIns)
|
|
||||||
|
|
||||||
return ResolvedFunctionReference(outerCall, functionReference, kFunctionType, mapping)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+35
-39
@@ -19,7 +19,10 @@ package org.jetbrains.kotlin.resolve.calls.components
|
|||||||
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
|
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
|
||||||
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.components.CreateDescriptorWithFreshTypeVariables.createToFreshVariableSubstitutorAndAddInitialConstraints
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
|
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
|
||||||
@@ -32,12 +35,10 @@ import org.jetbrains.kotlin.types.checker.hasSupertypeWithGivenTypeConstructor
|
|||||||
import org.jetbrains.kotlin.types.checker.intersectWrappedTypes
|
import org.jetbrains.kotlin.types.checker.intersectWrappedTypes
|
||||||
import org.jetbrains.kotlin.types.lowerIfFlexible
|
import org.jetbrains.kotlin.types.lowerIfFlexible
|
||||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||||
import org.jetbrains.kotlin.types.upperIfFlexible
|
import org.jetbrains.kotlin.types.upperIfFlexible
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import java.lang.UnsupportedOperationException
|
|
||||||
|
|
||||||
internal object CheckArguments : ResolutionPart {
|
internal object CheckArguments : ResolutionPart {
|
||||||
override fun SimpleKotlinResolutionCandidate.process(): List<KotlinCallDiagnostic> {
|
override fun SimpleKotlinResolutionCandidate.process(): List<KotlinCallDiagnostic> {
|
||||||
@@ -47,7 +48,8 @@ internal object CheckArguments : ResolutionPart {
|
|||||||
val resolvedCallArgument = argumentMappingByOriginal[parameterDescriptor.original] ?: continue
|
val resolvedCallArgument = argumentMappingByOriginal[parameterDescriptor.original] ?: continue
|
||||||
for (argument in resolvedCallArgument.arguments) {
|
for (argument in resolvedCallArgument.arguments) {
|
||||||
|
|
||||||
val diagnostic = checkArgument(callContext, kotlinCall, csBuilder, argument, argument.getExpectedType(parameterDescriptor))
|
val diagnostic = checkArgument(callContext, kotlinCall, csBuilder, argument, argument.getExpectedType(parameterDescriptor),
|
||||||
|
postponeCallableReferenceArguments)
|
||||||
diagnostics.addIfNotNull(diagnostic)
|
diagnostics.addIfNotNull(diagnostic)
|
||||||
|
|
||||||
if (diagnostic != null && !diagnostic.candidateApplicability.isSuccess) break
|
if (diagnostic != null && !diagnostic.candidateApplicability.isSuccess) break
|
||||||
@@ -61,13 +63,23 @@ internal object CheckArguments : ResolutionPart {
|
|||||||
kotlinCall: KotlinCall,
|
kotlinCall: KotlinCall,
|
||||||
csBuilder: ConstraintSystemBuilder,
|
csBuilder: ConstraintSystemBuilder,
|
||||||
argument: KotlinCallArgument,
|
argument: KotlinCallArgument,
|
||||||
expectedType: UnwrappedType
|
expectedType: UnwrappedType,
|
||||||
|
postponeCallableReferenceArguments: MutableList<PostponeCallableReferenceArgument>? = null
|
||||||
): KotlinCallDiagnostic? {
|
): KotlinCallDiagnostic? {
|
||||||
return when (argument) {
|
return when (argument) {
|
||||||
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, argument, expectedType, isReceiver = false)
|
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, argument, expectedType, isReceiver = false)
|
||||||
is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, argument, expectedType, isReceiver = false)
|
is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, argument, expectedType, isReceiver = false)
|
||||||
is LambdaKotlinCallArgument -> processLambdaArgument(kotlinCall, csBuilder, argument, expectedType)
|
is LambdaKotlinCallArgument -> processLambdaArgument(kotlinCall, csBuilder, argument, expectedType)
|
||||||
is CallableReferenceKotlinCallArgument -> processCallableReferenceArgument(callContext, kotlinCall, csBuilder, argument, expectedType)
|
is CallableReferenceKotlinCallArgument -> {
|
||||||
|
if (postponeCallableReferenceArguments == null) {
|
||||||
|
processCallableReferenceArgument(callContext, kotlinCall, csBuilder, argument, expectedType)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// callable reference resolution will be run after choosing single descriptor
|
||||||
|
postponeCallableReferenceArguments.add(PostponeCallableReferenceArgument(argument, expectedType))
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> error("Incorrect argument type: $argument, ${argument.javaClass.canonicalName}.")
|
else -> error("Incorrect argument type: $argument, ${argument.javaClass.canonicalName}.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,43 +170,27 @@ internal object CheckArguments : ResolutionPart {
|
|||||||
argument: CallableReferenceKotlinCallArgument,
|
argument: CallableReferenceKotlinCallArgument,
|
||||||
expectedType: UnwrappedType
|
expectedType: UnwrappedType
|
||||||
): KotlinCallDiagnostic? {
|
): KotlinCallDiagnostic? {
|
||||||
val position = ArgumentConstraintPosition(argument)
|
val subLHSCall = ((argument.lhsResult as? LHSResult.Expression)?.lshCallArgument as? SubKotlinCallArgument)
|
||||||
|
if (subLHSCall != null) {
|
||||||
if (argument !is ChosenCallableReferenceDescriptor) {
|
csBuilder.addInnerCall(subLHSCall.resolvedCall)
|
||||||
val lhsType = argument.lhsType
|
}
|
||||||
if (lhsType != null) {
|
val candidates = callContext.callableReferenceResolver.runRLSResolution(callContext, argument, expectedType) { checkCallableReference ->
|
||||||
// todo: case with two receivers
|
csBuilder.runTransaction { checkCallableReference(this); false }
|
||||||
val expectedReceiverType = expectedType.supertypes().firstOrNull { it.isFunctionType }?.arguments?.first()?.type?.unwrap()
|
}
|
||||||
if (expectedReceiverType != null) {
|
val chosenCandidate = when (candidates.size) {
|
||||||
// (lhsType) -> .. <: (expectedReceiverType) -> ... => expectedReceiverType <: lhsType
|
0 -> return NoneCallableReferenceCandidates(argument)
|
||||||
csBuilder.addSubtypeConstraint(expectedReceiverType, lhsType, position)
|
1 -> candidates.single()
|
||||||
}
|
else -> return CallableReferenceCandidatesAmbiguity(argument, candidates)
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val descriptor = argument.candidate.descriptor
|
|
||||||
when (descriptor) {
|
|
||||||
is FunctionDescriptor -> {
|
|
||||||
// todo store resolved
|
|
||||||
val resolvedFunctionReference = callContext.callableReferenceResolver.resolveFunctionReference(
|
|
||||||
argument, kotlinCall, expectedType)
|
|
||||||
|
|
||||||
csBuilder.addSubtypeConstraint(resolvedFunctionReference.reflectionType, expectedType, position)
|
val toFreshSubstitutor = createToFreshVariableSubstitutorAndAddInitialConstraints(chosenCandidate.candidate, csBuilder, kotlinCall = null)
|
||||||
return resolvedFunctionReference.argumentsMapping?.diagnostics?.let {
|
val reflectionType = toFreshSubstitutor.safeSubstitute(chosenCandidate.reflectionCandidateType)
|
||||||
ErrorCallableMapping(resolvedFunctionReference)
|
csBuilder.addSubtypeConstraint(reflectionType, expectedType, ArgumentConstraintPosition(argument))
|
||||||
}
|
|
||||||
}
|
val resolvedCallableReference = ResolvedCallableReferenceArgument(kotlinCall, argument, toFreshSubstitutor.freshVariables, chosenCandidate)
|
||||||
is PropertyDescriptor -> {
|
csBuilder.addCallableReferenceArgument(resolvedCallableReference)
|
||||||
|
|
||||||
// todo store resolved
|
|
||||||
val resolvedPropertyReference = callContext.callableReferenceResolver.resolvePropertyReference(descriptor,
|
|
||||||
argument, kotlinCall, callContext.scopeTower.lexicalScope.ownerDescriptor)
|
|
||||||
csBuilder.addSubtypeConstraint(resolvedPropertyReference.reflectionType, expectedType, position)
|
|
||||||
}
|
|
||||||
else -> throw UnsupportedOperationException("Callable reference resolved to an unsupported descriptor: $descriptor")
|
|
||||||
}
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
@@ -77,6 +77,7 @@ class KotlinCallCompleter(
|
|||||||
is VariableAsFunctionKotlinResolutionCandidate -> candidate.invokeCandidate
|
is VariableAsFunctionKotlinResolutionCandidate -> candidate.invokeCandidate
|
||||||
else -> candidate as SimpleKotlinResolutionCandidate
|
else -> candidate as SimpleKotlinResolutionCandidate
|
||||||
}
|
}
|
||||||
|
resolveCallableReferenceArguments(topLevelCall)
|
||||||
|
|
||||||
if (topLevelCall.prepareForCompletion(expectedType)) {
|
if (topLevelCall.prepareForCompletion(expectedType)) {
|
||||||
val c = candidate.lastCall.constraintSystem.asCallCompleterContext()
|
val c = candidate.lastCall.constraintSystem.asCallCompleterContext()
|
||||||
@@ -88,6 +89,14 @@ class KotlinCallCompleter(
|
|||||||
return ResolvedKotlinCall.OnlyResolvedKotlinCall(candidate)
|
return ResolvedKotlinCall.OnlyResolvedKotlinCall(candidate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun resolveCallableReferenceArguments(candidate: SimpleKotlinResolutionCandidate) {
|
||||||
|
for (callableReferenceArgument in candidate.postponeCallableReferenceArguments) {
|
||||||
|
CheckArguments.processCallableReferenceArgument(candidate.callContext, candidate.kotlinCall, candidate.csBuilder,
|
||||||
|
callableReferenceArgument.argument, callableReferenceArgument.expectedType)
|
||||||
|
}
|
||||||
|
candidate.postponeCallableReferenceArguments.clear()
|
||||||
|
}
|
||||||
|
|
||||||
private fun toCompletedBaseResolvedCall(
|
private fun toCompletedBaseResolvedCall(
|
||||||
c: Context,
|
c: Context,
|
||||||
candidate: KotlinResolutionCandidate,
|
candidate: KotlinResolutionCandidate,
|
||||||
|
|||||||
+9
-2
@@ -262,6 +262,13 @@ class MissingReceiver(val functionExpression: FunctionExpression) : KotlinCallDi
|
|||||||
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(functionExpression, this)
|
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(functionExpression, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ErrorCallableMapping(val functionReference: ResolvedFunctionReference) : KotlinCallDiagnostic(IMPOSSIBLE_TO_GENERATE) {
|
class NoneCallableReferenceCandidates(val argument: CallableReferenceKotlinCallArgument) : KotlinCallDiagnostic(IMPOSSIBLE_TO_GENERATE) {
|
||||||
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(functionReference.argument, this)
|
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class CallableReferenceCandidatesAmbiguity(
|
||||||
|
val argument: CallableReferenceKotlinCallArgument,
|
||||||
|
val candidates: Collection<CallableReferenceCandidate>
|
||||||
|
) : KotlinCallDiagnostic(IMPOSSIBLE_TO_GENERATE) {
|
||||||
|
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
|
||||||
}
|
}
|
||||||
+2
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.inference
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallableReferenceArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
@@ -36,6 +37,7 @@ interface ConstraintSystemOperation {
|
|||||||
interface ConstraintSystemBuilder : ConstraintSystemOperation {
|
interface ConstraintSystemBuilder : ConstraintSystemOperation {
|
||||||
fun addInnerCall(innerCall: ResolvedKotlinCall.OnlyResolvedKotlinCall)
|
fun addInnerCall(innerCall: ResolvedKotlinCall.OnlyResolvedKotlinCall)
|
||||||
fun addLambdaArgument(resolvedLambdaArgument: ResolvedLambdaArgument)
|
fun addLambdaArgument(resolvedLambdaArgument: ResolvedLambdaArgument)
|
||||||
|
fun addCallableReferenceArgument(resolvedCallableReferenceArgument: ResolvedCallableReferenceArgument)
|
||||||
|
|
||||||
// if runOperations return true, then this operation will be applied, and function return true
|
// if runOperations return true, then this operation will be applied, and function return true
|
||||||
fun runTransaction(runOperations: ConstraintSystemOperation.() -> Boolean): Boolean
|
fun runTransaction(runOperations: ConstraintSystemOperation.() -> Boolean): Boolean
|
||||||
|
|||||||
+3
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.model
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallableReferenceArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
||||||
import org.jetbrains.kotlin.types.TypeConstructor
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
@@ -55,6 +56,7 @@ interface ConstraintStorage {
|
|||||||
val errors: List<KotlinCallDiagnostic>
|
val errors: List<KotlinCallDiagnostic>
|
||||||
val fixedTypeVariables: Map<TypeConstructor, UnwrappedType>
|
val fixedTypeVariables: Map<TypeConstructor, UnwrappedType>
|
||||||
val lambdaArguments: List<ResolvedLambdaArgument>
|
val lambdaArguments: List<ResolvedLambdaArgument>
|
||||||
|
val callableReferenceArguments: List<ResolvedCallableReferenceArgument>
|
||||||
val innerCalls: List<ResolvedKotlinCall.OnlyResolvedKotlinCall>
|
val innerCalls: List<ResolvedKotlinCall.OnlyResolvedKotlinCall>
|
||||||
|
|
||||||
object Empty : ConstraintStorage {
|
object Empty : ConstraintStorage {
|
||||||
@@ -65,6 +67,7 @@ interface ConstraintStorage {
|
|||||||
override val errors: List<KotlinCallDiagnostic> get() = emptyList()
|
override val errors: List<KotlinCallDiagnostic> get() = emptyList()
|
||||||
override val fixedTypeVariables: Map<TypeConstructor, UnwrappedType> get() = emptyMap()
|
override val fixedTypeVariables: Map<TypeConstructor, UnwrappedType> get() = emptyMap()
|
||||||
override val lambdaArguments: List<ResolvedLambdaArgument> get() = emptyList()
|
override val lambdaArguments: List<ResolvedLambdaArgument> get() = emptyList()
|
||||||
|
override val callableReferenceArguments: List<ResolvedCallableReferenceArgument> get() = emptyList()
|
||||||
override val innerCalls: List<ResolvedKotlinCall.OnlyResolvedKotlinCall> get() = emptyList()
|
override val innerCalls: List<ResolvedKotlinCall.OnlyResolvedKotlinCall> get() = emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.model
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.trimToSize
|
import org.jetbrains.kotlin.resolve.calls.inference.trimToSize
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallableReferenceArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
||||||
import org.jetbrains.kotlin.types.TypeConstructor
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
@@ -84,5 +85,6 @@ internal class MutableConstraintStorage : ConstraintStorage {
|
|||||||
override val errors: MutableList<KotlinCallDiagnostic> = ArrayList()
|
override val errors: MutableList<KotlinCallDiagnostic> = ArrayList()
|
||||||
override val fixedTypeVariables: MutableMap<TypeConstructor, UnwrappedType> = LinkedHashMap()
|
override val fixedTypeVariables: MutableMap<TypeConstructor, UnwrappedType> = LinkedHashMap()
|
||||||
override val lambdaArguments: MutableList<ResolvedLambdaArgument> = ArrayList()
|
override val lambdaArguments: MutableList<ResolvedLambdaArgument> = ArrayList()
|
||||||
|
override val callableReferenceArguments: MutableList<ResolvedCallableReferenceArgument> = ArrayList()
|
||||||
override val innerCalls: MutableList<ResolvedKotlinCall.OnlyResolvedKotlinCall> = ArrayList()
|
override val innerCalls: MutableList<ResolvedKotlinCall.OnlyResolvedKotlinCall> = ArrayList()
|
||||||
}
|
}
|
||||||
+7
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.*
|
import org.jetbrains.kotlin.resolve.calls.inference.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallableReferenceArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||||
@@ -140,6 +141,11 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
|
|||||||
storage.lambdaArguments.add(resolvedLambdaArgument)
|
storage.lambdaArguments.add(resolvedLambdaArgument)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun addCallableReferenceArgument(resolvedCallableReferenceArgument: ResolvedCallableReferenceArgument) {
|
||||||
|
checkState(State.BUILDING, State.COMPLETION)
|
||||||
|
storage.callableReferenceArguments.add(resolvedCallableReferenceArgument)
|
||||||
|
}
|
||||||
|
|
||||||
private fun getVariablesForFixation(): Map<NewTypeVariable, UnwrappedType> {
|
private fun getVariablesForFixation(): Map<NewTypeVariable, UnwrappedType> {
|
||||||
val fixedVariables = LinkedHashMap<NewTypeVariable, UnwrappedType>()
|
val fixedVariables = LinkedHashMap<NewTypeVariable, UnwrappedType>()
|
||||||
|
|
||||||
@@ -185,6 +191,7 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
|
|||||||
storage.errors.addAll(otherSystem.errors)
|
storage.errors.addAll(otherSystem.errors)
|
||||||
storage.fixedTypeVariables.putAll(otherSystem.fixedTypeVariables)
|
storage.fixedTypeVariables.putAll(otherSystem.fixedTypeVariables)
|
||||||
storage.lambdaArguments.addAll(otherSystem.lambdaArguments)
|
storage.lambdaArguments.addAll(otherSystem.lambdaArguments)
|
||||||
|
storage.callableReferenceArguments.addAll(otherSystem.callableReferenceArguments)
|
||||||
storage.innerCalls.addAll(otherSystem.innerCalls)
|
storage.innerCalls.addAll(otherSystem.innerCalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.types.checker.prepareArgumentTypeRegardingCaptureTyp
|
|||||||
|
|
||||||
|
|
||||||
class FakeKotlinCallArgumentForCallableReference(
|
class FakeKotlinCallArgumentForCallableReference(
|
||||||
val callableReference: ChosenCallableReferenceDescriptor,
|
|
||||||
val index: Int
|
val index: Int
|
||||||
) : KotlinCallArgument {
|
) : KotlinCallArgument {
|
||||||
override val isSpread: Boolean get() = false
|
override val isSpread: Boolean get() = false
|
||||||
|
|||||||
+43
-11
@@ -16,12 +16,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.model
|
package org.jetbrains.kotlin.resolve.calls.model
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateWithBoundDispatchReceiver
|
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
|
|
||||||
|
|
||||||
@@ -71,20 +72,51 @@ interface FunctionExpression : LambdaKotlinCallArgument {
|
|||||||
val returnType: UnwrappedType?
|
val returnType: UnwrappedType?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cases: class A {}, class B { companion object }, object C, enum class D { E }
|
||||||
|
* A::foo <-> Type
|
||||||
|
* a::foo <-> Expression
|
||||||
|
* B::foo <-> Type
|
||||||
|
* C::foo <-> Object
|
||||||
|
* D.E::foo <-> Expression
|
||||||
|
*/
|
||||||
|
sealed class LHSResult {
|
||||||
|
class Type(val qualifier: QualifierReceiver): LHSResult() {
|
||||||
|
val unboundDetailedReceiver: ReceiverValueWithSmartCastInfo
|
||||||
|
|
||||||
|
init {
|
||||||
|
assert(qualifier.descriptor is ClassDescriptor) {
|
||||||
|
"Should be ClassDescriptor: ${qualifier.descriptor}"
|
||||||
|
}
|
||||||
|
|
||||||
|
val unboundReceiver = TransientReceiver((qualifier.descriptor as ClassDescriptor).defaultType)
|
||||||
|
unboundDetailedReceiver = ReceiverValueWithSmartCastInfo(unboundReceiver, emptySet(), isStable = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Object(val qualifier: QualifierReceiver): LHSResult() {
|
||||||
|
val objectValueReceiver: ReceiverValueWithSmartCastInfo
|
||||||
|
|
||||||
|
init {
|
||||||
|
assert(DescriptorUtils.isObject(qualifier.descriptor)) {
|
||||||
|
"Should be object descriptor: ${qualifier.descriptor}"
|
||||||
|
}
|
||||||
|
objectValueReceiver = qualifier.classValueReceiverWithSmartCastInfo ?: error("class value should be not null for $qualifier")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Expression(val lshCallArgument: SimpleKotlinCallArgument): LHSResult()
|
||||||
|
|
||||||
|
// todo this case is forbid for now
|
||||||
|
object Empty: LHSResult()
|
||||||
|
}
|
||||||
|
|
||||||
interface CallableReferenceKotlinCallArgument : KotlinCallArgument {
|
interface CallableReferenceKotlinCallArgument : KotlinCallArgument {
|
||||||
override val isSpread: Boolean
|
override val isSpread: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
|
|
||||||
// Foo::bar lhsType = Foo. For a::bar where a is expression, this type is null
|
val lhsResult: LHSResult
|
||||||
val lhsType: UnwrappedType?
|
|
||||||
|
|
||||||
val constraintStorage: ConstraintStorage
|
val rhsName: Name
|
||||||
}
|
|
||||||
|
|
||||||
interface ChosenCallableReferenceDescriptor : CallableReferenceKotlinCallArgument {
|
|
||||||
val candidate: CandidateWithBoundDispatchReceiver
|
|
||||||
|
|
||||||
val extensionReceiver: ReceiverValueWithSmartCastInfo?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+14
-1
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.model
|
package org.jetbrains.kotlin.resolve.calls.model
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.CheckArguments
|
import org.jetbrains.kotlin.resolve.calls.components.CheckArguments
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
|
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
|
||||||
@@ -38,7 +39,8 @@ class KotlinCallContext(
|
|||||||
val typeArgumentsToParametersMapper: TypeArgumentsToParametersMapper,
|
val typeArgumentsToParametersMapper: TypeArgumentsToParametersMapper,
|
||||||
val resultTypeResolver: ResultTypeResolver,
|
val resultTypeResolver: ResultTypeResolver,
|
||||||
val callableReferenceResolver: CallableReferenceResolver,
|
val callableReferenceResolver: CallableReferenceResolver,
|
||||||
val constraintInjector: ConstraintInjector
|
val constraintInjector: ConstraintInjector,
|
||||||
|
val reflectionTypes: ReflectionTypes
|
||||||
)
|
)
|
||||||
|
|
||||||
class SimpleCandidateFactory(val callContext: KotlinCallContext, val kotlinCall: KotlinCall): CandidateFactory<SimpleKotlinResolutionCandidate> {
|
class SimpleCandidateFactory(val callContext: KotlinCallContext, val kotlinCall: KotlinCall): CandidateFactory<SimpleKotlinResolutionCandidate> {
|
||||||
@@ -51,6 +53,17 @@ class SimpleCandidateFactory(val callContext: KotlinCallContext, val kotlinCall:
|
|||||||
explicitReceiver as? SimpleKotlinCallArgument ?: // qualifier receiver cannot be safe
|
explicitReceiver as? SimpleKotlinCallArgument ?: // qualifier receiver cannot be safe
|
||||||
fromResolution?.let { ReceiverExpressionKotlinCallArgument(it, isSafeCall = false) } // todo smartcast implicit this
|
fromResolution?.let { ReceiverExpressionKotlinCallArgument(it, isSafeCall = false) } // todo smartcast implicit this
|
||||||
|
|
||||||
|
private fun KotlinCall.getExplicitDispatchReceiver(explicitReceiverKind: ExplicitReceiverKind) = when (explicitReceiverKind) {
|
||||||
|
ExplicitReceiverKind.DISPATCH_RECEIVER -> explicitReceiver
|
||||||
|
ExplicitReceiverKind.BOTH_RECEIVERS -> dispatchReceiverForInvokeExtension
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KotlinCall.getExplicitExtensionReceiver(explicitReceiverKind: ExplicitReceiverKind) = when (explicitReceiverKind) {
|
||||||
|
ExplicitReceiverKind.EXTENSION_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> explicitReceiver
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
override fun createCandidate(
|
override fun createCandidate(
|
||||||
towerCandidate: CandidateWithBoundDispatchReceiver,
|
towerCandidate: CandidateWithBoundDispatchReceiver,
|
||||||
explicitReceiverKind: ExplicitReceiverKind,
|
explicitReceiverKind: ExplicitReceiverKind,
|
||||||
|
|||||||
+3
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.model
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.components.PostponeCallableReferenceArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper
|
import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
||||||
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
|||||||
import org.jetbrains.kotlin.resolve.calls.tower.Candidate
|
import org.jetbrains.kotlin.resolve.calls.tower.Candidate
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateStatus
|
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateStatus
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||||
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
@@ -112,6 +114,7 @@ open class SimpleKotlinResolutionCandidate(
|
|||||||
initialDiagnostics: Collection<KotlinCallDiagnostic>
|
initialDiagnostics: Collection<KotlinCallDiagnostic>
|
||||||
) : AbstractSimpleKotlinResolutionCandidate(NewConstraintSystemImpl(callContext.constraintInjector, callContext.resultTypeResolver), initialDiagnostics) {
|
) : AbstractSimpleKotlinResolutionCandidate(NewConstraintSystemImpl(callContext.constraintInjector, callContext.resultTypeResolver), initialDiagnostics) {
|
||||||
val csBuilder: ConstraintSystemBuilder get() = constraintSystem.getBuilder()
|
val csBuilder: ConstraintSystemBuilder get() = constraintSystem.getBuilder()
|
||||||
|
val postponeCallableReferenceArguments = SmartList<PostponeCallableReferenceArgument>()
|
||||||
|
|
||||||
lateinit var typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping
|
lateinit var typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping
|
||||||
lateinit var argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
lateinit var argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||||
|
|||||||
+9
-45
@@ -18,12 +18,9 @@ package org.jetbrains.kotlin.resolve.calls.model
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.createFunctionType
|
import org.jetbrains.kotlin.builtins.createFunctionType
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.ArgumentsToParametersMapper
|
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceCandidate
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.LambdaTypeVariable
|
import org.jetbrains.kotlin.resolve.calls.inference.model.LambdaTypeVariable
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlin.types.SimpleType
|
import org.jetbrains.kotlin.types.SimpleType
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||||
@@ -55,45 +52,12 @@ class ResolvedLambdaArgument(
|
|||||||
lateinit var resultArguments: List<KotlinCallArgument>
|
lateinit var resultArguments: List<KotlinCallArgument>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ResolvedCallableReferenceArgument(
|
||||||
class ResolvedPropertyReference(
|
override val outerCall: KotlinCall,
|
||||||
val outerCall: KotlinCall,
|
override val argument: CallableReferenceKotlinCallArgument,
|
||||||
val argument: ChosenCallableReferenceDescriptor,
|
override val myTypeVariables: Collection<NewTypeVariable>,
|
||||||
val reflectionType: UnwrappedType
|
val callableResolutionCandidate: CallableReferenceCandidate
|
||||||
) {
|
) : ArgumentWithPostponeResolution() {
|
||||||
val boundDispatchReceiver: ReceiverValue? get() = argument.candidate.dispatchReceiver?.receiverValue?.takeIf { it !is MockReceiverForCallableReference }
|
override val inputType: Collection<UnwrappedType> get() = emptyList()
|
||||||
val boundExtensionReceiver: ReceiverValue? get() = argument.extensionReceiver?.receiverValue?.takeIf { it !is MockReceiverForCallableReference }
|
override val outputType: UnwrappedType? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResolvedFunctionReference(
|
|
||||||
val outerCall: KotlinCall,
|
|
||||||
val argument: ChosenCallableReferenceDescriptor,
|
|
||||||
val reflectionType: UnwrappedType,
|
|
||||||
val argumentsMapping: ArgumentsToParametersMapper.ArgumentMapping?
|
|
||||||
) {
|
|
||||||
val boundDispatchReceiver: ReceiverValue? get() = argument.candidate.dispatchReceiver?.receiverValue?.takeIf { it !is MockReceiverForCallableReference }
|
|
||||||
val boundExtensionReceiver: ReceiverValue? get() = argument.extensionReceiver?.receiverValue?.takeIf { it !is MockReceiverForCallableReference }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun KotlinCall.getExplicitDispatchReceiver(explicitReceiverKind: ExplicitReceiverKind) = when (explicitReceiverKind) {
|
|
||||||
ExplicitReceiverKind.DISPATCH_RECEIVER -> explicitReceiver
|
|
||||||
ExplicitReceiverKind.BOTH_RECEIVERS -> dispatchReceiverForInvokeExtension
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun KotlinCall.getExplicitExtensionReceiver(explicitReceiverKind: ExplicitReceiverKind) = when (explicitReceiverKind) {
|
|
||||||
ExplicitReceiverKind.EXTENSION_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> explicitReceiver
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
class MockReceiverForCallableReference(val lhsOrDeclaredType: UnwrappedType) : ReceiverValue {
|
|
||||||
override fun getType() = lhsOrDeclaredType
|
|
||||||
override fun replaceType(newType: KotlinType) = MockReceiverForCallableReference(newType.unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
val ChosenCallableReferenceDescriptor.dispatchNotBoundReceiver : UnwrappedType?
|
|
||||||
get() = (candidate.dispatchReceiver?.receiverValue as? MockReceiverForCallableReference)?.lhsOrDeclaredType
|
|
||||||
|
|
||||||
val ChosenCallableReferenceDescriptor.extensionNotBoundReceiver : UnwrappedType?
|
|
||||||
get() = (extensionReceiver as? MockReceiverForCallableReference)?.lhsOrDeclaredType
|
|
||||||
|
|||||||
@@ -51,6 +51,23 @@ class FlatSignature<out T> private constructor(
|
|||||||
val isGeneric = typeParameters.isNotEmpty()
|
val isGeneric = typeParameters.isNotEmpty()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
fun <T> createFromReflectionType(
|
||||||
|
origin: T,
|
||||||
|
descriptor: CallableDescriptor,
|
||||||
|
numDefaults: Int,
|
||||||
|
reflectionType: UnwrappedType
|
||||||
|
): FlatSignature<T> {
|
||||||
|
return FlatSignature(origin,
|
||||||
|
descriptor.typeParameters,
|
||||||
|
reflectionType.arguments.map { it.type }, // should we drop return type?
|
||||||
|
hasExtensionReceiver = false,
|
||||||
|
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
|
||||||
|
numDefaults = numDefaults,
|
||||||
|
isHeader = descriptor is MemberDescriptor && descriptor.isHeader,
|
||||||
|
isSyntheticMember = descriptor is SyntheticMemberDescriptor<*>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun <T> create(
|
fun <T> create(
|
||||||
origin: T,
|
origin: T,
|
||||||
descriptor: CallableDescriptor,
|
descriptor: CallableDescriptor,
|
||||||
|
|||||||
Reference in New Issue
Block a user