From c19d45a2fc2f062439124b011d83aa9a46d4d9cf Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Wed, 4 Jul 2018 15:00:08 +0200 Subject: [PATCH] Initial lazy ir implementation --- .../ir/declarations/lazy/IrLazyClass.kt | 117 +++++++++++++++++ .../ir/declarations/lazy/IrLazyConstructor.kt | 68 ++++++++++ .../lazy/IrLazyDeclarationBase.kt | 98 ++++++++++++++ .../declarations/lazy/IrLazyEnumEntryImpl.kt | 65 +++++++++ .../ir/declarations/lazy/IrLazyFunction.kt | 93 +++++++++++++ .../declarations/lazy/IrLazyFunctionBase.kt | 81 ++++++++++++ .../ir/declarations/lazy/IrLazySymbolTable.kt | 61 +++++++++ .../declarations/lazy/IrLazyTypeParameter.kt | 77 +++++++++++ .../lazy/LazyScopedTypeParametersResolver.kt | 51 +++++++ .../ir/util/DeclarationStubGenerator.kt | 124 +++++++----------- .../ir/util/ExternalDependenciesGenerator.kt | 35 +++-- .../ir/util/ScopedTypeParametersResolver.kt | 15 ++- .../jetbrains/kotlin/ir/util/SymbolTable.kt | 45 ++++--- .../kotlin/ir/util/TypeTranslator.kt | 4 +- 14 files changed, 827 insertions(+), 107 deletions(-) create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyConstructor.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyEnumEntryImpl.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunction.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunctionBase.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazySymbolTable.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeParameter.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/LazyScopedTypeParametersResolver.kt diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt new file mode 100644 index 00000000000..57c922fc922 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt @@ -0,0 +1,117 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.ir.declarations.lazy + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator +import org.jetbrains.kotlin.ir.util.TypeTranslator +import org.jetbrains.kotlin.ir.util.transform +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal + +class IrLazyClass( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + override val symbol: IrClassSymbol, + override val name: Name, + override val kind: ClassKind, + override val visibility: Visibility, + override val modality: Modality, + override val isCompanion: Boolean, + override val isInner: Boolean, + override val isData: Boolean, + override val isExternal: Boolean, + stubGenerator: DeclarationStubGenerator, + typeTranslator: TypeTranslator +) : + IrLazyDeclarationBase(startOffset, endOffset, origin, stubGenerator, typeTranslator), + IrClass { + + constructor( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + symbol: IrClassSymbol, + stubGenerator: DeclarationStubGenerator, + TypeTranslator: TypeTranslator + ) : + this( + startOffset, endOffset, origin, symbol, + symbol.descriptor.name, symbol.descriptor.kind, + symbol.descriptor.visibility, symbol.descriptor.modality, + isCompanion = symbol.descriptor.isCompanionObject, + isInner = symbol.descriptor.isInner, + isData = symbol.descriptor.isData, + isExternal = symbol.descriptor.isEffectivelyExternal(), + stubGenerator = stubGenerator, + typeTranslator = TypeTranslator + ) + + init { + symbol.bind(this) + } + + override val annotations: MutableList = arrayListOf() + + override val descriptor: ClassDescriptor get() = symbol.descriptor + + override var thisReceiver: IrValueParameter? by lazyVar { + typeTranslator.buildWithScope(this) { + descriptor.thisAsReceiverParameter.generateReceiverParameterStub() + } + } + + + override val declarations: MutableList by lazyVar { + ArrayList().also { + typeTranslator.buildWithScope(this) { + generateChildStubs(descriptor.constructors, it) + generateMemberStubs(descriptor.defaultType.memberScope, it) + generateMemberStubs(descriptor.staticScope, it) + } + } + } + + override val typeParameters: MutableList by lazy { + descriptor.declaredTypeParameters.mapTo(arrayListOf()) { + stubGenerator.generateOrGetTypeParameterStub(it) + } + } + + override val superTypes: MutableList by lazy { + typeTranslator.buildWithScope(this) { + // TODO get rid of code duplication, see ClassGenerator#generateClass + descriptor.typeConstructor.supertypes.mapNotNullTo(arrayListOf()) { + it.toIrType() + } + } + } + + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitClass(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + thisReceiver?.accept(visitor, data) + typeParameters.forEach { it.accept(visitor, data) } + declarations.forEach { it.accept(visitor, data) } + } + + override fun transformChildren(transformer: IrElementTransformer, data: D) { + thisReceiver = thisReceiver?.transform(transformer, data) + typeParameters.transform { it.transform(transformer, data) } + declarations.transform { it.transform(transformer, data) } + } +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyConstructor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyConstructor.kt new file mode 100644 index 00000000000..1fe2adcacf9 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyConstructor.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.ir.declarations.lazy + +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor +import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator +import org.jetbrains.kotlin.ir.util.TypeTranslator +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal + +class IrLazyConstructor( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + override val symbol: IrConstructorSymbol, + name: Name, + visibility: Visibility, + isInline: Boolean, + isExternal: Boolean, + override val isPrimary: Boolean, + stubGenerator: DeclarationStubGenerator, + typeTranslator: TypeTranslator +) : + IrLazyFunctionBase( + startOffset, endOffset, origin, name, + visibility, isInline, isExternal, + stubGenerator, typeTranslator + ), + IrConstructor { + + constructor( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + symbol: IrConstructorSymbol, + stubGenerator: DeclarationStubGenerator, + TypeTranslator: TypeTranslator + ) : this( + startOffset, endOffset, origin, symbol, + symbol.descriptor.name, + symbol.descriptor.visibility, + symbol.descriptor.isInline, + symbol.descriptor.isEffectivelyExternal(), + symbol.descriptor.isPrimary, + stubGenerator, + TypeTranslator + ) + + override val typeParameters: MutableList = arrayListOf() + + init { + symbol.bind(this) + } + + override val descriptor: ClassConstructorDescriptor get() = symbol.descriptor + + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitConstructor(this, data) +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt new file mode 100644 index 00000000000..38e426a648c --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt @@ -0,0 +1,98 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.ir.declarations.lazy + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.IrElementBase +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator +import org.jetbrains.kotlin.ir.util.TypeTranslator +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.KotlinType +import kotlin.reflect.KProperty + +abstract class IrLazyDeclarationBase( + startOffset: Int, + endOffset: Int, + override val origin: IrDeclarationOrigin, + private val stubGenerator: DeclarationStubGenerator, + protected val typeTranslator: TypeTranslator +) : IrElementBase(startOffset, endOffset), IrDeclaration { + + protected fun KotlinType.toIrType() = typeTranslator.translateType(this) + + protected fun ReceiverParameterDescriptor.generateReceiverParameterStub(): IrValueParameter = + IrValueParameterImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, this, + type.toIrType(), null + ) + + protected fun generateMemberStubs(memberScope: MemberScope, container: MutableList) { + generateChildStubs(memberScope.getContributedDescriptors(), container) + } + + protected fun generateChildStubs(descriptors: Collection, declarations: MutableList) { + descriptors.mapTo(declarations) { generateMemberStub(it) } + } + + private fun generateMemberStub(descriptor: DeclarationDescriptor): IrDeclaration = + stubGenerator.generateMemberStub(descriptor) + + override var parent: IrDeclarationParent by lazyVar { + createLazyParent()!! + } + + override val annotations: MutableList = arrayListOf() + + private fun createLazyParent(): IrDeclarationParent? { + val currentDescriptor = descriptor + val containingDeclaration = currentDescriptor.containingDeclaration + return when (containingDeclaration) { + is PackageFragmentDescriptor -> stubGenerator.generateOrGetEmptyExternalPackageFragmentStub(containingDeclaration).also { + it.declarations.add(this) + } + is ClassDescriptor -> stubGenerator.generateClassStub(containingDeclaration) + is FunctionDescriptor -> stubGenerator.generateFunctionStub(containingDeclaration) + else -> throw AssertionError("Package or class expected: $containingDeclaration; for $currentDescriptor") + } + } +} + + +internal fun lazyVar(initializer: () -> T): UnsafeLazyVar = UnsafeLazyVar(initializer) + + +internal class UnsafeLazyVar(initializer: () -> T) { + private var isInitialized = false; + private var initializer: (() -> T)? = initializer + private var _value: Any? = null + + private val value: T + get() { + if (!isInitialized) { + _value = initializer!!() + isInitialized = true + initializer = null + } + @Suppress("UNCHECKED_CAST") + return _value as T + } + + override fun toString(): String = if (isInitialized) value.toString() else "Lazy value not initialized yet." + + operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value + + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { + this._value = value + isInitialized = true + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyEnumEntryImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyEnumEntryImpl.kt new file mode 100644 index 00000000000..abbcb62389c --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyEnumEntryImpl.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.ir.declarations.lazy + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrEnumEntry +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol +import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator +import org.jetbrains.kotlin.ir.util.TypeTranslator +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.name.Name + +class IrLazyEnumEntryImpl( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + override val symbol: IrEnumEntrySymbol, + stubGenerator: DeclarationStubGenerator, + typeTranslator: TypeTranslator +) : IrLazyDeclarationBase(startOffset, endOffset, origin, stubGenerator, typeTranslator), + IrEnumEntry { + + init { + symbol.bind(this) + } + + override val descriptor: ClassDescriptor get() = symbol.descriptor + override val name: Name = symbol.descriptor.name + + override var correspondingClass: IrClass? = null + + override var initializerExpression: IrExpression? = null + + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitEnumEntry(this, data) + } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + initializerExpression?.accept(visitor, data) + correspondingClass?.accept(visitor, data) + } + + override fun transformChildren(transformer: IrElementTransformer, data: D) { + initializerExpression = initializerExpression?.transform(transformer, data) + correspondingClass = correspondingClass?.transform(transformer, data) as? IrClass + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunction.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunction.kt new file mode 100644 index 00000000000..14e8e83bab3 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunction.kt @@ -0,0 +1,93 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.ir.declarations.lazy + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator +import org.jetbrains.kotlin.ir.util.TypeTranslator +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor + +class IrLazyFunction( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + override val symbol: IrSimpleFunctionSymbol, + name: Name, + visibility: Visibility, + override val modality: Modality, + isInline: Boolean, + isExternal: Boolean, + override val isTailrec: Boolean, + override val isSuspend: Boolean, + stubGenerator: DeclarationStubGenerator, + typeTranslator: TypeTranslator +) : + IrLazyFunctionBase(startOffset, endOffset, origin, name, visibility, isInline, isExternal, stubGenerator, typeTranslator), + IrSimpleFunction { + + constructor( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + symbol: IrSimpleFunctionSymbol, + stubGenerator: DeclarationStubGenerator, + TypeTranslator: TypeTranslator + ) : this( + startOffset, endOffset, origin, symbol, + symbol.descriptor.name, + symbol.descriptor.visibility, + symbol.descriptor.modality, + symbol.descriptor.isInline, + symbol.descriptor.isExternal, + symbol.descriptor.isTailrec, + symbol.descriptor.isSuspend, + stubGenerator, + TypeTranslator + ) + + override val descriptor: FunctionDescriptor = symbol.descriptor + + override val typeParameters: MutableList by lazy { + typeTranslator.buildWithScope(this) { + stubGenerator.symbolTable.enterScope(descriptor) + val propertyIfAccessor = descriptor.propertyIfAccessor + propertyIfAccessor.typeParameters.mapTo(arrayListOf()) { + if (descriptor != propertyIfAccessor) { + stubGenerator.generateOrGetScopedTypeParameterStub(it).also { + it.parent = this@IrLazyFunction + } + } else { + stubGenerator.generateOrGetTypeParameterStub(it) + } + }.also { + stubGenerator.symbolTable.leaveScope(descriptor) + } + } + } + + + override val overriddenSymbols: MutableList by lazy { + descriptor.overriddenDescriptors.mapTo(arrayListOf()) { + stubGenerator.generateFunctionStub(it.original).symbol + } + } + + override var correspondingProperty: IrProperty? = null + + init { + symbol.bind(this) + } + + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitSimpleFunction(this, data) +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunctionBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunctionBase.kt new file mode 100644 index 00000000000..0aeacee4238 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunctionBase.kt @@ -0,0 +1,81 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.ir.declarations.lazy + +import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.expressions.IrBody +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator +import org.jetbrains.kotlin.ir.util.TypeTranslator +import org.jetbrains.kotlin.ir.util.transform +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor + +abstract class IrLazyFunctionBase( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + override val name: Name, + override val visibility: Visibility, + override val isInline: Boolean, + override val isExternal: Boolean, + stubGenerator: DeclarationStubGenerator, + typeTranslator: TypeTranslator +) : + IrLazyDeclarationBase(startOffset, endOffset, origin, stubGenerator, typeTranslator), + IrFunction { + + override var dispatchReceiverParameter: IrValueParameter? by lazyVar { + typeTranslator.buildWithScope(this) { + descriptor.dispatchReceiverParameter?.generateReceiverParameterStub() + } + } + override var extensionReceiverParameter: IrValueParameter? by lazyVar { + typeTranslator.buildWithScope(this) { + descriptor.extensionReceiverParameter?.generateReceiverParameterStub() + } + } + + override val valueParameters: MutableList by lazy { + typeTranslator.buildWithScope(this) { + descriptor.valueParameters.mapTo(arrayListOf()) { stubGenerator.generateValueParameterStub(it) } + } + } + + final override var body: IrBody? = null + + final override var returnType: IrType by lazyVar { + typeTranslator.buildWithScope(this) { + descriptor.returnType!!.toIrType() + } + } + + 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.transform { it.transform(transformer, data) } + + dispatchReceiverParameter = dispatchReceiverParameter?.transform(transformer, data) + extensionReceiverParameter = extensionReceiverParameter?.transform(transformer, data) + valueParameters.transform { it.transform(transformer, data) } + + body = body?.transform(transformer, data) + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazySymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazySymbolTable.kt new file mode 100644 index 00000000000..f39179dd92c --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazySymbolTable.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.ir.declarations.lazy + +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator +import org.jetbrains.kotlin.ir.util.SymbolTable + + +class IrLazySymbolTable(private val stubGenerator: DeclarationStubGenerator, val originalTable: SymbolTable) : SymbolTable() { + + /*Don't force builtins class linking before unbound symbols linking: otherwise stdlib compilation will failed*/ + internal var unboundSymbolGeneration = false + + override fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol { + return originalTable.referenceClass(descriptor).also { + if (unboundSymbolGeneration && !it.isBound) { + stubGenerator.generateClassStub(descriptor).symbol + } + } + } + + override fun referenceConstructor(descriptor: ClassConstructorDescriptor): IrConstructorSymbol { + return originalTable.referenceConstructor(descriptor).also { + if (!it.isBound && unboundSymbolGeneration) { + stubGenerator.generateConstructorStub(descriptor).symbol + } + } + } + + override fun referenceEnumEntry(descriptor: ClassDescriptor): IrEnumEntrySymbol { + return originalTable.referenceEnumEntry(descriptor).also { + if (!it.isBound && unboundSymbolGeneration) { + stubGenerator.generateEnumEntryStub(descriptor).symbol + } + } + } + + override fun referenceSimpleFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol { + return originalTable.referenceSimpleFunction(descriptor).also { + if (!it.isBound && unboundSymbolGeneration) { + stubGenerator.generateFunctionStub(descriptor).symbol + } + } + } + + override fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol { + return originalTable.referenceTypeParameter(classifier).also { + if (!it.isBound && unboundSymbolGeneration) { + stubGenerator.generateOrGetTypeParameterStub(classifier).symbol + } + } + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeParameter.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeParameter.kt new file mode 100644 index 00000000000..8d297160228 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeParameter.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.ir.declarations.lazy + +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator +import org.jetbrains.kotlin.ir.util.TypeTranslator +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.Variance + +class IrLazyTypeParameter( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + override val symbol: IrTypeParameterSymbol, + override val name: Name, + override val index: Int, + override val variance: Variance, + stubGenerator: DeclarationStubGenerator, + typeTranslator: TypeTranslator +) : + IrLazyDeclarationBase(startOffset, endOffset, origin, stubGenerator, typeTranslator), + IrTypeParameter { + + constructor( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + symbol: IrTypeParameterSymbol, + stubGenerator: DeclarationStubGenerator, + TypeTranslator: TypeTranslator + ) : + this( + startOffset, endOffset, origin, symbol, + symbol.descriptor.name, + symbol.descriptor.index, + symbol.descriptor.variance, + stubGenerator, TypeTranslator + ) + + override val descriptor: TypeParameterDescriptor get() = symbol.descriptor + + init { + symbol.bind(this) + } + + override val superTypes: MutableList by lazy { + typeTranslator.buildWithScope(this.parent as IrTypeParametersContainer) { + val descriptor = symbol.descriptor + descriptor.upperBounds.mapTo(arrayListOf()) { it.toIrType() } + } + } + + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitTypeParameter(this, data) + + override fun transform(transformer: IrElementTransformer, data: D): IrTypeParameter = + transformer.visitTypeParameter(this, data) as IrTypeParameter + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + // no children + } + + override fun transformChildren(transformer: IrElementTransformer, data: D) { + // no children + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/LazyScopedTypeParametersResolver.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/LazyScopedTypeParametersResolver.kt new file mode 100644 index 00000000000..a7f9258e7a4 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/LazyScopedTypeParametersResolver.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.ir.declarations.lazy + +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.util.* +import java.util.* + +class LazyScopedTypeParametersResolver() : TypeParametersResolver { + + private val typeParameterScopes = ArrayDeque() + + override fun enterTypeParameterScope(typeParametersContainer: IrTypeParametersContainer) { + typeParameterScopes.addFirst( + typeParametersContainer + ) + } + + override fun leaveTypeParameterScope() { + typeParameterScopes.removeFirst() + } + + //TODO optimize + override fun resolveScopedTypeParameter(typeParameterDescriptor: TypeParameterDescriptor): IrTypeParameterSymbol? { + var parent = typeParameterScopes.first() + while (parent != null) { + val declaration = parent + val symbol = declaration.typeParameters.firstOrNull { + it.descriptor == typeParameterDescriptor + }?.symbol + if (symbol != null) return symbol + parent = calcParent(parent) + } + return null + } + + private fun calcParent(container: IrTypeParametersContainer): IrTypeParametersContainer? { + return when(container) { + is IrClass -> if (container.isObject || !container.isInner) null else container.parent + else -> (container as? IrDeclaration)?.parent + } as? IrTypeParametersContainer + } + +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt index 225895ee4b1..8b286bc3da3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt @@ -22,14 +22,13 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.declarations.lazy.* import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor -import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.KotlinType class DeclarationStubGenerator( @@ -38,8 +37,15 @@ class DeclarationStubGenerator( val origin: IrDeclarationOrigin, val languageVersionSettings: LanguageVersionSettings ) { - private val typeTranslator = TypeTranslator(symbolTable, languageVersionSettings) - private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable) + private val lazyTable = IrLazySymbolTable(this, symbolTable) + + internal var unboundSymbolGeneration: Boolean + get() = lazyTable.unboundSymbolGeneration + set(value) { lazyTable.unboundSymbolGeneration = value } + + + private val typeTranslator = TypeTranslator(lazyTable, languageVersionSettings, LazyScopedTypeParametersResolver()) + private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, lazyTable) init { typeTranslator.constantValueGenerator = constantValueGenerator @@ -49,8 +55,9 @@ class DeclarationStubGenerator( fun generateEmptyModuleFragmentStub(descriptor: ModuleDescriptor, irBuiltIns: IrBuiltIns): IrModuleFragment = IrModuleFragmentImpl(descriptor, irBuiltIns) - fun generateEmptyExternalPackageFragmentStub(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment = - symbolTable.declareExternalPackageFragment(descriptor) + fun generateOrGetEmptyExternalPackageFragmentStub(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment { + return symbolTable.declareExternalPackageFragment(descriptor) + } fun generateMemberStub(descriptor: DeclarationDescriptor): IrDeclaration = when (descriptor) { @@ -69,7 +76,7 @@ class DeclarationStubGenerator( throw AssertionError("Unexpected member descriptor: $descriptor") } - private fun generatePropertyStub(descriptor: PropertyDescriptor): IrProperty = + internal fun generatePropertyStub(descriptor: PropertyDescriptor): IrProperty = IrPropertyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irProperty -> val getterDescriptor = descriptor.getter if (getterDescriptor == null) { @@ -88,8 +95,13 @@ class DeclarationStubGenerator( irProperty.setter = descriptor.setter?.let { generateFunctionStub(it) } } - fun generateFunctionStub(descriptor: FunctionDescriptor): IrSimpleFunction = - symbolTable.declareSimpleFunctionWithOverrides( + fun generateFunctionStub(descriptor: FunctionDescriptor): IrSimpleFunction { + val referenced = symbolTable.referenceSimpleFunction(descriptor) + if (referenced.isBound) { + return referenced.owner + } + + return symbolTable.declareSimpleFunction( UNDEFINED_OFFSET, UNDEFINED_OFFSET, if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { IrDeclarationOrigin.FAKE_OVERRIDE @@ -97,41 +109,24 @@ class DeclarationStubGenerator( origin }, descriptor.original - ).also { irFunction -> - generateTypeParameterStubs(descriptor.propertyIfAccessor.typeParameters, irFunction) + ) { IrLazyFunction(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) } + } - typeTranslator.buildWithScope(irFunction) { - irFunction.returnType = descriptor.returnType!!.toIrType() - generateValueParametersStubs(irFunction) - } + internal fun generateConstructorStub(descriptor: ClassConstructorDescriptor): IrConstructor { + val referenced = symbolTable.referenceConstructor(descriptor) + if (referenced.isBound) { + return referenced.owner } - private fun generateConstructorStub(descriptor: ClassConstructorDescriptor): IrConstructor = - symbolTable.declareConstructor( + return symbolTable.declareConstructor( UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original - ).also { irConstructor -> - // So far, constructors in Kotlin can't have type parameters of their own. - irConstructor.returnType = descriptor.returnType.toIrType() - generateValueParametersStubs(irConstructor) - } - - private fun generateValueParametersStubs(function: IrFunction) { - val descriptor = function.descriptor - function.dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.generateReceiverParameterStub() - function.extensionReceiverParameter = descriptor.extensionReceiverParameter?.generateReceiverParameterStub() - descriptor.valueParameters.mapTo(function.valueParameters) { generateValueParameterStub(it) } + ) { IrLazyConstructor(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) } } private fun KotlinType.toIrType() = typeTranslator.translateType(this) - private fun ReceiverParameterDescriptor.generateReceiverParameterStub(): IrValueParameter = - IrValueParameterImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, this, - type.toIrType(), null - ) - - private fun generateValueParameterStub(descriptor: ValueParameterDescriptor): IrValueParameter = - IrValueParameterImpl( + internal fun generateValueParameterStub(descriptor: ValueParameterDescriptor): IrValueParameter { + return IrValueParameterImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor, descriptor.type.toIrType(), descriptor.varargElementType?.toIrType() ).also { irValueParameter -> @@ -145,49 +140,32 @@ class DeclarationStubGenerator( ) } } + } - private fun generateClassStub(descriptor: ClassDescriptor): IrClass = - symbolTable.declareClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irClass -> - generateTypeParameterStubs(descriptor.declaredTypeParameters, irClass) - - typeTranslator.buildWithScope(irClass) { - // TODO get rid of code duplication, see ClassGenerator#generateClass - descriptor.typeConstructor.supertypes.mapNotNullTo(irClass.superTypes) { - it.toIrType() - } - - irClass.thisReceiver = descriptor.thisAsReceiverParameter.generateReceiverParameterStub() - generateChildStubs(descriptor.constructors, irClass) - generateMemberStubs(descriptor.defaultType.memberScope, irClass) - generateMemberStubs(descriptor.staticScope, irClass) - } + internal fun generateClassStub(descriptor: ClassDescriptor): IrClass { + val referenceClass = symbolTable.referenceClass(descriptor) + if (referenceClass.isBound) { + return referenceClass.owner } + return symbolTable.declareClass( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor + ) { IrLazyClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) } + } - private fun generateEnumEntryStub(descriptor: ClassDescriptor): IrEnumEntry = - symbolTable.declareEnumEntry(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) - - private fun generateTypeParameterStubs(typeParameters: List, container: IrTypeParametersContainer) { - typeParameters.mapTo(container.typeParameters) { generateTypeParameterStub(it) } - - typeTranslator.buildWithScope(container) { - for (typeParameter in container.typeParameters) { - val descriptor = typeParameter.descriptor - descriptor.upperBounds.mapTo(typeParameter.superTypes) { it.toIrType() } - } + internal fun generateEnumEntryStub(descriptor: ClassDescriptor): IrEnumEntry { + val referenced = symbolTable.referenceEnumEntry(descriptor) + if (referenced.isBound) { + return referenced.owner + } + return symbolTable.declareEnumEntry(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) { + IrLazyEnumEntryImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) } } - private fun generateTypeParameterStub(descriptor: TypeParameterDescriptor): IrTypeParameter = - IrTypeParameterImpl( + internal fun generateTypeParameterStub(descriptor: TypeParameterDescriptor): IrTypeParameter { + return IrLazyTypeParameter( UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, - descriptor + IrTypeParameterSymbolImpl(descriptor), this, typeTranslator ) - - private fun generateMemberStubs(memberScope: MemberScope, container: IrDeclarationContainer) { - generateChildStubs(memberScope.getContributedDescriptors(), container) - } - - private fun generateChildStubs(descriptors: Collection, container: IrDeclarationContainer) { - descriptors.mapTo(container.declarations) { generateMemberStub(it) } } } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt index 0a2c48ea42e..e95efc0dc98 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt @@ -43,15 +43,32 @@ class ExternalDependenciesGenerator( private val packageFragments = HashMap() fun run() { - while (true) { - val collector = DependenciesCollector() - collector.collectTopLevelDescriptorsForUnboundSymbols(symbolTable) - if (collector.isEmpty) break - - collector.dependencyModules.mapTo(irModule.dependencyModules) { moduleDescriptor -> - generateModuleStub(collector, moduleDescriptor) - } + stubGenerator.unboundSymbolGeneration = true + ArrayList(symbolTable.unboundClasses).forEach { + stubGenerator.generateClassStub(it.descriptor) } + ArrayList(symbolTable.unboundConstructors).forEach { + stubGenerator.generateConstructorStub(it.descriptor) + } + ArrayList(symbolTable.unboundEnumEntries).forEach { + stubGenerator.generateEnumEntryStub(it.descriptor) + } + ArrayList(symbolTable.unboundFields).forEach { + stubGenerator.generatePropertyStub(it.descriptor) + } + ArrayList(symbolTable.unboundSimpleFunctions).forEach { + stubGenerator.generateFunctionStub(it.descriptor) + } + ArrayList(symbolTable.unboundTypeParameters).forEach { + stubGenerator.generateOrGetTypeParameterStub(it.descriptor) + } + + assert(symbolTable.unboundClasses.isEmpty()) + assert(symbolTable.unboundConstructors.isEmpty()) + assert(symbolTable.unboundEnumEntries.isEmpty()) + assert(symbolTable.unboundFields.isEmpty()) + assert(symbolTable.unboundSimpleFunctions.isEmpty()) + assert(symbolTable.unboundTypeParameters.isEmpty()) } private fun generateModuleStub(collector: DependenciesCollector, moduleDescriptor: ModuleDescriptor): IrModuleFragment = @@ -80,7 +97,7 @@ class ExternalDependenciesGenerator( private fun getOrCreatePackageFragment(packageFragmentDescriptor: PackageFragmentDescriptor) = packageFragments.getOrPut(packageFragmentDescriptor) { - stubGenerator.generateEmptyExternalPackageFragmentStub(packageFragmentDescriptor) + stubGenerator.generateOrGetEmptyExternalPackageFragmentStub(packageFragmentDescriptor) } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ScopedTypeParametersResolver.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ScopedTypeParametersResolver.kt index 9b343320f73..1e44e8e948b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ScopedTypeParametersResolver.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ScopedTypeParametersResolver.kt @@ -10,11 +10,18 @@ import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import java.util.* -class ScopedTypeParametersResolver { +interface TypeParametersResolver { + fun enterTypeParameterScope(typeParametersContainer: IrTypeParametersContainer) + fun leaveTypeParameterScope() + + fun resolveScopedTypeParameter(typeParameterDescriptor: TypeParameterDescriptor): IrTypeParameterSymbol? +} + +class ScopedTypeParametersResolver : TypeParametersResolver { private val typeParameterScopes = ArrayDeque>() - fun enterTypeParameterScope(typeParametersContainer: IrTypeParametersContainer) { + override fun enterTypeParameterScope(typeParametersContainer: IrTypeParametersContainer) { typeParameterScopes.addFirst( typeParametersContainer.typeParameters.associate { it.descriptor to it.symbol @@ -22,11 +29,11 @@ class ScopedTypeParametersResolver { ) } - fun leaveTypeParameterScope() { + override fun leaveTypeParameterScope() { typeParameterScopes.removeFirst() } - fun resolveScopedTypeParameter(typeParameterDescriptor: TypeParameterDescriptor): IrTypeParameterSymbol? { + override fun resolveScopedTypeParameter(typeParameterDescriptor: TypeParameterDescriptor): IrTypeParameterSymbol? { for (scope in typeParameterScopes) { val local = scope[typeParameterDescriptor] if (local != null) return local diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt index 98ec20672d4..451d859de50 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt @@ -26,7 +26,7 @@ import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.* import org.jetbrains.kotlin.ir.types.IrType -class SymbolTable { +open class SymbolTable { private abstract class SymbolTableBase> { val unboundSymbols = linkedSetOf() @@ -174,14 +174,17 @@ class SymbolTable { IrAnonymousInitializerSymbolImpl(descriptor) ) - fun declareClass(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor): IrClass = + fun declareClass( + startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor, + classFactory: (IrClassSymbol) -> IrClass = { IrClassImpl(startOffset, endOffset, origin, it) } + ): IrClass = classSymbolTable.declare( descriptor, { IrClassSymbolImpl(descriptor) }, - { IrClassImpl(startOffset, endOffset, origin, it) } + classFactory ) - fun referenceClass(descriptor: ClassDescriptor) = + open fun referenceClass(descriptor: ClassDescriptor) = classSymbolTable.referenced(descriptor) { IrClassSymbolImpl(descriptor) } val unboundClasses: Set get() = classSymbolTable.unboundSymbols @@ -190,27 +193,29 @@ class SymbolTable { startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, - descriptor: ClassConstructorDescriptor + descriptor: ClassConstructorDescriptor, + constructorFactory: (IrConstructorSymbol) -> IrConstructor = { IrConstructorImpl(startOffset, endOffset, origin, it) } ): IrConstructor = constructorSymbolTable.declare( descriptor, { IrConstructorSymbolImpl(descriptor) }, - { IrConstructorImpl(startOffset, endOffset, origin, it) } + constructorFactory ) - fun referenceConstructor(descriptor: ClassConstructorDescriptor) = + open fun referenceConstructor(descriptor: ClassConstructorDescriptor) = constructorSymbolTable.referenced(descriptor) { IrConstructorSymbolImpl(descriptor) } val unboundConstructors: Set get() = constructorSymbolTable.unboundSymbols - fun declareEnumEntry(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor): IrEnumEntry = + fun declareEnumEntry(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor, + factory: (IrEnumEntrySymbol) -> IrEnumEntry = { IrEnumEntryImpl(startOffset, endOffset, origin, it) }): IrEnumEntry = enumEntrySymbolTable.declare( descriptor, { IrEnumEntrySymbolImpl(descriptor) }, - { IrEnumEntryImpl(startOffset, endOffset, origin, it) } + factory ) - fun referenceEnumEntry(descriptor: ClassDescriptor) = + open fun referenceEnumEntry(descriptor: ClassDescriptor) = enumEntrySymbolTable.referenced(descriptor) { IrEnumEntrySymbolImpl(descriptor) } val unboundEnumEntries: Set get() = enumEntrySymbolTable.unboundSymbols @@ -220,12 +225,13 @@ class SymbolTable { endOffset: Int, origin: IrDeclarationOrigin, descriptor: PropertyDescriptor, - type: IrType + type: IrType, + fieldFactory: (IrFieldSymbol) -> IrField = { IrFieldImpl(startOffset, endOffset, origin, it, type) } ): IrField = fieldSymbolTable.declare( descriptor, { IrFieldSymbolImpl(descriptor) }, - { IrFieldImpl(startOffset, endOffset, origin, it, type) } + fieldFactory ) fun declareField( @@ -249,15 +255,16 @@ class SymbolTable { startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, - descriptor: FunctionDescriptor + descriptor: FunctionDescriptor, + functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction = { IrFunctionImpl(startOffset, endOffset, origin, it) } ): IrSimpleFunction = simpleFunctionSymbolTable.declare( descriptor, { IrSimpleFunctionSymbolImpl(descriptor) }, - { IrFunctionImpl(startOffset, endOffset, origin, it) } + functionFactory ) - fun referenceSimpleFunction(descriptor: FunctionDescriptor) = + open fun referenceSimpleFunction(descriptor: FunctionDescriptor) = simpleFunctionSymbolTable.referenced(descriptor) { IrSimpleFunctionSymbolImpl(descriptor) } fun referenceDeclaredFunction(descriptor: FunctionDescriptor) = @@ -314,7 +321,7 @@ class SymbolTable { throw AssertionError("Undefined parameter referenced: $descriptor\n${valueParameterSymbolTable.dump()}") } - fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol = + open fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol = scopedTypeParameterSymbolTable.get(classifier) ?: globalTypeParameterSymbolTable.referenced(classifier) { throw AssertionError("Undefined type parameter referenced: $classifier") @@ -363,9 +370,9 @@ class SymbolTable { fun referenceFunction(callable: CallableDescriptor): IrFunctionSymbol = when (callable) { is ClassConstructorDescriptor -> - constructorSymbolTable.referenced(callable) { IrConstructorSymbolImpl(callable) } + referenceConstructor(callable) is FunctionDescriptor -> - simpleFunctionSymbolTable.referenced(callable) { IrSimpleFunctionSymbolImpl(callable) } + referenceSimpleFunction(callable) else -> throw IllegalArgumentException("Unexpected callable descriptor: $callable") } @@ -385,7 +392,7 @@ class SymbolTable { is TypeParameterDescriptor -> referenceTypeParameter(classifier) is ClassDescriptor -> - classSymbolTable.referenced(classifier) { IrClassSymbolImpl(classifier) } + referenceClass(classifier) else -> throw IllegalArgumentException("Unexpected classifier descriptor: $classifier") } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt index 47a339cad9e..d7360c1c662 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt @@ -23,10 +23,10 @@ import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes class TypeTranslator( private val symbolTable: SymbolTable, - val languageVersionSettings: LanguageVersionSettings + val languageVersionSettings: LanguageVersionSettings, + private val typeParametersResolver: TypeParametersResolver = ScopedTypeParametersResolver() ) { - private val typeParametersResolver = ScopedTypeParametersResolver() private val typeApproximatorForNI = TypeApproximator() lateinit var constantValueGenerator: ConstantValueGenerator