[NI] Use new type substitutor instead of old in completion of callable references

It's necessary because of new type substitutor is eager than odl, so
  if there is a substitution of type parameter deep inside type arguments
  then second substitutor wins against first

#KT-35896 Fixed
This commit is contained in:
Dmitriy Novozhilov
2020-01-14 13:07:07 +03:00
parent 3428a17759
commit 88a1cb5a17
8 changed files with 86 additions and 12 deletions
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
@@ -255,6 +256,16 @@ class ResolvedAtomCompleter(
}
}
private fun NewTypeSubstitutor.toOldSubstitution(): TypeSubstitution = object : TypeSubstitution() {
override fun get(key: KotlinType): TypeProjection? {
return safeSubstitute(key.unwrap()).takeIf { it !== key }?.asTypeProjection()
}
override fun isEmpty(): Boolean {
return isEmpty
}
}
private fun completeCallableReference(
resolvedAtom: ResolvedCallableReferenceAtom
) {
@@ -264,20 +275,14 @@ class ResolvedAtomCompleter(
return
}
val resultTypeParameters =
callableCandidate.freshSubstitutor!!.freshVariables.map { resultSubstitutor.safeSubstitute(it.defaultType).asTypeProjection() }
callableCandidate.freshSubstitutor!!.freshVariables.map { resultSubstitutor.safeSubstitute(it.defaultType) }
val firstSubstitutor = IndexedParametersSubstitution(callableCandidate.candidate.typeParameters, resultTypeParameters)
val secondSubstitution = object : TypeSubstitution() {
override fun get(key: KotlinType): TypeProjection? {
return resultSubstitutor.safeSubstitute(key.unwrap()).takeIf { it !== key }?.asTypeProjection()
}
val typeParametersSubstitutor = NewTypeSubstitutorByConstructorMap((callableCandidate.candidate.typeParameters.map { it.typeConstructor } zip resultTypeParameters).toMap())
override fun isEmpty(): Boolean {
return resultSubstitutor.isEmpty
}
}
val firstSubstitution = typeParametersSubstitutor.toOldSubstitution()
val secondSubstitution = resultSubstitutor.toOldSubstitution()
val resultSubstitutor = TypeSubstitutor.createChainedSubstitutor(
firstSubstitutor,
firstSubstitution,
secondSubstitution
)