Remove descriptors from JvmOverloadsAnnotationLowering

This commit is contained in:
Georgy Bronnikov
2019-01-10 16:23:25 +03:00
parent f61072873f
commit 28bab6510e
2 changed files with 77 additions and 96 deletions
@@ -149,7 +149,9 @@ open class DefaultArgumentStubGenerator(
} }
// Remove default argument initializers. // Remove default argument initializers.
irFunction.valueParameters.forEach { irFunction.valueParameters.forEach {
it.defaultValue = IrExpressionBodyImpl(IrErrorExpressionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type, "Default Stub")) if (it.defaultValue != null) {
it.defaultValue = IrExpressionBodyImpl(IrErrorExpressionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type, "Default Stub"))
}
} }
return listOf(irFunction, newIrFunction) return listOf(irFunction, newIrFunction)
} }
@@ -7,33 +7,25 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.common.deepCopyWithWrappedDescriptors
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.addMember
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_OVERLOADS_FQ_NAME
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
internal val jvmOverloadsAnnotationPhase = makeIrFilePhase( internal val jvmOverloadsAnnotationPhase = makeIrFilePhase(
::JvmOverloadsAnnotationLowering, ::JvmOverloadsAnnotationLowering,
@@ -41,11 +33,13 @@ internal val jvmOverloadsAnnotationPhase = makeIrFilePhase(
description = "Handle JvmOverloads annotations" description = "Handle JvmOverloads annotations"
) )
// TODO: `IrValueParameter.defaultValue` property does not track default values in super-parameters. See KT-28637.
private class JvmOverloadsAnnotationLowering(val context: JvmBackendContext) : ClassLoweringPass { private class JvmOverloadsAnnotationLowering(val context: JvmBackendContext) : ClassLoweringPass {
override fun lower(irClass: IrClass) { override fun lower(irClass: IrClass) {
val functions = irClass.declarations.filterIsInstance<IrFunction>().filter { val functions = irClass.declarations.filterIsInstance<IrFunction>().filter {
it.descriptor.findJvmOverloadsAnnotation() != null it.hasAnnotation(JVM_OVERLOADS_FQ_NAME)
} }
functions.forEach { functions.forEach {
@@ -54,7 +48,7 @@ private class JvmOverloadsAnnotationLowering(val context: JvmBackendContext) : C
} }
private fun generateWrappers(target: IrFunction, irClass: IrClass) { private fun generateWrappers(target: IrFunction, irClass: IrClass) {
val numDefaultParameters = target.symbol.descriptor.valueParameters.count { it.hasDefaultValue() } val numDefaultParameters = target.valueParameters.count { it.defaultValue != null }
for (i in 0 until numDefaultParameters) { for (i in 0 until numDefaultParameters) {
val wrapper = generateWrapper(target, i) val wrapper = generateWrapper(target, i)
irClass.addMember(wrapper) irClass.addMember(wrapper)
@@ -62,24 +56,7 @@ private class JvmOverloadsAnnotationLowering(val context: JvmBackendContext) : C
} }
private fun generateWrapper(target: IrFunction, numDefaultParametersToExpect: Int): IrFunction { private fun generateWrapper(target: IrFunction, numDefaultParametersToExpect: Int): IrFunction {
val wrapperSymbol = generateWrapperSymbol(target.symbol, numDefaultParametersToExpect) val wrapperIrFunction = generateWrapperHeader(target, numDefaultParametersToExpect)
val wrapperIrFunction = when (wrapperSymbol) {
is IrConstructorSymbol -> IrConstructorImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
JvmLoweredDeclarationOrigin.JVM_OVERLOADS_WRAPPER,
wrapperSymbol,
returnType = target.returnType
)
is IrSimpleFunctionSymbol -> IrFunctionImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
JvmLoweredDeclarationOrigin.JVM_OVERLOADS_WRAPPER,
wrapperSymbol,
returnType = target.returnType
)
else -> error("expected IrConstructorSymbol or IrSimpleFunctionSymbol")
}
wrapperIrFunction.createParameterDeclarations()
val call = if (target is IrConstructor) val call = if (target is IrConstructor)
IrDelegatingConstructorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, target.returnType, target.symbol, target.descriptor) IrDelegatingConstructorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, target.returnType, target.symbol, target.descriptor)
@@ -101,7 +78,7 @@ private class JvmOverloadsAnnotationLowering(val context: JvmBackendContext) : C
var parametersCopied = 0 var parametersCopied = 0
var defaultParametersCopied = 0 var defaultParametersCopied = 0
for ((i, valueParameter) in target.valueParameters.withIndex()) { for ((i, valueParameter) in target.valueParameters.withIndex()) {
if ((valueParameter.descriptor as ValueParameterDescriptor).hasDefaultValue()) { if (valueParameter.defaultValue != null) {
if (defaultParametersCopied < numDefaultParametersToExpect) { if (defaultParametersCopied < numDefaultParametersToExpect) {
defaultParametersCopied++ defaultParametersCopied++
call.putValueArgument( call.putValueArgument(
@@ -130,78 +107,80 @@ private class JvmOverloadsAnnotationLowering(val context: JvmBackendContext) : C
UNDEFINED_OFFSET, UNDEFINED_OFFSET, call UNDEFINED_OFFSET, UNDEFINED_OFFSET, call
) )
target.annotations.mapTo(wrapperIrFunction.annotations) { it.deepCopyWithSymbols() }
return wrapperIrFunction return wrapperIrFunction
} }
private fun generateWrapperSymbol(oldSymbol: IrFunctionSymbol, numDefaultParametersToExpect: Int): IrFunctionSymbol { private fun generateWrapperHeader(oldFunction: IrFunction, numDefaultParametersToExpect: Int): IrFunction {
val oldDescriptor = oldSymbol.descriptor val res = when (oldFunction) {
val newDescriptor = if (oldDescriptor is ClassConstructorDescriptor) { is IrConstructor -> {
oldDescriptor.copyWithModifiedParameters(numDefaultParametersToExpect) val descriptor = WrappedClassConstructorDescriptor(oldFunction.descriptor.annotations)
} else { IrConstructorImpl(
val newParameters = generateNewValueParameters(oldDescriptor, numDefaultParametersToExpect) oldFunction.startOffset, oldFunction.endOffset,
oldDescriptor.newCopyBuilder() JvmLoweredDeclarationOrigin.JVM_OVERLOADS_WRAPPER,
.setValueParameters(newParameters) IrConstructorSymbolImpl(descriptor),
.setOriginal(null) oldFunction.name,
.setKind(CallableMemberDescriptor.Kind.SYNTHESIZED) oldFunction.visibility,
.build()!! returnType = oldFunction.returnType,
isInline = oldFunction.isInline,
isExternal = false,
isPrimary = false
).apply {
descriptor.bind(this)
}
}
is IrSimpleFunction -> {
val descriptor = WrappedSimpleFunctionDescriptor(oldFunction.descriptor.annotations)
IrFunctionImpl(
oldFunction.startOffset, oldFunction.endOffset,
JvmLoweredDeclarationOrigin.JVM_OVERLOADS_WRAPPER,
IrSimpleFunctionSymbolImpl(descriptor),
oldFunction.name,
oldFunction.visibility,
oldFunction.modality,
returnType = oldFunction.returnType,
isInline = oldFunction.isInline,
isExternal = false,
isTailrec = false,
isSuspend = oldFunction.isSuspend
).apply {
descriptor.bind(this)
}
}
else -> error("Unknown kind of IrFunction: $oldFunction")
} }
return createFunctionSymbol(newDescriptor) res.parent = oldFunction.parent
res.annotations.addAll(oldFunction.annotations.map { it.deepCopyWithWrappedDescriptors(res) })
res.copyTypeParametersFrom(oldFunction)
res.dispatchReceiverParameter = oldFunction.dispatchReceiverParameter?.copyTo(res)
res.extensionReceiverParameter = oldFunction.extensionReceiverParameter?.copyTo(res)
res.valueParameters.addAll(res.generateNewValueParameters(oldFunction, numDefaultParametersToExpect))
return res
} }
private fun ClassConstructorDescriptor.copyWithModifiedParameters(numDefaultParametersToExpect: Int): ClassConstructorDescriptor { private fun IrFunction.generateNewValueParameters(
val result = ClassConstructorDescriptorImpl.createSynthesized( oldFunction: IrFunction,
this.containingDeclaration,
annotations,
/* isPrimary = */ false,
source
)
// Call the long version of `initialize()`, because otherwise default implementation inserts
// an unwanted `dispatchReceiverParameter`.
result.initialize(
extensionReceiverParameter?.copy(result),
dispatchReceiverParameter,
typeParameters,
generateNewValueParameters(this, numDefaultParametersToExpect),
returnType,
modality,
visibility
)
return result
}
private fun generateNewValueParameters(
oldDescriptor: FunctionDescriptor,
numDefaultParametersToExpect: Int numDefaultParametersToExpect: Int
): List<ValueParameterDescriptor> { ): List<IrValueParameter> {
var parametersCopied = 0 var parametersCopied = 0
var defaultParametersCopied = 0 var defaultParametersCopied = 0
val result = mutableListOf<ValueParameterDescriptor>() val result = mutableListOf<IrValueParameter>()
for (oldValueParameter in oldDescriptor.valueParameters) { for (oldValueParameter in oldFunction.valueParameters) {
if (oldValueParameter.hasDefaultValue() && if (oldValueParameter.defaultValue != null &&
defaultParametersCopied < numDefaultParametersToExpect defaultParametersCopied < numDefaultParametersToExpect
) { ) {
defaultParametersCopied++ defaultParametersCopied++
result.add( result.add(
ValueParameterDescriptorImpl( oldValueParameter.copyTo(
oldDescriptor, // to be substituted with newDescriptor this,
null, index = parametersCopied++,
parametersCopied++, defaultValue = null,
oldValueParameter.annotations, isCrossinline = oldValueParameter.isCrossinline,
oldValueParameter.name, isNoinline = oldValueParameter.isNoinline
oldValueParameter.type,
declaresDefaultValue = false,
isCrossinline = false,
isNoinline = false,
varargElementType = oldValueParameter.varargElementType,
source = oldValueParameter.source
) )
) )
} else if (!oldValueParameter.hasDefaultValue()) { } else if (oldValueParameter.defaultValue == null) {
result.add(oldValueParameter.copy(oldDescriptor, oldValueParameter.name, parametersCopied++)) result.add(oldValueParameter.copyTo(this, index = parametersCopied++))
} }
} }
return result return result