FIR2IR (refactoring): introduce ConversionTypeContext

This commit is contained in:
Mikhail Glukhikh
2020-02-28 00:10:02 +03:00
parent 883dd95e3c
commit 9e69ffad36
2 changed files with 71 additions and 32 deletions
@@ -50,53 +50,72 @@ internal fun <T : IrElement> FirElement.convertWithOffsets(
internal fun createErrorType(): IrErrorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT)
internal enum class ConversionTypeOrigin {
DEFAULT,
SETTER
}
class ConversionTypeContext internal constructor(
internal val definitelyNotNull: Boolean,
internal val origin: ConversionTypeOrigin
) {
fun definitelyNotNull() = ConversionTypeContext(true, origin)
fun inSetter() = ConversionTypeContext(definitelyNotNull, ConversionTypeOrigin.SETTER)
companion object {
internal val DEFAULT = ConversionTypeContext(
definitelyNotNull = false, origin = ConversionTypeOrigin.DEFAULT
)
}
}
fun FirTypeRef.toIrType(
session: FirSession,
declarationStorage: Fir2IrDeclarationStorage,
irBuiltIns: IrBuiltIns,
forSetter: Boolean = false
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrType {
if (this !is FirResolvedTypeRef) {
return createErrorType()
}
return type.toIrType(session, declarationStorage, irBuiltIns, forSetter = forSetter)
return type.toIrType(session, declarationStorage, irBuiltIns, typeContext)
}
fun ConeKotlinType.toIrType(
session: FirSession,
declarationStorage: Fir2IrDeclarationStorage,
irBuiltIns: IrBuiltIns,
definitelyNotNull: Boolean = false,
forSetter: Boolean = false
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrType {
return when (this) {
is ConeKotlinErrorType -> createErrorType()
is ConeLookupTagBasedType -> {
val irSymbol = getArrayType(this.classId, irBuiltIns) ?: run {
val firSymbol = this.lookupTag.toSymbol(session) ?: return createErrorType()
firSymbol.toIrSymbol(session, declarationStorage, forSetter)
firSymbol.toIrSymbol(session, declarationStorage, typeContext)
}
// TODO: annotations
IrSimpleTypeImpl(
irSymbol, !definitelyNotNull && this.isMarkedNullable,
irSymbol, !typeContext.definitelyNotNull && this.isMarkedNullable,
typeArguments.map { it.toIrTypeArgument(session, declarationStorage, irBuiltIns) },
emptyList()
)
}
is ConeFlexibleType -> {
// TODO: yet we take more general type. Not quite sure it's Ok
upperBound.toIrType(session, declarationStorage, irBuiltIns, definitelyNotNull)
upperBound.toIrType(session, declarationStorage, irBuiltIns, typeContext)
}
is ConeCapturedType -> TODO()
is ConeDefinitelyNotNullType -> {
original.toIrType(session, declarationStorage, irBuiltIns, definitelyNotNull = true)
original.toIrType(session, declarationStorage, irBuiltIns, typeContext.definitelyNotNull())
}
is ConeIntersectionType -> {
// TODO: add intersectionTypeApproximation
intersectedTypes.first().toIrType(session, declarationStorage, irBuiltIns, definitelyNotNull)
intersectedTypes.first().toIrType(session, declarationStorage, irBuiltIns, typeContext)
}
is ConeStubType -> createErrorType()
is ConeIntegerLiteralType -> getApproximatedType().toIrType(session, declarationStorage, irBuiltIns, definitelyNotNull)
is ConeIntegerLiteralType -> getApproximatedType().toIrType(session, declarationStorage, irBuiltIns, typeContext)
}
}
@@ -141,11 +160,11 @@ fun ConeTypeProjection.toIrTypeArgument(
fun FirClassifierSymbol<*>.toIrSymbol(
session: FirSession,
declarationStorage: Fir2IrDeclarationStorage,
forSetter: Boolean = false
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrClassifierSymbol {
return when (this) {
is FirTypeParameterSymbol -> {
toTypeParameterSymbol(declarationStorage, forSetter)
toTypeParameterSymbol(declarationStorage, typeContext)
}
is FirTypeAliasSymbol -> {
val typeAlias = fir
@@ -201,9 +220,9 @@ fun FirClassSymbol<*>.toClassSymbol(declarationStorage: Fir2IrDeclarationStorage
fun FirTypeParameterSymbol.toTypeParameterSymbol(
declarationStorage: Fir2IrDeclarationStorage,
forSetter: Boolean = false
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrTypeParameterSymbol {
return declarationStorage.getIrTypeParameterSymbol(this, forSetter)
return declarationStorage.getIrTypeParameterSymbol(this, typeContext)
}
fun FirFunctionSymbol<*>.toFunctionSymbol(declarationStorage: Fir2IrDeclarationStorage): IrFunctionSymbol {
@@ -102,8 +102,11 @@ class Fir2IrDeclarationStorage(
irSymbolTable.leaveScope(descriptor)
}
private fun FirTypeRef.toIrType(session: FirSession, declarationStorage: Fir2IrDeclarationStorage, forSetter: Boolean = false) =
toIrType(session, declarationStorage, irBuiltIns, forSetter)
private fun FirTypeRef.toIrType(
session: FirSession,
declarationStorage: Fir2IrDeclarationStorage,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
) = toIrType(session, declarationStorage, irBuiltIns, typeContext)
private fun getIrExternalPackageFragment(fqName: FqName): IrExternalPackageFragment {
return fragmentCache.getOrPut(fqName) {
@@ -151,14 +154,17 @@ class Fir2IrDeclarationStorage(
owner.typeParameters.mapIndexed { index, typeParameter ->
getIrTypeParameter(typeParameter, index)
if (owner is FirProperty && owner.isVar) {
getIrTypeParameter(typeParameter, index, forSetter = true)
getIrTypeParameter(typeParameter, index, ConversionTypeContext.DEFAULT.inSetter())
}
}
}
private fun IrTypeParametersContainer.setTypeParameters(owner: FirTypeParametersOwner, forSetter: Boolean = false) {
private fun IrTypeParametersContainer.setTypeParameters(
owner: FirTypeParametersOwner,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
) {
typeParameters = owner.typeParameters.mapIndexed { index, typeParameter ->
getIrTypeParameter(typeParameter, index, forSetter).apply { parent = this@setTypeParameters }
getIrTypeParameter(typeParameter, index, typeContext).apply { parent = this@setTypeParameters }
}
}
@@ -328,12 +334,16 @@ class Fir2IrDeclarationStorage(
}.declareSupertypesAndTypeParameters(anonymousObject)
}
private fun getIrTypeParameter(typeParameter: FirTypeParameter, index: Int = -1, forSetter: Boolean = false): IrTypeParameter {
private fun getIrTypeParameter(
typeParameter: FirTypeParameter,
index: Int = -1,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrTypeParameter {
// Here transformation is a bit difficult because one FIR property type parameter
// can be transformed to two different type parameters: one for getter and another one for setter
val simpleCachedParameter = typeParameterCache[typeParameter]
if (simpleCachedParameter != null) {
if (!forSetter) {
if (typeContext.origin != ConversionTypeOrigin.SETTER) {
return simpleCachedParameter
}
if (index < 0) {
@@ -343,7 +353,7 @@ class Fir2IrDeclarationStorage(
}
}
}
if (forSetter) {
if (typeContext.origin == ConversionTypeOrigin.SETTER) {
typeParameterCacheForSetter[typeParameter]?.let { return it }
}
return typeParameter.run {
@@ -368,7 +378,7 @@ class Fir2IrDeclarationStorage(
}
// Cache the type parameter BEFORE processing its bounds/supertypes, to properly handle recursive type bounds.
if (forSetter) {
if (typeContext.origin == ConversionTypeOrigin.SETTER) {
typeParameterCacheForSetter[typeParameter] = irTypeParameter
} else {
typeParameterCache[typeParameter] = irTypeParameter
@@ -445,9 +455,13 @@ class Fir2IrDeclarationStorage(
setTypeParameters(function)
}
val forSetter = function is FirPropertyAccessor && function.isSetter
val typeContext = ConversionTypeContext(
definitelyNotNull = false,
origin = if (forSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
)
if (function is FirDefaultPropertySetter) {
val type = function.valueParameters.first().returnTypeRef.toIrType(
session, this@Fir2IrDeclarationStorage, forSetter = true
session, this@Fir2IrDeclarationStorage, ConversionTypeContext.DEFAULT.inSetter()
)
declareDefaultSetterParameter(type)
} else if (function != null) {
@@ -455,7 +469,7 @@ class Fir2IrDeclarationStorage(
createAndSaveIrParameter(
valueParameter, index,
useStubForDefaultValueStub = function !is FirConstructor || containingClass?.name != Name.identifier("Enum"),
forSetter = forSetter
typeContext
).apply {
this.parent = parent
}
@@ -468,7 +482,7 @@ class Fir2IrDeclarationStorage(
extensionReceiverParameter = receiverTypeRef.convertWithOffsets { startOffset, endOffset ->
declareThisReceiverParameter(
parent,
thisType = receiverTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, forSetter),
thisType = receiverTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, typeContext),
thisOrigin = thisOrigin,
startOffset = startOffset,
endOffset = endOffset
@@ -657,10 +671,13 @@ class Fir2IrDeclarationStorage(
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE,
isOperator = false
).apply {
setTypeParameters(property, forSetter = isSetter)
setTypeParameters(property, ConversionTypeContext(
definitelyNotNull = false,
origin = if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
))
if (propertyAccessor == null && isSetter) {
declareDefaultSetterParameter(
property.returnTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, forSetter = true)
property.returnTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, ConversionTypeContext.DEFAULT.inSetter())
)
}
}.bindAndDeclareParameters(
@@ -799,7 +816,7 @@ class Fir2IrDeclarationStorage(
valueParameter: FirValueParameter,
index: Int = -1,
useStubForDefaultValueStub: Boolean = true,
forSetter: Boolean = false
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrValueParameter {
val descriptor = WrappedValueParameterDescriptor()
val origin = IrDeclarationOrigin.DEFINED
@@ -813,7 +830,7 @@ class Fir2IrDeclarationStorage(
valueParameter.name, index, type,
if (!valueParameter.isVararg) null
else valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.arrayElementType(session)?.toIrType(
session, this, irBuiltIns, forSetter
session, this, irBuiltIns, typeContext
),
valueParameter.isCrossinline, valueParameter.isNoinline
).apply {
@@ -894,8 +911,11 @@ class Fir2IrDeclarationStorage(
return irSymbolTable.referenceClass(irClass.descriptor)
}
fun getIrTypeParameterSymbol(firTypeParameterSymbol: FirTypeParameterSymbol, forSetter: Boolean): IrTypeParameterSymbol {
val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir, forSetter = forSetter)
fun getIrTypeParameterSymbol(
firTypeParameterSymbol: FirTypeParameterSymbol,
typeContext: ConversionTypeContext
): IrTypeParameterSymbol {
val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir, typeContext = typeContext)
return irSymbolTable.referenceTypeParameter(irTypeParameter.descriptor)
}