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 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( fun FirTypeRef.toIrType(
session: FirSession, session: FirSession,
declarationStorage: Fir2IrDeclarationStorage, declarationStorage: Fir2IrDeclarationStorage,
irBuiltIns: IrBuiltIns, irBuiltIns: IrBuiltIns,
forSetter: Boolean = false typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrType { ): IrType {
if (this !is FirResolvedTypeRef) { if (this !is FirResolvedTypeRef) {
return createErrorType() return createErrorType()
} }
return type.toIrType(session, declarationStorage, irBuiltIns, forSetter = forSetter) return type.toIrType(session, declarationStorage, irBuiltIns, typeContext)
} }
fun ConeKotlinType.toIrType( fun ConeKotlinType.toIrType(
session: FirSession, session: FirSession,
declarationStorage: Fir2IrDeclarationStorage, declarationStorage: Fir2IrDeclarationStorage,
irBuiltIns: IrBuiltIns, irBuiltIns: IrBuiltIns,
definitelyNotNull: Boolean = false, typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
forSetter: Boolean = false
): IrType { ): IrType {
return when (this) { return when (this) {
is ConeKotlinErrorType -> createErrorType() is ConeKotlinErrorType -> createErrorType()
is ConeLookupTagBasedType -> { is ConeLookupTagBasedType -> {
val irSymbol = getArrayType(this.classId, irBuiltIns) ?: run { val irSymbol = getArrayType(this.classId, irBuiltIns) ?: run {
val firSymbol = this.lookupTag.toSymbol(session) ?: return createErrorType() val firSymbol = this.lookupTag.toSymbol(session) ?: return createErrorType()
firSymbol.toIrSymbol(session, declarationStorage, forSetter) firSymbol.toIrSymbol(session, declarationStorage, typeContext)
} }
// TODO: annotations // TODO: annotations
IrSimpleTypeImpl( IrSimpleTypeImpl(
irSymbol, !definitelyNotNull && this.isMarkedNullable, irSymbol, !typeContext.definitelyNotNull && this.isMarkedNullable,
typeArguments.map { it.toIrTypeArgument(session, declarationStorage, irBuiltIns) }, typeArguments.map { it.toIrTypeArgument(session, declarationStorage, irBuiltIns) },
emptyList() emptyList()
) )
} }
is ConeFlexibleType -> { is ConeFlexibleType -> {
// TODO: yet we take more general type. Not quite sure it's Ok // 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 ConeCapturedType -> TODO()
is ConeDefinitelyNotNullType -> { is ConeDefinitelyNotNullType -> {
original.toIrType(session, declarationStorage, irBuiltIns, definitelyNotNull = true) original.toIrType(session, declarationStorage, irBuiltIns, typeContext.definitelyNotNull())
} }
is ConeIntersectionType -> { is ConeIntersectionType -> {
// TODO: add intersectionTypeApproximation // TODO: add intersectionTypeApproximation
intersectedTypes.first().toIrType(session, declarationStorage, irBuiltIns, definitelyNotNull) intersectedTypes.first().toIrType(session, declarationStorage, irBuiltIns, typeContext)
} }
is ConeStubType -> createErrorType() 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( fun FirClassifierSymbol<*>.toIrSymbol(
session: FirSession, session: FirSession,
declarationStorage: Fir2IrDeclarationStorage, declarationStorage: Fir2IrDeclarationStorage,
forSetter: Boolean = false typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrClassifierSymbol { ): IrClassifierSymbol {
return when (this) { return when (this) {
is FirTypeParameterSymbol -> { is FirTypeParameterSymbol -> {
toTypeParameterSymbol(declarationStorage, forSetter) toTypeParameterSymbol(declarationStorage, typeContext)
} }
is FirTypeAliasSymbol -> { is FirTypeAliasSymbol -> {
val typeAlias = fir val typeAlias = fir
@@ -201,9 +220,9 @@ fun FirClassSymbol<*>.toClassSymbol(declarationStorage: Fir2IrDeclarationStorage
fun FirTypeParameterSymbol.toTypeParameterSymbol( fun FirTypeParameterSymbol.toTypeParameterSymbol(
declarationStorage: Fir2IrDeclarationStorage, declarationStorage: Fir2IrDeclarationStorage,
forSetter: Boolean = false typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrTypeParameterSymbol { ): IrTypeParameterSymbol {
return declarationStorage.getIrTypeParameterSymbol(this, forSetter) return declarationStorage.getIrTypeParameterSymbol(this, typeContext)
} }
fun FirFunctionSymbol<*>.toFunctionSymbol(declarationStorage: Fir2IrDeclarationStorage): IrFunctionSymbol { fun FirFunctionSymbol<*>.toFunctionSymbol(declarationStorage: Fir2IrDeclarationStorage): IrFunctionSymbol {
@@ -102,8 +102,11 @@ class Fir2IrDeclarationStorage(
irSymbolTable.leaveScope(descriptor) irSymbolTable.leaveScope(descriptor)
} }
private fun FirTypeRef.toIrType(session: FirSession, declarationStorage: Fir2IrDeclarationStorage, forSetter: Boolean = false) = private fun FirTypeRef.toIrType(
toIrType(session, declarationStorage, irBuiltIns, forSetter) session: FirSession,
declarationStorage: Fir2IrDeclarationStorage,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
) = toIrType(session, declarationStorage, irBuiltIns, typeContext)
private fun getIrExternalPackageFragment(fqName: FqName): IrExternalPackageFragment { private fun getIrExternalPackageFragment(fqName: FqName): IrExternalPackageFragment {
return fragmentCache.getOrPut(fqName) { return fragmentCache.getOrPut(fqName) {
@@ -151,14 +154,17 @@ class Fir2IrDeclarationStorage(
owner.typeParameters.mapIndexed { index, typeParameter -> owner.typeParameters.mapIndexed { index, typeParameter ->
getIrTypeParameter(typeParameter, index) getIrTypeParameter(typeParameter, index)
if (owner is FirProperty && owner.isVar) { 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 -> 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) }.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 // 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 // can be transformed to two different type parameters: one for getter and another one for setter
val simpleCachedParameter = typeParameterCache[typeParameter] val simpleCachedParameter = typeParameterCache[typeParameter]
if (simpleCachedParameter != null) { if (simpleCachedParameter != null) {
if (!forSetter) { if (typeContext.origin != ConversionTypeOrigin.SETTER) {
return simpleCachedParameter return simpleCachedParameter
} }
if (index < 0) { if (index < 0) {
@@ -343,7 +353,7 @@ class Fir2IrDeclarationStorage(
} }
} }
} }
if (forSetter) { if (typeContext.origin == ConversionTypeOrigin.SETTER) {
typeParameterCacheForSetter[typeParameter]?.let { return it } typeParameterCacheForSetter[typeParameter]?.let { return it }
} }
return typeParameter.run { return typeParameter.run {
@@ -368,7 +378,7 @@ class Fir2IrDeclarationStorage(
} }
// Cache the type parameter BEFORE processing its bounds/supertypes, to properly handle recursive type bounds. // 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 typeParameterCacheForSetter[typeParameter] = irTypeParameter
} else { } else {
typeParameterCache[typeParameter] = irTypeParameter typeParameterCache[typeParameter] = irTypeParameter
@@ -445,9 +455,13 @@ class Fir2IrDeclarationStorage(
setTypeParameters(function) setTypeParameters(function)
} }
val forSetter = function is FirPropertyAccessor && function.isSetter val forSetter = function is FirPropertyAccessor && function.isSetter
val typeContext = ConversionTypeContext(
definitelyNotNull = false,
origin = if (forSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
)
if (function is FirDefaultPropertySetter) { if (function is FirDefaultPropertySetter) {
val type = function.valueParameters.first().returnTypeRef.toIrType( val type = function.valueParameters.first().returnTypeRef.toIrType(
session, this@Fir2IrDeclarationStorage, forSetter = true session, this@Fir2IrDeclarationStorage, ConversionTypeContext.DEFAULT.inSetter()
) )
declareDefaultSetterParameter(type) declareDefaultSetterParameter(type)
} else if (function != null) { } else if (function != null) {
@@ -455,7 +469,7 @@ class Fir2IrDeclarationStorage(
createAndSaveIrParameter( createAndSaveIrParameter(
valueParameter, index, valueParameter, index,
useStubForDefaultValueStub = function !is FirConstructor || containingClass?.name != Name.identifier("Enum"), useStubForDefaultValueStub = function !is FirConstructor || containingClass?.name != Name.identifier("Enum"),
forSetter = forSetter typeContext
).apply { ).apply {
this.parent = parent this.parent = parent
} }
@@ -468,7 +482,7 @@ class Fir2IrDeclarationStorage(
extensionReceiverParameter = receiverTypeRef.convertWithOffsets { startOffset, endOffset -> extensionReceiverParameter = receiverTypeRef.convertWithOffsets { startOffset, endOffset ->
declareThisReceiverParameter( declareThisReceiverParameter(
parent, parent,
thisType = receiverTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, forSetter), thisType = receiverTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, typeContext),
thisOrigin = thisOrigin, thisOrigin = thisOrigin,
startOffset = startOffset, startOffset = startOffset,
endOffset = endOffset endOffset = endOffset
@@ -657,10 +671,13 @@ class Fir2IrDeclarationStorage(
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE, isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE,
isOperator = false isOperator = false
).apply { ).apply {
setTypeParameters(property, forSetter = isSetter) setTypeParameters(property, ConversionTypeContext(
definitelyNotNull = false,
origin = if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
))
if (propertyAccessor == null && isSetter) { if (propertyAccessor == null && isSetter) {
declareDefaultSetterParameter( declareDefaultSetterParameter(
property.returnTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, forSetter = true) property.returnTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, ConversionTypeContext.DEFAULT.inSetter())
) )
} }
}.bindAndDeclareParameters( }.bindAndDeclareParameters(
@@ -799,7 +816,7 @@ class Fir2IrDeclarationStorage(
valueParameter: FirValueParameter, valueParameter: FirValueParameter,
index: Int = -1, index: Int = -1,
useStubForDefaultValueStub: Boolean = true, useStubForDefaultValueStub: Boolean = true,
forSetter: Boolean = false typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrValueParameter { ): IrValueParameter {
val descriptor = WrappedValueParameterDescriptor() val descriptor = WrappedValueParameterDescriptor()
val origin = IrDeclarationOrigin.DEFINED val origin = IrDeclarationOrigin.DEFINED
@@ -813,7 +830,7 @@ class Fir2IrDeclarationStorage(
valueParameter.name, index, type, valueParameter.name, index, type,
if (!valueParameter.isVararg) null if (!valueParameter.isVararg) null
else valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.arrayElementType(session)?.toIrType( else valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.arrayElementType(session)?.toIrType(
session, this, irBuiltIns, forSetter session, this, irBuiltIns, typeContext
), ),
valueParameter.isCrossinline, valueParameter.isNoinline valueParameter.isCrossinline, valueParameter.isNoinline
).apply { ).apply {
@@ -894,8 +911,11 @@ class Fir2IrDeclarationStorage(
return irSymbolTable.referenceClass(irClass.descriptor) return irSymbolTable.referenceClass(irClass.descriptor)
} }
fun getIrTypeParameterSymbol(firTypeParameterSymbol: FirTypeParameterSymbol, forSetter: Boolean): IrTypeParameterSymbol { fun getIrTypeParameterSymbol(
val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir, forSetter = forSetter) firTypeParameterSymbol: FirTypeParameterSymbol,
typeContext: ConversionTypeContext
): IrTypeParameterSymbol {
val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir, typeContext = typeContext)
return irSymbolTable.referenceTypeParameter(irTypeParameter.descriptor) return irSymbolTable.referenceTypeParameter(irTypeParameter.descriptor)
} }