From 92b402759b2fe876d7ecee76b81d2290f9671215 Mon Sep 17 00:00:00 2001 From: "Denis.Zharkov" Date: Tue, 8 Dec 2020 16:48:31 +0300 Subject: [PATCH] Report incorrect JVM target only when @JvmRecord is actually used --- .../common/arguments/K2JVMCompilerArguments.kt | 1 + .../org/jetbrains/kotlin/cli/jvm/jvmArguments.kt | 12 ------------ .../jetbrains/kotlin/config/JvmAnalysisFlags.kt | 3 +++ .../checkers/JvmRecordApplicabilityChecker.kt | 16 +++++++++++++++- .../jvm/diagnostics/DefaultErrorMessagesJvm.java | 1 + .../resolve/jvm/diagnostics/ErrorsJvm.java | 1 + .../jvm/platform/JvmPlatformConfigurator.kt | 4 ++-- .../testData/cli/jvm/jvmRecordWrongTarget.args | 2 +- .../testData/cli/jvm/jvmRecordWrongTarget.out | 4 +++- .../testsWithJava15/jvmRecord/diagnostics.kt | 2 ++ .../jvmRecord/irrelevantFields.kt | 2 ++ .../jvmRecord/jvmRecordDescriptorStructure.kt | 2 ++ .../testsWithJava15/jvmRecord/supertypesCheck.kt | 2 ++ .../CompilerTestLanguageVersionSettings.kt | 2 ++ .../org/jetbrains/kotlin/test/KotlinBaseTest.kt | 3 ++- 15 files changed, 39 insertions(+), 18 deletions(-) diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt index 6ba157ce2d2..2137b548ada 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt @@ -445,6 +445,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() { result[JvmAnalysisFlags.sanitizeParentheses] = sanitizeParentheses result[JvmAnalysisFlags.suppressMissingBuiltinsError] = suppressMissingBuiltinsError result[JvmAnalysisFlags.irCheckLocalNames] = irCheckLocalNames + result[JvmAnalysisFlags.enableJvmPreview] = enableJvmPreview result[AnalysisFlags.reportErrorsOnIrDependencies] = !useIR && !useFir && !allowJvmIrDependencies result[JvmAnalysisFlags.disableUltraLightClasses] = disableUltraLightClasses return result diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt index 16b31435ac4..709ba73a6b3 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt @@ -67,21 +67,9 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu } } - if (languageVersionSettings.supportsFeature(LanguageFeature.JvmRecordSupport) && !jvmTarget.areRecordsAllowed(arguments.enableJvmPreview)) { - messageCollector.report( - ERROR, - "-XXLanguage:+${LanguageFeature.JvmRecordSupport} feature is only supported with JVM target ${JvmTarget.JVM_15.description} or later" - ) - } - addAll(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES, arguments.additionalJavaModules?.asList()) } -private fun JvmTarget.areRecordsAllowed(enableJvmPreview: Boolean): Boolean { - if (majorVersion < JvmTarget.JVM_15.majorVersion) return false - return enableJvmPreview || majorVersion > JvmTarget.JVM_15.majorVersion -} - fun CompilerConfiguration.configureJdkHome(arguments: K2JVMCompilerArguments): Boolean { val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) diff --git a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAnalysisFlags.kt b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAnalysisFlags.kt index 1626c05fa15..38f1b62fdce 100644 --- a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAnalysisFlags.kt +++ b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAnalysisFlags.kt @@ -33,6 +33,9 @@ object JvmAnalysisFlags { @JvmStatic val disableUltraLightClasses by AnalysisFlag.Delegates.Boolean + @JvmStatic + val enableJvmPreview by AnalysisFlag.Delegates.Boolean + private object Delegates { object JavaTypeEnhancementStateWarnByDefault { operator fun provideDelegate(instance: Any?, property: KProperty<*>): AnalysisFlag.Delegate = diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmRecordApplicabilityChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmRecordApplicabilityChecker.kt index 76c30d583f9..344a2b1c56b 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmRecordApplicabilityChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmRecordApplicabilityChecker.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.resolve.jvm.checkers import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.config.JvmAnalysisFlags +import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.diagnostics.Errors @@ -26,7 +28,7 @@ import org.jetbrains.kotlin.resolve.jvm.annotations.isJvmRecord import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult -object JvmRecordApplicabilityChecker : DeclarationChecker { +class JvmRecordApplicabilityChecker(private val jvmTarget: JvmTarget) : DeclarationChecker { override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { if (descriptor !is ClassDescriptor || declaration !is KtClassOrObject) return @@ -59,6 +61,13 @@ object JvmRecordApplicabilityChecker : DeclarationChecker { return } + if (!jvmTarget.areRecordsAllowed(context.languageVersionSettings.getFlag(JvmAnalysisFlags.enableJvmPreview))) { + context.trace.report( + ErrorsJvm.JVM_RECORDS_ILLEGAL_BYTECODE_TARGET.on(reportOn) + ) + return + } + if (descriptor.kind == ClassKind.ENUM_CLASS) { val modifierOrName = declaration.modifierList?.getModifier(KtTokens.ENUM_KEYWORD) @@ -153,3 +162,8 @@ object JvmRecordApplicabilityChecker : DeclarationChecker { private fun KtModifierList.findOneOfModifiers(vararg modifierTokens: KtModifierKeywordToken): PsiElement? = modifierTokens.firstNotNullResult(this::getModifier) + +private fun JvmTarget.areRecordsAllowed(enableJvmPreview: Boolean): Boolean { + if (majorVersion < JvmTarget.JVM_15.majorVersion) return false + return enableJvmPreview || majorVersion > JvmTarget.JVM_15.majorVersion +} diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java index 1ad721aace3..5bc4af923fd 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java @@ -165,6 +165,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { MAP.put(DELEGATION_BY_IN_JVM_RECORD, "Delegation is not allowed for @JvmRecord classes"); MAP.put(NON_DATA_CLASS_JVM_RECORD, "Only data classes are allowed to be marked as @JvmRecord"); MAP.put(ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE, "Classes cannot have explicit 'java.lang.Record' supertype"); + MAP.put(JVM_RECORDS_ILLEGAL_BYTECODE_TARGET, "Using @JvmRecord is only allowed with -jvm-target 15 and -Xjvm-enable-preview flag enabled"); String MESSAGE_FOR_CONCURRENT_HASH_MAP_CONTAINS = "Method 'contains' from ConcurrentHashMap may have unexpected semantics: it calls 'containsValue' instead of 'containsKey'. " + diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java index a78ee260315..4ad4694f415 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java @@ -128,6 +128,7 @@ public interface ErrorsJvm { DiagnosticFactory0 DELEGATION_BY_IN_JVM_RECORD = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 NON_DATA_CLASS_JVM_RECORD = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 JVM_RECORDS_ILLEGAL_BYTECODE_TARGET = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt index efb12405a6a..3f4fe948f76 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt @@ -41,8 +41,7 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase( JvmMultifileClassStateChecker, SynchronizedOnInlineMethodChecker, DefaultCheckerInTailrec, - FunctionDelegateMemberNameClashChecker, - JvmRecordApplicabilityChecker + FunctionDelegateMemberNameClashChecker ), additionalCallCheckers = listOf( @@ -111,6 +110,7 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase( container.useImpl() container.useImpl() container.useImpl() + container.useImpl() container.useInstance(FunctionWithBigAritySupport.LanguageVersionDependent) container.useInstance(GenericArrayClassLiteralSupport.Enabled) container.useInstance(JavaActualAnnotationArgumentExtractor()) diff --git a/compiler/testData/cli/jvm/jvmRecordWrongTarget.args b/compiler/testData/cli/jvm/jvmRecordWrongTarget.args index 807f3b5ee9a..e650dcec31e 100644 --- a/compiler/testData/cli/jvm/jvmRecordWrongTarget.args +++ b/compiler/testData/cli/jvm/jvmRecordWrongTarget.args @@ -5,7 +5,7 @@ $TEMP_DIR$ 1.5 -language-version 1.5 --cp +-jdk-home $JDK_15$ -XXLanguage:+JvmRecordSupport -jvm-target diff --git a/compiler/testData/cli/jvm/jvmRecordWrongTarget.out b/compiler/testData/cli/jvm/jvmRecordWrongTarget.out index 8e6229c35bd..ecb2e575bc2 100644 --- a/compiler/testData/cli/jvm/jvmRecordWrongTarget.out +++ b/compiler/testData/cli/jvm/jvmRecordWrongTarget.out @@ -8,5 +8,7 @@ as no stability/compatibility guarantees are given on compiler or generated code. Use it at your own risk! warning: language version 1.5 is experimental, there are no backwards compatibility guarantees for new language and library features -error: -XXLanguage:+JvmRecordSupport feature is only supported with JVM target 15 or later +compiler/testData/cli/jvm/jvmRecord.kt:1:1: error: using @JvmRecord is only allowed with -jvm-target 15 and -Xjvm-enable-preview flag enabled +@JvmRecord +^ COMPILATION_ERROR diff --git a/compiler/testData/diagnostics/testsWithJava15/jvmRecord/diagnostics.kt b/compiler/testData/diagnostics/testsWithJava15/jvmRecord/diagnostics.kt index 6e3584e5de5..9d5405ca797 100644 --- a/compiler/testData/diagnostics/testsWithJava15/jvmRecord/diagnostics.kt +++ b/compiler/testData/diagnostics/testsWithJava15/jvmRecord/diagnostics.kt @@ -1,6 +1,8 @@ // !API_VERSION: 1.5 // !LANGUAGE: +JvmRecordSupport // SKIP_TXT +// JVM_TARGET: 15 +// ENABLE_JVM_PREVIEW @JvmRecord class A0 diff --git a/compiler/testData/diagnostics/testsWithJava15/jvmRecord/irrelevantFields.kt b/compiler/testData/diagnostics/testsWithJava15/jvmRecord/irrelevantFields.kt index 4055201e76d..f2a38f74978 100644 --- a/compiler/testData/diagnostics/testsWithJava15/jvmRecord/irrelevantFields.kt +++ b/compiler/testData/diagnostics/testsWithJava15/jvmRecord/irrelevantFields.kt @@ -1,6 +1,8 @@ // !API_VERSION: 1.5 // !LANGUAGE: +JvmRecordSupport // SKIP_TXT +// JVM_TARGET: 15 +// ENABLE_JVM_PREVIEW interface I diff --git a/compiler/testData/diagnostics/testsWithJava15/jvmRecord/jvmRecordDescriptorStructure.kt b/compiler/testData/diagnostics/testsWithJava15/jvmRecord/jvmRecordDescriptorStructure.kt index a3e0630a40a..e5bf69480a8 100644 --- a/compiler/testData/diagnostics/testsWithJava15/jvmRecord/jvmRecordDescriptorStructure.kt +++ b/compiler/testData/diagnostics/testsWithJava15/jvmRecord/jvmRecordDescriptorStructure.kt @@ -1,5 +1,7 @@ // !API_VERSION: 1.5 // !LANGUAGE: +JvmRecordSupport +// JVM_TARGET: 15 +// ENABLE_JVM_PREVIEW @JvmRecord class BasicRecord(val x: String) diff --git a/compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.kt b/compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.kt index 2486625928b..0af7efaafc7 100644 --- a/compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.kt +++ b/compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.kt @@ -1,5 +1,7 @@ // !API_VERSION: 1.5 // !LANGUAGE: +JvmRecordSupport +// JVM_TARGET: 15 +// ENABLE_JVM_PREVIEW abstract class Abstract interface I diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt index 3c897f5ccfb..b3611f27d18 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt @@ -25,6 +25,7 @@ const val ALLOW_RESULT_RETURN_TYPE = "ALLOW_RESULT_RETURN_TYPE" const val INHERIT_MULTIFILE_PARTS = "INHERIT_MULTIFILE_PARTS" const val SANITIZE_PARENTHESES = "SANITIZE_PARENTHESES" const val CONSTRAINT_SYSTEM_FOR_OVERLOAD_RESOLUTION = "CONSTRAINT_SYSTEM_FOR_OVERLOAD_RESOLUTION" +const val ENABLE_JVM_PREVIEW = "ENABLE_JVM_PREVIEW" data class CompilerTestLanguageVersionSettings( private val initialLanguageFeatures: Map, @@ -67,6 +68,7 @@ fun parseLanguageVersionSettings(directives: Directives): CompilerTestLanguageVe analysisFlag(AnalysisFlags.allowResultReturnType, if (ALLOW_RESULT_RETURN_TYPE in directives) true else null), analysisFlag(JvmAnalysisFlags.inheritMultifileParts, if (INHERIT_MULTIFILE_PARTS in directives) true else null), analysisFlag(JvmAnalysisFlags.sanitizeParentheses, if (SANITIZE_PARENTHESES in directives) true else null), + analysisFlag(JvmAnalysisFlags.enableJvmPreview, if (ENABLE_JVM_PREVIEW in directives) true else null), analysisFlag(AnalysisFlags.constraintSystemForOverloadResolution, directives[CONSTRAINT_SYSTEM_FOR_OVERLOAD_RESOLUTION]?.let { ConstraintSystemForOverloadResolutionMode.valueOf(it) }), diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinBaseTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinBaseTest.kt index 07a8228493a..c5615da32dc 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinBaseTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinBaseTest.kt @@ -9,6 +9,7 @@ import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableMap import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings +import org.jetbrains.kotlin.checkers.ENABLE_JVM_PREVIEW import org.jetbrains.kotlin.checkers.parseLanguageVersionSettings import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment @@ -230,7 +231,7 @@ abstract class KotlinBaseTest : KtUsefulTestCase() configuration.put(JVMConfigurationKeys.JVM_TARGET, jvmTarget) } - if (directives.contains("ENABLE_JVM_PREVIEW")) { + if (directives.contains(ENABLE_JVM_PREVIEW)) { configuration.put(JVMConfigurationKeys.ENABLE_JVM_PREVIEW, true) }