[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)
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
}
}
}
}
@@ -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<FirExpression, FirValueParameter>,
valueParameters: List<FirValueParameter>,
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
}
}
@@ -347,7 +347,7 @@ internal class ClassMemberGenerator(
it.dispatchReceiver = visitor.convertToIrExpression(firDispatchReceiver)
}
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
fun create() = "OK"