[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
|
||||
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||
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.LambdaKotlinCallArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
@@ -110,8 +110,8 @@ class CallableReferenceKotlinCallArgumentImpl(
|
||||
override val dataFlowInfoAfterThisArgument: DataFlowInfo,
|
||||
val ktCallableReferenceExpression: KtCallableReferenceExpression,
|
||||
override val argumentName: Name?,
|
||||
override val lhsType: UnwrappedType?,
|
||||
override val constraintStorage: ConstraintStorage
|
||||
override val lhsResult: LHSResult,
|
||||
override val rhsName: Name
|
||||
) : CallableReferenceKotlinCallArgument, PSIKotlinCallArgument()
|
||||
|
||||
class SubKotlinCallArgumentImpl(
|
||||
@@ -137,6 +137,16 @@ class ExpressionKotlinCallArgumentImpl(
|
||||
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(
|
||||
context: BasicCallResolutionContext,
|
||||
valueArgument: ValueArgument,
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
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.TemporaryBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.TypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.*
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver
|
||||
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.components.ArgumentsToParametersMapper
|
||||
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.inference.components.ConstraintInjector
|
||||
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.results.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
@@ -75,6 +77,7 @@ class PSICallResolver(
|
||||
val resultTypeResolver: ResultTypeResolver,
|
||||
val callableReferenceResolver: CallableReferenceResolver,
|
||||
val constraintInjector: ConstraintInjector,
|
||||
val reflectionTypes: ReflectionTypes,
|
||||
private val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer,
|
||||
private val kotlinCallResolver: KotlinCallResolver,
|
||||
private val typeApproximator: TypeApproximator,
|
||||
@@ -146,7 +149,7 @@ class PSICallResolver(
|
||||
|
||||
private fun createCallContext(scopeTower: ASTScopeTower, resolutionCallbacks: KotlinResolutionCallbacks) =
|
||||
KotlinCallContext(scopeTower, resolutionCallbacks, argumentsToParametersMapper, typeArgumentsToParametersMapper, resultTypeResolver,
|
||||
callableReferenceResolver, constraintInjector)
|
||||
callableReferenceResolver, constraintInjector, reflectionTypes)
|
||||
|
||||
private fun <D : CallableDescriptor> convertToOverloadResolutionResults(
|
||||
context: BasicCallResolutionContext,
|
||||
@@ -456,17 +459,44 @@ class PSICallResolver(
|
||||
if (ktExpression is KtCallableReferenceExpression) {
|
||||
checkNoSpread(outerCallContext, valueArgument)
|
||||
|
||||
// todo analyze left expression and get constraint system
|
||||
val (lhsResult, rightResults) = doubleColonExpressionResolver.resolveCallableReference(
|
||||
ktExpression, ExpressionTypingContext.newContext(context), ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS)
|
||||
|
||||
val expressionTypingContext = ExpressionTypingContext.newContext(context)
|
||||
val lhsResult = if (ktExpression.isEmptyLHS) null else doubleColonExpressionResolver.resolveDoubleColonLHS(ktExpression, expressionTypingContext)
|
||||
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,
|
||||
ktExpression, argumentName, (lhsResult as? DoubleColonLHS.Type)?.type?.unwrap(),
|
||||
ConstraintStorage.Empty)
|
||||
ktExpression, argumentName, lhsNewResult, name)
|
||||
}
|
||||
|
||||
// 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
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
+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
|
||||
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
|
||||
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.SimpleConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.CallableReferenceKotlinCallArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature
|
||||
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.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(
|
||||
val reflectionTypes: ReflectionTypes,
|
||||
val argumentsToParametersMapper: ArgumentsToParametersMapper
|
||||
) {
|
||||
|
||||
fun resolvePropertyReference(
|
||||
descriptor: PropertyDescriptor,
|
||||
propertyReference: ChosenCallableReferenceDescriptor,
|
||||
outerCall: KotlinCall,
|
||||
scopeOwnerDescriptor: DeclarationDescriptor
|
||||
): ResolvedPropertyReference {
|
||||
val mutable = descriptor.isVar && run {
|
||||
val setter = descriptor.setter
|
||||
setter == null || Visibilities.isVisible(propertyReference.candidate.dispatchReceiver?.receiverValue, setter, scopeOwnerDescriptor)
|
||||
}
|
||||
|
||||
val reflectionType = reflectionTypes.getKPropertyType(Annotations.EMPTY, listOfNotNull(propertyReference.dispatchNotBoundReceiver,
|
||||
propertyReference.extensionNotBoundReceiver), descriptor.type.unwrap(), mutable)
|
||||
|
||||
return ResolvedPropertyReference(outerCall, propertyReference, reflectionType)
|
||||
}
|
||||
|
||||
private fun createFakeArgumentsAndMapArguments(
|
||||
functionReference: ChosenCallableReferenceDescriptor,
|
||||
argumentCount: Int?
|
||||
): Pair<List<UnwrappedType>, ArgumentsToParametersMapper.ArgumentMapping?> {
|
||||
if (argumentCount == null) {
|
||||
return functionReference.candidate.descriptor.valueParameters.map { it.varargElementType?.unwrap() ?: it.type.unwrap() } to null
|
||||
}
|
||||
|
||||
val fakeArguments = (0..(argumentCount - 1)).map { FakeKotlinCallArgumentForCallableReference(functionReference, it) }
|
||||
|
||||
val argumentsToParametersMapping = argumentsToParametersMapper.mapArguments(fakeArguments, null, functionReference.candidate.descriptor)
|
||||
val parameters = Array<UnwrappedType?>(argumentCount) { null }
|
||||
|
||||
for ((parameter, resolvedArgument) in argumentsToParametersMapping.parameterToCallArgumentMap) {
|
||||
for (argument in resolvedArgument.arguments) {
|
||||
val index = (argument as FakeKotlinCallArgumentForCallableReference).index
|
||||
parameters[index] = parameter.type.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
return parameters.map { it ?: ErrorUtils.createErrorType("Wrong parameters mapping") } to argumentsToParametersMapping
|
||||
}
|
||||
|
||||
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)
|
||||
class CallableReferenceOverloadConflictResolver(
|
||||
builtIns: KotlinBuiltIns,
|
||||
specificityComparator: TypeSpecificityComparator,
|
||||
isDescriptorFromSourcePredicate: IsDescriptorFromSourcePredicate,
|
||||
constraintInjector: ConstraintInjector,
|
||||
typeResolver: ResultTypeResolver
|
||||
) : OverloadingConflictResolver<CallableReferenceCandidate>(
|
||||
builtIns,
|
||||
specificityComparator,
|
||||
{ it.candidate },
|
||||
{ SimpleConstraintSystemImpl(constraintInjector, typeResolver) },
|
||||
Companion::createFlatSignature,
|
||||
{ null },
|
||||
isDescriptorFromSourcePredicate
|
||||
) {
|
||||
companion object {
|
||||
private fun createFlatSignature(candidate: CallableReferenceCandidate) =
|
||||
FlatSignature.createFromReflectionType(candidate, candidate.candidate, candidate.numDefaults, candidate.reflectionCandidateType)
|
||||
}
|
||||
}
|
||||
|
||||
class PostponeCallableReferenceArgument(
|
||||
val argument: CallableReferenceKotlinCallArgument,
|
||||
val expectedType: UnwrappedType
|
||||
)
|
||||
|
||||
class CallableReferenceResolver(
|
||||
val towerResolver: TowerResolver,
|
||||
val callableReferenceOverloadConflictResolver: CallableReferenceOverloadConflictResolver
|
||||
) {
|
||||
|
||||
fun runRLSResolution(
|
||||
outerCallContext: KotlinCallContext,
|
||||
callableReference: CallableReferenceKotlinCallArgument,
|
||||
expectedType: UnwrappedType?, // this type can have not fixed type variable inside
|
||||
compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit // you can run anything throw this operation and all this operation will be roll backed
|
||||
): Set<CallableReferenceCandidate> {
|
||||
val factory = CallableReferencesCandidateFactory(callableReference, outerCallContext, compatibilityChecker, expectedType)
|
||||
val processor = createCallableReferenceProcessor(factory)
|
||||
val candidates = towerResolver.runResolve(outerCallContext.scopeTower, processor, useOrder = true)
|
||||
return callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(candidates, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
discriminateGenerics = false,
|
||||
isDebuggerContext = outerCallContext.scopeTower.isDebuggerContext)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+35
-39
@@ -19,7 +19,10 @@ package org.jetbrains.kotlin.resolve.calls.components
|
||||
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
||||
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.addSubtypeConstraintIfCompatible
|
||||
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.lowerIfFlexible
|
||||
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.upperIfFlexible
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.lang.UnsupportedOperationException
|
||||
|
||||
internal object CheckArguments : ResolutionPart {
|
||||
override fun SimpleKotlinResolutionCandidate.process(): List<KotlinCallDiagnostic> {
|
||||
@@ -47,7 +48,8 @@ internal object CheckArguments : ResolutionPart {
|
||||
val resolvedCallArgument = argumentMappingByOriginal[parameterDescriptor.original] ?: continue
|
||||
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)
|
||||
|
||||
if (diagnostic != null && !diagnostic.candidateApplicability.isSuccess) break
|
||||
@@ -61,13 +63,23 @@ internal object CheckArguments : ResolutionPart {
|
||||
kotlinCall: KotlinCall,
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: KotlinCallArgument,
|
||||
expectedType: UnwrappedType
|
||||
expectedType: UnwrappedType,
|
||||
postponeCallableReferenceArguments: MutableList<PostponeCallableReferenceArgument>? = null
|
||||
): KotlinCallDiagnostic? {
|
||||
return when (argument) {
|
||||
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, argument, expectedType, isReceiver = false)
|
||||
is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, argument, expectedType, isReceiver = false)
|
||||
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}.")
|
||||
}
|
||||
}
|
||||
@@ -158,43 +170,27 @@ internal object CheckArguments : ResolutionPart {
|
||||
argument: CallableReferenceKotlinCallArgument,
|
||||
expectedType: UnwrappedType
|
||||
): KotlinCallDiagnostic? {
|
||||
val position = ArgumentConstraintPosition(argument)
|
||||
|
||||
if (argument !is ChosenCallableReferenceDescriptor) {
|
||||
val lhsType = argument.lhsType
|
||||
if (lhsType != null) {
|
||||
// todo: case with two receivers
|
||||
val expectedReceiverType = expectedType.supertypes().firstOrNull { it.isFunctionType }?.arguments?.first()?.type?.unwrap()
|
||||
if (expectedReceiverType != null) {
|
||||
// (lhsType) -> .. <: (expectedReceiverType) -> ... => expectedReceiverType <: lhsType
|
||||
csBuilder.addSubtypeConstraint(expectedReceiverType, lhsType, position)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
val subLHSCall = ((argument.lhsResult as? LHSResult.Expression)?.lshCallArgument as? SubKotlinCallArgument)
|
||||
if (subLHSCall != null) {
|
||||
csBuilder.addInnerCall(subLHSCall.resolvedCall)
|
||||
}
|
||||
val candidates = callContext.callableReferenceResolver.runRLSResolution(callContext, argument, expectedType) { checkCallableReference ->
|
||||
csBuilder.runTransaction { checkCallableReference(this); false }
|
||||
}
|
||||
val chosenCandidate = when (candidates.size) {
|
||||
0 -> return NoneCallableReferenceCandidates(argument)
|
||||
1 -> candidates.single()
|
||||
else -> return CallableReferenceCandidatesAmbiguity(argument, candidates)
|
||||
}
|
||||
|
||||
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)
|
||||
return resolvedFunctionReference.argumentsMapping?.diagnostics?.let {
|
||||
ErrorCallableMapping(resolvedFunctionReference)
|
||||
}
|
||||
}
|
||||
is PropertyDescriptor -> {
|
||||
val toFreshSubstitutor = createToFreshVariableSubstitutorAndAddInitialConstraints(chosenCandidate.candidate, csBuilder, kotlinCall = null)
|
||||
val reflectionType = toFreshSubstitutor.safeSubstitute(chosenCandidate.reflectionCandidateType)
|
||||
csBuilder.addSubtypeConstraint(reflectionType, expectedType, ArgumentConstraintPosition(argument))
|
||||
|
||||
val resolvedCallableReference = ResolvedCallableReferenceArgument(kotlinCall, argument, toFreshSubstitutor.freshVariables, chosenCandidate)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -77,6 +77,7 @@ class KotlinCallCompleter(
|
||||
is VariableAsFunctionKotlinResolutionCandidate -> candidate.invokeCandidate
|
||||
else -> candidate as SimpleKotlinResolutionCandidate
|
||||
}
|
||||
resolveCallableReferenceArguments(topLevelCall)
|
||||
|
||||
if (topLevelCall.prepareForCompletion(expectedType)) {
|
||||
val c = candidate.lastCall.constraintSystem.asCallCompleterContext()
|
||||
@@ -88,6 +89,14 @@ class KotlinCallCompleter(
|
||||
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(
|
||||
c: Context,
|
||||
candidate: KotlinResolutionCandidate,
|
||||
|
||||
+10
-3
@@ -262,6 +262,13 @@ class MissingReceiver(val functionExpression: FunctionExpression) : KotlinCallDi
|
||||
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(functionExpression, this)
|
||||
}
|
||||
|
||||
class ErrorCallableMapping(val functionReference: ResolvedFunctionReference) : KotlinCallDiagnostic(IMPOSSIBLE_TO_GENERATE) {
|
||||
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(functionReference.argument, this)
|
||||
}
|
||||
class NoneCallableReferenceCandidates(val argument: CallableReferenceKotlinCallArgument) : KotlinCallDiagnostic(IMPOSSIBLE_TO_GENERATE) {
|
||||
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.model.ConstraintPosition
|
||||
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.ResolvedLambdaArgument
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
@@ -36,6 +37,7 @@ interface ConstraintSystemOperation {
|
||||
interface ConstraintSystemBuilder : ConstraintSystemOperation {
|
||||
fun addInnerCall(innerCall: ResolvedKotlinCall.OnlyResolvedKotlinCall)
|
||||
fun addLambdaArgument(resolvedLambdaArgument: ResolvedLambdaArgument)
|
||||
fun addCallableReferenceArgument(resolvedCallableReferenceArgument: ResolvedCallableReferenceArgument)
|
||||
|
||||
// if runOperations return true, then this operation will be applied, and function return true
|
||||
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.model.ResolvedKotlinCall
|
||||
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.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
@@ -55,6 +56,7 @@ interface ConstraintStorage {
|
||||
val errors: List<KotlinCallDiagnostic>
|
||||
val fixedTypeVariables: Map<TypeConstructor, UnwrappedType>
|
||||
val lambdaArguments: List<ResolvedLambdaArgument>
|
||||
val callableReferenceArguments: List<ResolvedCallableReferenceArgument>
|
||||
val innerCalls: List<ResolvedKotlinCall.OnlyResolvedKotlinCall>
|
||||
|
||||
object Empty : ConstraintStorage {
|
||||
@@ -65,6 +67,7 @@ interface ConstraintStorage {
|
||||
override val errors: List<KotlinCallDiagnostic> get() = emptyList()
|
||||
override val fixedTypeVariables: Map<TypeConstructor, UnwrappedType> get() = emptyMap()
|
||||
override val lambdaArguments: List<ResolvedLambdaArgument> get() = emptyList()
|
||||
override val callableReferenceArguments: List<ResolvedCallableReferenceArgument> 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.model.ResolvedKotlinCall
|
||||
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.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
@@ -84,5 +85,6 @@ internal class MutableConstraintStorage : ConstraintStorage {
|
||||
override val errors: MutableList<KotlinCallDiagnostic> = ArrayList()
|
||||
override val fixedTypeVariables: MutableMap<TypeConstructor, UnwrappedType> = LinkedHashMap()
|
||||
override val lambdaArguments: MutableList<ResolvedLambdaArgument> = ArrayList()
|
||||
override val callableReferenceArguments: MutableList<ResolvedCallableReferenceArgument> = 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.components.*
|
||||
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.ResolvedLambdaArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
@@ -140,6 +141,11 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
|
||||
storage.lambdaArguments.add(resolvedLambdaArgument)
|
||||
}
|
||||
|
||||
override fun addCallableReferenceArgument(resolvedCallableReferenceArgument: ResolvedCallableReferenceArgument) {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
storage.callableReferenceArguments.add(resolvedCallableReferenceArgument)
|
||||
}
|
||||
|
||||
private fun getVariablesForFixation(): Map<NewTypeVariable, UnwrappedType> {
|
||||
val fixedVariables = LinkedHashMap<NewTypeVariable, UnwrappedType>()
|
||||
|
||||
@@ -185,6 +191,7 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
|
||||
storage.errors.addAll(otherSystem.errors)
|
||||
storage.fixedTypeVariables.putAll(otherSystem.fixedTypeVariables)
|
||||
storage.lambdaArguments.addAll(otherSystem.lambdaArguments)
|
||||
storage.callableReferenceArguments.addAll(otherSystem.callableReferenceArguments)
|
||||
storage.innerCalls.addAll(otherSystem.innerCalls)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.types.checker.prepareArgumentTypeRegardingCaptureTyp
|
||||
|
||||
|
||||
class FakeKotlinCallArgumentForCallableReference(
|
||||
val callableReference: ChosenCallableReferenceDescriptor,
|
||||
val index: Int
|
||||
) : KotlinCallArgument {
|
||||
override val isSpread: Boolean get() = false
|
||||
|
||||
+43
-11
@@ -16,12 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.model
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateWithBoundDispatchReceiver
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
|
||||
@@ -71,20 +72,51 @@ interface FunctionExpression : LambdaKotlinCallArgument {
|
||||
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 {
|
||||
override val isSpread: Boolean
|
||||
get() = false
|
||||
|
||||
// Foo::bar lhsType = Foo. For a::bar where a is expression, this type is null
|
||||
val lhsType: UnwrappedType?
|
||||
val lhsResult: LHSResult
|
||||
|
||||
val constraintStorage: ConstraintStorage
|
||||
}
|
||||
|
||||
interface ChosenCallableReferenceDescriptor : CallableReferenceKotlinCallArgument {
|
||||
val candidate: CandidateWithBoundDispatchReceiver
|
||||
|
||||
val extensionReceiver: ReceiverValueWithSmartCastInfo?
|
||||
val rhsName: Name
|
||||
}
|
||||
|
||||
|
||||
|
||||
+14
-1
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.model
|
||||
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.components.CheckArguments
|
||||
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
|
||||
@@ -38,7 +39,8 @@ class KotlinCallContext(
|
||||
val typeArgumentsToParametersMapper: TypeArgumentsToParametersMapper,
|
||||
val resultTypeResolver: ResultTypeResolver,
|
||||
val callableReferenceResolver: CallableReferenceResolver,
|
||||
val constraintInjector: ConstraintInjector
|
||||
val constraintInjector: ConstraintInjector,
|
||||
val reflectionTypes: ReflectionTypes
|
||||
)
|
||||
|
||||
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
|
||||
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(
|
||||
towerCandidate: CandidateWithBoundDispatchReceiver,
|
||||
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.ValueParameterDescriptor
|
||||
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.inference.ConstraintSystemBuilder
|
||||
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.ResolutionCandidateStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import java.util.*
|
||||
|
||||
|
||||
@@ -112,6 +114,7 @@ open class SimpleKotlinResolutionCandidate(
|
||||
initialDiagnostics: Collection<KotlinCallDiagnostic>
|
||||
) : AbstractSimpleKotlinResolutionCandidate(NewConstraintSystemImpl(callContext.constraintInjector, callContext.resultTypeResolver), initialDiagnostics) {
|
||||
val csBuilder: ConstraintSystemBuilder get() = constraintSystem.getBuilder()
|
||||
val postponeCallableReferenceArguments = SmartList<PostponeCallableReferenceArgument>()
|
||||
|
||||
lateinit var typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping
|
||||
lateinit var argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||
|
||||
+10
-46
@@ -18,12 +18,9 @@ package org.jetbrains.kotlin.resolve.calls.model
|
||||
|
||||
import org.jetbrains.kotlin.builtins.createFunctionType
|
||||
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.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.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
@@ -55,45 +52,12 @@ class ResolvedLambdaArgument(
|
||||
lateinit var resultArguments: List<KotlinCallArgument>
|
||||
}
|
||||
|
||||
|
||||
class ResolvedPropertyReference(
|
||||
val outerCall: KotlinCall,
|
||||
val argument: ChosenCallableReferenceDescriptor,
|
||||
val reflectionType: UnwrappedType
|
||||
) {
|
||||
val boundDispatchReceiver: ReceiverValue? get() = argument.candidate.dispatchReceiver?.receiverValue?.takeIf { it !is MockReceiverForCallableReference }
|
||||
val boundExtensionReceiver: ReceiverValue? get() = argument.extensionReceiver?.receiverValue?.takeIf { it !is MockReceiverForCallableReference }
|
||||
}
|
||||
|
||||
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
|
||||
class ResolvedCallableReferenceArgument(
|
||||
override val outerCall: KotlinCall,
|
||||
override val argument: CallableReferenceKotlinCallArgument,
|
||||
override val myTypeVariables: Collection<NewTypeVariable>,
|
||||
val callableResolutionCandidate: CallableReferenceCandidate
|
||||
) : ArgumentWithPostponeResolution() {
|
||||
override val inputType: Collection<UnwrappedType> get() = emptyList()
|
||||
override val outputType: UnwrappedType? = null
|
||||
}
|
||||
@@ -51,6 +51,23 @@ class FlatSignature<out T> private constructor(
|
||||
val isGeneric = typeParameters.isNotEmpty()
|
||||
|
||||
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(
|
||||
origin: T,
|
||||
descriptor: CallableDescriptor,
|
||||
|
||||
Reference in New Issue
Block a user