Fix intersection type handling in PSI2IR
This commit is contained in:
+6
-6
@@ -299,19 +299,19 @@ internal class InsertImplicitCasts(
|
||||
null
|
||||
|
||||
private fun IrExpression.cast(
|
||||
expectedType: KotlinType?,
|
||||
originalExpectedType: KotlinType? = expectedType,
|
||||
possiblyNonDenotableExpectedType: KotlinType?,
|
||||
originalExpectedType: KotlinType? = possiblyNonDenotableExpectedType,
|
||||
isLambdaReturnValue: Boolean = false
|
||||
): IrExpression {
|
||||
if (expectedType == null) return this
|
||||
if (expectedType.isError) return this
|
||||
if (possiblyNonDenotableExpectedType == null) return this
|
||||
if (possiblyNonDenotableExpectedType.isError) return this
|
||||
|
||||
val expectedType = typeTranslator.approximate(possiblyNonDenotableExpectedType)
|
||||
|
||||
if (this is IrFunctionExpression && originalExpectedType != null) {
|
||||
recordExpectedLambdaReturnTypeIfAppropriate(expectedType, originalExpectedType)
|
||||
}
|
||||
|
||||
// TODO here we can have non-denotable KotlinTypes (both in 'this@cast.type' and 'expectedType').
|
||||
|
||||
val notNullableExpectedType = expectedType.makeNotNullable()
|
||||
|
||||
val valueType = this.type.originalKotlinType!!
|
||||
|
||||
@@ -62,27 +62,27 @@ class TypeTranslator(
|
||||
}
|
||||
|
||||
fun translateType(kotlinType: KotlinType): IrType =
|
||||
translateType(kotlinType, kotlinType, Variance.INVARIANT).type
|
||||
translateType(kotlinType, Variance.INVARIANT).type
|
||||
|
||||
private fun translateType(kotlinType: KotlinType, approximatedKotlinType: KotlinType, variance: Variance): IrTypeProjection {
|
||||
val approximatedType = LegacyTypeApproximation().approximate(kotlinType)
|
||||
private fun translateType(kotlinType: KotlinType, variance: Variance): IrTypeProjection {
|
||||
val flexibleApproximatedType = approximate(kotlinType)
|
||||
|
||||
when {
|
||||
approximatedType.isError ->
|
||||
return IrErrorTypeImpl(approximatedKotlinType, translateTypeAnnotations(approximatedType.annotations), variance)
|
||||
approximatedType.isDynamic() ->
|
||||
return IrDynamicTypeImpl(approximatedKotlinType, translateTypeAnnotations(approximatedType.annotations), variance)
|
||||
approximatedType.isFlexible() ->
|
||||
return translateType(approximatedType.upperIfFlexible(), approximatedType, variance)
|
||||
flexibleApproximatedType.isError ->
|
||||
return IrErrorTypeImpl(flexibleApproximatedType, translateTypeAnnotations(flexibleApproximatedType.annotations), variance)
|
||||
flexibleApproximatedType.isDynamic() ->
|
||||
return IrDynamicTypeImpl(flexibleApproximatedType, translateTypeAnnotations(flexibleApproximatedType.annotations), variance)
|
||||
}
|
||||
|
||||
val approximatedType = flexibleApproximatedType.upperIfFlexible()
|
||||
|
||||
val ktTypeConstructor = approximatedType.constructor
|
||||
val ktTypeDescriptor = ktTypeConstructor.declarationDescriptor
|
||||
?: throw AssertionError("No descriptor for type $approximatedType")
|
||||
|
||||
return IrSimpleTypeBuilder().apply {
|
||||
this.kotlinType = approximatedKotlinType
|
||||
hasQuestionMark = approximatedType.isMarkedNullable
|
||||
this.kotlinType = flexibleApproximatedType
|
||||
this.hasQuestionMark = approximatedType.isMarkedNullable
|
||||
this.variance = variance
|
||||
this.abbreviation = approximatedType.getAbbreviation()?.toIrTypeAbbreviation()
|
||||
when (ktTypeDescriptor) {
|
||||
@@ -116,46 +116,42 @@ class TypeTranslator(
|
||||
)
|
||||
}
|
||||
|
||||
private inner class LegacyTypeApproximation {
|
||||
fun approximate(ktType: KotlinType): KotlinType {
|
||||
val properlyApproximatedType = approximateByKotlinRules(ktType)
|
||||
|
||||
fun approximate(ktType: KotlinType): KotlinType {
|
||||
val properlyApproximatedType = approximateByKotlinRules(ktType)
|
||||
|
||||
// If there's an intersection type, take the most common supertype of its intermediate supertypes.
|
||||
// That's what old back-end effectively does.
|
||||
val typeConstructor = properlyApproximatedType.constructor
|
||||
if (typeConstructor is IntersectionTypeConstructor) {
|
||||
val commonSupertype = CommonSupertypes.commonSupertype(typeConstructor.supertypes)
|
||||
return approximate(commonSupertype.replaceArgumentsWithStarProjections())
|
||||
}
|
||||
|
||||
// Other types should be approximated properly. Right? Riiight?
|
||||
return properlyApproximatedType
|
||||
// If there's an intersection type, take the most common supertype of its intermediate supertypes.
|
||||
// That's what old back-end effectively does.
|
||||
val typeConstructor = properlyApproximatedType.constructor
|
||||
if (typeConstructor is IntersectionTypeConstructor) {
|
||||
val commonSupertype = CommonSupertypes.commonSupertype(typeConstructor.supertypes)
|
||||
return approximate(commonSupertype.replaceArgumentsWithStarProjections())
|
||||
}
|
||||
|
||||
private val isWithNewInference = languageVersionSettings.supportsFeature(LanguageFeature.NewInference)
|
||||
|
||||
private fun approximateByKotlinRules(ktType: KotlinType): KotlinType =
|
||||
if (isWithNewInference) {
|
||||
if (ktType.constructor.isDenotable && ktType.arguments.isEmpty())
|
||||
ktType
|
||||
else
|
||||
typeApproximatorForNI.approximateDeclarationType(
|
||||
ktType,
|
||||
local = false,
|
||||
languageVersionSettings = languageVersionSettings
|
||||
)
|
||||
} else {
|
||||
// Hack to preserve *-projections in arguments in OI.
|
||||
// Expected to be removed as soon as OI is deprecated.
|
||||
if (ktType.constructor.isDenotable)
|
||||
ktType
|
||||
else
|
||||
approximateCapturedTypes(ktType).upper
|
||||
}
|
||||
|
||||
// Assume that other types are approximated properly.
|
||||
return properlyApproximatedType
|
||||
}
|
||||
|
||||
private val isWithNewInference = languageVersionSettings.supportsFeature(LanguageFeature.NewInference)
|
||||
|
||||
private fun approximateByKotlinRules(ktType: KotlinType): KotlinType =
|
||||
if (isWithNewInference) {
|
||||
if (ktType.constructor.isDenotable && ktType.arguments.isEmpty())
|
||||
ktType
|
||||
else
|
||||
typeApproximatorForNI.approximateDeclarationType(
|
||||
ktType,
|
||||
local = false,
|
||||
languageVersionSettings = languageVersionSettings
|
||||
)
|
||||
} else {
|
||||
// Hack to preserve *-projections in arguments in OI.
|
||||
// Expected to be removed as soon as OI is deprecated.
|
||||
if (ktType.constructor.isDenotable)
|
||||
ktType
|
||||
else
|
||||
approximateCapturedTypes(ktType).upper
|
||||
}
|
||||
|
||||
private fun translateTypeAnnotations(annotations: Annotations): List<IrConstructorCall> =
|
||||
annotations.mapNotNull(constantValueGenerator::generateAnnotationConstructorCall)
|
||||
|
||||
@@ -164,6 +160,6 @@ class TypeTranslator(
|
||||
if (it.isStarProjection)
|
||||
IrStarProjectionImpl
|
||||
else
|
||||
translateType(it.type, it.type, it.projectionKind)
|
||||
translateType(it.type, it.projectionKind)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user