From cbebb065745c5cef6e9d6cf98d4207796288b0f7 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 30 Nov 2016 17:10:47 +0300 Subject: [PATCH] Do not return star-projections during approximation See comment in test for clarification #KT-14453 Fixed --- .../capturedTypes/starProjectionRegression.kt | 17 +++++++++++++++++ .../capturedTypes/starProjectionRegression.txt | 16 ++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 ++++++ .../kotlin/types/CapturedTypeApproximation.kt | 6 +++++- 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/starProjectionRegression.kt create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/starProjectionRegression.txt diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/starProjectionRegression.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/starProjectionRegression.kt new file mode 100644 index 00000000000..bfee91bf948 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/starProjectionRegression.kt @@ -0,0 +1,17 @@ +// See KT-14453 +val KClass1.primaryConstructor: KFunction1? get() = null!! + +interface KClass1 +interface KFunction1 +fun f(type: KClass1<*>): KFunction1? = + // What happens here: + // 1. Create captured type for type argument T (it's built upon star-projection from `KClass<*>` that's argument is <: Any) + // 2. Approximate resulting descriptor, now it 'KClass1<*>.primaryConstructor: KFunction1<*>' + // Note that star-projection in 'KFunction1<*>' is obtained from KClass and its `projectionType` is Any (not-nullable). + // Of course that situation is already strange + // 3. When checking subtyping after call completion we get that 'KFunction1<*>' is not a subtype of 'KFunction1' in new type checker. + // The answer is correct, but this old type checker used `projectionType` for this and it was resulting in KFunction1<*> <: KFunction1 + // + // So to fix the issue we use 'out starProjectionType' instead of star-projection itself in approximation + // Note that in new inference there should be no approximation for IN-position types (they must remain captured) + type.primaryConstructor diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/starProjectionRegression.txt b/compiler/testData/diagnostics/tests/inference/capturedTypes/starProjectionRegression.txt new file mode 100644 index 00000000000..690efd1d759 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/starProjectionRegression.txt @@ -0,0 +1,16 @@ +package + +public val KClass1.primaryConstructor: KFunction1? +public fun f(/*0*/ type: KClass1<*>): KFunction1? + +public interface KClass1 { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface KFunction1 { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index e9833b71c64..10c682fa4ef 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -9740,6 +9740,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/overApproximationForOutCaptured.kt"); doTest(fileName); } + + @TestMetadata("starProjectionRegression.kt") + public void testStarProjectionRegression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/starProjectionRegression.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/diagnostics/tests/inference/commonSystem") diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt b/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt index e989b9a9eed..81ad0a3eb57 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt @@ -86,7 +86,11 @@ fun approximateCapturedTypesIfNecessary(typeProjection: TypeProjection?, approxi private fun substituteCapturedTypesWithProjections(typeProjection: TypeProjection): TypeProjection? { val typeSubstitutor = TypeSubstitutor.create(object : TypeConstructorSubstitution() { override fun get(key: TypeConstructor): TypeProjection? { - return (key as? CapturedTypeConstructor)?.typeProjection + val capturedTypeConstructor = key as? CapturedTypeConstructor ?: return null + if (capturedTypeConstructor.typeProjection.isStarProjection) { + return TypeProjectionImpl(Variance.OUT_VARIANCE, capturedTypeConstructor.typeProjection.type) + } + return capturedTypeConstructor.typeProjection } }) return typeSubstitutor.substituteWithoutApproximation(typeProjection)