[NI] Fix substitution in completion of callable references in coroutine inference

This commit is contained in:
Dmitriy Novozhilov
2019-12-20 11:37:01 +03:00
parent 04d4366f2a
commit b54169d312
8 changed files with 80 additions and 5 deletions
@@ -237,4 +237,6 @@ class ComposedSubstitutor(val left: NewTypeSubstitutor, val right: NewTypeSubsti
right.substituteNotNullTypeWithConstructor(constructor)?.constructor ?: constructor
)
}
override val isEmpty: Boolean get() = left.isEmpty && right.isEmpty
}
@@ -264,15 +264,25 @@ class ResolvedAtomCompleter(
return
}
val resultTypeParameters =
callableCandidate.freshSubstitutor!!.freshVariables.map { resultSubstitutor.safeSubstitute(it.defaultType) }
callableCandidate.freshSubstitutor!!.freshVariables.map { resultSubstitutor.safeSubstitute(it.defaultType).asTypeProjection() }
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()
}
override fun isEmpty(): Boolean {
return resultSubstitutor.isEmpty
}
}
val resultSubstitutor = TypeSubstitutor.createChainedSubstitutor(
firstSubstitutor,
secondSubstitution
)
val psiCallArgument = resolvedAtom.atom.psiCallArgument as CallableReferenceKotlinCallArgumentImpl
val callableReferenceExpression = psiCallArgument.ktCallableReferenceExpression
val resultSubstitutor = IndexedParametersSubstitution(
callableCandidate.candidate.typeParameters,
resultTypeParameters.map { it.asTypeProjection() }).buildSubstitutor()
// write down type for callable reference expression
val resultType = resultSubstitutor.safeSubstitute(callableCandidate.reflectionCandidateType, Variance.INVARIANT)
@@ -21,6 +21,8 @@ interface NewTypeSubstitutor: TypeSubstitutorMarker {
fun safeSubstitute(type: UnwrappedType): UnwrappedType =
substitute(type, runCapturedChecks = true, keepAnnotation = true) ?: type
val isEmpty: Boolean
private fun substitute(type: UnwrappedType, keepAnnotation: Boolean, runCapturedChecks: Boolean): UnwrappedType? =
when (type) {
is SimpleType -> substitute(type, keepAnnotation, runCapturedChecks)
@@ -170,10 +172,14 @@ interface NewTypeSubstitutor: TypeSubstitutorMarker {
object EmptySubstitutor : NewTypeSubstitutor {
override fun substituteNotNullTypeWithConstructor(constructor: TypeConstructor): UnwrappedType? = null
override val isEmpty: Boolean get() = true
}
class NewTypeSubstitutorByConstructorMap(val map: Map<TypeConstructor, UnwrappedType>) : NewTypeSubstitutor {
override fun substituteNotNullTypeWithConstructor(constructor: TypeConstructor): UnwrappedType? = map[constructor]
override val isEmpty: Boolean get() = map.isEmpty()
}
class FreshVariableNewTypeSubstitutor(val freshVariables: List<TypeVariableFromCallableDescriptor>) : NewTypeSubstitutor {
@@ -185,6 +191,8 @@ class FreshVariableNewTypeSubstitutor(val freshVariables: List<TypeVariableFromC
return typeVariable.defaultType
}
override val isEmpty: Boolean get() = freshVariables.isEmpty()
companion object {
val Empty = FreshVariableNewTypeSubstitutor(emptyList())
}
@@ -205,6 +213,8 @@ fun createCompositeSubstitutor(appliedFirst: NewTypeSubstitutor, appliedLast: Ty
}
}
}
override val isEmpty: Boolean get() = appliedFirst.isEmpty && appliedLast.isEmpty
}
}
@@ -0,0 +1,33 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// !LANGUAGE: +NewInference
// ISSUE: KT-33545
import kotlin.experimental.ExperimentalTypeInference
interface Flow<out T> {
suspend fun collect(collector: FlowCollector<T>)
}
interface FlowCollector<in T> {
suspend fun emit(value: T)
}
inline fun <T> Flow<T>.collect(crossinline action: suspend (value: T) -> Unit): Unit {}
abstract class LiveData<T>
interface LiveDataScope<T> {
suspend fun emit(value: T)
}
@UseExperimental(ExperimentalTypeInference::class)
fun <T> liveData(@BuilderInference block: suspend LiveDataScope<T>.() -> Unit): LiveData<T> = null!!
fun <Value> Flow<Value>.asLiveData() = liveData {
collect(this::emit)
// collect { emit(it) }
}
fun box(): String = "OK"
@@ -12518,6 +12518,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/inference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("builderInference.kt")
public void testBuilderInference() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference.kt");
}
@TestMetadata("capturedStarProjection.kt")
public void testCapturedStarProjection() throws Exception {
runTest("compiler/testData/codegen/box/inference/capturedStarProjection.kt");
@@ -12518,6 +12518,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/inference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("builderInference.kt")
public void testBuilderInference() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference.kt");
}
@TestMetadata("capturedStarProjection.kt")
public void testCapturedStarProjection() throws Exception {
runTest("compiler/testData/codegen/box/inference/capturedStarProjection.kt");
@@ -11368,6 +11368,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/inference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("builderInference.kt")
public void testBuilderInference() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference.kt");
}
@TestMetadata("capturedStarProjection.kt")
public void testCapturedStarProjection() throws Exception {
runTest("compiler/testData/codegen/box/inference/capturedStarProjection.kt");
@@ -11368,6 +11368,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/inference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("builderInference.kt")
public void testBuilderInference() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference.kt");
}
@TestMetadata("capturedStarProjection.kt")
public void testCapturedStarProjection() throws Exception {
runTest("compiler/testData/codegen/box/inference/capturedStarProjection.kt");