Allow IrConstTransformer to visit and evaluate vararg elements

This commit is contained in:
Ivan Kylchik
2020-06-26 14:43:42 +03:00
parent 6fa03297f9
commit de2b20482a
4 changed files with 27 additions and 11 deletions
@@ -55,19 +55,37 @@ class IrConstTransformer(irModuleFragment: IrModuleFragment) : IrElementTransfor
}
private fun transformAnnotations(annotationContainer: IrAnnotationContainer) {
annotationContainer.annotations.forEach {
for (i in 0 until it.valueArgumentsCount) {
val arg = it.getValueArgument(i) ?: continue
if (arg.accept(IrCompileTimeChecker(mode = EvaluationMode.ONLY_BUILTINS), null)) {
val const = interpreter.interpret(arg).replaceIfError(arg)
it.putValueArgument(i, const.convertToConstIfPossible(it.symbol.owner.valueParameters[i].type))
annotationContainer.annotations.forEach { annotation ->
// TODO this check can be removed after fix with annotation call arguments mapping
if ((0 until annotation.valueArgumentsCount).any { annotation.getValueArgument(it) == null }) return@forEach
for (i in 0 until annotation.valueArgumentsCount) {
val arg = annotation.getValueArgument(i) ?: continue
when (arg) {
is IrVararg -> arg.transformVarArg()
else -> annotation.putValueArgument(i, arg.transformSingleArg(annotation.symbol.owner.valueParameters[i].type))
}
}
}
}
private fun IrVararg.transformVarArg() {
for (i in this.elements.indices) {
val irVarargElement = this.elements[i] as? IrExpression ?: continue
this.putElement(i, irVarargElement.transformSingleArg(this.varargElementType))
}
}
private fun IrExpression.transformSingleArg(expectedType: IrType): IrExpression {
if (this.accept(IrCompileTimeChecker(mode = EvaluationMode.ONLY_BUILTINS), null)) {
val const = interpreter.interpret(this).replaceIfError(this)
return const.convertToConstIfPossible(expectedType)
}
return this
}
private fun IrExpression.convertToConstIfPossible(type: IrType): IrExpression {
if (this !is IrConst<*>) return this
if (this !is IrConst<*> || type is IrErrorType) return this
if (type.isArray()) return this.convertToConstIfPossible((type as IrSimpleType).arguments.single().typeOrNull!!)
return this.value.toIrConst(type, this.startOffset, this.endOffset)
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_REFLECT
// TARGET_BACKEND: JVM
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not
@@ -38,9 +38,9 @@ FILE fqName:<root> fileName:/constExpressionsInAnnotationArguments.kt
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit
annotations:
A(x = CALL 'public final fun <get-ONE> (): kotlin.Int declared in <root>' type=kotlin.Int origin=GET_PROPERTY)
A(x = '1')
BLOCK_BODY
FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.Unit
annotations:
A(x = CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null)
A(x = '2')
BLOCK_BODY