[FIR2IR] Fix conversion of default vararg arguments for annotations

This commit is contained in:
Mikhail Glukhikh
2020-07-21 10:49:37 +03:00
parent 240baa64a5
commit 828524bde4
5 changed files with 45 additions and 33 deletions
@@ -316,16 +316,20 @@ class Fir2IrVisitor(
) )
} else convertToIrExpression(this) } else convertToIrExpression(this)
private fun convertToIrCall(functionCall: FirFunctionCall, annotationMode: Boolean): IrExpression {
val explicitReceiverExpression = convertToIrReceiverExpression(
functionCall.explicitReceiver, functionCall.calleeReference
)
return callGenerator.convertToIrCall(functionCall, functionCall.typeRef, explicitReceiverExpression, annotationMode)
}
override fun visitFunctionCall(functionCall: FirFunctionCall, data: Any?): IrExpression { override fun visitFunctionCall(functionCall: FirFunctionCall, data: Any?): IrExpression {
val convertibleCall = if (functionCall.toResolvedCallableSymbol()?.fir is FirIntegerOperator) { val convertibleCall = if (functionCall.toResolvedCallableSymbol()?.fir is FirIntegerOperator) {
functionCall.copy().transformSingle(integerApproximator, null) functionCall.copy().transformSingle(integerApproximator, null)
} else { } else {
functionCall functionCall
} }
val explicitReceiverExpression = convertToIrReceiverExpression( return convertToIrCall(functionCall = convertibleCall, annotationMode = false)
functionCall.explicitReceiver, functionCall.calleeReference
)
return callGenerator.convertToIrCall(convertibleCall, convertibleCall.typeRef, explicitReceiverExpression)
} }
override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: Any?): IrElement { override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: Any?): IrElement {
@@ -513,7 +517,7 @@ class Fir2IrVisitor(
return accept(this@Fir2IrVisitor, null) as IrStatement return accept(this@Fir2IrVisitor, null) as IrStatement
} }
internal fun convertToIrExpression(expression: FirExpression): IrExpression { internal fun convertToIrExpression(expression: FirExpression, annotationMode: Boolean = false): IrExpression {
return when (expression) { return when (expression) {
is FirBlock -> expression.convertToIrExpressionOrBlock() is FirBlock -> expression.convertToIrExpressionOrBlock()
is FirUnitExpression -> expression.convertWithOffsets { startOffset, endOffset -> is FirUnitExpression -> expression.convertWithOffsets { startOffset, endOffset ->
@@ -522,7 +526,18 @@ class Fir2IrVisitor(
this.symbolTable.referenceClass(this.irBuiltIns.builtIns.unit) this.symbolTable.referenceClass(this.irBuiltIns.builtIns.unit)
) )
} }
else -> expression.accept(this, null) as IrExpression else -> {
val unwrappedExpression = if (expression is FirWrappedArgumentExpression) {
expression.expression
} else {
expression
}
if (annotationMode && unwrappedExpression is FirFunctionCall) {
convertToIrCall(unwrappedExpression, annotationMode)
} else {
expression.accept(this, null) as IrExpression
}
}
} }
} }
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.toArrayOrPrimitiveArrayType
import org.jetbrains.kotlin.ir.util.parentClassOrNull import org.jetbrains.kotlin.ir.util.parentClassOrNull
import org.jetbrains.kotlin.psi.KtPropertyDelegate import org.jetbrains.kotlin.psi.KtPropertyDelegate
import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects
@@ -118,7 +119,8 @@ class CallAndReferenceGenerator(
fun convertToIrCall( fun convertToIrCall(
qualifiedAccess: FirQualifiedAccess, qualifiedAccess: FirQualifiedAccess,
typeRef: FirTypeRef, typeRef: FirTypeRef,
explicitReceiverExpression: IrExpression? explicitReceiverExpression: IrExpression?,
annotationMode: Boolean = false
): IrExpression { ): IrExpression {
val type = typeRef.toIrType() val type = typeRef.toIrType()
val samConstructorCall = qualifiedAccess.tryConvertToSamConstructorCall(type) val samConstructorCall = qualifiedAccess.tryConvertToSamConstructorCall(type)
@@ -200,7 +202,7 @@ class CallAndReferenceGenerator(
is IrEnumEntrySymbol -> IrGetEnumValueImpl(startOffset, endOffset, type, symbol) is IrEnumEntrySymbol -> IrGetEnumValueImpl(startOffset, endOffset, type, symbol)
else -> generateErrorCallExpression(startOffset, endOffset, qualifiedAccess.calleeReference, type) else -> generateErrorCallExpression(startOffset, endOffset, qualifiedAccess.calleeReference, type)
} }
}.applyCallArguments(qualifiedAccess as? FirCall) }.applyCallArguments(qualifiedAccess as? FirCall, annotationMode)
.applyTypeArguments(qualifiedAccess).applyReceivers(qualifiedAccess, explicitReceiverExpression) .applyTypeArguments(qualifiedAccess).applyReceivers(qualifiedAccess, explicitReceiverExpression)
} }
@@ -285,7 +287,7 @@ class CallAndReferenceGenerator(
) )
} }
} }
}.applyCallArguments(annotationCall) }.applyCallArguments(annotationCall, annotationMode = true)
} }
fun convertToGetObject(qualifier: FirResolvedQualifier): IrExpression { fun convertToGetObject(qualifier: FirResolvedQualifier): IrExpression {
@@ -315,7 +317,7 @@ class CallAndReferenceGenerator(
} }
} }
internal fun IrExpression.applyCallArguments(call: FirCall?): IrExpression { internal fun IrExpression.applyCallArguments(call: FirCall?, annotationMode: Boolean): IrExpression {
if (call == null) return this if (call == null) return this
return when (this) { return when (this) {
is IrMemberAccessExpression<*> -> { is IrMemberAccessExpression<*> -> {
@@ -333,7 +335,7 @@ class CallAndReferenceGenerator(
val argumentMapping = call.argumentMapping val argumentMapping = call.argumentMapping
if (argumentMapping != null && argumentMapping.isNotEmpty()) { if (argumentMapping != null && argumentMapping.isNotEmpty()) {
if (valueParameters != null) { if (valueParameters != null) {
return applyArgumentsWithReorderingIfNeeded(call, argumentMapping, valueParameters) return applyArgumentsWithReorderingIfNeeded(call, argumentMapping, valueParameters, annotationMode)
} }
} }
for ((index, argument) in call.arguments.withIndex()) { for ((index, argument) in call.arguments.withIndex()) {
@@ -367,10 +369,11 @@ class CallAndReferenceGenerator(
call: FirCall, call: FirCall,
argumentMapping: Map<FirExpression, FirValueParameter>, argumentMapping: Map<FirExpression, FirValueParameter>,
valueParameters: List<FirValueParameter>, valueParameters: List<FirValueParameter>,
annotationMode: Boolean
): IrExpression { ): IrExpression {
// Assuming compile-time constants only inside annotation, we don't need a block to reorder arguments to preserve semantics. // Assuming compile-time constants only inside annotation, we don't need a block to reorder arguments to preserve semantics.
// But, we still need to pick correct indices for named arguments. // But, we still need to pick correct indices for named arguments.
if (call !is FirAnnotationCall && if (!annotationMode &&
needArgumentReordering(argumentMapping.values, valueParameters) needArgumentReordering(argumentMapping.values, valueParameters)
) { ) {
return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply { return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply {
@@ -391,9 +394,21 @@ class CallAndReferenceGenerator(
} }
} else { } else {
for ((argument, parameter) in argumentMapping) { for ((argument, parameter) in argumentMapping) {
val argumentExpression = visitor.convertToIrExpression(argument).applySamConversionIfNeeded(argument, parameter) val argumentExpression =
visitor.convertToIrExpression(argument, annotationMode)
.applySamConversionIfNeeded(argument, parameter)
putValueArgument(valueParameters.indexOf(parameter), argumentExpression) putValueArgument(valueParameters.indexOf(parameter), argumentExpression)
} }
if (annotationMode) {
for ((index, parameter) in valueParameters.withIndex()) {
if (parameter.isVararg && !argumentMapping.containsValue(parameter)) {
val elementType = parameter.returnTypeRef.toIrType()
putValueArgument(
index, IrVarargImpl(-1, -1, elementType, elementType.toArrayOrPrimitiveArrayType(irBuiltIns))
)
}
}
}
return this return this
} }
} }
@@ -347,7 +347,7 @@ internal class ClassMemberGenerator(
it.dispatchReceiver = visitor.convertToIrExpression(firDispatchReceiver) it.dispatchReceiver = visitor.convertToIrExpression(firDispatchReceiver)
} }
with(callGenerator) { with(callGenerator) {
it.applyCallArguments(this@toIrDelegatingConstructorCall) it.applyCallArguments(this@toIrDelegatingConstructorCall, annotationMode = false)
} }
} }
} }
@@ -1,19 +0,0 @@
FILE fqName:<root> fileName:/deprecated.kt
FUN name:create visibility:public modality:FINAL <> () returnType:kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun create (): kotlin.String declared in <root>'
CONST String type=kotlin.String value="OK"
FUN name:create visibility:public modality:FINAL <> (s:kotlin.String) returnType:kotlin.String
annotations:
Deprecated(message = 'Use create() instead()', replaceWith = ReplaceWith(expression = 'create()', imports = <null>), level = <null>)
VALUE_PARAMETER name:s index:0 type:kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun create (s: kotlin.String): kotlin.String declared in <root>'
CALL 'public final fun create (): kotlin.String declared in <root>' type=kotlin.String origin=null
FUN name:create visibility:public modality:FINAL <> (b:kotlin.Boolean) returnType:kotlin.String
annotations:
Deprecated(message = 'Use create() instead()', replaceWith = <null>, level = <null>)
VALUE_PARAMETER name:b index:0 type:kotlin.Boolean
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun create (b: kotlin.Boolean): kotlin.String declared in <root>'
CALL 'public final fun create (): kotlin.String declared in <root>' type=kotlin.String origin=null
+1
View File
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// WITH_RUNTIME // WITH_RUNTIME
fun create() = "OK" fun create() = "OK"