[IR] Drop all explicit usages of EvaluationMode from interpreter checker
This commit is contained in:
@@ -35,7 +35,6 @@ import kotlin.math.floor
|
|||||||
val intrinsicConstEvaluationAnnotation = FqName("kotlin.internal.IntrinsicConstEvaluation")
|
val intrinsicConstEvaluationAnnotation = FqName("kotlin.internal.IntrinsicConstEvaluation")
|
||||||
val compileTimeAnnotation = FqName("kotlin.CompileTimeCalculation")
|
val compileTimeAnnotation = FqName("kotlin.CompileTimeCalculation")
|
||||||
val evaluateIntrinsicAnnotation = FqName("kotlin.EvaluateIntrinsic")
|
val evaluateIntrinsicAnnotation = FqName("kotlin.EvaluateIntrinsic")
|
||||||
val contractsDslAnnotation = FqName("kotlin.internal.ContractsDsl")
|
|
||||||
|
|
||||||
internal val IrElement.fqName: String
|
internal val IrElement.fqName: String
|
||||||
get() = (this as? IrDeclarationWithName)?.fqNameWhenAvailable?.asString() ?: ""
|
get() = (this as? IrDeclarationWithName)?.fqNameWhenAvailable?.asString() ?: ""
|
||||||
|
|||||||
+34
-24
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.interpreter.*
|
import org.jetbrains.kotlin.ir.interpreter.*
|
||||||
import org.jetbrains.kotlin.ir.interpreter.hasAnnotation
|
import org.jetbrains.kotlin.ir.interpreter.hasAnnotation
|
||||||
import org.jetbrains.kotlin.ir.types.isAny
|
|
||||||
import org.jetbrains.kotlin.ir.types.isPrimitiveType
|
import org.jetbrains.kotlin.ir.types.isPrimitiveType
|
||||||
import org.jetbrains.kotlin.ir.types.isString
|
import org.jetbrains.kotlin.ir.types.isString
|
||||||
import org.jetbrains.kotlin.ir.types.isUnsignedType
|
import org.jetbrains.kotlin.ir.types.isUnsignedType
|
||||||
@@ -19,14 +18,23 @@ import org.jetbrains.kotlin.ir.util.*
|
|||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
enum class EvaluationMode(protected val mustCheckBody: Boolean) {
|
enum class EvaluationMode {
|
||||||
FULL(mustCheckBody = true) {
|
FULL {
|
||||||
override fun canEvaluateFunction(function: IrFunction, context: IrCall?): Boolean = true
|
override fun canEvaluateFunction(function: IrFunction, context: IrCall?): Boolean = true
|
||||||
override fun canEvaluateEnumValue(enumEntry: IrGetEnumValue, context: IrCall?): Boolean = true
|
override fun canEvaluateEnumValue(enumEntry: IrGetEnumValue, context: IrCall?): Boolean = true
|
||||||
override fun canEvaluateReference(reference: IrCallableReference<*>, context: IrCall?): Boolean = true
|
override fun canEvaluateFunctionExpression(expression: IrFunctionExpression, context: IrCall?): Boolean = true
|
||||||
|
override fun canEvaluateCallableReference(reference: IrCallableReference<*>, context: IrCall?): Boolean = true
|
||||||
|
override fun canEvaluateClassReference(reference: IrDeclarationReference): Boolean = true
|
||||||
|
|
||||||
|
override fun canEvaluateBlock(block: IrBlock): Boolean = true
|
||||||
|
override fun canEvaluateComposite(composite: IrComposite): Boolean = true
|
||||||
|
|
||||||
|
override fun canEvaluateExpression(expression: IrExpression): Boolean = true
|
||||||
|
|
||||||
|
override fun mustCheckBodyOf(function: IrFunction): Boolean = true
|
||||||
},
|
},
|
||||||
|
|
||||||
ONLY_BUILTINS(mustCheckBody = false) {
|
ONLY_BUILTINS {
|
||||||
private val allowedMethodsOnPrimitives = setOf(
|
private val allowedMethodsOnPrimitives = setOf(
|
||||||
"not", "unaryMinus", "unaryPlus", "inv",
|
"not", "unaryMinus", "unaryPlus", "inv",
|
||||||
"toString", "toChar", "toByte", "toShort", "toInt", "toLong", "toFloat", "toDouble",
|
"toString", "toChar", "toByte", "toShort", "toInt", "toLong", "toFloat", "toDouble",
|
||||||
@@ -59,20 +67,21 @@ enum class EvaluationMode(protected val mustCheckBody: Boolean) {
|
|||||||
parentType == null -> fqName in allowedExtensionFunctions || fqName in allowedBuiltinExtensionFunctions
|
parentType == null -> fqName in allowedExtensionFunctions || fqName in allowedBuiltinExtensionFunctions
|
||||||
parentType.isPrimitiveType() -> function.name.asString() in allowedMethodsOnPrimitives
|
parentType.isPrimitiveType() -> function.name.asString() in allowedMethodsOnPrimitives
|
||||||
parentType.isString() -> function.name.asString() in allowedMethodsOnStrings
|
parentType.isString() -> function.name.asString() in allowedMethodsOnStrings
|
||||||
parentType.isAny() -> function.name.asString() == "toString" && context?.dispatchReceiver !is IrGetObjectValue
|
|
||||||
parent.isObject -> parent.parentClassOrNull?.defaultType?.let { it.isPrimitiveType() || it.isUnsigned() } == true
|
parent.isObject -> parent.parentClassOrNull?.defaultType?.let { it.isPrimitiveType() || it.isUnsigned() } == true
|
||||||
parentType.isUnsignedType() && function is IrConstructor -> true
|
parentType.isUnsignedType() && function is IrConstructor -> true
|
||||||
else -> fqName in allowedExtensionFunctions || fqName in allowedBuiltinExtensionFunctions
|
else -> fqName in allowedExtensionFunctions || fqName in allowedBuiltinExtensionFunctions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun canEvaluateEnumValue(enumEntry: IrGetEnumValue, context: IrCall?): Boolean = false
|
override fun canEvaluateBlock(block: IrBlock): Boolean = block.statements.size == 1
|
||||||
override fun canEvaluateReference(reference: IrCallableReference<*>, context: IrCall?): Boolean = false
|
override fun canEvaluateExpression(expression: IrExpression): Boolean = expression is IrCall
|
||||||
},
|
},
|
||||||
|
|
||||||
ONLY_INTRINSIC_CONST(mustCheckBody = false) {
|
ONLY_INTRINSIC_CONST {
|
||||||
override fun canEvaluateFunction(function: IrFunction, context: IrCall?): Boolean {
|
override fun canEvaluateFunction(function: IrFunction, context: IrCall?): Boolean {
|
||||||
return function.isCompileTimePropertyAccessor() || function.isMarkedAsIntrinsicConstEvaluation() || context.isIntrinsicConstEvaluationNameProperty()
|
return function.isCompileTimePropertyAccessor() ||
|
||||||
|
function.isMarkedAsIntrinsicConstEvaluation() ||
|
||||||
|
context.isIntrinsicConstEvaluationNameProperty()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunction?.isCompileTimePropertyAccessor(): Boolean {
|
private fun IrFunction?.isCompileTimePropertyAccessor(): Boolean {
|
||||||
@@ -84,10 +93,13 @@ enum class EvaluationMode(protected val mustCheckBody: Boolean) {
|
|||||||
return context.isIntrinsicConstEvaluationNameProperty()
|
return context.isIntrinsicConstEvaluationNameProperty()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun canEvaluateReference(reference: IrCallableReference<*>, context: IrCall?): Boolean {
|
override fun canEvaluateCallableReference(reference: IrCallableReference<*>, context: IrCall?): Boolean {
|
||||||
return context.isIntrinsicConstEvaluationNameProperty()
|
return context.isIntrinsicConstEvaluationNameProperty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun canEvaluateBlock(block: IrBlock): Boolean = block.origin == IrStatementOrigin.WHEN || block.statements.size == 1
|
||||||
|
override fun canEvaluateExpression(expression: IrExpression): Boolean = expression is IrCall || expression is IrWhen
|
||||||
|
|
||||||
private fun IrCall?.isIntrinsicConstEvaluationNameProperty(): Boolean {
|
private fun IrCall?.isIntrinsicConstEvaluationNameProperty(): Boolean {
|
||||||
if (this == null) return false
|
if (this == null) return false
|
||||||
val owner = this.symbol.owner
|
val owner = this.symbol.owner
|
||||||
@@ -96,24 +108,22 @@ enum class EvaluationMode(protected val mustCheckBody: Boolean) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
abstract fun canEvaluateFunction(function: IrFunction, context: IrCall? = null): Boolean
|
open fun canEvaluateFunction(function: IrFunction, context: IrCall? = null): Boolean = false
|
||||||
abstract fun canEvaluateEnumValue(enumEntry: IrGetEnumValue, context: IrCall? = null): Boolean
|
open fun canEvaluateEnumValue(enumEntry: IrGetEnumValue, context: IrCall? = null): Boolean = false
|
||||||
abstract fun canEvaluateReference(reference: IrCallableReference<*>, context: IrCall? = null): Boolean
|
open fun canEvaluateFunctionExpression(expression: IrFunctionExpression, context: IrCall? = null): Boolean = false
|
||||||
|
open fun canEvaluateCallableReference(reference: IrCallableReference<*>, context: IrCall? = null): Boolean = false
|
||||||
|
open fun canEvaluateClassReference(reference: IrDeclarationReference): Boolean = false
|
||||||
|
|
||||||
fun mustCheckBodyOf(function: IrFunction): Boolean {
|
open fun canEvaluateBlock(block: IrBlock): Boolean = false
|
||||||
if (function.property != null) return true
|
open fun canEvaluateComposite(composite: IrComposite): Boolean {
|
||||||
return (mustCheckBody || function.isLocal) && !function.isContract() && !function.isMarkedAsEvaluateIntrinsic()
|
return composite.origin == IrStatementOrigin.DESTRUCTURING_DECLARATION || composite.origin == null
|
||||||
}
|
}
|
||||||
|
|
||||||
protected val compileTimeTypeAliases = setOf(
|
open fun canEvaluateExpression(expression: IrExpression): Boolean = false
|
||||||
"java.lang.StringBuilder", "java.lang.IllegalArgumentException", "java.util.NoSuchElementException"
|
|
||||||
)
|
open fun mustCheckBodyOf(function: IrFunction): Boolean = false
|
||||||
|
|
||||||
fun IrDeclaration.isMarkedAsCompileTime() = isMarkedWith(compileTimeAnnotation)
|
|
||||||
protected fun IrDeclaration.isMarkedAsIntrinsicConstEvaluation() = isMarkedWith(intrinsicConstEvaluationAnnotation)
|
protected fun IrDeclaration.isMarkedAsIntrinsicConstEvaluation() = isMarkedWith(intrinsicConstEvaluationAnnotation)
|
||||||
private fun IrDeclaration.isContract() = isMarkedWith(contractsDslAnnotation)
|
|
||||||
private fun IrDeclaration.isMarkedAsEvaluateIntrinsic() = isMarkedWith(evaluateIntrinsicAnnotation)
|
|
||||||
protected fun IrDeclaration.isCompileTimeTypeAlias() = this.parentClassOrNull?.fqName in compileTimeTypeAliases
|
|
||||||
|
|
||||||
protected fun IrDeclaration.isMarkedWith(annotation: FqName): Boolean {
|
protected fun IrDeclaration.isMarkedWith(annotation: FqName): Boolean {
|
||||||
if (this is IrClass && this.isCompanion) return false
|
if (this is IrClass && this.isCompanion) return false
|
||||||
|
|||||||
+39
-44
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.interpreter.fqName
|
|||||||
import org.jetbrains.kotlin.ir.interpreter.isAccessToNotNullableObject
|
import org.jetbrains.kotlin.ir.interpreter.isAccessToNotNullableObject
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.constructors
|
import org.jetbrains.kotlin.ir.util.constructors
|
||||||
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
import org.jetbrains.kotlin.ir.util.statements
|
import org.jetbrains.kotlin.ir.util.statements
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
|
|
||||||
@@ -26,14 +27,14 @@ class IrCompileTimeChecker(
|
|||||||
private var contextExpression: IrCall? = null
|
private var contextExpression: IrCall? = null
|
||||||
private val visitedStack = mutableListOf<IrElement>().apply { if (containingDeclaration != null) add(containingDeclaration) }
|
private val visitedStack = mutableListOf<IrElement>().apply { if (containingDeclaration != null) add(containingDeclaration) }
|
||||||
|
|
||||||
private fun IrElement.asVisited(block: () -> Boolean): Boolean {
|
private inline fun IrElement.asVisited(crossinline block: () -> Boolean): Boolean {
|
||||||
visitedStack += this
|
visitedStack += this
|
||||||
val result = block()
|
val result = block()
|
||||||
visitedStack.removeAt(visitedStack.lastIndex)
|
visitedStack.removeAt(visitedStack.lastIndex)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <R> IrCall.saveContext(block: () -> R): R {
|
private inline fun <R> IrCall.saveContext(crossinline block: () -> R): R {
|
||||||
val oldContext = contextExpression
|
val oldContext = contextExpression
|
||||||
contextExpression = this
|
contextExpression = this
|
||||||
return block().apply { contextExpression = oldContext }
|
return block().apply { contextExpression = oldContext }
|
||||||
@@ -46,24 +47,21 @@ class IrCompileTimeChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun visitStatements(statements: List<IrStatement>): Boolean {
|
private fun visitStatements(statements: List<IrStatement>): Boolean {
|
||||||
when (mode) {
|
return statements.all { it.accept(this, null) }
|
||||||
EvaluationMode.ONLY_BUILTINS, EvaluationMode.ONLY_INTRINSIC_CONST -> {
|
|
||||||
val statement = statements.singleOrNull() ?: return false
|
|
||||||
return statement.accept(this, null)
|
|
||||||
}
|
|
||||||
else -> return statements.all { it.accept(this, null) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun visitConstructor(expression: IrFunctionAccessExpression): Boolean {
|
private fun visitConstructor(expression: IrFunctionAccessExpression): Boolean {
|
||||||
return when {
|
val constructor = expression.symbol.owner
|
||||||
!visitValueArguments(expression, null) || !mode.canEvaluateFunction(expression.symbol.owner, contextExpression) -> false
|
|
||||||
else -> expression.symbol.owner.visitBodyIfNeeded()
|
if (!mode.canEvaluateFunction(constructor, contextExpression)) return false
|
||||||
}
|
if (!visitValueArguments(expression, null)) return false
|
||||||
|
return constructor.visitBodyIfNeeded() &&
|
||||||
|
constructor.parentAsClass.declarations.filterIsInstance<IrAnonymousInitializer>().all { it.accept(this, null) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunction.visitBodyIfNeeded(): Boolean {
|
private fun IrFunction.visitBodyIfNeeded(): Boolean {
|
||||||
return this.asVisited { !mode.mustCheckBodyOf(this) || (this.body?.accept(this@IrCompileTimeChecker, null) ?: true) }
|
if (!mode.mustCheckBodyOf(this)) return true
|
||||||
|
return this.asVisited { this.body?.accept(this@IrCompileTimeChecker, null) ?: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrCall.isGetterToConstVal(): Boolean {
|
private fun IrCall.isGetterToConstVal(): Boolean {
|
||||||
@@ -71,6 +69,8 @@ class IrCompileTimeChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall, data: Nothing?): Boolean {
|
override fun visitCall(expression: IrCall, data: Nothing?): Boolean {
|
||||||
|
if (!mode.canEvaluateExpression(expression)) return false
|
||||||
|
|
||||||
val owner = expression.symbol.owner
|
val owner = expression.symbol.owner
|
||||||
if (!mode.canEvaluateFunction(owner, expression)) return false
|
if (!mode.canEvaluateFunction(owner, expression)) return false
|
||||||
|
|
||||||
@@ -114,19 +114,23 @@ class IrCompileTimeChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBlock(expression: IrBlock, data: Nothing?): Boolean {
|
override fun visitBlock(expression: IrBlock, data: Nothing?): Boolean {
|
||||||
if (mode == EvaluationMode.ONLY_INTRINSIC_CONST && expression.origin == IrStatementOrigin.WHEN) {
|
if (!mode.canEvaluateBlock(expression)) return false
|
||||||
return expression.statements.all { it.accept(this, null) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// `IrReturnableBlock` will be created from IrCall after inline. We should do basically the same check as for IrCall.
|
// `IrReturnableBlock` will be created from IrCall after inline. We should do basically the same check as for IrCall.
|
||||||
if (expression is IrReturnableBlock) {
|
if (expression is IrReturnableBlock) {
|
||||||
// TODO after JVM inline MR 8122 will be pushed check original IrCall.
|
val inlinedBlock = expression.statements.singleOrNull() as? IrInlinedFunctionBlock
|
||||||
TODO("Interpretation of `IrReturnableBlock` is not implemented")
|
if (inlinedBlock != null) return inlinedBlock.inlineCall.accept(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
return visitStatements(expression.statements)
|
return visitStatements(expression.statements)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitComposite(expression: IrComposite, data: Nothing?): Boolean {
|
||||||
|
if (!mode.canEvaluateComposite(expression)) return false
|
||||||
|
|
||||||
|
return visitStatements(expression.statements)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitSyntheticBody(body: IrSyntheticBody, data: Nothing?): Boolean {
|
override fun visitSyntheticBody(body: IrSyntheticBody, data: Nothing?): Boolean {
|
||||||
return body.kind == IrSyntheticBodyKind.ENUM_VALUES || body.kind == IrSyntheticBodyKind.ENUM_VALUEOF
|
return body.kind == IrSyntheticBodyKind.ENUM_VALUES || body.kind == IrSyntheticBodyKind.ENUM_VALUEOF
|
||||||
}
|
}
|
||||||
@@ -147,13 +151,6 @@ class IrCompileTimeChecker(
|
|||||||
return spread.expression.accept(this, data)
|
return spread.expression.accept(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitComposite(expression: IrComposite, data: Nothing?): Boolean {
|
|
||||||
if (expression.origin == IrStatementOrigin.DESTRUCTURING_DECLARATION || expression.origin == null) {
|
|
||||||
return visitStatements(expression.statements)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitStringConcatenation(expression: IrStringConcatenation, data: Nothing?): Boolean {
|
override fun visitStringConcatenation(expression: IrStringConcatenation, data: Nothing?): Boolean {
|
||||||
return expression.arguments.all { arg ->
|
return expression.arguments.all { arg ->
|
||||||
when (arg) {
|
when (arg) {
|
||||||
@@ -162,7 +159,7 @@ class IrCompileTimeChecker(
|
|||||||
.filterIsInstance<IrSimpleFunction>()
|
.filterIsInstance<IrSimpleFunction>()
|
||||||
.single { it.name.asString() == "toString" && it.valueParameters.isEmpty() && it.extensionReceiverParameter == null }
|
.single { it.name.asString() == "toString" && it.valueParameters.isEmpty() && it.extensionReceiverParameter == null }
|
||||||
|
|
||||||
mode.canEvaluateFunction(toString, null) && toString.visitBodyIfNeeded()
|
mode.canEvaluateFunction(toString) && toString.visitBodyIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> arg.accept(this, data)
|
else -> arg.accept(this, data)
|
||||||
@@ -177,6 +174,7 @@ class IrCompileTimeChecker(
|
|||||||
|
|
||||||
override fun visitGetEnumValue(expression: IrGetEnumValue, data: Nothing?): Boolean {
|
override fun visitGetEnumValue(expression: IrGetEnumValue, data: Nothing?): Boolean {
|
||||||
if (!mode.canEvaluateEnumValue(expression, contextExpression)) return false
|
if (!mode.canEvaluateEnumValue(expression, contextExpression)) return false
|
||||||
|
|
||||||
// we want to avoid recursion in cases like "enum class E(val srt: String) { OK(OK.name) }"
|
// we want to avoid recursion in cases like "enum class E(val srt: String) { OK(OK.name) }"
|
||||||
if (visitedStack.contains(expression)) return true
|
if (visitedStack.contains(expression)) return true
|
||||||
return expression.asVisited {
|
return expression.asVisited {
|
||||||
@@ -197,7 +195,7 @@ class IrCompileTimeChecker(
|
|||||||
val property = owner.correspondingPropertySymbol?.owner
|
val property = owner.correspondingPropertySymbol?.owner
|
||||||
val fqName = owner.fqName
|
val fqName = owner.fqName
|
||||||
fun isJavaStaticWithPrimitiveOrString(): Boolean {
|
fun isJavaStaticWithPrimitiveOrString(): Boolean {
|
||||||
return owner.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && owner.isStatic &&
|
return owner.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && owner.isStatic && owner.isFinal &&
|
||||||
(owner.type.isPrimitiveType() || owner.type.isStringClassType())
|
(owner.type.isPrimitiveType() || owner.type.isStringClassType())
|
||||||
}
|
}
|
||||||
return when {
|
return when {
|
||||||
@@ -247,7 +245,6 @@ class IrCompileTimeChecker(
|
|||||||
val classProperties = irClass.declarations.filterIsInstance<IrProperty>()
|
val classProperties = irClass.declarations.filterIsInstance<IrProperty>()
|
||||||
val anonymousInitializer = irClass.declarations.filterIsInstance<IrAnonymousInitializer>().filter { !it.isStatic }
|
val anonymousInitializer = irClass.declarations.filterIsInstance<IrAnonymousInitializer>().filter { !it.isStatic }
|
||||||
|
|
||||||
|
|
||||||
return anonymousInitializer.all { init -> init.body.accept(this, data) } && classProperties.all {
|
return anonymousInitializer.all { init -> init.body.accept(this, data) } && classProperties.all {
|
||||||
val propertyInitializer = it.backingField?.initializer?.expression
|
val propertyInitializer = it.backingField?.initializer?.expression
|
||||||
if ((propertyInitializer as? IrGetValue)?.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER) return@all true
|
if ((propertyInitializer as? IrGetValue)?.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER) return@all true
|
||||||
@@ -256,7 +253,7 @@ class IrCompileTimeChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunctionReference(expression: IrFunctionReference, data: Nothing?): Boolean {
|
override fun visitFunctionReference(expression: IrFunctionReference, data: Nothing?): Boolean {
|
||||||
if (!mode.canEvaluateReference(expression, contextExpression)) return false
|
if (!mode.canEvaluateCallableReference(expression, contextExpression)) return false
|
||||||
|
|
||||||
val owner = expression.symbol.owner
|
val owner = expression.symbol.owner
|
||||||
val dispatchReceiverComputable = expression.dispatchReceiver?.accept(this, null) ?: true
|
val dispatchReceiverComputable = expression.dispatchReceiver?.accept(this, null) ?: true
|
||||||
@@ -269,12 +266,10 @@ class IrCompileTimeChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunctionExpression(expression: IrFunctionExpression, data: Nothing?): Boolean {
|
override fun visitFunctionExpression(expression: IrFunctionExpression, data: Nothing?): Boolean {
|
||||||
if (mode == EvaluationMode.ONLY_BUILTINS || mode == EvaluationMode.ONLY_INTRINSIC_CONST) return false
|
if (!mode.canEvaluateFunctionExpression(expression)) return false
|
||||||
val isLambda = expression.origin == IrStatementOrigin.LAMBDA || expression.origin == IrStatementOrigin.ANONYMOUS_FUNCTION
|
|
||||||
val isCompileTime = mode.canEvaluateFunction(expression.function)
|
val body = expression.function.body ?: return false
|
||||||
return expression.function.asVisited {
|
return expression.function.asVisited { body.accept(this, data) }
|
||||||
if (isLambda || isCompileTime) expression.function.body?.accept(this, data) == true else false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: Nothing?): Boolean {
|
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: Nothing?): Boolean {
|
||||||
@@ -291,6 +286,8 @@ class IrCompileTimeChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitWhen(expression: IrWhen, data: Nothing?): Boolean {
|
override fun visitWhen(expression: IrWhen, data: Nothing?): Boolean {
|
||||||
|
if (!mode.canEvaluateExpression(expression)) return false
|
||||||
|
|
||||||
return expression.branches.all { it.accept(this, data) }
|
return expression.branches.all { it.accept(this, data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +308,8 @@ class IrCompileTimeChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTry(aTry: IrTry, data: Nothing?): Boolean {
|
override fun visitTry(aTry: IrTry, data: Nothing?): Boolean {
|
||||||
if (mode == EvaluationMode.ONLY_BUILTINS || mode == EvaluationMode.ONLY_INTRINSIC_CONST) return false
|
if (!mode.canEvaluateExpression(aTry)) return false
|
||||||
|
|
||||||
if (!aTry.tryResult.accept(this, data)) return false
|
if (!aTry.tryResult.accept(this, data)) return false
|
||||||
if (aTry.finallyExpression != null && aTry.finallyExpression?.accept(this, data) == false) return false
|
if (aTry.finallyExpression != null && aTry.finallyExpression?.accept(this, data) == false) return false
|
||||||
return aTry.catches.all { it.result.accept(this, data) }
|
return aTry.catches.all { it.result.accept(this, data) }
|
||||||
@@ -327,11 +325,13 @@ class IrCompileTimeChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitThrow(expression: IrThrow, data: Nothing?): Boolean {
|
override fun visitThrow(expression: IrThrow, data: Nothing?): Boolean {
|
||||||
|
if (!mode.canEvaluateExpression(expression)) return false
|
||||||
|
|
||||||
return expression.value.accept(this, data)
|
return expression.value.accept(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitPropertyReference(expression: IrPropertyReference, data: Nothing?): Boolean {
|
override fun visitPropertyReference(expression: IrPropertyReference, data: Nothing?): Boolean {
|
||||||
if (!mode.canEvaluateReference(expression, contextExpression)) return false
|
if (!mode.canEvaluateCallableReference(expression, contextExpression)) return false
|
||||||
|
|
||||||
val dispatchReceiverComputable = expression.dispatchReceiver?.accept(this, null) ?: true
|
val dispatchReceiverComputable = expression.dispatchReceiver?.accept(this, null) ?: true
|
||||||
val extensionReceiverComputable = expression.extensionReceiver?.accept(this, null) ?: true
|
val extensionReceiverComputable = expression.extensionReceiver?.accept(this, null) ?: true
|
||||||
@@ -341,11 +341,6 @@ class IrCompileTimeChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClassReference(expression: IrClassReference, data: Nothing?): Boolean {
|
override fun visitClassReference(expression: IrClassReference, data: Nothing?): Boolean {
|
||||||
return with(mode) {
|
return mode.canEvaluateClassReference(expression)
|
||||||
when (this) {
|
|
||||||
EvaluationMode.FULL -> true
|
|
||||||
EvaluationMode.ONLY_BUILTINS, EvaluationMode.ONLY_INTRINSIC_CONST -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user