FIR2IR (refactoring): introduce Fir2IrTypeConverter

This commit is contained in:
Mikhail Glukhikh
2020-03-02 16:17:29 +03:00
parent 9257949a5a
commit 4c2522631b
4 changed files with 197 additions and 191 deletions
@@ -22,18 +22,10 @@ import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrErrorType import org.jetbrains.kotlin.ir.types.IrErrorType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeArgument
import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl
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.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
@@ -70,93 +62,6 @@ class ConversionTypeContext internal constructor(
} }
} }
fun FirTypeRef.toIrType(
session: FirSession,
declarationStorage: Fir2IrDeclarationStorage,
irBuiltIns: IrBuiltIns,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrType {
if (this !is FirResolvedTypeRef) {
return createErrorType()
}
return type.toIrType(session, declarationStorage, irBuiltIns, typeContext)
}
fun ConeKotlinType.toIrType(
session: FirSession,
declarationStorage: Fir2IrDeclarationStorage,
irBuiltIns: IrBuiltIns,
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, typeContext)
}
// TODO: annotations
IrSimpleTypeImpl(
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, typeContext)
}
is ConeCapturedType -> TODO()
is ConeDefinitelyNotNullType -> {
original.toIrType(session, declarationStorage, irBuiltIns, typeContext.definitelyNotNull())
}
is ConeIntersectionType -> {
// TODO: add intersectionTypeApproximation
intersectedTypes.first().toIrType(session, declarationStorage, irBuiltIns, typeContext)
}
is ConeStubType -> createErrorType()
is ConeIntegerLiteralType -> getApproximatedType().toIrType(session, declarationStorage, irBuiltIns, typeContext)
}
}
private fun getArrayType(classId: ClassId?, irBuiltIns: IrBuiltIns): IrClassifierSymbol? {
val irType = when (classId) {
ClassId(FqName("kotlin"), FqName("Array"), false) -> return irBuiltIns.arrayClass
ClassId(FqName("kotlin"), FqName("BooleanArray"), false) -> irBuiltIns.booleanType
ClassId(FqName("kotlin"), FqName("ByteArray"), false) -> irBuiltIns.byteType
ClassId(FqName("kotlin"), FqName("CharArray"), false) -> irBuiltIns.charType
ClassId(FqName("kotlin"), FqName("DoubleArray"), false) -> irBuiltIns.doubleType
ClassId(FqName("kotlin"), FqName("FloatArray"), false) -> irBuiltIns.floatType
ClassId(FqName("kotlin"), FqName("IntArray"), false) -> irBuiltIns.intType
ClassId(FqName("kotlin"), FqName("LongArray"), false) -> irBuiltIns.longType
ClassId(FqName("kotlin"), FqName("ShortArray"), false) -> irBuiltIns.shortType
else -> null
}
return irType?.let { irBuiltIns.primitiveArrayForType.getValue(it) }
}
fun ConeTypeProjection.toIrTypeArgument(
session: FirSession,
declarationStorage: Fir2IrDeclarationStorage,
irBuiltIns: IrBuiltIns
): IrTypeArgument {
return when (this) {
ConeStarProjection -> IrStarProjectionImpl
is ConeKotlinTypeProjectionIn -> {
val irType = this.type.toIrType(session, declarationStorage, irBuiltIns)
makeTypeProjection(irType, Variance.IN_VARIANCE)
}
is ConeKotlinTypeProjectionOut -> {
val irType = this.type.toIrType(session, declarationStorage, irBuiltIns)
makeTypeProjection(irType, Variance.OUT_VARIANCE)
}
is ConeKotlinType -> {
val irType = toIrType(session, declarationStorage, irBuiltIns)
makeTypeProjection(irType, Variance.INVARIANT)
}
}
}
fun FirClassifierSymbol<*>.toIrSymbol( fun FirClassifierSymbol<*>.toIrSymbol(
session: FirSession, session: FirSession,
declarationStorage: Fir2IrDeclarationStorage, declarationStorage: Fir2IrDeclarationStorage,
@@ -46,8 +46,7 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
class Fir2IrDeclarationStorage( class Fir2IrDeclarationStorage(
private val session: FirSession, private val session: FirSession,
private val irSymbolTable: SymbolTable, private val irSymbolTable: SymbolTable,
private val moduleDescriptor: FirModuleDescriptor, private val moduleDescriptor: FirModuleDescriptor
private val irBuiltIns: IrBuiltIns
) { ) {
private val firSymbolProvider = session.firSymbolProvider private val firSymbolProvider = session.firSymbolProvider
@@ -75,7 +74,7 @@ class Fir2IrDeclarationStorage(
private val localStorage = Fir2IrLocalStorage() private val localStorage = Fir2IrLocalStorage()
private val unitType = session.builtinTypes.unitType.toIrType(session, this) lateinit var typeConverter: Fir2IrTypeConverter
fun registerFile(firFile: FirFile, irFile: IrFile) { fun registerFile(firFile: FirFile, irFile: IrFile) {
fileCache[firFile] = irFile fileCache[firFile] = irFile
@@ -102,11 +101,11 @@ class Fir2IrDeclarationStorage(
irSymbolTable.leaveScope(descriptor) irSymbolTable.leaveScope(descriptor)
} }
private fun FirTypeRef.toIrType( private fun FirTypeRef.toIrType(typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT): IrType =
session: FirSession, with(typeConverter) { toIrType(typeContext) }
declarationStorage: Fir2IrDeclarationStorage,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT private fun ConeKotlinType.toIrType(typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT): IrType =
) = toIrType(session, declarationStorage, irBuiltIns, typeContext) with(typeConverter) { toIrType(typeContext) }
private fun getIrExternalPackageFragment(fqName: FqName): IrExternalPackageFragment { private fun getIrExternalPackageFragment(fqName: FqName): IrExternalPackageFragment {
return fragmentCache.getOrPut(fqName) { return fragmentCache.getOrPut(fqName) {
@@ -172,9 +171,7 @@ class Fir2IrDeclarationStorage(
if (klass is FirRegularClass) { if (klass is FirRegularClass) {
setTypeParameters(klass) setTypeParameters(klass)
} }
superTypes = klass.superTypeRefs.map { superTypeRef -> superTypes = klass.superTypeRefs.map { superTypeRef -> superTypeRef.toIrType() }
superTypeRef.toIrType(session, this@Fir2IrDeclarationStorage)
}
return this return this
} }
@@ -348,7 +345,7 @@ class Fir2IrDeclarationStorage(
} }
if (index < 0) { if (index < 0) {
val parent = simpleCachedParameter.parent val parent = simpleCachedParameter.parent
if (parent !is IrSimpleFunction || parent.returnType == unitType) { if (parent !is IrSimpleFunction || parent.returnType == typeConverter.unitType) {
return simpleCachedParameter return simpleCachedParameter
} }
} }
@@ -383,7 +380,7 @@ class Fir2IrDeclarationStorage(
} else { } else {
typeParameterCache[typeParameter] = irTypeParameter typeParameterCache[typeParameter] = irTypeParameter
} }
bounds.mapTo(irTypeParameter.superTypes) { it.toIrType(session, this@Fir2IrDeclarationStorage) } bounds.mapTo(irTypeParameter.superTypes) { it.toIrType() }
irTypeParameter irTypeParameter
} }
} }
@@ -460,9 +457,7 @@ class Fir2IrDeclarationStorage(
origin = if (forSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT 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(ConversionTypeContext.DEFAULT.inSetter())
session, this@Fir2IrDeclarationStorage, ConversionTypeContext.DEFAULT.inSetter()
)
declareDefaultSetterParameter(type) declareDefaultSetterParameter(type)
} else if (function != null) { } else if (function != null) {
valueParameters = function.valueParameters.mapIndexed { index, valueParameter -> valueParameters = function.valueParameters.mapIndexed { index, valueParameter ->
@@ -482,7 +477,7 @@ class Fir2IrDeclarationStorage(
extensionReceiverParameter = receiverTypeRef.convertWithOffsets { startOffset, endOffset -> extensionReceiverParameter = receiverTypeRef.convertWithOffsets { startOffset, endOffset ->
declareThisReceiverParameter( declareThisReceiverParameter(
parent, parent,
thisType = receiverTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, typeContext), thisType = receiverTypeRef.toIrType(typeContext),
thisOrigin = thisOrigin, thisOrigin = thisOrigin,
startOffset = startOffset, startOffset = startOffset,
endOffset = endOffset endOffset = endOffset
@@ -542,7 +537,7 @@ class Fir2IrDeclarationStorage(
IrFunctionImpl( IrFunctionImpl(
startOffset, endOffset, updatedOrigin, symbol, startOffset, endOffset, updatedOrigin, symbol,
function.name, function.visibility, function.modality!!, function.name, function.visibility, function.modality!!,
function.returnTypeRef.toIrType(session, this), function.returnTypeRef.toIrType(),
isInline = function.isInline, isInline = function.isInline,
isExternal = function.isExternal, isExternal = function.isExternal,
isTailrec = function.isTailRec, isTailrec = function.isTailRec,
@@ -594,7 +589,7 @@ class Fir2IrDeclarationStorage(
startOffset, endOffset, origin, symbol, startOffset, endOffset, origin, symbol,
if (isLambda) Name.special("<anonymous>") else Name.special("<no name provided>"), if (isLambda) Name.special("<anonymous>") else Name.special("<no name provided>"),
Visibilities.LOCAL, Modality.FINAL, Visibilities.LOCAL, Modality.FINAL,
function.returnTypeRef.toIrType(session, this), function.returnTypeRef.toIrType(),
isInline = false, isExternal = false, isTailrec = false, isInline = false, isExternal = false, isTailrec = false,
// TODO: suspend lambda // TODO: suspend lambda
isSuspend = false, isSuspend = false,
@@ -630,7 +625,7 @@ class Fir2IrDeclarationStorage(
IrConstructorImpl( IrConstructorImpl(
startOffset, endOffset, origin, symbol, startOffset, endOffset, origin, symbol,
Name.special("<init>"), visibility, Name.special("<init>"), visibility,
constructor.returnTypeRef.toIrType(session, this), constructor.returnTypeRef.toIrType(),
isInline = false, isExternal = false, isPrimary = isPrimary, isExpect = false isInline = false, isExternal = false, isPrimary = isPrimary, isExpect = false
).bindAndDeclareParameters(constructor, descriptor, irParent, isStatic = true, shouldLeaveScope = shouldLeaveScope) ).bindAndDeclareParameters(constructor, descriptor, irParent, isStatic = true, shouldLeaveScope = shouldLeaveScope)
} }
@@ -661,7 +656,7 @@ class Fir2IrDeclarationStorage(
propertyAccessor?.psi?.endOffset ?: endOffset, propertyAccessor?.psi?.endOffset ?: endOffset,
origin, descriptor origin, descriptor
) { symbol -> ) { symbol ->
val accessorReturnType = if (isSetter) unitType else propertyType val accessorReturnType = if (isSetter) typeConverter.unitType else propertyType
IrFunctionImpl( IrFunctionImpl(
startOffset, endOffset, origin, symbol, startOffset, endOffset, origin, symbol,
Name.special("<$prefix-${correspondingProperty.name}>"), Name.special("<$prefix-${correspondingProperty.name}>"),
@@ -671,13 +666,15 @@ class Fir2IrDeclarationStorage(
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE, isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE,
isOperator = false isOperator = false
).apply { ).apply {
setTypeParameters(property, ConversionTypeContext( setTypeParameters(
definitelyNotNull = false, property, ConversionTypeContext(
origin = if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT 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, ConversionTypeContext.DEFAULT.inSetter()) property.returnTypeRef.toIrType(ConversionTypeContext.DEFAULT.inSetter())
) )
} }
}.bindAndDeclareParameters( }.bindAndDeclareParameters(
@@ -707,7 +704,7 @@ class Fir2IrDeclarationStorage(
startOffset, endOffset, origin, symbol, enumEntry.name startOffset, endOffset, origin, symbol, enumEntry.name
).apply { ).apply {
desc.bind(this) desc.bind(this)
val irType = enumEntry.returnTypeRef.toIrType(session, this@Fir2IrDeclarationStorage) val irType = enumEntry.returnTypeRef.toIrType()
if (irParent != null) { if (irParent != null) {
this.parent = irParent this.parent = irParent
} }
@@ -758,7 +755,7 @@ class Fir2IrDeclarationStorage(
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE
).apply { ).apply {
descriptor.bind(this) descriptor.bind(this)
val type = property.returnTypeRef.toIrType(session, this@Fir2IrDeclarationStorage) val type = property.returnTypeRef.toIrType()
getter = createIrPropertyAccessor( getter = createIrPropertyAccessor(
property.getter, property, this, type, irParent, false, property.getter, property, this, type, irParent, false,
when { when {
@@ -791,7 +788,7 @@ class Fir2IrDeclarationStorage(
return fieldCache.getOrPut(field) { return fieldCache.getOrPut(field) {
val descriptor = WrappedFieldDescriptor() val descriptor = WrappedFieldDescriptor()
val origin = IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB val origin = IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
val type = field.returnTypeRef.toIrType(session, this) val type = field.returnTypeRef.toIrType()
field.convertWithOffsets { startOffset, endOffset -> field.convertWithOffsets { startOffset, endOffset ->
irSymbolTable.declareField( irSymbolTable.declareField(
startOffset, endOffset, startOffset, endOffset,
@@ -820,7 +817,7 @@ class Fir2IrDeclarationStorage(
): IrValueParameter { ): IrValueParameter {
val descriptor = WrappedValueParameterDescriptor() val descriptor = WrappedValueParameterDescriptor()
val origin = IrDeclarationOrigin.DEFINED val origin = IrDeclarationOrigin.DEFINED
val type = valueParameter.returnTypeRef.toIrType(session, this) val type = valueParameter.returnTypeRef.toIrType()
val irParameter = valueParameter.convertWithOffsets { startOffset, endOffset -> val irParameter = valueParameter.convertWithOffsets { startOffset, endOffset ->
irSymbolTable.declareValueParameter( irSymbolTable.declareValueParameter(
startOffset, endOffset, origin, descriptor, type startOffset, endOffset, origin, descriptor, type
@@ -829,9 +826,7 @@ class Fir2IrDeclarationStorage(
startOffset, endOffset, origin, symbol, startOffset, endOffset, origin, symbol,
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(typeContext),
session, this, irBuiltIns, typeContext
),
valueParameter.isCrossinline, valueParameter.isNoinline valueParameter.isCrossinline, valueParameter.isNoinline
).apply { ).apply {
descriptor.bind(this) descriptor.bind(this)
@@ -878,7 +873,7 @@ class Fir2IrDeclarationStorage(
} }
fun createAndSaveIrVariable(variable: FirVariable<*>, givenOrigin: IrDeclarationOrigin? = null): IrVariable { fun createAndSaveIrVariable(variable: FirVariable<*>, givenOrigin: IrDeclarationOrigin? = null): IrVariable {
val type = variable.returnTypeRef.toIrType(session, this) val type = variable.returnTypeRef.toIrType()
// Some temporary variables are produced in RawFirBuilder, but we consistently use special names for them. // Some temporary variables are produced in RawFirBuilder, but we consistently use special names for them.
val origin = when { val origin = when {
givenOrigin != null -> givenOrigin givenOrigin != null -> givenOrigin
@@ -0,0 +1,111 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeArgument
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.name.FqName
import org.jetbrains.kotlin.types.Variance
class Fir2IrTypeConverter(
private val session: FirSession,
private val declarationStorage: Fir2IrDeclarationStorage,
private val irBuiltIns: IrBuiltIns
) {
lateinit var nothingType: IrType
lateinit var unitType: IrType
lateinit var booleanType: IrType
lateinit var stringType: IrType
fun initBuiltinTypes() {
nothingType = session.builtinTypes.nothingType.toIrType()
unitType = session.builtinTypes.unitType.toIrType()
booleanType = session.builtinTypes.booleanType.toIrType()
stringType = session.builtinTypes.stringType.toIrType()
}
fun FirTypeRef.toIrType(typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT): IrType {
if (this !is FirResolvedTypeRef) {
return createErrorType()
}
return type.toIrType(typeContext)
}
fun ConeKotlinType.toIrType(typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT): IrType {
return when (this) {
is ConeKotlinErrorType -> createErrorType()
is ConeLookupTagBasedType -> {
val irSymbol = getArrayType(this.classId) ?: run {
val firSymbol = this.lookupTag.toSymbol(session) ?: return createErrorType()
firSymbol.toIrSymbol(session, declarationStorage, typeContext)
}
// TODO: annotations
IrSimpleTypeImpl(
irSymbol, !typeContext.definitelyNotNull && this.isMarkedNullable,
typeArguments.map { it.toIrTypeArgument() },
emptyList()
)
}
is ConeFlexibleType -> {
// TODO: yet we take more general type. Not quite sure it's Ok
upperBound.toIrType(typeContext)
}
is ConeCapturedType -> TODO()
is ConeDefinitelyNotNullType -> {
original.toIrType(typeContext.definitelyNotNull())
}
is ConeIntersectionType -> {
// TODO: add intersectionTypeApproximation
intersectedTypes.first().toIrType(typeContext)
}
is ConeStubType -> createErrorType()
is ConeIntegerLiteralType -> getApproximatedType().toIrType(typeContext)
}
}
private fun ConeTypeProjection.toIrTypeArgument(): IrTypeArgument {
return when (this) {
ConeStarProjection -> IrStarProjectionImpl
is ConeKotlinTypeProjectionIn -> {
val irType = this.type.toIrType()
makeTypeProjection(irType, Variance.IN_VARIANCE)
}
is ConeKotlinTypeProjectionOut -> {
val irType = this.type.toIrType()
makeTypeProjection(irType, Variance.OUT_VARIANCE)
}
is ConeKotlinType -> {
val irType = toIrType()
makeTypeProjection(irType, Variance.INVARIANT)
}
}
}
private fun getArrayType(classId: ClassId?): IrClassifierSymbol? {
val irType = when (classId) {
ClassId(FqName("kotlin"), FqName("Array"), false) -> return irBuiltIns.arrayClass
ClassId(FqName("kotlin"), FqName("BooleanArray"), false) -> irBuiltIns.booleanType
ClassId(FqName("kotlin"), FqName("ByteArray"), false) -> irBuiltIns.byteType
ClassId(FqName("kotlin"), FqName("CharArray"), false) -> irBuiltIns.charType
ClassId(FqName("kotlin"), FqName("DoubleArray"), false) -> irBuiltIns.doubleType
ClassId(FqName("kotlin"), FqName("FloatArray"), false) -> irBuiltIns.floatType
ClassId(FqName("kotlin"), FqName("IntArray"), false) -> irBuiltIns.intType
ClassId(FqName("kotlin"), FqName("LongArray"), false) -> irBuiltIns.longType
ClassId(FqName("kotlin"), FqName("ShortArray"), false) -> irBuiltIns.shortType
else -> null
}
return irType?.let { irBuiltIns.primitiveArrayForType.getValue(it) }
}
}
@@ -68,15 +68,12 @@ class Fir2IrVisitor(
private val integerApproximator = IntegerLiteralTypeApproximationTransformer(session.firSymbolProvider, session.inferenceContext) private val integerApproximator = IntegerLiteralTypeApproximationTransformer(session.firSymbolProvider, session.inferenceContext)
private val declarationStorage = Fir2IrDeclarationStorage(session, symbolTable, moduleDescriptor, irBuiltIns) private val declarationStorage = Fir2IrDeclarationStorage(session, symbolTable, moduleDescriptor)
private val nothingType = session.builtinTypes.nothingType.toIrType(session, declarationStorage) private val typeConverter = Fir2IrTypeConverter(session, declarationStorage, irBuiltIns).also {
declarationStorage.typeConverter = it
private val unitType = session.builtinTypes.unitType.toIrType(session, declarationStorage) it.initBuiltinTypes()
}
private val booleanType = session.builtinTypes.booleanType.toIrType(session, declarationStorage)
private val stringType = session.builtinTypes.stringType.toIrType(session, declarationStorage)
private fun ModuleDescriptor.findPackageFragmentForFile(file: FirFile): PackageFragmentDescriptor = private fun ModuleDescriptor.findPackageFragmentForFile(file: FirFile): PackageFragmentDescriptor =
getPackage(file.packageFqName).fragments.first() getPackage(file.packageFqName).fragments.first()
@@ -143,8 +140,9 @@ class Fir2IrVisitor(
return result return result
} }
private fun FirTypeRef.toIrType(session: FirSession, declarationStorage: Fir2IrDeclarationStorage) = private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() }
toIrType(session, declarationStorage, irBuiltIns)
private fun ConeKotlinType.toIrType(): IrType = with(typeConverter) { toIrType() }
override fun visitElement(element: FirElement, data: Any?): IrElement { override fun visitElement(element: FirElement, data: Any?): IrElement {
TODO("Should not be here: ${element.render()}") TODO("Should not be here: ${element.render()}")
@@ -403,7 +401,7 @@ class Fir2IrVisitor(
} }
private fun FirDelegatedConstructorCall.toIrDelegatingConstructorCall(): IrCallWithIndexedArgumentsBase? { private fun FirDelegatedConstructorCall.toIrDelegatingConstructorCall(): IrCallWithIndexedArgumentsBase? {
val constructedIrType = constructedTypeRef.toIrType(this@Fir2IrVisitor.session, declarationStorage) val constructedIrType = constructedTypeRef.toIrType()
val constructorSymbol = (this.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirConstructorSymbol val constructorSymbol = (this.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirConstructorSymbol
?: return null ?: return null
return convertWithOffsets { startOffset, endOffset -> return convertWithOffsets { startOffset, endOffset ->
@@ -416,7 +414,7 @@ class Fir2IrVisitor(
).apply { ).apply {
val typeArguments = (constructedTypeRef as? FirResolvedTypeRef)?.type?.typeArguments val typeArguments = (constructedTypeRef as? FirResolvedTypeRef)?.type?.typeArguments
if (typeArguments?.isNotEmpty() == true) { if (typeArguments?.isNotEmpty() == true) {
val irType = (typeArguments.first() as ConeKotlinTypeProjection).type.toIrType(session, declarationStorage, irBuiltIns) val irType = (typeArguments.first() as ConeKotlinTypeProjection).type.toIrType()
putTypeArgument(0, irType) putTypeArgument(0, irType)
} }
} }
@@ -451,7 +449,7 @@ class Fir2IrVisitor(
setFunctionContent(irFunction.descriptor, anonymousFunction) setFunctionContent(irFunction.descriptor, anonymousFunction)
} }
val type = anonymousFunction.typeRef.toIrType(session, declarationStorage) val type = anonymousFunction.typeRef.toIrType()
IrFunctionExpressionImpl(startOffset, endOffset, type, irFunction, IrStatementOrigin.LAMBDA) IrFunctionExpressionImpl(startOffset, endOffset, type, irFunction, IrStatementOrigin.LAMBDA)
} }
@@ -490,7 +488,7 @@ class Fir2IrVisitor(
firInitializerExpression: FirExpression?, firInitializerExpression: FirExpression?,
type: IrType? = null type: IrType? = null
): IrField { ): IrField {
val inferredType = type ?: firInitializerExpression!!.typeRef.toIrType(session, declarationStorage) val inferredType = type ?: firInitializerExpression!!.typeRef.toIrType()
return symbolTable.declareField( return symbolTable.declareField(
startOffset, endOffset, origin, descriptor, inferredType startOffset, endOffset, origin, descriptor, inferredType
) { symbol -> ) { symbol ->
@@ -519,7 +517,7 @@ class Fir2IrVisitor(
val initializer = property.initializer val initializer = property.initializer
val delegate = property.delegate val delegate = property.delegate
val irParent = this.parent val irParent = this.parent
val propertyType = property.returnTypeRef.toIrType(session, declarationStorage) val propertyType = property.returnTypeRef.toIrType()
// TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself // TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself
// TODO (2): backing field should be created inside declaration storage // TODO (2): backing field should be created inside declaration storage
if (property.modality != Modality.ABSTRACT && (irParent !is IrClass || !irParent.isInterface)) { if (property.modality != Modality.ABSTRACT && (irParent !is IrClass || !irParent.isInterface)) {
@@ -607,13 +605,13 @@ class Fir2IrVisitor(
startOffset, endOffset, startOffset, endOffset,
listOf( listOf(
if (isSetter) { if (isSetter) {
IrSetFieldImpl(startOffset, endOffset, fieldSymbol, unitType).apply { IrSetFieldImpl(startOffset, endOffset, fieldSymbol, typeConverter.unitType).apply {
setReceiver(declaration) setReceiver(declaration)
value = IrGetValueImpl(startOffset, endOffset, propertyType, valueParameters.first().symbol) value = IrGetValueImpl(startOffset, endOffset, propertyType, valueParameters.first().symbol)
} }
} else { } else {
IrReturnImpl( IrReturnImpl(
startOffset, endOffset, nothingType, symbol, startOffset, endOffset, typeConverter.nothingType, symbol,
IrGetFieldImpl(startOffset, endOffset, fieldSymbol, propertyType).setReceiver(declaration) IrGetFieldImpl(startOffset, endOffset, fieldSymbol, propertyType).setReceiver(declaration)
) )
} }
@@ -641,7 +639,7 @@ class Fir2IrVisitor(
val result = returnExpression.result val result = returnExpression.result
val descriptor = irTarget.descriptor val descriptor = irTarget.descriptor
IrReturnImpl( IrReturnImpl(
startOffset, endOffset, nothingType, startOffset, endOffset, typeConverter.nothingType,
when (descriptor) { when (descriptor) {
is ClassConstructorDescriptor -> symbolTable.referenceConstructor(descriptor) is ClassConstructorDescriptor -> symbolTable.referenceConstructor(descriptor)
else -> symbolTable.referenceSimpleFunction(descriptor) else -> symbolTable.referenceSimpleFunction(descriptor)
@@ -657,9 +655,9 @@ class Fir2IrVisitor(
} }
override fun visitVarargArgumentsExpression(varargArgumentsExpression: FirVarargArgumentsExpression, data: Any?): IrElement { override fun visitVarargArgumentsExpression(varargArgumentsExpression: FirVarargArgumentsExpression, data: Any?): IrElement {
val irReturnType = varargArgumentsExpression.typeRef.toIrType(session, declarationStorage) val irReturnType = varargArgumentsExpression.typeRef.toIrType()
return IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irReturnType, return IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irReturnType,
varargArgumentsExpression.varargElementType.toIrType(session, declarationStorage), varargArgumentsExpression.varargElementType.toIrType(),
varargArgumentsExpression.arguments.map { arg -> varargArgumentsExpression.arguments.map { arg ->
arg.toIrExpression().run { arg.toIrExpression().run {
if (arg is FirSpreadArgumentExpression) IrSpreadElementImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this) if (arg is FirSpreadArgumentExpression) IrSpreadElementImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this)
@@ -687,7 +685,7 @@ class Fir2IrVisitor(
} }
private fun FirQualifiedAccess.toIrExpression(typeRef: FirTypeRef): IrExpression { private fun FirQualifiedAccess.toIrExpression(typeRef: FirTypeRef): IrExpression {
val type = typeRef.toIrType(this@Fir2IrVisitor.session, declarationStorage) val type = typeRef.toIrType()
val symbol = calleeReference.toSymbol(declarationStorage) val symbol = calleeReference.toSymbol(declarationStorage)
return typeRef.convertWithOffsets { startOffset, endOffset -> return typeRef.convertWithOffsets { startOffset, endOffset ->
if (calleeReference is FirSuperReference) { if (calleeReference is FirSuperReference) {
@@ -725,7 +723,7 @@ class Fir2IrVisitor(
private fun FirAnnotationCall.toIrExpression(): IrExpression { private fun FirAnnotationCall.toIrExpression(): IrExpression {
val coneType = (annotationTypeRef as? FirResolvedTypeRef)?.type as? ConeLookupTagBasedType val coneType = (annotationTypeRef as? FirResolvedTypeRef)?.type as? ConeLookupTagBasedType
val firSymbol = coneType?.lookupTag?.toSymbol(session) as? FirClassSymbol val firSymbol = coneType?.lookupTag?.toSymbol(session) as? FirClassSymbol
val type = coneType?.toIrType(session, declarationStorage, irBuiltIns) val type = coneType?.toIrType()
val symbol = type?.classifierOrNull val symbol = type?.classifierOrNull
return convertWithOffsets { startOffset, endOffset -> return convertWithOffsets { startOffset, endOffset ->
when (symbol) { when (symbol) {
@@ -790,10 +788,7 @@ class Fir2IrVisitor(
if (argumentsCount <= typeArgumentsCount) { if (argumentsCount <= typeArgumentsCount) {
apply { apply {
for ((index, argument) in access.typeArguments.withIndex()) { for ((index, argument) in access.typeArguments.withIndex()) {
val argumentIrType = (argument as FirTypeProjectionWithVariance).typeRef.toIrType( val argumentIrType = (argument as FirTypeProjectionWithVariance).typeRef.toIrType()
session,
declarationStorage
)
putTypeArgument(index, argumentIrType) putTypeArgument(index, argumentIrType)
} }
} }
@@ -936,7 +931,7 @@ class Fir2IrVisitor(
override fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast, data: Any?): IrElement { override fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast, data: Any?): IrElement {
// Generate the expression with the original type and then cast it to the smart cast type. // Generate the expression with the original type and then cast it to the smart cast type.
val value = expressionWithSmartcast.originalExpression.toIrExpression() val value = expressionWithSmartcast.originalExpression.toIrExpression()
val castType = expressionWithSmartcast.typeRef.toIrType(session, declarationStorage) val castType = expressionWithSmartcast.typeRef.toIrType()
if (value.type == castType) return value if (value.type == castType) return value
return IrTypeOperatorCallImpl( return IrTypeOperatorCallImpl(
value.startOffset, value.startOffset,
@@ -950,7 +945,7 @@ class Fir2IrVisitor(
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement { override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement {
val symbol = callableReferenceAccess.calleeReference.toSymbol(declarationStorage) val symbol = callableReferenceAccess.calleeReference.toSymbol(declarationStorage)
val type = callableReferenceAccess.typeRef.toIrType(this@Fir2IrVisitor.session, declarationStorage) val type = callableReferenceAccess.typeRef.toIrType()
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset -> return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
when (symbol) { when (symbol) {
is IrPropertySymbol -> { is IrPropertySymbol -> {
@@ -996,7 +991,7 @@ class Fir2IrVisitor(
if (symbol != null && symbol.isBound) { if (symbol != null && symbol.isBound) {
when (symbol) { when (symbol) {
is IrFieldSymbol -> IrSetFieldImpl( is IrFieldSymbol -> IrSetFieldImpl(
startOffset, endOffset, symbol, unitType startOffset, endOffset, symbol, typeConverter.unitType
).apply { ).apply {
value = variableAssignment.rValue.toIrExpression() value = variableAssignment.rValue.toIrExpression()
} }
@@ -1005,7 +1000,7 @@ class Fir2IrVisitor(
val backingField = irProperty.backingField val backingField = irProperty.backingField
if (backingField != null) { if (backingField != null) {
IrSetFieldImpl( IrSetFieldImpl(
startOffset, endOffset, backingField.symbol, unitType startOffset, endOffset, backingField.symbol, typeConverter.unitType
).apply { ).apply {
value = variableAssignment.rValue.toIrExpression() value = variableAssignment.rValue.toIrExpression()
} }
@@ -1044,7 +1039,7 @@ class Fir2IrVisitor(
} as T ?: constExpression.value } as T ?: constExpression.value
IrConstImpl( IrConstImpl(
startOffset, endOffset, startOffset, endOffset,
constExpression.typeRef.toIrType(session, declarationStorage), constExpression.typeRef.toIrType(),
kind, value kind, value
) )
} }
@@ -1085,7 +1080,7 @@ class Fir2IrVisitor(
is FirBlock -> convertToIrExpressionOrBlock() is FirBlock -> convertToIrExpressionOrBlock()
is FirUnitExpression -> convertWithOffsets { startOffset, endOffset -> is FirUnitExpression -> convertWithOffsets { startOffset, endOffset ->
IrGetObjectValueImpl( IrGetObjectValueImpl(
startOffset, endOffset, unitType, startOffset, endOffset, typeConverter.unitType,
symbolTable.referenceClass(irBuiltIns.builtIns.unit) symbolTable.referenceClass(irBuiltIns.builtIns.unit)
) )
} }
@@ -1123,7 +1118,7 @@ class Fir2IrVisitor(
startOffset, endOffset, startOffset, endOffset,
if (irStatements.isNotEmpty()) { if (irStatements.isNotEmpty()) {
irStatements.filterNotNull().takeIf { it.isNotEmpty() } irStatements.filterNotNull().takeIf { it.isNotEmpty() }
?: listOf(IrBlockImpl(startOffset, endOffset, unitType, null, emptyList())) ?: listOf(IrBlockImpl(startOffset, endOffset, typeConverter.unitType, null, emptyList()))
} else { } else {
emptyList() emptyList()
} }
@@ -1139,7 +1134,7 @@ class Fir2IrVisitor(
} }
} }
val type = val type =
(statements.lastOrNull() as? FirExpression)?.typeRef?.toIrType(this@Fir2IrVisitor.session, declarationStorage) ?: unitType (statements.lastOrNull() as? FirExpression)?.typeRef?.toIrType() ?: typeConverter.unitType
return convertWithOffsets { startOffset, endOffset -> return convertWithOffsets { startOffset, endOffset ->
IrBlockImpl( IrBlockImpl(
startOffset, endOffset, type, origin, startOffset, endOffset, type, origin,
@@ -1152,7 +1147,7 @@ class Fir2IrVisitor(
return errorExpression.convertWithOffsets { startOffset, endOffset -> return errorExpression.convertWithOffsets { startOffset, endOffset ->
IrErrorExpressionImpl( IrErrorExpressionImpl(
startOffset, endOffset, startOffset, endOffset,
errorExpression.typeRef.toIrType(session, declarationStorage), errorExpression.typeRef.toIrType(),
errorExpression.diagnostic.reason errorExpression.diagnostic.reason
) )
} }
@@ -1189,7 +1184,7 @@ class Fir2IrVisitor(
whenExpression.convertWithOffsets { startOffset, endOffset -> whenExpression.convertWithOffsets { startOffset, endOffset ->
val irWhen = IrWhenImpl( val irWhen = IrWhenImpl(
startOffset, endOffset, startOffset, endOffset,
whenExpression.typeRef.toIrType(session, declarationStorage), whenExpression.typeRef.toIrType(),
origin origin
).apply { ).apply {
for (branch in whenExpression.branches) { for (branch in whenExpression.branches) {
@@ -1212,7 +1207,7 @@ class Fir2IrVisitor(
val condition = whenBranch.condition val condition = whenBranch.condition
val irResult = whenBranch.result.toIrExpression() val irResult = whenBranch.result.toIrExpression()
if (condition is FirElseIfTrueCondition) { if (condition is FirElseIfTrueCondition) {
IrElseBranchImpl(IrConstImpl.boolean(irResult.startOffset, irResult.endOffset, booleanType, true), irResult) IrElseBranchImpl(IrConstImpl.boolean(irResult.startOffset, irResult.endOffset, typeConverter.booleanType, true), irResult)
} else { } else {
IrBranchImpl(startOffset, endOffset, condition.toIrExpression(), irResult) IrBranchImpl(startOffset, endOffset, condition.toIrExpression(), irResult)
} }
@@ -1231,7 +1226,7 @@ class Fir2IrVisitor(
override fun visitDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: Any?): IrElement { override fun visitDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: Any?): IrElement {
return doWhileLoop.convertWithOffsets { startOffset, endOffset -> return doWhileLoop.convertWithOffsets { startOffset, endOffset ->
IrDoWhileLoopImpl( IrDoWhileLoopImpl(
startOffset, endOffset, unitType, startOffset, endOffset, typeConverter.unitType,
IrStatementOrigin.DO_WHILE_LOOP IrStatementOrigin.DO_WHILE_LOOP
).apply { ).apply {
loopMap[doWhileLoop] = this loopMap[doWhileLoop] = this
@@ -1247,7 +1242,7 @@ class Fir2IrVisitor(
return whileLoop.convertWithOffsets { startOffset, endOffset -> return whileLoop.convertWithOffsets { startOffset, endOffset ->
val origin = if (whileLoop.psi is KtForExpression) IrStatementOrigin.FOR_LOOP_INNER_WHILE val origin = if (whileLoop.psi is KtForExpression) IrStatementOrigin.FOR_LOOP_INNER_WHILE
else IrStatementOrigin.WHILE_LOOP else IrStatementOrigin.WHILE_LOOP
IrWhileLoopImpl(startOffset, endOffset, unitType, origin).apply { IrWhileLoopImpl(startOffset, endOffset, typeConverter.unitType, origin).apply {
loopMap[whileLoop] = this loopMap[whileLoop] = this
label = whileLoop.label?.name label = whileLoop.label?.name
condition = whileLoop.condition.toIrExpression() condition = whileLoop.condition.toIrExpression()
@@ -1264,7 +1259,7 @@ class Fir2IrVisitor(
val firLoop = target.labeledElement val firLoop = target.labeledElement
val irLoop = loopMap[firLoop] val irLoop = loopMap[firLoop]
if (irLoop == null) { if (irLoop == null) {
IrErrorExpressionImpl(startOffset, endOffset, nothingType, "Unbound loop: ${render()}") IrErrorExpressionImpl(startOffset, endOffset, typeConverter.nothingType, "Unbound loop: ${render()}")
} else { } else {
f(startOffset, endOffset, irLoop).apply { f(startOffset, endOffset, irLoop).apply {
label = irLoop.label.takeIf { target.labelName != null } label = irLoop.label.takeIf { target.labelName != null }
@@ -1275,26 +1270,26 @@ class Fir2IrVisitor(
override fun visitBreakExpression(breakExpression: FirBreakExpression, data: Any?): IrElement { override fun visitBreakExpression(breakExpression: FirBreakExpression, data: Any?): IrElement {
return breakExpression.convertJumpWithOffsets { startOffset, endOffset, irLoop -> return breakExpression.convertJumpWithOffsets { startOffset, endOffset, irLoop ->
IrBreakImpl(startOffset, endOffset, nothingType, irLoop) IrBreakImpl(startOffset, endOffset, typeConverter.nothingType, irLoop)
} }
} }
override fun visitContinueExpression(continueExpression: FirContinueExpression, data: Any?): IrElement { override fun visitContinueExpression(continueExpression: FirContinueExpression, data: Any?): IrElement {
return continueExpression.convertJumpWithOffsets { startOffset, endOffset, irLoop -> return continueExpression.convertJumpWithOffsets { startOffset, endOffset, irLoop ->
IrContinueImpl(startOffset, endOffset, nothingType, irLoop) IrContinueImpl(startOffset, endOffset, typeConverter.nothingType, irLoop)
} }
} }
override fun visitThrowExpression(throwExpression: FirThrowExpression, data: Any?): IrElement { override fun visitThrowExpression(throwExpression: FirThrowExpression, data: Any?): IrElement {
return throwExpression.convertWithOffsets { startOffset, endOffset -> return throwExpression.convertWithOffsets { startOffset, endOffset ->
IrThrowImpl(startOffset, endOffset, nothingType, throwExpression.exception.toIrExpression()) IrThrowImpl(startOffset, endOffset, typeConverter.nothingType, throwExpression.exception.toIrExpression())
} }
} }
override fun visitTryExpression(tryExpression: FirTryExpression, data: Any?): IrElement { override fun visitTryExpression(tryExpression: FirTryExpression, data: Any?): IrElement {
return tryExpression.convertWithOffsets { startOffset, endOffset -> return tryExpression.convertWithOffsets { startOffset, endOffset ->
IrTryImpl( IrTryImpl(
startOffset, endOffset, tryExpression.typeRef.toIrType(session, declarationStorage), startOffset, endOffset, tryExpression.typeRef.toIrType(),
tryExpression.tryBlock.convertToIrExpressionOrBlock(), tryExpression.tryBlock.convertToIrExpressionOrBlock(),
tryExpression.catches.map { it.accept(this, data) as IrCatch }, tryExpression.catches.map { it.accept(this, data) as IrCatch },
tryExpression.finallyBlock?.convertToIrExpressionOrBlock() tryExpression.finallyBlock?.convertToIrExpressionOrBlock()
@@ -1328,7 +1323,7 @@ class Fir2IrVisitor(
return primitiveOp2( return primitiveOp2(
startOffset, endOffset, startOffset, endOffset,
symbol!!, symbol!!,
booleanType, typeConverter.booleanType,
origin, origin,
visitFunctionCall(comparisonExpression.compareToCall, null), visitFunctionCall(comparisonExpression.compareToCall, null),
IrConstImpl.int(startOffset, endOffset, irBuiltIns.intType, 0) IrConstImpl.int(startOffset, endOffset, irBuiltIns.intType, 0)
@@ -1356,7 +1351,7 @@ class Fir2IrVisitor(
val (symbol, origin) = getSymbolAndOriginForComparison(operation, simpleType.classifierOrFail) val (symbol, origin) = getSymbolAndOriginForComparison(operation, simpleType.classifierOrFail)
return primitiveOp2( return primitiveOp2(
startOffset, endOffset, symbol!!, booleanType, origin, startOffset, endOffset, symbol!!, typeConverter.booleanType, origin,
comparisonExpression.left.toIrExpression(), comparisonExpression.right.toIrExpression() comparisonExpression.left.toIrExpression(), comparisonExpression.right.toIrExpression()
) )
} }
@@ -1378,11 +1373,11 @@ class Fir2IrVisitor(
startOffset: Int, endOffset: Int, operation: FirOperation, arguments: List<FirExpression> startOffset: Int, endOffset: Int, operation: FirOperation, arguments: List<FirExpression>
): IrExpression { ): IrExpression {
val (type, symbol, origin) = when (operation) { val (type, symbol, origin) = when (operation) {
FirOperation.EQ -> Triple(booleanType, irBuiltIns.eqeqSymbol, IrStatementOrigin.EQEQ) FirOperation.EQ -> Triple(typeConverter.booleanType, irBuiltIns.eqeqSymbol, IrStatementOrigin.EQEQ)
FirOperation.NOT_EQ -> Triple(booleanType, irBuiltIns.eqeqSymbol, IrStatementOrigin.EXCLEQ) FirOperation.NOT_EQ -> Triple(typeConverter.booleanType, irBuiltIns.eqeqSymbol, IrStatementOrigin.EXCLEQ)
FirOperation.IDENTITY -> Triple(booleanType, irBuiltIns.eqeqeqSymbol, IrStatementOrigin.EQEQEQ) FirOperation.IDENTITY -> Triple(typeConverter.booleanType, irBuiltIns.eqeqeqSymbol, IrStatementOrigin.EQEQEQ)
FirOperation.NOT_IDENTITY -> Triple(booleanType, irBuiltIns.eqeqeqSymbol, IrStatementOrigin.EXCLEQEQ) FirOperation.NOT_IDENTITY -> Triple(typeConverter.booleanType, irBuiltIns.eqeqeqSymbol, IrStatementOrigin.EXCLEQEQ)
FirOperation.EXCL -> Triple(booleanType, irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL) FirOperation.EXCL -> Triple(typeConverter.booleanType, irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL)
FirOperation.LT, FirOperation.GT, FirOperation.LT, FirOperation.GT,
FirOperation.LT_EQ, FirOperation.GT_EQ, FirOperation.LT_EQ, FirOperation.GT_EQ,
FirOperation.OTHER, FirOperation.ASSIGN, FirOperation.PLUS_ASSIGN, FirOperation.OTHER, FirOperation.ASSIGN, FirOperation.PLUS_ASSIGN,
@@ -1400,7 +1395,7 @@ class Fir2IrVisitor(
primitiveOp2(startOffset, endOffset, symbol, type, origin, arguments[0].toIrExpression(), arguments[1].toIrExpression()) primitiveOp2(startOffset, endOffset, symbol, type, origin, arguments[0].toIrExpression(), arguments[1].toIrExpression())
} }
if (operation !in NEGATED_OPERATIONS) return result if (operation !in NEGATED_OPERATIONS) return result
return primitiveOp1(startOffset, endOffset, irBuiltIns.booleanNotSymbol, booleanType, origin, result) return primitiveOp1(startOffset, endOffset, irBuiltIns.booleanNotSymbol, typeConverter.booleanType, origin, result)
} }
override fun visitOperatorCall(operatorCall: FirOperatorCall, data: Any?): IrElement { override fun visitOperatorCall(operatorCall: FirOperatorCall, data: Any?): IrElement {
@@ -1412,7 +1407,7 @@ class Fir2IrVisitor(
override fun visitStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall, data: Any?): IrElement { override fun visitStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall, data: Any?): IrElement {
return stringConcatenationCall.convertWithOffsets { startOffset, endOffset -> return stringConcatenationCall.convertWithOffsets { startOffset, endOffset ->
IrStringConcatenationImpl( IrStringConcatenationImpl(
startOffset, endOffset, stringType, startOffset, endOffset, typeConverter.stringType,
stringConcatenationCall.arguments.map { it.toIrExpression() } stringConcatenationCall.arguments.map { it.toIrExpression() }
) )
} }
@@ -1420,10 +1415,10 @@ class Fir2IrVisitor(
override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Any?): IrElement { override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Any?): IrElement {
return typeOperatorCall.convertWithOffsets { startOffset, endOffset -> return typeOperatorCall.convertWithOffsets { startOffset, endOffset ->
val irTypeOperand = typeOperatorCall.conversionTypeRef.toIrType(session, declarationStorage) val irTypeOperand = typeOperatorCall.conversionTypeRef.toIrType()
val (irType, irTypeOperator) = when (typeOperatorCall.operation) { val (irType, irTypeOperator) = when (typeOperatorCall.operation) {
FirOperation.IS -> booleanType to IrTypeOperator.INSTANCEOF FirOperation.IS -> typeConverter.booleanType to IrTypeOperator.INSTANCEOF
FirOperation.NOT_IS -> booleanType to IrTypeOperator.NOT_INSTANCEOF FirOperation.NOT_IS -> typeConverter.booleanType to IrTypeOperator.NOT_INSTANCEOF
FirOperation.AS -> irTypeOperand to IrTypeOperator.CAST FirOperation.AS -> irTypeOperand to IrTypeOperator.CAST
FirOperation.SAFE_AS -> irTypeOperand.makeNullable() to IrTypeOperator.SAFE_CAST FirOperation.SAFE_AS -> irTypeOperand.makeNullable() to IrTypeOperator.SAFE_CAST
else -> TODO("Should not be here: ${typeOperatorCall.operation} in type operator call") else -> TODO("Should not be here: ${typeOperatorCall.operation} in type operator call")
@@ -1440,11 +1435,11 @@ class Fir2IrVisitor(
return checkNotNullCall.convertWithOffsets { startOffset, endOffset -> return checkNotNullCall.convertWithOffsets { startOffset, endOffset ->
IrCallImpl( IrCallImpl(
startOffset, endOffset, startOffset, endOffset,
checkNotNullCall.typeRef.toIrType(session, declarationStorage), checkNotNullCall.typeRef.toIrType(),
irBuiltIns.checkNotNullSymbol, irBuiltIns.checkNotNullSymbol,
IrStatementOrigin.EXCLEXCL IrStatementOrigin.EXCLEXCL
).apply { ).apply {
putTypeArgument(0, checkNotNullCall.argument.typeRef.toIrType(session, declarationStorage).makeNotNull()) putTypeArgument(0, checkNotNullCall.argument.typeRef.toIrType().makeNotNull())
putValueArgument(0, checkNotNullCall.argument.toIrExpression()) putValueArgument(0, checkNotNullCall.argument.toIrExpression())
} }
} }
@@ -1453,12 +1448,12 @@ class Fir2IrVisitor(
override fun visitGetClassCall(getClassCall: FirGetClassCall, data: Any?): IrElement { override fun visitGetClassCall(getClassCall: FirGetClassCall, data: Any?): IrElement {
return getClassCall.convertWithOffsets { startOffset, endOffset -> return getClassCall.convertWithOffsets { startOffset, endOffset ->
val argument = getClassCall.argument val argument = getClassCall.argument
val irType = getClassCall.typeRef.toIrType(session, declarationStorage) val irType = getClassCall.typeRef.toIrType()
if (argument is FirResolvedReifiedParameterReference) { if (argument is FirResolvedReifiedParameterReference) {
IrClassReferenceImpl( IrClassReferenceImpl(
startOffset, endOffset, irType, startOffset, endOffset, irType,
argument.symbol.toTypeParameterSymbol(declarationStorage), argument.symbol.toTypeParameterSymbol(declarationStorage),
argument.typeRef.toIrType(session, declarationStorage) argument.typeRef.toIrType()
) )
} else { } else {
IrGetClassImpl( IrGetClassImpl(
@@ -1472,7 +1467,7 @@ class Fir2IrVisitor(
override fun visitArraySetCall(arraySetCall: FirArraySetCall, data: Any?): IrElement { override fun visitArraySetCall(arraySetCall: FirArraySetCall, data: Any?): IrElement {
return arraySetCall.convertWithOffsets { startOffset, endOffset -> return arraySetCall.convertWithOffsets { startOffset, endOffset ->
IrErrorCallExpressionImpl( IrErrorCallExpressionImpl(
startOffset, endOffset, unitType, startOffset, endOffset, typeConverter.unitType,
"FirArraySetCall (resolve isn't supported yet)" "FirArraySetCall (resolve isn't supported yet)"
) )
} }
@@ -1484,7 +1479,7 @@ class Fir2IrVisitor(
return resolvedQualifier.convertWithOffsets { startOffset, endOffset -> return resolvedQualifier.convertWithOffsets { startOffset, endOffset ->
IrGetObjectValueImpl( IrGetObjectValueImpl(
startOffset, endOffset, startOffset, endOffset,
resolvedQualifier.typeRef.toIrType(session, declarationStorage), resolvedQualifier.typeRef.toIrType(),
classSymbol.toIrSymbol(session, declarationStorage) as IrClassSymbol classSymbol.toIrSymbol(session, declarationStorage) as IrClassSymbol
) )
} }