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), getSubstitutorWithoutFlexibleTypes(substitutor, explicitTypeArguments),
) )
} }
is FunctionDescriptor -> candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor) is FunctionDescriptor -> {
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor, candidateDescriptor.isNotSimpleCall())
}
is PropertyDescriptor -> { is PropertyDescriptor -> {
if (candidateDescriptor.typeParameters.isNotEmpty()) if (candidateDescriptor.isNotSimpleCall()) {
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor) candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor)
else { } else {
val shouldForceApproximationAndSubstitution = candidateDescriptor.returnType?.let { type -> candidateDescriptor
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 inferredTypeVariablesSubstitutor = substitutor ?: FreshVariableNewTypeSubstitutor.Empty
val compositeSubstitutor = inferredTypeVariablesSubstitutor.composeWith(resolvedCallAtom.knownParametersSubstitutor) val compositeSubstitutor = inferredTypeVariablesSubstitutor.composeWith(resolvedCallAtom.knownParametersSubstitutor)
return substitute(resolvedCallAtom.freshVariablesSubstitutor) return substitute(resolvedCallAtom.freshVariablesSubstitutor)
.substituteAndApproximateTypes(compositeSubstitutor, typeApproximator) .substituteAndApproximateTypes(compositeSubstitutor, if (shouldApproximate) typeApproximator else null)
} }
fun getArgumentTypeForConstantConvertedArgument(valueArgument: ValueArgument): IntegerValueTypeConstant? { fun getArgumentTypeForConstantConvertedArgument(valueArgument: ValueArgument): IntegerValueTypeConstant? {
@@ -914,3 +907,15 @@ fun NewResolvedCallImpl<*>.hasInferredReturnType(): Boolean {
val returnType = this.resultingDescriptor.returnType ?: return false val returnType = this.resultingDescriptor.returnType ?: return false
return !returnType.contains { ErrorUtils.isUninferredParameter(it) } 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( fun CallableDescriptor.substituteAndApproximateTypes(
substitutor: NewTypeSubstitutor, substitutor: NewTypeSubstitutor,
typeApproximator: TypeApproximator typeApproximator: TypeApproximator?
): CallableDescriptor { ): CallableDescriptor {
val wrappedSubstitution = object : TypeSubstitution() { val wrappedSubstitution = object : TypeSubstitution() {
override fun get(key: KotlinType): TypeProjection? = null override fun get(key: KotlinType): TypeProjection? = null
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) =
substitutor.safeSubstitute(topLevelType.unwrap()).let { substitutedType -> substitutor.safeSubstitute(topLevelType.unwrap()).let { substitutedType ->
typeApproximator.approximateToSuperType( typeApproximator?.approximateToSuperType(
substitutedType, substitutedType,
TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
) ?: substitutedType ) ?: substitutedType