Change error message of EXCEPTION_IN_CONST_VAL_INITIALIZER
This commit is contained in:
+1
-1
@@ -76,6 +76,6 @@ object KtDefaultJvmErrorMessages : BaseDiagnosticRendererFactory() {
|
||||
map.put(JvmBackendErrors.SCRIPT_CAPTURING_ENUM, "Enum class {0} captures the script class instance. Try to use class or anonymous object instead", STRING)
|
||||
map.put(JvmBackendErrors.SCRIPT_CAPTURING_ENUM_ENTRY, "Enum entry {0} captures the script class instance. Try to use class or anonymous object instead", STRING)
|
||||
|
||||
map.put(JvmBackendErrors.EXCEPTION_IN_CONST_VAL_INITIALIZER, "An exception occur while evaluating const value initializer: {0}", STRING)
|
||||
map.put(JvmBackendErrors.EXCEPTION_IN_CONST_VAL_INITIALIZER, "Cannot evaluate constant expression: {0}", STRING)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.backend.common.phaser.makeIrModulePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.IrConstTransformer
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmBackendErrors
|
||||
@@ -22,7 +24,8 @@ val constEvaluationPhase = makeIrModulePhase(
|
||||
|
||||
// TODO make context common
|
||||
class ConstEvaluationLowering(val context: JvmBackendContext) : FileLoweringPass {
|
||||
val interpreter = IrInterpreter(context.irBuiltIns)
|
||||
val configuration = IrInterpreterConfiguration(printOnlyExceptionMessage = true)
|
||||
val interpreter = IrInterpreter(IrInterpreterEnvironment(context.irBuiltIns, configuration), emptyMap())
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
val transformer = IrConstTransformer(interpreter, irFile, mode = EvaluationMode.ONLY_INTRINSIC_CONST) { element, error ->
|
||||
|
||||
@@ -60,7 +60,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
callStack.popInstruction().handle()
|
||||
}
|
||||
|
||||
return callStack.popState().toIrExpression(expression).apply { callStack.dropFrame() }
|
||||
return environment.stateToIrExpression(callStack.popState(), expression).apply { callStack.dropFrame() }
|
||||
}
|
||||
|
||||
internal fun withNewCallStack(call: IrCall, init: IrInterpreter.() -> Any?): State {
|
||||
@@ -221,7 +221,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
// this check is used to be sure that object will be created once
|
||||
val objectState = when (constructorCall) {
|
||||
!is IrConstructorCall -> callStack.loadState(constructorCall.getThisReceiver())
|
||||
else -> (if (irClass.isSubclassOfThrowable()) ExceptionState(irClass, callStack.getStackTrace()) else Common(irClass))
|
||||
else -> (if (irClass.isSubclassOfThrowable()) ExceptionState(irClass, environment) else Common(irClass))
|
||||
.apply {
|
||||
// must set object's state here, before actual initialization, to avoid cyclic evaluation
|
||||
if (irClass.isObject) environment.mapOfObjects[irClass.symbol] = this
|
||||
|
||||
+2
@@ -17,4 +17,6 @@ class IrInterpreterConfiguration(
|
||||
val maxStack: Int = 10_000,
|
||||
val maxCommands: Int = 1_000_000,
|
||||
val createNonCompileTimeObjects: Boolean = false,
|
||||
val printOnlyExceptionMessage: Boolean = false,
|
||||
val collapseStackTraceFromJDK: Boolean = true,
|
||||
)
|
||||
|
||||
+31
-4
@@ -9,20 +9,21 @@ import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.CallStack
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.Common
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.Complex
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.ExceptionState
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.Primitive
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.State
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.Wrapper
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.typeOrNull
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
||||
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
||||
|
||||
@@ -116,6 +117,32 @@ class IrInterpreterEnvironment(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun stateToIrExpression(state: State, original: IrExpression): IrExpression {
|
||||
val start = original.startOffset
|
||||
val end = original.endOffset
|
||||
val type = original.type.makeNotNull()
|
||||
return when (state) {
|
||||
is Primitive<*> ->
|
||||
when {
|
||||
state.value == null -> state.value.toIrConst(type, start, end)
|
||||
type.isPrimitiveType() || type.isString() -> state.value.toIrConst(type, start, end)
|
||||
else -> original // TODO support for arrays
|
||||
}
|
||||
is ExceptionState -> {
|
||||
val message = if (configuration.printOnlyExceptionMessage) state.getShortDescription() else "\n" + state.getFullDescription()
|
||||
IrErrorExpressionImpl(original.startOffset, original.endOffset, original.type, message)
|
||||
}
|
||||
is Complex -> {
|
||||
val stateType = state.irClass.defaultType
|
||||
when {
|
||||
stateType.isUnsignedType() -> (state.fields.values.single() as Primitive<*>).value.toIrConst(type, start, end)
|
||||
else -> original
|
||||
}
|
||||
}
|
||||
else -> original // TODO support
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClassSymbol.getIrClassOfReflectionFromList(name: String): IrClassSymbol? {
|
||||
val property = this.owner.declarations.singleOrNull { it.nameForIrSerialization.asString() == name } as? IrProperty
|
||||
val list = property?.getter?.returnType as? IrSimpleType
|
||||
|
||||
-25
@@ -65,31 +65,6 @@ fun Any?.toIrConst(irType: IrType, startOffset: Int = SYNTHETIC_OFFSET, endOffse
|
||||
toIrConstOrNull(irType, startOffset, endOffset)
|
||||
?: throw UnsupportedOperationException("Unsupported const element type ${irType.makeNotNull().render()}")
|
||||
|
||||
internal fun State.toIrExpression(expression: IrExpression): IrExpression {
|
||||
val start = expression.startOffset
|
||||
val end = expression.endOffset
|
||||
val type = expression.type.makeNotNull()
|
||||
return when (this) {
|
||||
is Primitive<*> ->
|
||||
when {
|
||||
this.value == null -> this.value.toIrConst(type, start, end)
|
||||
type.isPrimitiveType() || type.isString() -> this.value.toIrConst(type, start, end)
|
||||
else -> expression // TODO support for arrays
|
||||
}
|
||||
is ExceptionState -> {
|
||||
IrErrorExpressionImpl(expression.startOffset, expression.endOffset, expression.type, "\n" + this.getFullDescription())
|
||||
}
|
||||
is Complex -> {
|
||||
val stateType = this.irClass.defaultType
|
||||
when {
|
||||
stateType.isUnsignedType() -> (this.fields.values.single() as Primitive<*>).value.toIrConst(type, start, end)
|
||||
else -> expression
|
||||
}
|
||||
}
|
||||
else -> expression // TODO support
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrFunction.createCall(origin: IrStatementOrigin? = null): IrCall {
|
||||
this as IrSimpleFunction
|
||||
return IrCallImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, returnType, symbol, typeParameters.size, valueParameters.size, origin)
|
||||
|
||||
+1
-1
@@ -34,6 +34,6 @@ internal fun Throwable.handleUserException(environment: IrInterpreterEnvironment
|
||||
val exceptionName = this::class.java.simpleName
|
||||
val irExceptionClass = environment.irExceptions.firstOrNull { it.name.asString() == exceptionName }
|
||||
?: environment.irBuiltIns.throwableClass.owner
|
||||
environment.callStack.pushState(ExceptionState(this, irExceptionClass, environment.callStack.getStackTrace()))
|
||||
environment.callStack.pushState(ExceptionState(this, irExceptionClass, environment.callStack.getStackTrace(), environment))
|
||||
environment.callStack.dropFramesUntilTryCatch()
|
||||
}
|
||||
+18
-6
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.ir.interpreter.state
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment
|
||||
import org.jetbrains.kotlin.ir.interpreter.getOriginalPropertyByName
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Field
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Fields
|
||||
@@ -39,11 +40,13 @@ internal class ExceptionState private constructor(
|
||||
if (!fields.containsKey(causeProperty.symbol)) setCause(null)
|
||||
}
|
||||
|
||||
constructor(irClass: IrClass, stackTrace: List<String>) : this(irClass, mutableMapOf(), stackTrace)
|
||||
constructor(
|
||||
irClass: IrClass, environment: IrInterpreterEnvironment
|
||||
) : this(irClass, mutableMapOf(), environment.callStack.getStackTrace())
|
||||
|
||||
constructor(
|
||||
exception: Throwable, irClass: IrClass, stackTrace: List<String>
|
||||
) : this(irClass, evaluateFields(exception, irClass, stackTrace), stackTrace + evaluateAdditionalStackTrace(exception)) {
|
||||
exception: Throwable, irClass: IrClass, stackTrace: List<String>, environment: IrInterpreterEnvironment
|
||||
) : this(irClass, evaluateFields(exception, irClass, environment), stackTrace + evaluateAdditionalStackTrace(exception, environment)) {
|
||||
setCause(null) // TODO check this fact
|
||||
if (irClass.name.asString() != exception::class.java.simpleName) {
|
||||
// ir class wasn't found in classpath, a stub was passed => need to save java class hierarchy
|
||||
@@ -88,6 +91,10 @@ internal class ExceptionState private constructor(
|
||||
setField(causeProperty.symbol, causeValue ?: Primitive.nullStateOfType(causeProperty.getter!!.returnType))
|
||||
}
|
||||
|
||||
fun getShortDescription(): String {
|
||||
return message.let { if (it?.isNotEmpty() == true) it else "???" }
|
||||
}
|
||||
|
||||
fun getFullDescription(): String {
|
||||
// TODO remainder of the stack trace with "..."
|
||||
val message = message.let { if (it?.isNotEmpty() == true) ": $it" else "" }
|
||||
@@ -102,18 +109,19 @@ internal class ExceptionState private constructor(
|
||||
override fun toString(): String = message?.let { "$exceptionFqName: $it" } ?: exceptionFqName
|
||||
|
||||
companion object {
|
||||
private fun evaluateFields(exception: Throwable, irClass: IrClass, stackTrace: List<String>): Fields {
|
||||
private fun evaluateFields(exception: Throwable, irClass: IrClass, environment: IrInterpreterEnvironment): Fields {
|
||||
val stackTrace = environment.callStack.getStackTrace()
|
||||
val messageProperty = irClass.getOriginalPropertyByName("message")
|
||||
val causeProperty = irClass.getOriginalPropertyByName("cause")
|
||||
|
||||
val messageVar = messageProperty.symbol to Primitive(exception.message, messageProperty.getter!!.returnType)
|
||||
val causeVar = exception.cause?.let {
|
||||
causeProperty.symbol to ExceptionState(it, irClass, stackTrace + it.stackTrace.reversed().map { "at $it" })
|
||||
causeProperty.symbol to ExceptionState(it, irClass, stackTrace + it.stackTrace.reversed().map { "at $it" }, environment)
|
||||
}
|
||||
return causeVar?.let { mutableMapOf(messageVar, it) } ?: mutableMapOf(messageVar)
|
||||
}
|
||||
|
||||
private fun evaluateAdditionalStackTrace(e: Throwable): List<String> {
|
||||
private fun evaluateAdditionalStackTrace(e: Throwable, environment: IrInterpreterEnvironment): List<String> {
|
||||
// TODO do we really need this?... It will point to JVM stdlib
|
||||
val additionalStack = mutableListOf<String>()
|
||||
if (e.stackTrace.any { it.className == "java.lang.invoke.MethodHandle" }) {
|
||||
@@ -137,6 +145,10 @@ internal class ExceptionState private constructor(
|
||||
cause = cause.cause
|
||||
}
|
||||
}
|
||||
|
||||
if (environment.configuration.collapseStackTraceFromJDK && additionalStack.isNotEmpty()) {
|
||||
return listOf("at <JDK>")
|
||||
}
|
||||
return additionalStack
|
||||
}
|
||||
}
|
||||
|
||||
+3
-9
@@ -1,11 +1,5 @@
|
||||
/exceptionFromInterpreter_ir.kt:7:26: error: An exception occur while evaluating const value initializer:
|
||||
Exception java.lang.ArithmeticException: / by zero
|
||||
at ExceptionFromInterpreter_irKt.<clinit>(exceptionFromInterpreter_ir.kt:7)
|
||||
/exceptionFromInterpreter_ir.kt:6:26: error: Cannot evaluate constant expression: / by zero
|
||||
|
||||
/exceptionFromInterpreter_ir.kt:8:39: error: An exception occur while evaluating const value initializer:
|
||||
Exception java.lang.IllegalArgumentException: marginPrefix must be non-blank string.
|
||||
at ExceptionFromInterpreter_irKt.<clinit>(exceptionFromInterpreter_ir.kt:8)
|
||||
/exceptionFromInterpreter_ir.kt:7:39: error: Cannot evaluate constant expression: marginPrefix must be non-blank string.
|
||||
|
||||
/exceptionFromInterpreter_ir.kt:12:4: error: An exception occur while evaluating const value initializer:
|
||||
Exception java.lang.ArithmeticException: / by zero
|
||||
at ExceptionFromInterpreter_irKt.<clinit>(exceptionFromInterpreter_ir.kt:12)
|
||||
/exceptionFromInterpreter_ir.kt:11:4: error: Cannot evaluate constant expression: / by zero
|
||||
@@ -6,7 +6,6 @@ fun append(sb: StringBuilder, value: CharSequence, start: Int, end: Int): String
|
||||
const val a = <!EVALUATED: `Some string with not zero length!!!`!>append(StringBuilder("Some string with not zero length"), "!!!", 0, 3)<!>
|
||||
const val b = <!WAS_NOT_EVALUATED: `
|
||||
Exception java.lang.IndexOutOfBoundsException: start -1, end 0, s.length() 3
|
||||
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:539)
|
||||
at java.lang.StringBuilder.append(StringBuilder.java:175)
|
||||
at <JDK>
|
||||
at ExceptionFromWrapperKt.append(exceptionFromWrapper.kt:3)
|
||||
at ExceptionFromWrapperKt.<clinit>(exceptionFromWrapper.kt:7)`!>append(StringBuilder("Some string with not zero length"), "!!!", -1, 0)<!>
|
||||
|
||||
Reference in New Issue
Block a user