From 6e12cee62656453c4527311e98c25cdf0761b5bf Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Wed, 19 May 2021 18:15:41 +0300 Subject: [PATCH] Extract common checker logic into `accessesTopLevelOrObjectField` --- .../ir/interpreter/InstructionsUnfolder.kt | 4 +--- .../kotlin/ir/interpreter/IrInterpreter.kt | 2 +- .../jetbrains/kotlin/ir/interpreter/Utils.kt | 4 ++++ .../checker/IrCompileTimeChecker.kt | 19 ++++++++----------- .../kotlin/ir/interpreter/state/Complex.kt | 12 +++++------- 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt index f71d16e35d6..6a2147e5d3a 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt @@ -211,9 +211,7 @@ private fun unfoldReturn(expression: IrReturn, callStack: CallStack) { private fun unfoldSetField(expression: IrSetField, callStack: CallStack) { // receiver is null, for example, for top level fields; cannot interpret set on top level var - if (expression.receiver.let { it == null || (it.type.classifierOrNull?.owner as? IrClass)?.isObject == true }) { - error("Cannot interpret set method on top level properties") - } + if (expression.accessesTopLevelOrObjectField()) error("Cannot interpret set method on top level properties") callStack.addInstruction(SimpleInstruction(expression)) callStack.addInstruction(CompoundInstruction(expression.value)) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt index 3c68938315b..1320a248cad 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt @@ -369,7 +369,7 @@ class IrInterpreter private constructor( field.origin == IrDeclarationOrigin.PROPERTY_BACKING_FIELD && field.correspondingPropertySymbol?.owner?.isConst == true -> { callStack.addInstruction(CompoundInstruction(field.initializer?.expression)) } - expression.receiver.let { it == null || it.type.classOrNull?.owner?.isObject == true } -> { + expression.accessesTopLevelOrObjectField() -> { // receiver is null, for example, for top level fields val propertyOwner = field.correspondingPropertySymbol?.owner val isConst = propertyOwner?.isConst == true || propertyOwner?.backingField?.initializer?.expression is IrConst<*> diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt index aa42093578d..5b5f298eb9a 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt @@ -266,4 +266,8 @@ internal fun IrFunction.getArgsForMethodInvocation( internal fun IrType.getOnlyName(): String { if (this !is IrSimpleType) return this.render() return (this.classifierOrFail.owner as IrDeclarationWithName).name.asString() + (if (this.hasQuestionMark) "?" else "") +} + +internal fun IrFieldAccessExpression.accessesTopLevelOrObjectField(): Boolean { + return this.receiver == null || (this.receiver?.type?.classifierOrNull?.owner as? IrClass)?.isObject == true } \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrCompileTimeChecker.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrCompileTimeChecker.kt index 7d148c6c402..9699f04a784 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrCompileTimeChecker.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrCompileTimeChecker.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.interpreter.accessesTopLevelOrObjectField import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -131,18 +132,16 @@ class IrCompileTimeChecker( val owner = expression.symbol.owner val property = owner.correspondingPropertySymbol?.owner val fqName = owner.fqNameForIrSerialization + fun isJavaStaticWithPrimitiveOrString(): Boolean { + return owner.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && owner.isStatic && + (owner.type.isPrimitiveType() || owner.type.isStringClassType()) + } return when { // TODO fix later; used it here because java boolean resolves very strange, // its type is flexible (so its not primitive) and there is no initializer at backing field fqName.toString().let { it == "java.lang.Boolean.FALSE" || it == "java.lang.Boolean.TRUE" } -> true - owner.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && owner.isStatic && - (owner.type.isPrimitiveType() || owner.type.isStringClassType()) -> { - // if is java primitive static - owner.initializer?.accept(this, data) == true - } - expression.receiver == null -> { - property?.isConst == true && owner.initializer?.accept(this, null) == true - } + isJavaStaticWithPrimitiveOrString() -> owner.initializer?.accept(this, data) == true + expression.receiver == null -> property?.isConst == true && owner.initializer?.accept(this, null) == true owner.origin == IrDeclarationOrigin.PROPERTY_BACKING_FIELD && property?.isConst == true -> { val receiverComputable = expression.receiver?.accept(this, null) ?: true val initializerComputable = owner.initializer?.accept(this, null) ?: false @@ -157,9 +156,7 @@ class IrCompileTimeChecker( } override fun visitSetField(expression: IrSetField, data: Nothing?): Boolean { - if (expression.receiver.let { it == null || it.type.classOrNull?.owner?.isObject == true }) { - return false - } + if (expression.accessesTopLevelOrObjectField()) return false //todo check receiver? val property = expression.symbol.owner.correspondingPropertySymbol?.owner val parent = expression.symbol.owner.parent as IrDeclarationContainer diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Complex.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Complex.kt index 10ac702e493..7a85c433c97 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Complex.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Complex.kt @@ -15,9 +15,7 @@ import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.isAny -import org.jetbrains.kotlin.ir.types.isNullableAny import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.name.Name internal interface Complex: State { var superWrapperClass: Wrapper? @@ -27,10 +25,10 @@ internal interface Complex: State { return irClass.fqNameForIrSerialization.toString() } - private fun IrClass.getIrFunction(symbol: IrFunctionSymbol): IrFunction? { - val propertyGetters = this.declarations.filterIsInstance().mapNotNull { it.getter } - val propertySetters = this.declarations.filterIsInstance().mapNotNull { it.setter } - val functions = this.declarations.filterIsInstance() + private fun getIrFunctionFromGivenClass(irClass: IrClass, symbol: IrFunctionSymbol): IrFunction? { + val propertyGetters = irClass.declarations.filterIsInstance().mapNotNull { it.getter } + val propertySetters = irClass.declarations.filterIsInstance().mapNotNull { it.setter } + val functions = irClass.declarations.filterIsInstance() return (propertyGetters + propertySetters + functions).firstOrNull { val owner = symbol.owner when { @@ -58,7 +56,7 @@ internal interface Complex: State { override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? { val receiver = getThisOrSuperReceiver(expression.superQualifierSymbol?.owner) ?: return null - val irFunction = receiver.getIrFunction(expression.symbol) ?: return null + val irFunction = getIrFunctionFromGivenClass(receiver, expression.symbol) ?: return null return getOverridden(irFunction as IrSimpleFunction) } } \ No newline at end of file