From 9b1f11b22bbfdb2ebcfcfae297bc19061efcc255 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Fri, 14 Aug 2020 19:51:39 +0300 Subject: [PATCH] Extend compile time checker to check constructors body --- .../checker/IrCompileTimeChecker.kt | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) 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 683ac606d29..60e4ad24f85 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 @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.name.FqName class IrCompileTimeChecker( containingDeclaration: IrElement? = null, private val mode: EvaluationMode = EvaluationMode.WITH_ANNOTATIONS ) : IrElementVisitor { - private val visitedStack = mutableListOf().apply { if (containingDeclaration != null) add(containingDeclaration) } + private val visitedStack = mutableListOf().apply { if (containingDeclaration != null) add(containingDeclaration) } private fun IrElement.asVisited(block: () -> Boolean): Boolean { visitedStack += this @@ -39,7 +39,7 @@ class IrCompileTimeChecker( private fun visitConstructor(expression: IrFunctionAccessExpression): Boolean { return when { !visitValueParameters(expression, null) -> false - else -> mode.canEvaluateFunction(expression.symbol.owner) + else -> if (mode.canEvaluateBody(expression.symbol.owner)) expression.symbol.owner.body?.accept(this, null) != false else true } } @@ -93,7 +93,7 @@ class IrCompileTimeChecker( } override fun visitComposite(expression: IrComposite, data: Nothing?): Boolean { - if (expression.origin == IrStatementOrigin.DESTRUCTURING_DECLARATION) { + if (expression.origin == IrStatementOrigin.DESTRUCTURING_DECLARATION || expression.origin == null) { return visitStatements(expression.statements, data) } return false @@ -130,7 +130,8 @@ class IrCompileTimeChecker( return true } - if (expression.receiver == null) return expression.symbol.owner.correspondingPropertySymbol?.owner?.isConst == true + if (expression.receiver == null) + return expression.symbol.owner.correspondingPropertySymbol?.owner?.let { it.isConst || it.backingField?.initializer?.expression is IrConst<*> } == true val property = expression.symbol.owner.correspondingPropertySymbol?.owner val owner = expression.symbol.owner @@ -146,10 +147,13 @@ class IrCompileTimeChecker( val getter = parent.declarations.filterIsInstance().single { it == property }.getter val isJavaPrimitiveStatic = owner.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && owner.isStatic && (owner.type.isPrimitiveType() || owner.type.isStringClassType()) - return visitedStack.contains(getter) || isJavaPrimitiveStatic + return getter?.let { visitedStack.contains(it) } == true || isJavaPrimitiveStatic } override fun visitSetField(expression: IrSetField, data: Nothing?): Boolean { + if (expression.receiver.let { it == null || (it.type.classifierOrNull?.owner as? IrClass)?.isObject == true }) { + return false + } //todo check receiver? val property = expression.symbol.owner.correspondingPropertySymbol?.owner val parent = expression.symbol.owner.parent as IrDeclarationContainer @@ -161,10 +165,28 @@ class IrCompileTimeChecker( return visitConstructor(expression) } + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: Nothing?): Boolean { + if (expression.symbol.owner.returnType.isAny()) return true + return visitConstructor(expression) + } + override fun visitEnumConstructorCall(expression: IrEnumConstructorCall, data: Nothing?): Boolean { return visitConstructor(expression) } + override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, data: Nothing?): Boolean { + val irClass = expression.classSymbol.owner + val classProperties = irClass.declarations.filterIsInstance() + val anonymousInitializer = irClass.declarations.filterIsInstance().filter { !it.isStatic } + + + return anonymousInitializer.all { init -> init.body.accept(this, data) } && classProperties.all { + val propertyInitializer = it.backingField?.initializer?.expression + if ((propertyInitializer as? IrGetValue)?.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER) return@all true + return@all (propertyInitializer?.accept(this, data) != false) + } + } + override fun visitFunctionReference(expression: IrFunctionReference, data: Nothing?): Boolean { return expression.asVisited { mode.canEvaluateFunction(expression.symbol.owner) && expression.symbol.owner.body?.accept(this, data) == true