From 828524bde43b3ccc75715e0bed99b38f6684f831 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 21 Jul 2020 10:49:37 +0300 Subject: [PATCH] [FIR2IR] Fix conversion of default vararg arguments for annotations --- .../kotlin/fir/backend/Fir2IrVisitor.kt | 27 +++++++++++++---- .../generators/CallAndReferenceGenerator.kt | 29 ++++++++++++++----- .../generators/ClassMemberGenerator.kt | 2 +- .../ir/irText/firProblems/deprecated.fir.txt | 19 ------------ .../ir/irText/firProblems/deprecated.kt | 1 + 5 files changed, 45 insertions(+), 33 deletions(-) delete mode 100644 compiler/testData/ir/irText/firProblems/deprecated.fir.txt diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index b3971e106fc..294381f5271 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -316,16 +316,20 @@ class Fir2IrVisitor( ) } 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 { val convertibleCall = if (functionCall.toResolvedCallableSymbol()?.fir is FirIntegerOperator) { functionCall.copy().transformSingle(integerApproximator, null) } else { functionCall } - val explicitReceiverExpression = convertToIrReceiverExpression( - functionCall.explicitReceiver, functionCall.calleeReference - ) - return callGenerator.convertToIrCall(convertibleCall, convertibleCall.typeRef, explicitReceiverExpression) + return convertToIrCall(functionCall = convertibleCall, annotationMode = false) } override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: Any?): IrElement { @@ -513,7 +517,7 @@ class Fir2IrVisitor( 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) { is FirBlock -> expression.convertToIrExpressionOrBlock() is FirUnitExpression -> expression.convertWithOffsets { startOffset, endOffset -> @@ -522,7 +526,18 @@ class Fir2IrVisitor( 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 + } + } } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index d756792876e..7d35e935a70 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.IrType 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.psi.KtPropertyDelegate import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects @@ -118,7 +119,8 @@ class CallAndReferenceGenerator( fun convertToIrCall( qualifiedAccess: FirQualifiedAccess, typeRef: FirTypeRef, - explicitReceiverExpression: IrExpression? + explicitReceiverExpression: IrExpression?, + annotationMode: Boolean = false ): IrExpression { val type = typeRef.toIrType() val samConstructorCall = qualifiedAccess.tryConvertToSamConstructorCall(type) @@ -200,7 +202,7 @@ class CallAndReferenceGenerator( is IrEnumEntrySymbol -> IrGetEnumValueImpl(startOffset, endOffset, type, symbol) else -> generateErrorCallExpression(startOffset, endOffset, qualifiedAccess.calleeReference, type) } - }.applyCallArguments(qualifiedAccess as? FirCall) + }.applyCallArguments(qualifiedAccess as? FirCall, annotationMode) .applyTypeArguments(qualifiedAccess).applyReceivers(qualifiedAccess, explicitReceiverExpression) } @@ -285,7 +287,7 @@ class CallAndReferenceGenerator( ) } } - }.applyCallArguments(annotationCall) + }.applyCallArguments(annotationCall, annotationMode = true) } 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 return when (this) { is IrMemberAccessExpression<*> -> { @@ -333,7 +335,7 @@ class CallAndReferenceGenerator( val argumentMapping = call.argumentMapping if (argumentMapping != null && argumentMapping.isNotEmpty()) { if (valueParameters != null) { - return applyArgumentsWithReorderingIfNeeded(call, argumentMapping, valueParameters) + return applyArgumentsWithReorderingIfNeeded(call, argumentMapping, valueParameters, annotationMode) } } for ((index, argument) in call.arguments.withIndex()) { @@ -367,10 +369,11 @@ class CallAndReferenceGenerator( call: FirCall, argumentMapping: Map, valueParameters: List, + annotationMode: Boolean ): IrExpression { // 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. - if (call !is FirAnnotationCall && + if (!annotationMode && needArgumentReordering(argumentMapping.values, valueParameters) ) { return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply { @@ -391,9 +394,21 @@ class CallAndReferenceGenerator( } } else { 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) } + 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 } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt index dfa4e979c2d..fcbebeb83ff 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt @@ -347,7 +347,7 @@ internal class ClassMemberGenerator( it.dispatchReceiver = visitor.convertToIrExpression(firDispatchReceiver) } with(callGenerator) { - it.applyCallArguments(this@toIrDelegatingConstructorCall) + it.applyCallArguments(this@toIrDelegatingConstructorCall, annotationMode = false) } } } diff --git a/compiler/testData/ir/irText/firProblems/deprecated.fir.txt b/compiler/testData/ir/irText/firProblems/deprecated.fir.txt deleted file mode 100644 index 9506401baea..00000000000 --- a/compiler/testData/ir/irText/firProblems/deprecated.fir.txt +++ /dev/null @@ -1,19 +0,0 @@ -FILE fqName: 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 ' - 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 = ), level = ) - 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 ' - CALL 'public final fun create (): kotlin.String declared in ' 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 = , level = ) - 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 ' - CALL 'public final fun create (): kotlin.String declared in ' type=kotlin.String origin=null diff --git a/compiler/testData/ir/irText/firProblems/deprecated.kt b/compiler/testData/ir/irText/firProblems/deprecated.kt index c71316aeb93..0640c5aecb7 100644 --- a/compiler/testData/ir/irText/firProblems/deprecated.kt +++ b/compiler/testData/ir/irText/firProblems/deprecated.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // WITH_RUNTIME fun create() = "OK"