diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index e21d3afffa4..d4248688fc9 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -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 diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyDeclaration.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyDeclaration.kt index 6eb17ec479c..9ce78ab6b5a 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyDeclaration.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyDeclaration.kt @@ -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 -) : 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 + override var metadata: Nothing? get() = null set(_) = error("We should never need to store metadata of external declarations.") diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt index 8b2d7eb0073..78888e2193a 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt @@ -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 - 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 } } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt new file mode 100644 index 00000000000..6963d009527 --- /dev/null +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt @@ -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( + 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 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 by lazyVar { + val containingClass = parent as? IrClass + containingClass?.findMatchingOverriddenSymbolsFromSupertypes(irBuiltIns, this) + ?.filterIsInstance().orEmpty() + } + + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitSimpleFunction(this, data) + } + + override fun acceptChildren(visitor: IrElementVisitor, 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 transformChildren(transformer: IrElementTransformer, 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) + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/javaInterop/samTypeParameter.kt b/compiler/testData/codegen/box/javaInterop/samTypeParameter.kt index d48bd83eb41..ef15ed5dfd6 100644 --- a/compiler/testData/codegen/box/javaInterop/samTypeParameter.kt +++ b/compiler/testData/codegen/box/javaInterop/samTypeParameter.kt @@ -1,5 +1,4 @@ // TARGET_BACKEND: JVM -// IGNORE_BACKEND_FIR: JVM_IR // FILE: Generic.java class Generic { T id(T x) { return x; } diff --git a/compiler/testData/ir/irText/stubs/builtinMap.fir.txt b/compiler/testData/ir/irText/stubs/builtinMap.fir.txt index 01e4770f49d..711a680f788 100644 --- a/compiler/testData/ir/irText/stubs/builtinMap.fir.txt +++ b/compiler/testData/ir/irText/stubs/builtinMap.fir.txt @@ -27,7 +27,7 @@ FILE fqName: fileName:/builtinMap.kt $receiver: VALUE_PARAMETER name: type:java.util.LinkedHashMap.plus?, V1 of .plus?> BLOCK_BODY RETURN type=kotlin.Nothing from='local final fun (): kotlin.Unit declared in .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 .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 .plus? origin=null $this: GET_VAR ': java.util.LinkedHashMap.plus?, V1 of .plus?> declared in .plus.' type=java.util.LinkedHashMap.plus?, V1 of .plus?> origin=null p0: CALL 'public final fun (): A of kotlin.Pair declared in kotlin.Pair' type=K1 of .plus origin=GET_PROPERTY $this: GET_VAR 'pair: kotlin.Pair.plus, V1 of .plus> declared in .plus' type=kotlin.Pair.plus, V1 of .plus> origin=null