Do not return star-projections during approximation

See comment in test for clarification

 #KT-14453 Fixed
This commit is contained in:
Denis Zharkov
2016-11-30 17:10:47 +03:00
parent b8e1ce7a05
commit cbebb06574
4 changed files with 44 additions and 1 deletions
@@ -0,0 +1,17 @@
// See KT-14453
val <T : Any> KClass1<T>.primaryConstructor: KFunction1<T>? get() = null!!
interface KClass1<F : Any>
interface KFunction1<out R>
fun f(type: KClass1<*>): KFunction1<Any>? =
// 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<Any>' in new type checker.
// The answer is correct, but this old type checker used `projectionType` for this and it was resulting in KFunction1<*> <: KFunction1<Any>
//
// 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
@@ -0,0 +1,16 @@
package
public val </*0*/ T : kotlin.Any> KClass1<T>.primaryConstructor: KFunction1<T>?
public fun f(/*0*/ type: KClass1<*>): KFunction1<kotlin.Any>?
public interface KClass1</*0*/ F : kotlin.Any> {
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</*0*/ out R> {
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
}
@@ -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")
@@ -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)