diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 53b1a10db0c..5155a7d6dd6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,7 +45,6 @@ import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContextUtils; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.constants.ConstantValue; -import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import org.jetbrains.kotlin.resolve.jvm.AsmTypes; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; @@ -92,8 +91,6 @@ public abstract class MemberCodegen parentCodegen, @@ -111,7 +108,6 @@ public abstract class MemberCodegen wrapped, T declaration, FieldOwnerContext codegenContext) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt index 20dcfcfe887..2d551911ca5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt @@ -21,6 +21,8 @@ import com.intellij.psi.util.PsiTreeUtil import com.intellij.util.text.LiteralFormatUtil import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl import org.jetbrains.kotlin.diagnostics.Errors @@ -44,7 +46,8 @@ import java.math.BigInteger import java.util.* class ConstantExpressionEvaluator( - internal val builtIns: KotlinBuiltIns + internal val builtIns: KotlinBuiltIns, + internal val languageVersionSettings: LanguageVersionSettings ) { internal val constantValueFactory = ConstantValueFactory(builtIns) @@ -456,7 +459,8 @@ private class ConstantExpressionEvaluatorVisitor( val parentExpression: KtExpression = PsiTreeUtil.getParentOfType(receiverExpression, KtExpression::class.java)!! trace.report(Errors.DIVISION_BY_ZERO.on(parentExpression)) - if (isIntegerType(argumentForReceiver.value) && isIntegerType(argumentForParameter.value)) { + if ((isIntegerType(argumentForReceiver.value) && isIntegerType(argumentForParameter.value)) || + !constantExpressionEvaluator.languageVersionSettings.supportsFeature(LanguageFeature.DivisionByZeroInConstantExpressions)) { return factory.createErrorValue("Division by zero").wrap() } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/scriptAnnotationsPreprocessing.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/scriptAnnotationsPreprocessing.kt index c9ddaab7dcf..62c1fb51c79 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/scriptAnnotationsPreprocessing.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/scriptAnnotationsPreprocessing.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.script import org.jetbrains.kotlin.builtins.DefaultBuiltIns +import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.KtUserType import org.jetbrains.kotlin.resolve.BindingTraceContext @@ -42,7 +43,7 @@ internal class KtAnnotationWrapper(val psi: KtAnnotationEntry, val targetClass: // TODO: annotation constructors unsupported yet in kotlin reflection, test and correct when they will be ready val targetAnnParams = targetClass.primaryConstructor?.parameters psi.valueArguments.mapIndexed { i, arg -> - val evaluator = ConstantExpressionEvaluator(DefaultBuiltIns.Instance) + val evaluator = ConstantExpressionEvaluator(DefaultBuiltIns.Instance, LanguageVersionSettingsImpl.DEFAULT) val trace = BindingTraceContext() val result = evaluator.evaluateToConstantValue(arg.getArgumentExpression()!!, trace, TypeUtils.NO_EXPECTED_TYPE) // TODO: consider inspecting `trace` to find diagnostics reported during the computation (such as division by zero, integer overflow, invalid annotation parameters etc.) diff --git a/compiler/testData/diagnostics/tests/modifiers/const/noDivisionByZeroFeature.kt b/compiler/testData/diagnostics/tests/modifiers/const/noDivisionByZeroFeature.kt new file mode 100644 index 00000000000..208ce8a8a1d --- /dev/null +++ b/compiler/testData/diagnostics/tests/modifiers/const/noDivisionByZeroFeature.kt @@ -0,0 +1,11 @@ +// !LANGUAGE: -DivisionByZeroInConstantExpressions +// !DIAGNOSTICS:-DIVISION_BY_ZERO + +const val a = 1 / 0.0 +const val b = 1.0 / 0 +const val c = 0.0 / 0 + +const val i = 1 / 0 + +val nonConst1 = 1.0 / 0 +val nonConst2 = 1 / 0 diff --git a/compiler/testData/diagnostics/tests/modifiers/const/noDivisionByZeroFeature.txt b/compiler/testData/diagnostics/tests/modifiers/const/noDivisionByZeroFeature.txt new file mode 100644 index 00000000000..bcd14134351 --- /dev/null +++ b/compiler/testData/diagnostics/tests/modifiers/const/noDivisionByZeroFeature.txt @@ -0,0 +1,8 @@ +package + +public const val a: kotlin.Double +public const val b: kotlin.Double +public const val c: kotlin.Double +public const val i: kotlin.Int +public val nonConst1: kotlin.Double +public val nonConst2: kotlin.Int diff --git a/compiler/tests-common/org/jetbrains/kotlin/resolve/constants/evaluate/AbstractCompileTimeConstantEvaluatorTest.kt b/compiler/tests-common/org/jetbrains/kotlin/resolve/constants/evaluate/AbstractCompileTimeConstantEvaluatorTest.kt index 121920aa0f6..321c96a671d 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/resolve/constants/evaluate/AbstractCompileTimeConstantEvaluatorTest.kt +++ b/compiler/tests-common/org/jetbrains/kotlin/resolve/constants/evaluate/AbstractCompileTimeConstantEvaluatorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.resolve.constants.evaluate import com.intellij.openapi.util.io.FileUtil +import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.resolve.BindingContext @@ -64,7 +65,7 @@ abstract class AbstractCompileTimeConstantEvaluatorTest : AbstractAnnotationDesc private fun evaluateInitializer(context: BindingContext, property: VariableDescriptor): CompileTimeConstant<*>? { val propertyDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(property) as KtProperty - val compileTimeConstant = ConstantExpressionEvaluator(property.builtIns).evaluateExpression( + val compileTimeConstant = ConstantExpressionEvaluator(property.builtIns, LanguageVersionSettingsImpl.DEFAULT).evaluateExpression( propertyDeclaration.initializer!!, DelegatingBindingTrace(context, "trace for evaluating compile time constant"), property.type diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 2327e6148ab..56ae965e6b1 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -12261,6 +12261,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("noDivisionByZeroFeature.kt") + public void testNoDivisionByZeroFeature() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/const/noDivisionByZeroFeature.kt"); + doTest(fileName); + } + @TestMetadata("types.kt") public void testTypes() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/const/types.kt"); diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index a8943d7a6f5..1a9a02f8697 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -33,6 +33,7 @@ enum class LanguageFeature(val sinceVersion: LanguageVersion?) { SingleUnderscoreForParameterName(KOTLIN_1_1), DslMarkersSupport(KOTLIN_1_1), UnderscoresInNumericLiterals(KOTLIN_1_1), + DivisionByZeroInConstantExpressions(KOTLIN_1_1), // Experimental features MultiPlatformProjects(null), diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractableSubstringInfo.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractableSubstringInfo.kt index 0167ac84302..8eb8714dc7d 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractableSubstringInfo.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractableSubstringInfo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import com.intellij.openapi.util.Key import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.idea.analysis.analyzeInContext import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.util.getResolutionScope @@ -54,7 +55,8 @@ class ExtractableSubstringInfo( val tempContext = expr.analyzeInContext(scope, template) val trace = DelegatingBindingTrace(tempContext, "Evaluate '$literal'") - val value = ConstantExpressionEvaluator(builtIns).evaluateExpression(expr, trace) + val languageVersionSettings = facade.getFrontendService(LanguageVersionSettings::class.java) + val value = ConstantExpressionEvaluator(builtIns, languageVersionSettings).evaluateExpression(expr, trace) if (value == null || value.isError) return stringType return value.toConstantValue(TypeUtils.NO_EXPECTED_TYPE).type diff --git a/idea/src/org/jetbrains/kotlin/idea/KotlinLightConstantExpressionEvaluator.kt b/idea/src/org/jetbrains/kotlin/idea/KotlinLightConstantExpressionEvaluator.kt index 0ae6a091d12..c0c54f90978 100644 --- a/idea/src/org/jetbrains/kotlin/idea/KotlinLightConstantExpressionEvaluator.kt +++ b/idea/src/org/jetbrains/kotlin/idea/KotlinLightConstantExpressionEvaluator.kt @@ -23,6 +23,7 @@ import com.intellij.psi.PsiExpression import com.intellij.psi.impl.ConstantExpressionEvaluator import org.jetbrains.kotlin.asJava.elements.KtLightAnnotation import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.resolve.DelegatingBindingTrace import org.jetbrains.kotlin.resolve.constants.ArrayValue @@ -53,7 +54,8 @@ class KotlinLightConstantExpressionEvaluator : ConstantExpressionEvaluator { return when (expressionToCompute) { is KtExpression -> { val resolutionFacade = expressionToCompute.getResolutionFacade() - val evaluator = FrontendConstantExpressionEvaluator(resolutionFacade.moduleDescriptor.builtIns) + val evaluator = FrontendConstantExpressionEvaluator(resolutionFacade.moduleDescriptor.builtIns, + expressionToCompute.languageVersionSettings) val evaluatorTrace = DelegatingBindingTrace(resolutionFacade.analyze(expressionToCompute), "Evaluating annotation argument") val constant = evaluator.evaluateExpression(expressionToCompute, evaluatorTrace) ?: return null