[FIR2IR] Introduce & use lazy function for external class functions
This commit is contained in:
+27
-2
@@ -20,6 +20,8 @@ import org.jetbrains.kotlin.fir.descriptors.FirPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
@@ -721,7 +723,7 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
private fun createIrParameter(
|
||||
internal fun createIrParameter(
|
||||
valueParameter: FirValueParameter,
|
||||
index: Int = -1,
|
||||
useStubForDefaultValueStub: Boolean = true,
|
||||
@@ -833,14 +835,37 @@ class Fir2IrDeclarationStorage(
|
||||
getCachedIrFunction(firDeclaration)?.let { return it.symbol }
|
||||
val signature = signatureComposer.composeSignature(firDeclaration)
|
||||
val irParent = findIrParent(firDeclaration)
|
||||
val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED
|
||||
if (signature != null) {
|
||||
symbolTable.referenceSimpleFunctionIfAny(signature)?.let { irFunctionSymbol ->
|
||||
val irFunction = irFunctionSymbol.owner
|
||||
functionCache[firDeclaration] = irFunction
|
||||
return irFunctionSymbol
|
||||
}
|
||||
// TODO: package fragment members (?)
|
||||
if (firDeclaration is FirSimpleFunction && irParent is Fir2IrLazyClass) {
|
||||
if (parentOrigin == IrDeclarationOrigin.DEFINED) {
|
||||
throw AssertionError()
|
||||
}
|
||||
val symbol = Fir2IrSimpleFunctionSymbol(signature, firDeclaration.containerSource)
|
||||
val irFunction = firDeclaration.convertWithOffsets { startOffset, endOffset ->
|
||||
symbolTable.declareSimpleFunction(signature, { symbol }) {
|
||||
val isFakeOverride =
|
||||
firFunctionSymbol is FirNamedFunctionSymbol && firFunctionSymbol.isFakeOverride &&
|
||||
firFunctionSymbol.callableId != firFunctionSymbol.overriddenSymbol?.callableId
|
||||
Fir2IrLazySimpleFunction(
|
||||
components, startOffset, endOffset, parentOrigin, firDeclaration, symbol, isFakeOverride
|
||||
).apply {
|
||||
parent = irParent
|
||||
}
|
||||
}
|
||||
}
|
||||
functionCache[firDeclaration] = irFunction
|
||||
// NB: this is needed to prevent recursions in case of self bounds
|
||||
(irFunction as Fir2IrLazySimpleFunction).prepareTypeParameters()
|
||||
return symbol
|
||||
}
|
||||
}
|
||||
val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED
|
||||
createIrFunction(firDeclaration, irParent, origin = parentOrigin).apply {
|
||||
setAndModifyParent(irParent)
|
||||
}.symbol
|
||||
|
||||
+16
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.lazy
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
|
||||
import org.jetbrains.kotlin.fir.backend.toIrType
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrBindableSymbol
|
||||
import org.jetbrains.kotlin.ir.IrElementBase
|
||||
@@ -22,7 +23,21 @@ abstract class AbstractFir2IrLazyDeclaration<F : FirMemberDeclaration, D : IrSym
|
||||
override var origin: IrDeclarationOrigin,
|
||||
val fir: F,
|
||||
open val symbol: Fir2IrBindableSymbol<*, D>
|
||||
) : IrElementBase(startOffset, endOffset), IrDeclaration, Fir2IrComponents by components {
|
||||
) : IrElementBase(startOffset, endOffset), IrDeclaration, IrDeclarationParent, Fir2IrComponents by components {
|
||||
internal fun prepareTypeParameters() {
|
||||
typeParameters = fir.typeParameters.mapIndexedNotNull { index, typeParameter ->
|
||||
if (typeParameter !is FirTypeParameter) return@mapIndexedNotNull null
|
||||
classifierStorage.getIrTypeParameter(typeParameter, index).apply {
|
||||
parent = this@AbstractFir2IrLazyDeclaration
|
||||
if (superTypes.isEmpty()) {
|
||||
typeParameter.bounds.mapTo(superTypes) { it.toIrType(typeConverter) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lateinit var typeParameters: List<IrTypeParameter>
|
||||
|
||||
override var metadata: Nothing?
|
||||
get() = null
|
||||
set(_) = error("We should never need to store metadata of external declarations.")
|
||||
|
||||
@@ -41,18 +41,6 @@ class Fir2IrLazyClass(
|
||||
classifierStorage.preCacheTypeParameters(fir)
|
||||
}
|
||||
|
||||
internal fun prepareTypeParameters() {
|
||||
typeParameters = fir.typeParameters.mapIndexedNotNull { index, typeParameter ->
|
||||
if (typeParameter !is FirTypeParameter) return@mapIndexedNotNull null
|
||||
classifierStorage.getIrTypeParameter(typeParameter, index).apply {
|
||||
parent = this@Fir2IrLazyClass
|
||||
if (superTypes.isEmpty()) {
|
||||
typeParameter.bounds.mapTo(superTypes) { it.toIrType(typeConverter) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val source: SourceElement
|
||||
get() = SourceElement.NO_SOURCE
|
||||
|
||||
@@ -112,8 +100,6 @@ class Fir2IrLazyClass(
|
||||
fir.superTypeRefs.map { it.toIrType(typeConverter) }
|
||||
}
|
||||
|
||||
override lateinit var typeParameters: List<IrTypeParameter>
|
||||
|
||||
override var thisReceiver: IrValueParameter? by lazyVar {
|
||||
symbolTable.enterScope(this)
|
||||
val typeArguments = fir.typeParameters.map {
|
||||
@@ -151,12 +137,12 @@ class Fir2IrLazyClass(
|
||||
return@processFunctionsByName
|
||||
}
|
||||
result += if (!it.isFakeOverride) {
|
||||
declarationStorage.createIrFunction(it.fir, irParent = this, origin = origin)
|
||||
declarationStorage.getIrFunctionSymbol(it).owner
|
||||
} else {
|
||||
val fakeOverrideSymbol =
|
||||
FirClassSubstitutionScope.createFakeOverrideFunction(session, it.fir, it)
|
||||
classifierStorage.preCacheTypeParameters(it.fir)
|
||||
declarationStorage.createIrFunction(fakeOverrideSymbol.fir, irParent = this)
|
||||
declarationStorage.getIrFunctionSymbol(fakeOverrideSymbol).owner
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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.lazy
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
|
||||
import org.jetbrains.kotlin.fir.backend.declareThisReceiverParameter
|
||||
import org.jetbrains.kotlin.fir.backend.findMatchingOverriddenSymbolsFromSupertypes
|
||||
import org.jetbrains.kotlin.fir.backend.toIrType
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.mapOptimized
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class Fir2IrLazySimpleFunction(
|
||||
components: Fir2IrComponents,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
fir: FirSimpleFunction,
|
||||
symbol: Fir2IrSimpleFunctionSymbol,
|
||||
override val isFakeOverride: Boolean
|
||||
) : AbstractFir2IrLazyDeclaration<FirSimpleFunction, IrSimpleFunction>(
|
||||
components, startOffset, endOffset, origin, fir, symbol
|
||||
), IrSimpleFunction {
|
||||
init {
|
||||
symbol.bind(this)
|
||||
classifierStorage.preCacheTypeParameters(fir)
|
||||
}
|
||||
|
||||
override val isTailrec: Boolean
|
||||
get() = fir.isTailRec
|
||||
|
||||
override val isSuspend: Boolean
|
||||
get() = fir.isSuspend
|
||||
|
||||
override val isOperator: Boolean
|
||||
get() = fir.isOperator
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
override val descriptor: FunctionDescriptor
|
||||
get() = super.descriptor as FunctionDescriptor
|
||||
|
||||
override val symbol: Fir2IrSimpleFunctionSymbol
|
||||
get() = super.symbol as Fir2IrSimpleFunctionSymbol
|
||||
|
||||
override val isInline: Boolean
|
||||
get() = fir.isInline
|
||||
|
||||
override val isExternal: Boolean
|
||||
get() = fir.isExternal
|
||||
|
||||
override val isExpect: Boolean
|
||||
get() = fir.isExpect
|
||||
|
||||
override var body: IrBody? = null
|
||||
|
||||
override val name: Name
|
||||
get() = fir.name
|
||||
|
||||
override val visibility: Visibility
|
||||
get() = fir.visibility
|
||||
|
||||
override val modality: Modality
|
||||
get() = fir.modality!!
|
||||
|
||||
override var correspondingPropertySymbol: IrPropertySymbol? = null
|
||||
|
||||
override var attributeOwnerId: IrAttributeContainer = this
|
||||
|
||||
override var returnType: IrType by lazyVar {
|
||||
fir.returnTypeRef.toIrType(typeConverter)
|
||||
}
|
||||
|
||||
override var dispatchReceiverParameter: IrValueParameter? by lazyVar {
|
||||
val containingClass = parent as? IrClass
|
||||
if (!fir.isStatic && containingClass != null) {
|
||||
declarationStorage.enterScope(this)
|
||||
declareThisReceiverParameter(
|
||||
symbolTable,
|
||||
thisType = containingClass.thisReceiver?.type
|
||||
?: throw AssertionError(),
|
||||
thisOrigin = origin
|
||||
).apply {
|
||||
declarationStorage.leaveScope(this@Fir2IrLazySimpleFunction)
|
||||
}
|
||||
} else null
|
||||
}
|
||||
|
||||
override var extensionReceiverParameter: IrValueParameter? by lazyVar {
|
||||
fir.receiverTypeRef?.let {
|
||||
declarationStorage.enterScope(this)
|
||||
declareThisReceiverParameter(
|
||||
symbolTable,
|
||||
thisType = it.toIrType(typeConverter),
|
||||
thisOrigin = origin,
|
||||
).apply {
|
||||
declarationStorage.leaveScope(this@Fir2IrLazySimpleFunction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override var valueParameters: List<IrValueParameter> by lazyVar {
|
||||
declarationStorage.enterScope(this)
|
||||
fir.valueParameters.mapIndexed { index, valueParameter ->
|
||||
declarationStorage.createIrParameter(
|
||||
valueParameter, index,
|
||||
).apply {
|
||||
this.parent = this@Fir2IrLazySimpleFunction
|
||||
}
|
||||
}.apply {
|
||||
declarationStorage.leaveScope(this@Fir2IrLazySimpleFunction)
|
||||
}
|
||||
}
|
||||
|
||||
override var overriddenSymbols: List<IrSimpleFunctionSymbol> by lazyVar {
|
||||
val containingClass = parent as? IrClass
|
||||
containingClass?.findMatchingOverriddenSymbolsFromSupertypes(irBuiltIns, this)
|
||||
?.filterIsInstance<IrSimpleFunctionSymbol>().orEmpty()
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
|
||||
return visitor.visitSimpleFunction(this, data)
|
||||
}
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
typeParameters.forEach { it.accept(visitor, data) }
|
||||
|
||||
dispatchReceiverParameter?.accept(visitor, data)
|
||||
extensionReceiverParameter?.accept(visitor, data)
|
||||
valueParameters.forEach { it.accept(visitor, data) }
|
||||
|
||||
body?.accept(visitor, data)
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
typeParameters = typeParameters.mapOptimized { it.transform(transformer, data) }
|
||||
|
||||
dispatchReceiverParameter = dispatchReceiverParameter?.transform(transformer, data)
|
||||
extensionReceiverParameter = extensionReceiverParameter?.transform(transformer, data)
|
||||
valueParameters = valueParameters.mapOptimized { it.transform(transformer, data) }
|
||||
|
||||
body = body?.transform(transformer, data)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FILE: Generic.java
|
||||
class Generic<T> {
|
||||
T id(T x) { return x; }
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ FILE fqName:<root> fileName:/builtinMap.kt
|
||||
$receiver: VALUE_PARAMETER name:<this> type:java.util.LinkedHashMap<K1 of <root>.plus?, V1 of <root>.plus?>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Unit declared in <root>.plus'
|
||||
CALL 'public open fun put (p0: K of java.util.LinkedHashMap?, p1: V of java.util.LinkedHashMap?): V of java.util.LinkedHashMap? declared in java.util.LinkedHashMap' type=V1 of <root>.plus? origin=null
|
||||
CALL 'public open fun put (p0: K of java.util.LinkedHashMap?, p1: V of java.util.LinkedHashMap?): V of java.util.LinkedHashMap? [fake_override] declared in java.util.LinkedHashMap' type=V1 of <root>.plus? origin=null
|
||||
$this: GET_VAR '<this>: java.util.LinkedHashMap<K1 of <root>.plus?, V1 of <root>.plus?> declared in <root>.plus.<anonymous>' type=java.util.LinkedHashMap<K1 of <root>.plus?, V1 of <root>.plus?> origin=null
|
||||
p0: CALL 'public final fun <get-first> (): A of kotlin.Pair declared in kotlin.Pair' type=K1 of <root>.plus origin=GET_PROPERTY
|
||||
$this: GET_VAR 'pair: kotlin.Pair<K1 of <root>.plus, V1 of <root>.plus> declared in <root>.plus' type=kotlin.Pair<K1 of <root>.plus, V1 of <root>.plus> origin=null
|
||||
|
||||
Reference in New Issue
Block a user