FirJavaGenericVarianceViolationTypeChecker: make code a bit more clear

This commit is contained in:
Mikhail Glukhikh
2021-08-17 18:02:50 +03:00
committed by TeamCityServer
parent f37d880964
commit 0a6e51e47f
@@ -110,7 +110,7 @@ object FirJavaGenericVarianceViolationTypeChecker : FirFunctionCallChecker() {
// actually created because of type projection from `get`. Hence, to workaround this problem, we simply remove all the out // actually created because of type projection from `get`. Hence, to workaround this problem, we simply remove all the out
// projection and type capturing and compare the types after such erasure. This way, we won't incorrectly reject any valid code // projection and type capturing and compare the types after such erasure. This way, we won't incorrectly reject any valid code
// though we may accept some invalid code. But in presence of the unsound flexible types, we are allowing invalid code already. // though we may accept some invalid code. But in presence of the unsound flexible types, we are allowing invalid code already.
val argTypeWithoutOutProjection = argType.removeOutProjection(true) val argTypeWithoutOutProjection = argType.removeOutProjection(isCovariant = true)
val lowerBoundWithoutCapturing = context.session.inferenceComponents.approximator.approximateToSuperType( val lowerBoundWithoutCapturing = context.session.inferenceComponents.approximator.approximateToSuperType(
lowerBound, lowerBound,
TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
@@ -127,31 +127,34 @@ object FirJavaGenericVarianceViolationTypeChecker : FirFunctionCallChecker() {
} }
} }
private fun ConeKotlinType.removeOutProjection(positive: Boolean): ConeKotlinType { private fun ConeKotlinType.removeOutProjection(isCovariant: Boolean): ConeKotlinType {
return when (this) { return when (this) {
is ConeFlexibleType -> ConeFlexibleType(lowerBound.removeOutProjection(positive), upperBound.removeOutProjection(positive)) is ConeFlexibleType -> ConeFlexibleType(
lowerBound.removeOutProjection(isCovariant),
upperBound.removeOutProjection(isCovariant)
)
is ConeCapturedType -> ConeCapturedType( is ConeCapturedType -> ConeCapturedType(
captureStatus, captureStatus,
lowerType?.removeOutProjection(positive), lowerType?.removeOutProjection(isCovariant),
nullability, nullability,
constructor.apply { constructor.apply {
ConeCapturedTypeConstructor( ConeCapturedTypeConstructor(
projection.removeOutProjection(positive), projection.removeOutProjection(isCovariant),
supertypes?.map { it.removeOutProjection(positive) }, supertypes?.map { it.removeOutProjection(isCovariant) },
typeParameterMarker typeParameterMarker
) )
}, },
attributes, attributes,
isProjectionNotNull isProjectionNotNull
) )
is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType(original.removeOutProjection(positive)) is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType(original.removeOutProjection(isCovariant))
is ConeIntersectionType -> ConeIntersectionType( is ConeIntersectionType -> ConeIntersectionType(
intersectedTypes.map { it.removeOutProjection(positive) }, intersectedTypes.map { it.removeOutProjection(isCovariant) },
alternativeType?.removeOutProjection(positive) alternativeType?.removeOutProjection(isCovariant)
) )
is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl( is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(
lookupTag, lookupTag,
typeArguments.map { it.removeOutProjection(positive) }.toTypedArray(), typeArguments.map { it.removeOutProjection(isCovariant) }.toTypedArray(),
isNullable, isNullable,
attributes attributes
) )
@@ -159,11 +162,17 @@ object FirJavaGenericVarianceViolationTypeChecker : FirFunctionCallChecker() {
} }
} }
private fun ConeTypeProjection.removeOutProjection(positive: Boolean): ConeTypeProjection { /**
* @param isCovariant true if the current context is covariant and false if contravariant.
*
* This function only remove out projections in covariant context.
* 'in' projections are never removed, nor would an out projection in a contravariant context.
*/
private fun ConeTypeProjection.removeOutProjection(isCovariant: Boolean): ConeTypeProjection {
return when (this) { return when (this) {
is ConeKotlinTypeProjectionOut -> if (positive) type else this is ConeKotlinTypeProjectionOut -> if (isCovariant) type else this
is ConeKotlinTypeProjectionIn -> ConeKotlinTypeProjectionIn(type.removeOutProjection(!positive)) is ConeKotlinTypeProjectionIn -> ConeKotlinTypeProjectionIn(type.removeOutProjection(!isCovariant))
is ConeStarProjection -> if (positive) StandardTypes.Any else this is ConeStarProjection -> if (isCovariant) StandardTypes.Any else this
// Don't remove nested projections for types at invariant position. // Don't remove nested projections for types at invariant position.
is ConeKotlinTypeConflictingProjection, is ConeKotlinTypeConflictingProjection,
is ConeKotlinType -> this is ConeKotlinType -> this
@@ -182,7 +191,10 @@ object FirJavaGenericVarianceViolationTypeChecker : FirFunctionCallChecker() {
for (immediateSuperType in subTypeConstructor.supertypes()) { for (immediateSuperType in subTypeConstructor.supertypes()) {
val immediateSuperTypeConstructor = immediateSuperType.typeConstructor() val immediateSuperTypeConstructor = immediateSuperType.typeConstructor()
if (superTypeConstructor == immediateSuperTypeConstructor) return true if (superTypeConstructor == immediateSuperTypeConstructor) return true
if (this@isTypeConstructorEqualOrSubClassOf.isTypeConstructorEqualOrSubClassOf(immediateSuperTypeConstructor, superTypeConstructor)) return true if (this@isTypeConstructorEqualOrSubClassOf.isTypeConstructorEqualOrSubClassOf(
immediateSuperTypeConstructor, superTypeConstructor
)
) return true
} }
return false return false
} }