From 8041c3aa1dcec1a43968e4507bd1012426e913cb Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Wed, 7 Apr 2021 17:11:10 +0300 Subject: [PATCH] Support Char.code in constant evaluator, KT-46036 But do not consider Char.code a pure integer constant. --- .../FirOldFrontendDiagnosticsTestGenerated.java | 16 ++++++++++++++++ .../evaluate/ConstantExpressionEvaluator.kt | 5 +++-- .../constants/evaluate/OperationsMapGenerated.kt | 1 + .../evaluate/charCodeExpType.fir.kt | 8 ++++++++ .../testsWithStdLib/evaluate/charCodeExpType.kt | 8 ++++++++ .../testsWithStdLib/evaluate/charCodeExpType.txt | 10 ++++++++++ compiler/testData/evaluate/constant/integers.kt | 3 +++ .../test/runners/DiagnosticTestGenerated.java | 16 ++++++++++++++++ .../jetbrains/kotlin/builtins/StandardNames.kt | 4 +++- generators/evaluate/GenerateOperationsMap.kt | 2 ++ 10 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.fir.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.txt diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 930fc1b48ec..4f4ec1ed454 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -33788,6 +33788,22 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti } } + @Nested + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/evaluate") + @TestDataPath("$PROJECT_ROOT") + public class Evaluate { + @Test + public void testAllFilesPresentInEvaluate() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/evaluate"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Test + @TestMetadata("charCodeExpType.kt") + public void testCharCodeExpType() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.kt"); + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental") @TestDataPath("$PROJECT_ROOT") 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 83e0e3298c1..e185805cc36 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 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -635,13 +635,14 @@ private class ConstantExpressionEvaluatorVisitor( val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression) val usesNonConstValAsConstant = usesNonConstValAsConstant(argumentForReceiver.expression) val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS + val isCharCode = argumentForReceiver.ctcType == CHAR && resultingDescriptorName == StandardNames.CHAR_CODE val dontCreateILT = !isUnaryPlusMinus && !hasIntegerLiteralType(receiverExpression) return createConstant( result, expectedType, CompileTimeConstant.Parameters( canBeUsedInAnnotation, - !isNumberConversionMethod && isArgumentPure, + !isNumberConversionMethod && !isCharCode && isArgumentPure, isUnsignedNumberLiteral = false, isUnsignedLongNumberLiteral = false, usesVariableAsConstant, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/OperationsMapGenerated.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/OperationsMapGenerated.kt index 1c9b3822cea..44d28201692 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/OperationsMapGenerated.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/OperationsMapGenerated.kt @@ -38,6 +38,7 @@ internal fun evalUnaryOp(name: String, type: CompileTimeType, value: Any): Any? "toLong" -> return (value as Char).toLong() "toShort" -> return (value as Char).toShort() "toString" -> return (value as Char).toString() + "code" -> return (value as Char).code } DOUBLE -> when (name) { "toByte" -> return (value as Double).toByte() diff --git a/compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.fir.kt new file mode 100644 index 00000000000..e407f9a26c9 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.fir.kt @@ -0,0 +1,8 @@ +const val p1: Int = '\n'.code +const val p2: Long = '\n'.code.toLong() +const val p3: Byte = '\n'.code.toByte() +const val p4: Short = '\n'.code.toShort() + +const val e2: Long = '\n'.code +const val e3: Byte = '\n'.code +const val e4: Short = '\n'.code diff --git a/compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.kt b/compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.kt new file mode 100644 index 00000000000..7dd187df404 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.kt @@ -0,0 +1,8 @@ +const val p1: Int = '\n'.code +const val p2: Long = '\n'.code.toLong() +const val p3: Byte = '\n'.code.toByte() +const val p4: Short = '\n'.code.toShort() + +const val e2: Long = '\n'.code +const val e3: Byte = '\n'.code +const val e4: Short = '\n'.code diff --git a/compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.txt b/compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.txt new file mode 100644 index 00000000000..e2a98968864 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.txt @@ -0,0 +1,10 @@ +package + +public const val e2: kotlin.Long = 10 +public const val e3: kotlin.Byte = 10 +public const val e4: kotlin.Short = 10 +public const val p1: kotlin.Int = 10 +public const val p2: kotlin.Long = 10.toLong() +public const val p3: kotlin.Byte = 10.toByte() +public const val p4: kotlin.Short = 10.toShort() + diff --git a/compiler/testData/evaluate/constant/integers.kt b/compiler/testData/evaluate/constant/integers.kt index be7d466d8e6..04c7d36e2e0 100644 --- a/compiler/testData/evaluate/constant/integers.kt +++ b/compiler/testData/evaluate/constant/integers.kt @@ -8,3 +8,6 @@ val prop2: Long = 0x7777777777 // val prop3: 513105426295.toLong() val prop3 = 0x7777777777 + +// val prop4: 10 +const val prop4 = '\n'.code \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 98bcca49d9c..ec4fb21c449 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -33884,6 +33884,22 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { } } + @Nested + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/evaluate") + @TestDataPath("$PROJECT_ROOT") + public class Evaluate { + @Test + public void testAllFilesPresentInEvaluate() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/evaluate"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Test + @TestMetadata("charCodeExpType.kt") + public void testCharCodeExpType() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/evaluate/charCodeExpType.kt"); + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental") @TestDataPath("$PROJECT_ROOT") diff --git a/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt b/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt index da825427116..1e93a8ad10d 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -20,6 +20,8 @@ object StandardNames { @JvmField val ENUM_VALUE_OF = Name.identifier("valueOf") + @JvmField val CHAR_CODE = Name.identifier("code") + @JvmField val COROUTINES_PACKAGE_FQ_NAME_RELEASE = FqName("kotlin.coroutines") @JvmField val COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL = COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("experimental")) diff --git a/generators/evaluate/GenerateOperationsMap.kt b/generators/evaluate/GenerateOperationsMap.kt index ea0e233ec09..a5f1c30240a 100644 --- a/generators/evaluate/GenerateOperationsMap.kt +++ b/generators/evaluate/GenerateOperationsMap.kt @@ -68,6 +68,8 @@ fun generate(): String { } } + unaryOperationsMap.add(Triple("code", listOf(builtIns.charType), false)) + for (type in integerTypes) { for (otherType in integerTypes) { val parameters = listOf(type, otherType)