Avoid substitution and type approximation for simple calls

#KT-37392 fixed
This commit is contained in:
Ilya Chernikov
2020-03-16 14:30:43 +01:00
parent e1ae81e0a1
commit 950ab01596
2 changed files with 25 additions and 20 deletions
@@ -773,35 +773,28 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
getSubstitutorWithoutFlexibleTypes(substitutor, explicitTypeArguments),
)
}
is FunctionDescriptor -> candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor)
is FunctionDescriptor -> {
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor, candidateDescriptor.isNotSimpleCall())
}
is PropertyDescriptor -> {
if (candidateDescriptor.typeParameters.isNotEmpty())
if (candidateDescriptor.isNotSimpleCall()) {
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor)
else {
val shouldForceApproximationAndSubstitution = candidateDescriptor.returnType?.let { type ->
type.contains {
it is NewCapturedType ||
it.constructor is IntegerLiteralTypeConstructor ||
it is DefinitelyNotNullType ||
it is StubType
}
} ?: false
if (shouldForceApproximationAndSubstitution)
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor)
else
candidateDescriptor
} else {
candidateDescriptor
}
}
else -> candidateDescriptor
}
private fun CallableDescriptor.substituteInferredVariablesAndApproximate(substitutor: NewTypeSubstitutor?): CallableDescriptor {
private fun CallableDescriptor.substituteInferredVariablesAndApproximate(
substitutor: NewTypeSubstitutor?,
shouldApproximate: Boolean = true
): CallableDescriptor {
val inferredTypeVariablesSubstitutor = substitutor ?: FreshVariableNewTypeSubstitutor.Empty
val compositeSubstitutor = inferredTypeVariablesSubstitutor.composeWith(resolvedCallAtom.knownParametersSubstitutor)
return substitute(resolvedCallAtom.freshVariablesSubstitutor)
.substituteAndApproximateTypes(compositeSubstitutor, typeApproximator)
.substituteAndApproximateTypes(compositeSubstitutor, if (shouldApproximate) typeApproximator else null)
}
fun getArgumentTypeForConstantConvertedArgument(valueArgument: ValueArgument): IntegerValueTypeConstant? {
@@ -914,3 +907,15 @@ fun NewResolvedCallImpl<*>.hasInferredReturnType(): Boolean {
val returnType = this.resultingDescriptor.returnType ?: return false
return !returnType.contains { ErrorUtils.isUninferredParameter(it) }
}
private fun CallableMemberDescriptor.isNotSimpleCall(): Boolean =
typeParameters.isNotEmpty() ||
(returnType?.let { type ->
type.contains {
it is NewCapturedType ||
it.constructor is IntegerLiteralTypeConstructor ||
it is DefinitelyNotNullType ||
it is StubType
}
} ?: false)
@@ -80,14 +80,14 @@ fun CallableDescriptor.substitute(substitutor: NewTypeSubstitutor): CallableDesc
fun CallableDescriptor.substituteAndApproximateTypes(
substitutor: NewTypeSubstitutor,
typeApproximator: TypeApproximator
typeApproximator: TypeApproximator?
): 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(
typeApproximator?.approximateToSuperType(
substitutedType,
TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
) ?: substitutedType