[FIR2IR] Approximate non-denotable types when converting ConeType to IrType

This commit is contained in:
Dmitriy Novozhilov
2021-02-27 15:19:23 +03:00
committed by TeamCityServer
parent c271f953d7
commit da0fd7cc15
31 changed files with 147 additions and 325 deletions
@@ -236,7 +236,8 @@ class ConeRawType(lowerBound: ConeKotlinType, upperBound: ConeKotlinType) : Cone
* only via ConeTypeIntersector
*/
class ConeIntersectionType(
val intersectedTypes: Collection<ConeKotlinType>
val intersectedTypes: Collection<ConeKotlinType>,
val alternativeType: ConeKotlinType? = null,
) : ConeSimpleKotlinType(), IntersectionTypeConstructorMarker {
override val typeArguments: Array<out ConeTypeProjection>
get() = emptyArray()
@@ -266,7 +267,10 @@ class ConeIntersectionType(
if (hashCode != 0) return hashCode
return intersectedTypes.hashCode().also { hashCode = it }
}
}
fun ConeIntersectionType.withAlternative(alternativeType: ConeKotlinType): ConeIntersectionType {
return ConeIntersectionType(intersectedTypes, alternativeType)
}
fun ConeIntersectionType.mapTypes(func: (ConeKotlinType) -> ConeKotlinType): ConeIntersectionType {
@@ -8,8 +8,11 @@ package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.classId
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
@@ -20,6 +23,7 @@ import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.types.Variance
class Fir2IrTypeConverter(
@@ -60,6 +64,8 @@ class Fir2IrTypeConverter(
private val capturedTypeCache = mutableMapOf<ConeCapturedType, IrType>()
private val errorTypeForCapturedTypeStub by lazy { createErrorType() }
private val typeApproximator = ConeTypeApproximator(session.typeContext)
fun FirTypeRef.toIrType(typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT): IrType {
capturedTypeCache.clear()
return when (this) {
@@ -106,9 +112,10 @@ class Fir2IrTypeConverter(
typeAnnotations += callGenerator.convertToIrConstructorCall(attributeAnnotation) as? IrConstructorCall ?: continue
}
val expandedType = fullyExpandedType(session)
val approximatedType = approximateType(expandedType)
IrSimpleTypeImpl(
irSymbol, !typeContext.definitelyNotNull && expandedType.isMarkedNullable,
expandedType.typeArguments.map { it.toIrTypeArgument(typeContext) },
irSymbol, !typeContext.definitelyNotNull && approximatedType.isMarkedNullable,
approximatedType.typeArguments.map { it.toIrTypeArgument(typeContext) },
typeAnnotations
)
}
@@ -211,6 +218,22 @@ class Fir2IrTypeConverter(
private fun getBuiltInClassSymbol(classId: ClassId?): IrClassSymbol? {
return classIdToSymbolMap[classId] ?: getArrayClassSymbol(classId)
}
private fun approximateType(type: ConeKotlinType): ConeKotlinType {
if (type is ConeClassLikeType && type.typeArguments.isEmpty()) return type
val substitutor = object : AbstractConeSubstitutor() {
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
return if (type is ConeIntersectionType) {
type.alternativeType?.let { substituteOrSelf(it) }
} else null
}
}
val typeWithSpecifiedIntersectionTypes = substitutor.substituteOrSelf(type)
return typeApproximator.approximateToSuperType(
typeWithSpecifiedIntersectionTypes,
TypeApproximatorConfiguration.PublicDeclaration
) ?: type
}
}
fun FirTypeRef.toIrType(
@@ -16616,6 +16616,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inference/integerLiteralTypeInLamdaReturnType.kt");
}
@Test
@TestMetadata("intersectionTypeInArguments.kt")
public void testIntersectionTypeInArguments() throws Exception {
runTest("compiler/testData/codegen/box/inference/intersectionTypeInArguments.kt");
}
@Test
@TestMetadata("kt10822.kt")
public void testKt10822() throws Exception {
@@ -485,7 +485,11 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
firstCandidate: KotlinTypeMarker,
secondCandidate: KotlinTypeMarker
): KotlinTypeMarker {
// TODO
return firstCandidate
require(firstCandidate is ConeKotlinType)
require(secondCandidate is ConeKotlinType)
val intersectionType = firstCandidate.lowerBoundIfFlexible() as? ConeIntersectionType ?: error {
"Expected type is intersection, found $firstCandidate"
}
return intersectionType.withAlternative(secondCandidate)
}
}