NI: Fix regression for star-projections approximation
See the test added ^KT-35703 Fixed
This commit is contained in:
@@ -144,7 +144,8 @@ fun ConeKotlinType.lowerBoundIfFlexible() = (this as? ConeFlexibleType)?.lowerBo
|
||||
|
||||
class ConeCapturedTypeConstructor(
|
||||
val projection: ConeKotlinTypeProjection,
|
||||
var supertypes: List<ConeKotlinType>? = null
|
||||
var supertypes: List<ConeKotlinType>? = null,
|
||||
val typeParameterMarker: TypeParameterMarker? = null
|
||||
) : CapturedTypeConstructorMarker
|
||||
|
||||
class ConeCapturedType(
|
||||
@@ -153,11 +154,15 @@ class ConeCapturedType(
|
||||
override val nullability: ConeNullability = ConeNullability.NOT_NULL,
|
||||
val constructor: ConeCapturedTypeConstructor
|
||||
) : ConeSimpleKotlinType(), CapturedTypeMarker {
|
||||
constructor(captureStatus: CaptureStatus, lowerType: ConeKotlinType?, projection: ConeKotlinTypeProjection) : this(
|
||||
constructor(
|
||||
captureStatus: CaptureStatus, lowerType: ConeKotlinType?, projection: ConeKotlinTypeProjection,
|
||||
typeParameterMarker: TypeParameterMarker
|
||||
) : this(
|
||||
captureStatus,
|
||||
lowerType,
|
||||
constructor = ConeCapturedTypeConstructor(
|
||||
projection
|
||||
projection,
|
||||
typeParameterMarker = typeParameterMarker
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
+5
@@ -257,6 +257,11 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
||||
return this.constructor.projection
|
||||
}
|
||||
|
||||
override fun CapturedTypeMarker.typeParameter(): TypeParameterMarker? {
|
||||
require(this is ConeCapturedType)
|
||||
return this.constructor.typeParameterMarker
|
||||
}
|
||||
|
||||
override fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker {
|
||||
require(this is ConeDefinitelyNotNullType)
|
||||
return this.original as SimpleTypeMarker
|
||||
|
||||
@@ -319,7 +319,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
||||
null
|
||||
}
|
||||
|
||||
ConeCapturedType(status, lowerType, argument as ConeKotlinTypeProjection)
|
||||
ConeCapturedType(status, lowerType, argument, typeConstructor.getParameter(index))
|
||||
}
|
||||
|
||||
for (index in 0 until argumentsCount) {
|
||||
|
||||
Generated
+5
@@ -10058,6 +10058,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/inference/starApproximationFlexible.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("starApproximationFromDifferentTypeParameter.kt")
|
||||
public void testStarApproximationFromDifferentTypeParameter() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/starApproximationFromDifferentTypeParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("tooEagerSmartcast.kt")
|
||||
public void testTooEagerSmartcast() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/tooEagerSmartcast.kt");
|
||||
|
||||
+4
-1
@@ -83,7 +83,10 @@ interface NewTypeSubstitutor: TypeSubstitutorMarker {
|
||||
if (innerType is StubType || substitutedInnerType is StubType) {
|
||||
return NewCapturedType(
|
||||
capturedType.captureStatus,
|
||||
NewCapturedTypeConstructor(TypeProjectionImpl(typeConstructor.projection.projectionKind, substitutedInnerType)),
|
||||
NewCapturedTypeConstructor(
|
||||
TypeProjectionImpl(typeConstructor.projection.projectionKind, substitutedInnerType),
|
||||
typeParameter = typeConstructor.typeParameter
|
||||
),
|
||||
lowerType = if (capturedType.lowerType != null) substitutedInnerType else null
|
||||
)
|
||||
} else {
|
||||
|
||||
@@ -485,12 +485,14 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon
|
||||
|
||||
val argumentType = newArguments[index]?.getType() ?: argument.getType()
|
||||
|
||||
val capturedType = argumentType.lowerBoundIfFlexible().asCapturedType()
|
||||
val capturedStarProjectionOrNull =
|
||||
argumentType.lowerBoundIfFlexible().asCapturedType()?.typeConstructorProjection()?.takeIf { it.isStarProjection() }
|
||||
capturedType?.typeConstructorProjection()?.takeIf { it.isStarProjection() }
|
||||
|
||||
if (capturedStarProjectionOrNull != null &&
|
||||
(effectiveVariance == TypeVariance.OUT || effectiveVariance == TypeVariance.INV) &&
|
||||
toSuper
|
||||
toSuper &&
|
||||
capturedType.typeParameter() == parameter
|
||||
) {
|
||||
newArguments[index] = capturedStarProjectionOrNull
|
||||
continue@loop
|
||||
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
// SKIP_TXT
|
||||
// !LANGUAGE: +NewInference
|
||||
|
||||
// See KT-14453 and KT-35703
|
||||
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
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
// SKIP_TXT
|
||||
// !LANGUAGE: +NewInference
|
||||
|
||||
// See KT-14453 and KT-35703
|
||||
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
|
||||
@@ -10065,6 +10065,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/starApproximationFlexible.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("starApproximationFromDifferentTypeParameter.kt")
|
||||
public void testStarApproximationFromDifferentTypeParameter() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/starApproximationFromDifferentTypeParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("tooEagerSmartcast.kt")
|
||||
public void testTooEagerSmartcast() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/tooEagerSmartcast.kt");
|
||||
|
||||
Generated
+5
@@ -10060,6 +10060,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/inference/starApproximationFlexible.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("starApproximationFromDifferentTypeParameter.kt")
|
||||
public void testStarApproximationFromDifferentTypeParameter() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/starApproximationFromDifferentTypeParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("tooEagerSmartcast.kt")
|
||||
public void testTooEagerSmartcast() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/tooEagerSmartcast.kt");
|
||||
|
||||
@@ -404,6 +404,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
||||
return this.constructor.projection
|
||||
}
|
||||
|
||||
override fun CapturedTypeMarker.typeParameter(): TypeParameterMarker? {
|
||||
require(this is NewCapturedType, this::errorMessage)
|
||||
return this.constructor.typeParameter
|
||||
}
|
||||
|
||||
override fun CapturedTypeMarker.captureStatus(): CaptureStatus {
|
||||
require(this is NewCapturedType, this::errorMessage)
|
||||
return this.captureStatus
|
||||
|
||||
@@ -63,7 +63,7 @@ internal fun captureFromArguments(
|
||||
val arguments = type.arguments
|
||||
if (arguments.all { it.projectionKind == Variance.INVARIANT }) return null
|
||||
|
||||
val capturedArguments = arguments.map { projection ->
|
||||
val capturedArguments = arguments.zip(type.constructor.parameters).map { (projection, parameter) ->
|
||||
if (projection.projectionKind == Variance.INVARIANT) return@map projection
|
||||
|
||||
val lowerType =
|
||||
@@ -73,7 +73,7 @@ internal fun captureFromArguments(
|
||||
null
|
||||
}
|
||||
|
||||
NewCapturedType(status, lowerType, projection).asTypeProjection() // todo optimization: do not create type projection
|
||||
NewCapturedType(status, lowerType, projection, parameter).asTypeProjection() // todo optimization: do not create type projection
|
||||
}
|
||||
|
||||
val substitutor = TypeConstructorSubstitution.create(type.constructor, capturedArguments).buildSubstitutor()
|
||||
@@ -112,8 +112,9 @@ class NewCapturedType(
|
||||
override val annotations: Annotations = Annotations.EMPTY,
|
||||
override val isMarkedNullable: Boolean = false
|
||||
) : SimpleType(), CapturedTypeMarker {
|
||||
internal constructor(captureStatus: CaptureStatus, lowerType: UnwrappedType?, projection: TypeProjection) :
|
||||
this(captureStatus, NewCapturedTypeConstructor(projection), lowerType)
|
||||
internal constructor(
|
||||
captureStatus: CaptureStatus, lowerType: UnwrappedType?, projection: TypeProjection, typeParameter: TypeParameterDescriptor
|
||||
) : this(captureStatus, NewCapturedTypeConstructor(projection, typeParameter = typeParameter), lowerType)
|
||||
|
||||
override val arguments: List<TypeProjection> get() = listOf()
|
||||
|
||||
@@ -140,7 +141,8 @@ class NewCapturedType(
|
||||
class NewCapturedTypeConstructor(
|
||||
override val projection: TypeProjection,
|
||||
private var supertypesComputation: (() -> List<UnwrappedType>)? = null,
|
||||
private val original: NewCapturedTypeConstructor? = null
|
||||
private val original: NewCapturedTypeConstructor? = null,
|
||||
val typeParameter: TypeParameterDescriptor? = null
|
||||
) : CapturedTypeConstructor {
|
||||
|
||||
constructor(
|
||||
@@ -177,7 +179,8 @@ class NewCapturedTypeConstructor(
|
||||
supertypes.map { it.refine(kotlinTypeRefiner) }
|
||||
}
|
||||
},
|
||||
original ?: this
|
||||
original ?: this,
|
||||
typeParameter = typeParameter
|
||||
)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
||||
@@ -153,6 +153,7 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
||||
fun KotlinTypeMarker.mayBeTypeVariable(): Boolean
|
||||
|
||||
fun CapturedTypeMarker.typeConstructorProjection(): TypeArgumentMarker
|
||||
fun CapturedTypeMarker.typeParameter(): TypeParameterMarker?
|
||||
|
||||
fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker
|
||||
|
||||
|
||||
Reference in New Issue
Block a user