Generate type parameter declarations for property accessors

This requires "scoped" type parameter symbols, because in the ugly world
of descriptors property accessors have no type parameters of their own.
This commit is contained in:
Dmitry Petrov
2018-03-02 13:12:01 +03:00
parent 31996f1139
commit 13a7270129
16 changed files with 473 additions and 44 deletions
@@ -59,7 +59,7 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
irClass.descriptor.thisAsReceiverParameter
)
declarationGenerator.generateTypeParameterDeclarations(irClass, descriptor.declaredTypeParameters)
declarationGenerator.generateGlobalTypeParametersDeclarations(irClass, descriptor.declaredTypeParameters)
val irPrimaryConstructor = generatePrimaryConstructor(irClass, ktClassOrObject)
if (irPrimaryConstructor != null) {
@@ -75,31 +75,63 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
)
fun generateTypeParameterDeclarations(
fun generateGlobalTypeParametersDeclarations(
irTypeParametersOwner: IrTypeParametersContainer,
from: List<TypeParameterDescriptor>
) {
generateTypeParameterDeclarations(irTypeParametersOwner, from) { startOffset, endOffset, typeParameterDescriptor ->
context.symbolTable.declareGlobalTypeParameter(
startOffset,
endOffset,
IrDeclarationOrigin.DEFINED,
typeParameterDescriptor
)
}
}
fun generateScopedTypeParameterDeclarations(
irTypeParametersOwner: IrTypeParametersContainer,
from: List<TypeParameterDescriptor>
) {
generateTypeParameterDeclarations(irTypeParametersOwner, from) { startOffset, endOffset, typeParameterDescriptor ->
context.symbolTable.declareScopedTypeParameter(
startOffset,
endOffset,
IrDeclarationOrigin.DEFINED,
typeParameterDescriptor
)
}
}
private fun generateTypeParameterDeclarations(
irTypeParametersOwner: IrTypeParametersContainer,
from: List<TypeParameterDescriptor>,
declareTypeParameter: (Int, Int, TypeParameterDescriptor) -> IrTypeParameter
) {
from.mapTo(irTypeParametersOwner.typeParameters) { typeParameterDescriptor ->
val ktTypeParameterDeclaration = DescriptorToSourceUtils.getSourceFromDescriptor(typeParameterDescriptor)
val startOffset = ktTypeParameterDeclaration.startOffsetOrUndefined
val endOffset = ktTypeParameterDeclaration.endOffsetOrUndefined
declareTypeParameterWithSuperClassifiers(startOffset, endOffset, IrDeclarationOrigin.DEFINED, typeParameterDescriptor)
declareTypeParameter(
startOffset,
endOffset,
typeParameterDescriptor
).also { irTypeParameter ->
mapSuperClassifiers(typeParameterDescriptor, irTypeParameter)
}
}
}
private fun declareTypeParameterWithSuperClassifiers(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: TypeParameterDescriptor
) =
context.symbolTable.declareTypeParameter(startOffset, endOffset, origin, descriptor).also { irTypeParameter ->
descriptor.typeConstructor.supertypes.mapNotNullTo(irTypeParameter.superClassifiers) {
it.constructor.declarationDescriptor?.let {
context.symbolTable.referenceClassifier(it)
}
private fun mapSuperClassifiers(
descriptor: TypeParameterDescriptor,
irTypeParameter: IrTypeParameter
) {
descriptor.typeConstructor.supertypes.mapNotNullTo(irTypeParameter.superClassifiers) {
it.constructor.declarationDescriptor?.let {
context.symbolTable.referenceClassifier(it)
}
}
}
fun generateInitializerBody(scopeOwnerSymbol: IrSymbol, ktBody: KtExpression): IrExpressionBody =
createBodyGenerator(scopeOwnerSymbol).generateExpressionBody(ktBody)
@@ -83,7 +83,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
ktParameterOwner: KtElement?,
ktReceiverParameterElement: KtElement?
) {
declarationGenerator.generateTypeParameterDeclarations(irFunction, irFunction.descriptor.typeParameters)
declarationGenerator.generateScopedTypeParameterDeclarations(irFunction, irFunction.descriptor.typeParameters)
generateValueParameterDeclarations(irFunction, ktParameterOwner, ktReceiverParameterElement)
}
@@ -98,6 +98,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
if (ktAccessor != null) IrDeclarationOrigin.DEFINED else IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR,
descriptor
).buildWithScope { irAccessor ->
declarationGenerator.generateScopedTypeParameterDeclarations(irAccessor, descriptor.correspondingProperty.typeParameters)
generateFunctionParameterDeclarations(irAccessor, ktAccessor ?: ktProperty, ktProperty.receiverTypeReference)
val ktBodyExpression = ktAccessor?.bodyExpression
irAccessor.body =
@@ -117,7 +118,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR,
descriptor
).buildWithScope { irAccessor ->
declarationGenerator.generateTypeParameterDeclarations(irAccessor, descriptor.typeParameters)
declarationGenerator.generateScopedTypeParameterDeclarations(irAccessor, descriptor.typeParameters)
FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irAccessor)
irAccessor.body = generateDefaultAccessorBody(ktParameter, descriptor, irAccessor)
}
@@ -229,7 +230,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
}
fun generateSyntheticFunctionParameterDeclarations(irFunction: IrFunction) {
declarationGenerator.generateTypeParameterDeclarations(irFunction, irFunction.descriptor.typeParameters)
declarationGenerator.generateGlobalTypeParametersDeclarations(irFunction, irFunction.descriptor.typeParameters)
generateValueParameterDeclarations(irFunction, null, null, withDefaultValues = false)
}
@@ -17,13 +17,17 @@
package org.jetbrains.kotlin.psi2ir.transformations
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.psi2ir.containsNull
@@ -33,12 +37,43 @@ import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.isNullabilityFlexible
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.upperIfFlexible
import java.util.*
fun insertImplicitCasts(builtIns: KotlinBuiltIns, element: IrElement, symbolTable: SymbolTable) {
element.transformChildren(InsertImplicitCasts(builtIns, symbolTable), null)
}
class InsertImplicitCasts(private val builtIns: KotlinBuiltIns, private val symbolTable: SymbolTable) : IrElementTransformerVoid() {
private val typeParameterScopes = ArrayDeque<Map<TypeParameterDescriptor, IrTypeParameterSymbol>>()
private inline fun <T> runInTypeParameterScope(typeParametersContainer: IrTypeParametersContainer, fn: () -> T): T {
enterTypeParameterScope(typeParametersContainer)
val result = fn()
leaveTypeParameterScope()
return result
}
private fun enterTypeParameterScope(typeParametersContainer: IrTypeParametersContainer) {
typeParameterScopes.addFirst(
typeParametersContainer.typeParameters.associate {
it.descriptor to it.symbol
}
)
}
private fun leaveTypeParameterScope() {
typeParameterScopes.removeFirst()
}
private fun resolveScopedTypeParameter(classifier: ClassifierDescriptor): IrTypeParameterSymbol? {
if (classifier !is TypeParameterDescriptor) return null
for (scope in typeParameterScopes) {
val local = scope[classifier]
if (local != null) return local
}
return null
}
override fun visitCallableReference(expression: IrCallableReference): IrExpression =
expression.transformPostfix {
transformReceiverArguments()
@@ -110,9 +145,11 @@ class InsertImplicitCasts(private val builtIns: KotlinBuiltIns, private val symb
}
override fun visitFunction(declaration: IrFunction): IrStatement =
declaration.transformPostfix {
valueParameters.forEach {
it.defaultValue?.coerceInnerExpression(it.descriptor.type)
runInTypeParameterScope(declaration) {
declaration.transformPostfix {
valueParameters.forEach {
it.defaultValue?.coerceInnerExpression(it.descriptor.type)
}
}
}
@@ -205,7 +242,7 @@ class InsertImplicitCasts(private val builtIns: KotlinBuiltIns, private val symb
return IrTypeOperatorCallImpl(
startOffset, endOffset,
targetType, typeOperator, targetType, this,
symbolTable.referenceClassifier(typeDescriptor)
resolveScopedTypeParameter(typeDescriptor) ?: symbolTable.referenceClassifier(typeDescriptor)
)
}
@@ -154,9 +154,15 @@ open class DeepCopyIrTree : IrElementTransformerVoid() {
}
}
private fun FunctionDescriptor.getTypeParametersToTransform() =
when {
this is PropertyAccessorDescriptor -> correspondingProperty.typeParameters
else -> typeParameters
}
protected fun <T : IrFunction> T.transformParameters(original: T): T =
apply {
transformTypeParameters(original, descriptor.typeParameters)
transformTypeParameters(original, descriptor.getTypeParametersToTransform())
transformValueParameters(original)
}
@@ -29,7 +29,7 @@ class SymbolTable {
private abstract class SymbolTableBase<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> {
val unboundSymbols = linkedSetOf<S>()
protected abstract fun get(d: D): S?
abstract fun get(d: D): S?
protected abstract fun set(d: D, s: S)
inline fun declare(d: D, createSymbol: () -> S, createOwner: (S) -> B): B {
@@ -45,10 +45,10 @@ class SymbolTable {
return createOwner(symbol)
}
inline fun referenced(d: D, createSymbol: () -> S): S {
inline fun referenced(d: D, orElse: () -> S): S {
val s = get(d)
if (s == null) {
val new = createSymbol()
val new = orElse()
assert(unboundSymbols.add(new)) {
"Symbol for ${new.descriptor} was already referenced"
}
@@ -149,10 +149,11 @@ class SymbolTable {
private val fieldSymbolTable = FlatSymbolTable<PropertyDescriptor, IrField, IrFieldSymbol>()
private val simpleFunctionSymbolTable = FlatSymbolTable<FunctionDescriptor, IrSimpleFunction, IrSimpleFunctionSymbol>()
private val typeParameterSymbolTable = FlatSymbolTable<TypeParameterDescriptor, IrTypeParameter, IrTypeParameterSymbol>()
private val globalTypeParameterSymbolTable = FlatSymbolTable<TypeParameterDescriptor, IrTypeParameter, IrTypeParameterSymbol>()
private val scopedTypeParameterSymbolTable = ScopedSymbolTable<TypeParameterDescriptor, IrTypeParameter, IrTypeParameterSymbol>()
private val valueParameterSymbolTable = ScopedSymbolTable<ParameterDescriptor, IrValueParameter, IrValueParameterSymbol>()
private val variableSymbolTable = ScopedSymbolTable<VariableDescriptor, IrVariable, IrVariableSymbol>()
private val scopedSymbolTables = listOf(valueParameterSymbolTable, variableSymbolTable)
private val scopedSymbolTables = listOf(valueParameterSymbolTable, variableSymbolTable, scopedTypeParameterSymbolTable)
fun declareFile(fileEntry: SourceManager.FileEntry, packageFragmentDescriptor: PackageFragmentDescriptor): IrFile =
IrFileImpl(fileEntry, IrFileSymbolImpl(packageFragmentDescriptor))
@@ -250,22 +251,31 @@ class SymbolTable {
val unboundSimpleFunctions: Set<IrSimpleFunctionSymbol> get() = simpleFunctionSymbolTable.unboundSymbols
fun declareTypeParameter(
fun declareGlobalTypeParameter(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: TypeParameterDescriptor
): IrTypeParameter =
typeParameterSymbolTable.declare(
globalTypeParameterSymbolTable.declare(
descriptor,
{ IrTypeParameterSymbolImpl(descriptor) },
{ IrTypeParameterImpl(startOffset, endOffset, origin, it) }
)
fun referenceTypeParameter(descriptor: TypeParameterDescriptor) =
typeParameterSymbolTable.referenced(descriptor) { throw AssertionError("Undefined type parameter referenced: $descriptor") }
fun declareScopedTypeParameter(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: TypeParameterDescriptor
): IrTypeParameter =
scopedTypeParameterSymbolTable.declare(
descriptor,
{ IrTypeParameterSymbolImpl(descriptor) },
{ IrTypeParameterImpl(startOffset, endOffset, origin, it) }
)
val unboundTypeParameters: Set<IrTypeParameterSymbol> get() = typeParameterSymbolTable.unboundSymbols
val unboundTypeParameters: Set<IrTypeParameterSymbol> get() = globalTypeParameterSymbolTable.unboundSymbols
fun declareValueParameter(
startOffset: Int,
@@ -288,6 +298,12 @@ class SymbolTable {
throw AssertionError("Undefined parameter referenced: $descriptor\n${valueParameterSymbolTable.dump()}")
}
fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol =
scopedTypeParameterSymbolTable.get(classifier)
?: globalTypeParameterSymbolTable.referenced(classifier) {
throw AssertionError("Undefined type parameter referenced: $classifier")
}
val unboundValueParameters: Set<IrValueParameterSymbol> get() = valueParameterSymbolTable.unboundSymbols
fun declareVariable(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: VariableDescriptor): IrVariable =
@@ -342,9 +358,7 @@ class SymbolTable {
fun referenceClassifier(classifier: ClassifierDescriptor): IrClassifierSymbol =
when (classifier) {
is TypeParameterDescriptor ->
typeParameterSymbolTable.referenced(classifier) {
throw AssertionError("Undefined type parameter referenced: $classifier")
}
referenceTypeParameter(classifier)
is ClassDescriptor ->
classSymbolTable.referenced(classifier) { IrClassSymbolImpl(classifier) }
else ->