FIR2IR: add declarations to all library classes from kotlin.* package

Before this commit, all library classes were just stubs.
This commit helps to solve problems with some functions
indirectly used by BE, like IntProgression.first.
This commit is contained in:
Mikhail Glukhikh
2020-02-13 14:49:23 +03:00
parent 4a4fb5a590
commit 83e68be2dc
3 changed files with 100 additions and 43 deletions
@@ -8,6 +8,9 @@ package org.jetbrains.kotlin.fir.backend
import com.intellij.psi.PsiCompiledElement
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirConstKind
import org.jetbrains.kotlin.fir.psi
@@ -31,6 +34,7 @@ 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.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
import org.jetbrains.kotlin.types.Variance
@@ -215,3 +219,38 @@ private fun FirConstKind<*>.toIrConstKind(): IrConstKind<*> = when (this) {
FirConstKind.Double -> IrConstKind.Double
FirConstKind.IntegerLiteral -> throw IllegalArgumentException()
}
internal fun FirClass<*>.collectCallableNamesFromSupertypes(session: FirSession, result: MutableList<Name> = mutableListOf()): List<Name> {
for (superTypeRef in superTypeRefs) {
superTypeRef.collectCallableNamesFromThisAndSupertypes(session, result)
}
return result
}
private fun FirTypeRef.collectCallableNamesFromThisAndSupertypes(
session: FirSession,
result: MutableList<Name> = mutableListOf()
): List<Name> {
if (this is FirResolvedTypeRef) {
val superType = type
if (superType is ConeClassLikeType) {
when (val superSymbol = superType.lookupTag.toSymbol(session)) {
is FirClassSymbol -> {
val superClass = superSymbol.fir as FirClass<*>
for (declaration in superClass.declarations) {
when (declaration) {
is FirSimpleFunction -> result += declaration.name
is FirVariable<*> -> result += declaration.name
}
}
superClass.collectCallableNamesFromSupertypes(session, result)
}
is FirTypeAliasSymbol -> {
val superAlias = superSymbol.fir
superAlias.expandedTypeRef.collectCallableNamesFromThisAndSupertypes(session, result)
}
}
}
}
return result
}
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.descriptors.FirPackageFragmentDescriptor
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -159,7 +160,7 @@ class Fir2IrDeclarationStorage(
return this
}
fun getIrClass(klass: FirClass<*>, setParent: Boolean = true): IrClass {
fun getIrClass(klass: FirClass<*>, setParentAndContent: Boolean = true): IrClass {
val regularClass = klass as? FirRegularClass
fun create(): IrClass {
@@ -187,7 +188,7 @@ class Fir2IrDeclarationStorage(
isFun = false // TODO FirRegularClass.isFun
).apply {
descriptor.bind(this)
if (setParent && regularClass != null) {
if (setParentAndContent && regularClass != null) {
val classId = regularClass.classId
val parentId = classId.outerClassId
if (parentId != null) {
@@ -216,9 +217,57 @@ class Fir2IrDeclarationStorage(
return created
}
// NB: klass can be either FirRegularClass or FirAnonymousObject
return classCache.getOrPut(klass as FirRegularClass, { create() }) {
it.declareSupertypesAndTypeParameters(klass)
it.setThisReceiver()
return classCache.getOrPut(klass as FirRegularClass, { create() }) { irClass ->
irClass.declareSupertypesAndTypeParameters(klass)
irClass.setThisReceiver()
if (setParentAndContent && regularClass != null &&
regularClass.symbol.classId.packageFqName.startsWith(Name.identifier("kotlin"))
) {
// Note: yet this is necessary only for *Range / *Progression classes
// due to BE optimizations (for lowering) that use their first / last / step members
// TODO: think how to refactor this piece of code and/or merge it with similar Fir2IrVisitor fragment
val processedNames = mutableSetOf<Name>()
for (declaration in regularClass.declarations) {
irClass.declarations += when (declaration) {
is FirSimpleFunction -> {
processedNames += declaration.name
getIrFunction(declaration, irClass, shouldLeaveScope = true)
}
is FirProperty -> {
processedNames += declaration.name
getIrProperty(declaration, irClass)
}
is FirConstructor -> getIrConstructor(declaration, irClass, shouldLeaveScope = true)
is FirRegularClass -> getIrClass(declaration)
else -> continue
}
}
val allNames = regularClass.collectCallableNamesFromSupertypes(session)
val scope = regularClass.buildUseSiteMemberScope(session, ScopeSession())
if (scope != null) {
for (name in allNames) {
if (name in processedNames) continue
processedNames += name
scope.processFunctionsByName(name) { functionSymbol ->
if (functionSymbol is FirNamedFunctionSymbol) {
val fakeOverrideSymbol =
FirClassSubstitutionScope.createFakeOverrideFunction(session, functionSymbol.fir, functionSymbol)
irClass.declarations += getIrFunction(fakeOverrideSymbol.fir, irClass, shouldLeaveScope = true)
}
}
scope.processPropertiesByName(name) { propertySymbol ->
if (propertySymbol is FirPropertySymbol) {
val fakeOverrideSymbol =
FirClassSubstitutionScope.createFakeOverrideProperty(session, propertySymbol.fir, propertySymbol)
irClass.declarations += getIrProperty(fakeOverrideSymbol.fir, irClass)
}
}
}
}
for (irDeclaration in irClass.declarations) {
irDeclaration.parent = irClass
}
}
}
}
@@ -183,44 +183,12 @@ class Fir2IrVisitor(
return irEnumEntry.setParentByParentStack()
}
private fun FirTypeRef.collectCallableNamesFromThisAndSupertypes(result: MutableList<Name> = mutableListOf()): List<Name> {
if (this is FirResolvedTypeRef) {
val superType = type
if (superType is ConeClassLikeType) {
when (val superSymbol = superType.lookupTag.toSymbol(this@Fir2IrVisitor.session)) {
is FirClassSymbol -> {
val superClass = superSymbol.fir as FirClass<*>
for (declaration in superClass.declarations) {
when (declaration) {
is FirSimpleFunction -> result += declaration.name
is FirVariable<*> -> result += declaration.name
}
}
superClass.collectCallableNamesFromSupertypes(result)
}
is FirTypeAliasSymbol -> {
val superAlias = superSymbol.fir
superAlias.expandedTypeRef.collectCallableNamesFromThisAndSupertypes(result)
}
}
}
}
return result
}
private fun FirClass<*>.collectCallableNamesFromSupertypes(result: MutableList<Name> = mutableListOf()): List<Name> {
for (superTypeRef in superTypeRefs) {
superTypeRef.collectCallableNamesFromThisAndSupertypes(result)
}
return result
}
private fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? =
declarations.filterIsInstance<FirConstructor>().firstOrNull()?.takeIf { it.isPrimary }
private fun IrClass.addFakeOverrides(klass: FirClass<*>, processedCallableNames: MutableList<Name>) {
if (fakeOverrideMode == FakeOverrideMode.NONE) return
val superTypesCallableNames = klass.collectCallableNamesFromSupertypes()
val superTypesCallableNames = klass.collectCallableNamesFromSupertypes(session)
val useSiteMemberScope = (klass as? FirRegularClass)?.buildUseSiteMemberScope(session, ScopeSession()) ?: return
for (name in superTypesCallableNames) {
if (name in processedCallableNames) continue
@@ -315,7 +283,7 @@ class Fir2IrVisitor(
}
override fun visitRegularClass(regularClass: FirRegularClass, data: Any?): IrElement {
return declarationStorage.getIrClass(regularClass, setParent = false)
return declarationStorage.getIrClass(regularClass, setParentAndContent = false)
.setParentByParentStack()
.withParent {
setClassContent(regularClass)
@@ -360,7 +328,7 @@ class Fir2IrVisitor(
lastClass
} else {
val firClass = classLikeSymbol.fir as FirClass<*>
declarationStorage.getIrClass(firClass, setParent = false)
declarationStorage.getIrClass(firClass, setParentAndContent = false)
}
}
}
@@ -850,7 +818,7 @@ class Fir2IrVisitor(
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
}
firClass?.convertWithOffsets { startOffset, endOffset ->
val irClass = declarationStorage.getIrClass(firClass, setParent = false)
val irClass = declarationStorage.getIrClass(firClass, setParentAndContent = false)
IrGetObjectValueImpl(startOffset, endOffset, irClass.defaultType, irClass.symbol)
}
}
@@ -928,7 +896,7 @@ class Fir2IrVisitor(
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
}
if (firObject != null) {
val irObject = declarationStorage.getIrClass(firObject, setParent = false)
val irObject = declarationStorage.getIrClass(firObject, setParentAndContent = false)
if (irObject != classStack.lastOrNull()) {
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
IrGetObjectValueImpl(startOffset, endOffset, irObject.defaultType, irObject.symbol)
@@ -1360,7 +1328,8 @@ class Fir2IrVisitor(
FirOperation.MINUS_ASSIGN, FirOperation.TIMES_ASSIGN,
FirOperation.DIV_ASSIGN, FirOperation.REM_ASSIGN,
FirOperation.IS, FirOperation.NOT_IS,
FirOperation.AS, FirOperation.SAFE_AS -> {
FirOperation.AS, FirOperation.SAFE_AS
-> {
TODO("Should not be here: incompatible operation in FirOperatorCall: $operation")
}
}