[NI] Fix some argument mapping problems
1. Value arguments for the resolved call are indexed with resulting descriptor value parameters (which can be substituted). 2. Simple argument can be a single vararg element if the corresponding value parameter is a vararg parameter. 3. Resulting descriptor should be approximated to super-type. This doesn't affect type inference, but the JVM BE expects types with proper classifiers.
This commit is contained in:
committed by
Stanislav Erokhin
parent
0c79949cf1
commit
eb7e9196b5
+22
-15
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedT
|
|||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isFakeElement
|
import org.jetbrains.kotlin.resolve.calls.callUtil.isFakeElement
|
||||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.CallPosition
|
import org.jetbrains.kotlin.resolve.calls.context.CallPosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
@@ -244,7 +245,7 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor>(): ResolvedCall<D>
|
|||||||
abstract val kotlinCall: KotlinCall
|
abstract val kotlinCall: KotlinCall
|
||||||
|
|
||||||
private var argumentToParameterMap: Map<ValueArgument, ArgumentMatchImpl>? = null
|
private var argumentToParameterMap: Map<ValueArgument, ArgumentMatchImpl>? = null
|
||||||
private val _valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument> by lazy(this::createValueArguments)
|
private val _valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument> by lazy { createValueArguments() }
|
||||||
|
|
||||||
override fun getCall(): Call = kotlinCall.psiKotlinCall.psiCall
|
override fun getCall(): Call = kotlinCall.psiKotlinCall.psiCall
|
||||||
|
|
||||||
@@ -298,7 +299,7 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor>(): ResolvedCall<D>
|
|||||||
resultingDescriptor: CallableDescriptor,
|
resultingDescriptor: CallableDescriptor,
|
||||||
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>
|
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>
|
||||||
): Map<ValueArgument, ArgumentMatchImpl> =
|
): Map<ValueArgument, ArgumentMatchImpl> =
|
||||||
HashMap<ValueArgument, ArgumentMatchImpl>().also { result ->
|
LinkedHashMap<ValueArgument, ArgumentMatchImpl>().also { result ->
|
||||||
for (parameter in resultingDescriptor.valueParameters) {
|
for (parameter in resultingDescriptor.valueParameters) {
|
||||||
val resolvedArgument = valueArguments[parameter] ?: continue
|
val resolvedArgument = valueArguments[parameter] ?: continue
|
||||||
for (arguments in resolvedArgument.arguments) {
|
for (arguments in resolvedArgument.arguments) {
|
||||||
@@ -307,22 +308,28 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor>(): ResolvedCall<D>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> {
|
private fun createValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> =
|
||||||
val result = HashMap<ValueParameterDescriptor, ResolvedValueArgument>()
|
LinkedHashMap<ValueParameterDescriptor, ResolvedValueArgument>().also { result ->
|
||||||
for (parameter in candidateDescriptor.valueParameters) {
|
for ((originalParameter, resolvedCallArgument) in argumentMappingByOriginal) {
|
||||||
val resolvedCallArgument = argumentMappingByOriginal[parameter.original] ?: continue
|
val resultingParameter = resultingDescriptor.valueParameters[originalParameter.index]
|
||||||
val valueArgument = when (resolvedCallArgument) {
|
result[resultingParameter] = when (resolvedCallArgument) {
|
||||||
ResolvedCallArgument.DefaultArgument -> DefaultValueArgument.DEFAULT
|
ResolvedCallArgument.DefaultArgument ->
|
||||||
is ResolvedCallArgument.SimpleArgument -> ExpressionValueArgument(resolvedCallArgument.callArgument.psiCallArgument.valueArgument)
|
DefaultValueArgument.DEFAULT
|
||||||
is ResolvedCallArgument.VarargArgument -> VarargValueArgument().apply {
|
is ResolvedCallArgument.SimpleArgument -> {
|
||||||
resolvedCallArgument.arguments.map { it.psiCallArgument.valueArgument }.forEach(this::addArgument)
|
val valueArgument = resolvedCallArgument.callArgument.psiCallArgument.valueArgument
|
||||||
|
if (resultingParameter.isVararg)
|
||||||
|
VarargValueArgument().apply { addArgument(valueArgument) }
|
||||||
|
else
|
||||||
|
ExpressionValueArgument(valueArgument)
|
||||||
|
}
|
||||||
|
is ResolvedCallArgument.VarargArgument ->
|
||||||
|
VarargValueArgument().apply {
|
||||||
|
resolvedCallArgument.arguments.map { it.psiCallArgument.valueArgument }.forEach { addArgument(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result[parameter] = valueArgument
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class NewResolvedCallImpl<D : CallableDescriptor>(
|
class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||||
|
|||||||
+15
-7
@@ -17,6 +17,8 @@
|
|||||||
package org.jetbrains.kotlin.resolve.calls.components
|
package org.jetbrains.kotlin.resolve.calls.components
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
|
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
|
||||||
@@ -28,7 +30,7 @@ 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.inference.model.NotEnoughInformationForTypeParameter
|
import org.jetbrains.kotlin.resolve.calls.inference.model.NotEnoughInformationForTypeParameter
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.returnTypeOrNothing
|
import org.jetbrains.kotlin.resolve.calls.inference.returnTypeOrNothing
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateCapturedTypes
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
|
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateStatus
|
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateStatus
|
||||||
@@ -71,11 +73,9 @@ class KotlinCallCompleter(
|
|||||||
): ResolvedKotlinCall {
|
): ResolvedKotlinCall {
|
||||||
lambdaAnalyzer.bindStubResolvedCallForCandidate(candidate)
|
lambdaAnalyzer.bindStubResolvedCallForCandidate(candidate)
|
||||||
val topLevelCall =
|
val topLevelCall =
|
||||||
if (candidate is VariableAsFunctionKotlinResolutionCandidate) {
|
when (candidate) {
|
||||||
candidate.invokeCandidate
|
is VariableAsFunctionKotlinResolutionCandidate -> candidate.invokeCandidate
|
||||||
}
|
else -> candidate as SimpleKotlinResolutionCandidate
|
||||||
else {
|
|
||||||
candidate as SimpleKotlinResolutionCandidate
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topLevelCall.prepareForCompletion(expectedType)) {
|
if (topLevelCall.prepareForCompletion(expectedType)) {
|
||||||
@@ -111,7 +111,15 @@ class KotlinCallCompleter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun SimpleKotlinResolutionCandidate.toCompletedCall(substitutor: NewTypeSubstitutor): CompletedKotlinCall.Simple {
|
private fun SimpleKotlinResolutionCandidate.toCompletedCall(substitutor: NewTypeSubstitutor): CompletedKotlinCall.Simple {
|
||||||
val resultingDescriptor = if (descriptorWithFreshTypes.typeParameters.isNotEmpty()) descriptorWithFreshTypes.substitute(substitutor)!! else descriptorWithFreshTypes
|
val resultingDescriptor = when {
|
||||||
|
descriptorWithFreshTypes is FunctionDescriptor ||
|
||||||
|
descriptorWithFreshTypes is PropertyDescriptor && descriptorWithFreshTypes.typeParameters.isNotEmpty() ->
|
||||||
|
// this code is very suspicious. Now it is very useful for BE, because they cannot do nothing with captured types,
|
||||||
|
// but it seems like temporary solution.
|
||||||
|
descriptorWithFreshTypes.substituteAndApproximateCapturedTypes(substitutor)!!
|
||||||
|
else ->
|
||||||
|
descriptorWithFreshTypes
|
||||||
|
}
|
||||||
|
|
||||||
val typeArguments = descriptorWithFreshTypes.typeParameters.map { substitutor.safeSubstitute(it.defaultType) }
|
val typeArguments = descriptorWithFreshTypes.typeParameters.map { substitutor.safeSubstitute(it.defaultType) }
|
||||||
|
|
||||||
|
|||||||
+13
@@ -44,3 +44,16 @@ fun CallableDescriptor.substitute(substitutor: NewTypeSubstitutor): CallableDesc
|
|||||||
return substitute(TypeSubstitutor.create(wrappedSubstitution))
|
return substitute(TypeSubstitutor.create(wrappedSubstitution))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun CallableDescriptor.substituteAndApproximateCapturedTypes(substitutor: NewTypeSubstitutor): CallableDescriptor? {
|
||||||
|
val wrappedSubstitution = object : TypeSubstitution() {
|
||||||
|
override fun get(key: KotlinType): TypeProjection? = null
|
||||||
|
|
||||||
|
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) =
|
||||||
|
substitutor.safeSubstitute(topLevelType.unwrap()).let { substitutedType ->
|
||||||
|
TypeApproximator().approximateToSuperType(substitutedType, TypeApproximatorConfiguration.CapturedTypesApproximation) ?:
|
||||||
|
substitutedType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return substitute(TypeSubstitutor.create(wrappedSubstitution))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user