Extract ReferenceSymbolTable, support lazy type parameters

This commit is contained in:
Mikhael Bogdanov
2018-07-31 09:09:49 +02:00
parent 6623799671
commit 1bf3f4bda7
9 changed files with 168 additions and 105 deletions
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
@@ -26,7 +26,7 @@ abstract class Ir<out T : CommonBackendContext>(val context: T, val irModule: Ir
open fun shouldGenerateHandlerParameterForDefaultBodyFun() = false
}
abstract class Symbols<out T : CommonBackendContext>(val context: T, private val symbolTable: SymbolTable) {
abstract class Symbols<out T : CommonBackendContext>(val context: T, private val symbolTable: ReferenceSymbolTable) {
protected val builtIns
get() = context.builtIns
@@ -31,7 +31,7 @@ class AnnotationGenerator(
generateAnnotationsForDeclaration(declaration)
visitElement(declaration)
if (declaration is IrTypeParametersContainer) {
typeTranslator.leaveScope()
typeTranslator.leaveScope(declaration)
}
}
@@ -16,6 +16,6 @@
package org.jetbrains.kotlin.ir.declarations
interface IrTypeParametersContainer {
interface IrTypeParametersContainer : IrDeclaration {
val typeParameters: MutableList<IrTypeParameter>
}
@@ -5,57 +5,66 @@
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.descriptors.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.ir.util.SymbolTable
class IrLazySymbolTable(private val stubGenerator: DeclarationStubGenerator, val originalTable: SymbolTable) : SymbolTable() {
class IrLazySymbolTable(private val originalTable: SymbolTable) : ReferenceSymbolTable by originalTable {
override val declarationSystemTable: SymbolTable = originalTable
override val referenceSymbolTable: ReferenceSymbolTable = this
/*Don't force builtins class linking before unbound symbols linking: otherwise stdlib compilation will failed*/
internal var unboundSymbolGeneration = false
var stubGenerator: DeclarationStubGenerator? = null
override fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol {
return originalTable.referenceClass(descriptor).also {
if (unboundSymbolGeneration && !it.isBound) {
stubGenerator.generateClassStub(descriptor).symbol
if (!it.isBound) {
stubGenerator?.generateClassStub(descriptor)
}
}
}
override fun referenceConstructor(descriptor: ClassConstructorDescriptor): IrConstructorSymbol {
return originalTable.referenceConstructor(descriptor).also {
if (!it.isBound && unboundSymbolGeneration) {
stubGenerator.generateConstructorStub(descriptor).symbol
if (!it.isBound) {
stubGenerator?.generateConstructorStub(descriptor)
}
}
}
override fun referenceEnumEntry(descriptor: ClassDescriptor): IrEnumEntrySymbol {
return originalTable.referenceEnumEntry(descriptor).also {
if (!it.isBound && unboundSymbolGeneration) {
stubGenerator.generateEnumEntryStub(descriptor).symbol
if (!it.isBound) {
stubGenerator?.generateEnumEntryStub(descriptor)
}
}
}
override fun referenceSimpleFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol {
return originalTable.referenceSimpleFunction(descriptor).also {
if (!it.isBound && unboundSymbolGeneration) {
stubGenerator.generateFunctionStub(descriptor).symbol
if (!it.isBound) {
stubGenerator?.generateFunctionStub(descriptor)
}
}
}
override fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol {
return originalTable.referenceTypeParameter(classifier).also {
if (!it.isBound && unboundSymbolGeneration) {
stubGenerator.generateOrGetTypeParameterStub(classifier).symbol
if (!it.isBound) {
stubGenerator?.generateOrGetTypeParameterStub(classifier)
}
}
}
override fun referenceFunction(callable: CallableDescriptor): IrFunctionSymbol {
return super.referenceFunction(callable)
}
override fun referenceClassifier(classifier: ClassifierDescriptor): IrClassifierSymbol {
return super.referenceClassifier(classifier)
}
}
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.util.*
import java.util.*
class LazyScopedTypeParametersResolver() : TypeParametersResolver {
class LazyScopedTypeParametersResolver(private val symbolTable: ReferenceSymbolTable) : TypeParametersResolver {
private val typeParameterScopes = ArrayDeque<IrTypeParametersContainer>()
@@ -27,25 +27,13 @@ class LazyScopedTypeParametersResolver() : TypeParametersResolver {
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 {
//Just support accessor scoped symbols resolve in external declaration
//there should be enough to process only parent typeparameters
return typeParameterScopes.firstOrNull()?.let { parent ->
parent.typeParameters.firstOrNull {
it.descriptor == typeParameterDescriptor
}?.symbol
if (symbol != null) return symbol
parent = calcParent(parent)
}
return null
} ?: 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
}
}
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class ConstantValueGenerator(
private val moduleDescriptor: ModuleDescriptor,
private val symbolTable: SymbolTable
private val symbolTable: ReferenceSymbolTable
) {
lateinit var typeTranslator: TypeTranslator
@@ -27,7 +27,6 @@ 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.types.KotlinType
@@ -37,14 +36,17 @@ class DeclarationStubGenerator(
val origin: IrDeclarationOrigin,
val languageVersionSettings: LanguageVersionSettings
) {
private val lazyTable = IrLazySymbolTable(this, symbolTable)
private val lazyTable = symbolTable.lazyWrapper
internal var unboundSymbolGeneration: Boolean
get() = lazyTable.unboundSymbolGeneration
set(value) { lazyTable.unboundSymbolGeneration = value }
get() = lazyTable.stubGenerator != null
set(value) {
lazyTable.stubGenerator = if (value) this else null
}
private val typeTranslator = TypeTranslator(lazyTable, languageVersionSettings, LazyScopedTypeParametersResolver())
private val typeTranslator = TypeTranslator(lazyTable, languageVersionSettings, LazyScopedTypeParametersResolver(lazyTable), true)
private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, lazyTable)
init {
@@ -101,13 +103,13 @@ class DeclarationStubGenerator(
return referenced.owner
}
val origin =
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE)
IrDeclarationOrigin.FAKE_OVERRIDE
else origin
return symbolTable.declareSimpleFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
IrDeclarationOrigin.FAKE_OVERRIDE
} else {
origin
},
origin,
descriptor.original
) { IrLazyFunction(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) }
}
@@ -162,10 +164,29 @@ class DeclarationStubGenerator(
}
}
internal fun generateTypeParameterStub(descriptor: TypeParameterDescriptor): IrTypeParameter {
return IrLazyTypeParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin,
IrTypeParameterSymbolImpl(descriptor), this, typeTranslator
)
internal fun generateOrGetTypeParameterStub(descriptor: TypeParameterDescriptor): IrTypeParameter {
val referenced = symbolTable.referenceTypeParameter(descriptor)
if (referenced.isBound) {
return referenced.owner
}
return symbolTable.declareGlobalTypeParameter(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) {
IrLazyTypeParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin,
it, this, typeTranslator
)
}
}
internal fun generateOrGetScopedTypeParameterStub(descriptor: TypeParameterDescriptor): IrTypeParameter {
val referenced = symbolTable.referenceTypeParameter(descriptor)
if (referenced.isBound) {
return referenced.owner
}
return symbolTable.declareScopedTypeParameter(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) {
IrLazyTypeParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin,
it, this, typeTranslator
)
}
}
}
@@ -20,13 +20,65 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.SourceManager
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazySymbolTable
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.types.IrType
open class SymbolTable {
interface ReferenceSymbolTable {
fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol
fun referenceConstructor(descriptor: ClassConstructorDescriptor): IrConstructorSymbol
fun referenceEnumEntry(descriptor: ClassDescriptor): IrEnumEntrySymbol
fun referenceField(descriptor: PropertyDescriptor): IrFieldSymbol
fun referenceSimpleFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol
fun referenceDeclaredFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol
fun referenceValueParameter(descriptor: ParameterDescriptor): IrValueParameterSymbol
fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol
fun referenceVariable(descriptor: VariableDescriptor): IrVariableSymbol
fun referenceFunction(callable: CallableDescriptor): IrFunctionSymbol =
when (callable) {
is ClassConstructorDescriptor ->
referenceConstructor(callable)
is FunctionDescriptor ->
referenceSimpleFunction(callable)
else ->
throw IllegalArgumentException("Unexpected callable descriptor: $callable")
}
fun referenceClassifier(classifier: ClassifierDescriptor): IrClassifierSymbol =
when (classifier) {
is TypeParameterDescriptor ->
referenceTypeParameter(classifier)
is ClassDescriptor ->
referenceClass(classifier)
else ->
throw IllegalArgumentException("Unexpected classifier descriptor: $classifier")
}
val declarationSystemTable: SymbolTable
val referenceSymbolTable: ReferenceSymbolTable
fun enterScope(owner: DeclarationDescriptor)
fun leaveScope(owner: DeclarationDescriptor)
}
open class SymbolTable : ReferenceSymbolTable {
override val declarationSystemTable: SymbolTable = this
override val referenceSymbolTable: ReferenceSymbolTable = IrLazySymbolTable(this)
val lazyWrapper = referenceSymbolTable as IrLazySymbolTable
private abstract class SymbolTableBase<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> {
val unboundSymbols = linkedSetOf<S>()
@@ -102,7 +154,7 @@ open class SymbolTable {
override fun get(d: D): S? {
val scope = currentScope
?: throw AssertionError("No active scope")
?: throw AssertionError("No active scope")
return scope[d]
}
@@ -177,14 +229,15 @@ open class SymbolTable {
fun declareClass(
startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor,
classFactory: (IrClassSymbol) -> IrClass = { IrClassImpl(startOffset, endOffset, origin, it) }
): IrClass =
classSymbolTable.declare(
): IrClass {
return classSymbolTable.declare(
descriptor,
{ IrClassSymbolImpl(descriptor) },
classFactory
)
}
open fun referenceClass(descriptor: ClassDescriptor) =
override fun referenceClass(descriptor: ClassDescriptor) =
classSymbolTable.referenced(descriptor) { IrClassSymbolImpl(descriptor) }
val unboundClasses: Set<IrClassSymbol> get() = classSymbolTable.unboundSymbols
@@ -202,20 +255,22 @@ open class SymbolTable {
constructorFactory
)
open fun referenceConstructor(descriptor: ClassConstructorDescriptor) =
override fun referenceConstructor(descriptor: ClassConstructorDescriptor) =
constructorSymbolTable.referenced(descriptor) { IrConstructorSymbolImpl(descriptor) }
val unboundConstructors: Set<IrConstructorSymbol> get() = constructorSymbolTable.unboundSymbols
fun declareEnumEntry(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor,
factory: (IrEnumEntrySymbol) -> IrEnumEntry = { IrEnumEntryImpl(startOffset, endOffset, origin, it) }): 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) },
factory
)
open fun referenceEnumEntry(descriptor: ClassDescriptor) =
override fun referenceEnumEntry(descriptor: ClassDescriptor) =
enumEntrySymbolTable.referenced(descriptor) { IrEnumEntrySymbolImpl(descriptor) }
val unboundEnumEntries: Set<IrEnumEntrySymbol> get() = enumEntrySymbolTable.unboundSymbols
@@ -246,7 +301,7 @@ open class SymbolTable {
initializer = irInitializer
}
fun referenceField(descriptor: PropertyDescriptor) =
override fun referenceField(descriptor: PropertyDescriptor) =
fieldSymbolTable.referenced(descriptor) { IrFieldSymbolImpl(descriptor) }
val unboundFields: Set<IrFieldSymbol> get() = fieldSymbolTable.unboundSymbols
@@ -257,17 +312,18 @@ open class SymbolTable {
origin: IrDeclarationOrigin,
descriptor: FunctionDescriptor,
functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction = { IrFunctionImpl(startOffset, endOffset, origin, it) }
): IrSimpleFunction =
simpleFunctionSymbolTable.declare(
): IrSimpleFunction {
return simpleFunctionSymbolTable.declare(
descriptor,
{ IrSimpleFunctionSymbolImpl(descriptor) },
functionFactory
)
}
open fun referenceSimpleFunction(descriptor: FunctionDescriptor) =
override fun referenceSimpleFunction(descriptor: FunctionDescriptor) =
simpleFunctionSymbolTable.referenced(descriptor) { IrSimpleFunctionSymbolImpl(descriptor) }
fun referenceDeclaredFunction(descriptor: FunctionDescriptor) =
override fun referenceDeclaredFunction(descriptor: FunctionDescriptor) =
simpleFunctionSymbolTable.referenced(descriptor) { throw AssertionError("Function is not declared: $descriptor") }
val unboundSimpleFunctions: Set<IrSimpleFunctionSymbol> get() = simpleFunctionSymbolTable.unboundSymbols
@@ -276,26 +332,29 @@ open class SymbolTable {
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: TypeParameterDescriptor
descriptor: TypeParameterDescriptor,
typeParameterFactory: (IrTypeParameterSymbol) -> IrTypeParameter = { IrTypeParameterImpl(startOffset, endOffset, origin, it) }
): IrTypeParameter =
globalTypeParameterSymbolTable.declare(
descriptor,
{ IrTypeParameterSymbolImpl(descriptor) },
{ IrTypeParameterImpl(startOffset, endOffset, origin, it) }
typeParameterFactory
)
fun declareScopedTypeParameter(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: TypeParameterDescriptor
descriptor: TypeParameterDescriptor,
typeParameterFactory: (IrTypeParameterSymbol) -> IrTypeParameter = { IrTypeParameterImpl(startOffset, endOffset, origin, it) }
): IrTypeParameter =
scopedTypeParameterSymbolTable.declare(
descriptor,
{ IrTypeParameterSymbolImpl(descriptor) },
{ IrTypeParameterImpl(startOffset, endOffset, origin, it) }
typeParameterFactory
)
val unboundTypeParameters: Set<IrTypeParameterSymbol> get() = globalTypeParameterSymbolTable.unboundSymbols
fun declareValueParameter(
@@ -316,16 +375,15 @@ open class SymbolTable {
valueParameterSymbolTable.introduceLocal(irValueParameter.descriptor, irValueParameter.symbol)
}
fun referenceValueParameter(descriptor: ParameterDescriptor) =
override fun referenceValueParameter(descriptor: ParameterDescriptor) =
valueParameterSymbolTable.referenced(descriptor) {
throw AssertionError("Undefined parameter referenced: $descriptor\n${valueParameterSymbolTable.dump()}")
}
open fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol =
scopedTypeParameterSymbolTable.get(classifier)
?: globalTypeParameterSymbolTable.referenced(classifier) {
throw AssertionError("Undefined type parameter referenced: $classifier")
}
override fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol =
scopedTypeParameterSymbolTable.get(classifier) ?: globalTypeParameterSymbolTable.referenced(classifier) {
IrTypeParameterSymbolImpl(classifier)
}
val unboundValueParameters: Set<IrValueParameterSymbol> get() = valueParameterSymbolTable.unboundSymbols
@@ -354,29 +412,19 @@ open class SymbolTable {
initializer = irInitializerExpression
}
fun referenceVariable(descriptor: VariableDescriptor) =
override fun referenceVariable(descriptor: VariableDescriptor) =
variableSymbolTable.referenced(descriptor) { throw AssertionError("Undefined variable referenced: $descriptor") }
val unboundVariables: Set<IrVariableSymbol> get() = variableSymbolTable.unboundSymbols
fun enterScope(owner: DeclarationDescriptor) {
override fun enterScope(owner: DeclarationDescriptor) {
scopedSymbolTables.forEach { it.enterScope(owner) }
}
fun leaveScope(owner: DeclarationDescriptor) {
override fun leaveScope(owner: DeclarationDescriptor) {
scopedSymbolTables.forEach { it.leaveScope(owner) }
}
fun referenceFunction(callable: CallableDescriptor): IrFunctionSymbol =
when (callable) {
is ClassConstructorDescriptor ->
referenceConstructor(callable)
is FunctionDescriptor ->
referenceSimpleFunction(callable)
else ->
throw IllegalArgumentException("Unexpected callable descriptor: $callable")
}
fun referenceValue(value: ValueDescriptor): IrValueSymbol =
when (value) {
is ParameterDescriptor ->
@@ -386,16 +434,6 @@ open class SymbolTable {
else ->
throw IllegalArgumentException("Unexpected value descriptor: $value")
}
fun referenceClassifier(classifier: ClassifierDescriptor): IrClassifierSymbol =
when (classifier) {
is TypeParameterDescriptor ->
referenceTypeParameter(classifier)
is ClassDescriptor ->
referenceClass(classifier)
else ->
throw IllegalArgumentException("Unexpected classifier descriptor: $classifier")
}
}
inline fun <T> SymbolTable.withScope(owner: DeclarationDescriptor, block: SymbolTable.() -> T): T {
@@ -22,9 +22,10 @@ import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
class TypeTranslator(
private val symbolTable: SymbolTable,
private val symbolTable: ReferenceSymbolTable,
val languageVersionSettings: LanguageVersionSettings,
private val typeParametersResolver: TypeParametersResolver = ScopedTypeParametersResolver()
private val typeParametersResolver: TypeParametersResolver = ScopedTypeParametersResolver(),
private val enterTableScope: Boolean = false
) {
private val typeApproximatorForNI = TypeApproximator()
@@ -32,16 +33,22 @@ class TypeTranslator(
fun enterScope(irElement: IrTypeParametersContainer) {
typeParametersResolver.enterTypeParameterScope(irElement)
if(enterTableScope) {
symbolTable.enterScope(irElement.descriptor)
}
}
fun leaveScope() {
fun leaveScope(irElement: IrTypeParametersContainer) {
typeParametersResolver.leaveTypeParameterScope()
if(enterTableScope) {
symbolTable.leaveScope(irElement.descriptor)
}
}
inline fun <T> buildWithScope(container: IrTypeParametersContainer, builder: () -> T): T {
enterScope(container)
val result = builder()
leaveScope()
leaveScope(container)
return result
}