[K2] Support interpretation of values in type annotations

#KT-57812
This commit is contained in:
Ivan Kylchik
2023-04-20 11:44:47 +02:00
committed by Space Team
parent 846ad95c9e
commit d26e3871ba
18 changed files with 324 additions and 26 deletions
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.ir.interpreter.checker
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
@@ -19,7 +16,7 @@ import org.jetbrains.kotlin.ir.interpreter.isPrimitiveArray
import org.jetbrains.kotlin.ir.interpreter.toIrConst
import org.jetbrains.kotlin.ir.types.*
internal class IrConstAnnotationTransformer(
internal abstract class IrConstAnnotationTransformer(
interpreter: IrInterpreter,
irFile: IrFile,
mode: EvaluationMode,
@@ -28,17 +25,7 @@ internal class IrConstAnnotationTransformer(
onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
suppressExceptions: Boolean,
) : IrConstTransformer(interpreter, irFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions) {
override fun visitField(declaration: IrField): IrStatement {
transformAnnotations(declaration)
return super.visitField(declaration)
}
override fun visitDeclaration(declaration: IrDeclarationBase): IrStatement {
transformAnnotations(declaration)
return super.visitDeclaration(declaration)
}
private fun transformAnnotations(annotationContainer: IrAnnotationContainer) {
protected fun transformAnnotations(annotationContainer: IrAnnotationContainer) {
annotationContainer.annotations.forEach { annotation ->
transformAnnotation(annotation)
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.interpreter.checker
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrErrorExpression
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
internal class IrConstDeclarationAnnotationTransformer(
interpreter: IrInterpreter,
irFile: IrFile,
mode: EvaluationMode,
evaluatedConstTracker: EvaluatedConstTracker?,
onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit,
onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
suppressExceptions: Boolean,
) : IrConstAnnotationTransformer(interpreter, irFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions) {
override fun visitDeclaration(declaration: IrDeclarationBase, data: Nothing?): IrStatement {
transformAnnotations(declaration)
return super.visitDeclaration(declaration, data)
}
}
@@ -26,27 +26,27 @@ internal class IrConstExpressionTransformer(
onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
suppressExceptions: Boolean,
) : IrConstTransformer(interpreter, irFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions) {
override fun visitCall(expression: IrCall): IrExpression {
override fun visitCall(expression: IrCall, data: Nothing?): IrElement {
if (expression.canBeInterpreted()) {
return expression.interpret(failAsError = false)
}
return super.visitCall(expression)
return super.visitCall(expression, data)
}
override fun visitField(declaration: IrField): IrStatement {
override fun visitField(declaration: IrField, data: Nothing?): IrStatement {
val initializer = declaration.initializer
val expression = initializer?.expression ?: return declaration
val isConst = declaration.correspondingPropertySymbol?.owner?.isConst == true
if (!isConst) return super.visitField(declaration)
if (!isConst) return super.visitField(declaration, data)
if (expression.canBeInterpreted(declaration, interpreter.environment.configuration.copy(treatFloatInSpecialWay = false))) {
initializer.expression = expression.interpret(failAsError = true)
}
return super.visitField(declaration)
return super.visitField(declaration, data)
}
override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression {
override fun visitStringConcatenation(expression: IrStringConcatenation, data: Nothing?): IrExpression {
fun IrExpression.wrapInStringConcat(): IrExpression = IrStringConcatenationImpl(
this.startOffset, this.endOffset, expression.type, listOf(this@wrapInStringConcat)
)
@@ -18,13 +18,13 @@ import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
import org.jetbrains.kotlin.ir.interpreter.toConstantValue
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.name.Name
fun IrFile.transformConst(
interpreter: IrInterpreter,
mode: EvaluationMode,
evaluatedConstTracker: EvaluatedConstTracker?,
evaluatedConstTracker: EvaluatedConstTracker? = null,
onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
suppressExceptions: Boolean = false,
@@ -32,13 +32,19 @@ fun IrFile.transformConst(
val irConstExpressionTransformer = IrConstExpressionTransformer(
interpreter, this, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions
)
val irConstAnnotationTransformer = IrConstAnnotationTransformer(
val irConstDeclarationAnnotationTransformer = IrConstDeclarationAnnotationTransformer(
interpreter, this, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions
)
val irConstTypeAnnotationTransformer = IrConstTypeAnnotationTransformer(
interpreter, this, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions
)
this.transform(irConstExpressionTransformer, null)
this.transform(irConstAnnotationTransformer, null)
this.transform(irConstDeclarationAnnotationTransformer, null)
this.transform(irConstTypeAnnotationTransformer, null)
}
// Note: We are using `IrElementTransformer` here instead of `IrElementTransformerVoid` to avoid conflicts with `IrTypeVisitorVoid`
// that is used later in `IrConstTypeAnnotationTransformer`.
internal abstract class IrConstTransformer(
protected val interpreter: IrInterpreter,
private val irFile: IrFile,
@@ -47,7 +53,7 @@ internal abstract class IrConstTransformer(
private val onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit,
private val onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
private val suppressExceptions: Boolean,
) : IrElementTransformerVoid() {
) : IrElementTransformer<Nothing?> {
private fun IrExpression.warningIfError(original: IrExpression): IrExpression {
if (this is IrErrorExpression) {
onWarning(irFile, original, this)
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.interpreter.checker
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.visitors.IrTypeTransformerVoid
internal class IrConstTypeAnnotationTransformer(
interpreter: IrInterpreter,
irFile: IrFile,
mode: EvaluationMode,
evaluatedConstTracker: EvaluatedConstTracker?,
onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit,
onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
suppressExceptions: Boolean,
) : IrConstAnnotationTransformer(interpreter, irFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions),
IrTypeTransformerVoid<Nothing?> {
override fun <Type : IrType?> transformType(container: IrElement, type: Type, data: Nothing?): Type {
if (type == null) return type
transformAnnotations(type)
if (type is IrSimpleType) {
type.arguments.mapNotNull { it.typeOrNull }.forEach { transformType(container, it, data) }
}
return type
}
}