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 8839b64eb83..4dc4392336f 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 @@ -34867,6 +34867,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalIsNotEnabled.kt"); } + @Test + @TestMetadata("experimentalOnOverrideWarning.kt") + public void testExperimentalOnOverrideWarning() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.kt"); + } + @Test @TestMetadata("experimentalSetter.kt") public void testExperimentalSetter() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index ac0e56ada7d..03234b87d46 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -34867,6 +34867,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalIsNotEnabled.kt"); } + @Test + @TestMetadata("experimentalOnOverrideWarning.kt") + public void testExperimentalOnOverrideWarning() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.kt"); + } + @Test @TestMetadata("experimentalSetter.kt") public void testExperimentalSetter() throws Exception { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ExplicitMetadataChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ExplicitMetadataChecker.kt index 389bd18e8d4..12e04fa1b09 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ExplicitMetadataChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ExplicitMetadataChecker.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.resolve.jvm.checkers +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtAnnotationEntry @@ -16,7 +17,12 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm object ExplicitMetadataChecker : AdditionalAnnotationChecker { private val METADATA_FQ_NAME = FqName("kotlin.Metadata") - override fun checkEntries(entries: List, actualTargets: List, trace: BindingTrace) { + override fun checkEntries( + entries: List, + actualTargets: List, + trace: BindingTrace, + languageVersionSettings: LanguageVersionSettings + ) { for (entry in entries) { val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue if (descriptor.fqName == METADATA_FQ_NAME) { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/FileClassAnnotationsChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/FileClassAnnotationsChecker.kt index 39dfe950449..fe5c973a36b 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/FileClassAnnotationsChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/FileClassAnnotationsChecker.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.resolve.jvm.checkers +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention @@ -36,7 +37,12 @@ object FileClassAnnotationsChecker : AdditionalAnnotationChecker { // JvmName & JvmMultifileClass annotations are applicable to multi-file class parts regardless of their retention. private val alwaysApplicable = hashSetOf(JvmFileClassUtil.JVM_NAME, JvmFileClassUtil.JVM_MULTIFILE_CLASS) - override fun checkEntries(entries: List, actualTargets: List, trace: BindingTrace) { + override fun checkEntries( + entries: List, + actualTargets: List, + trace: BindingTrace, + languageVersionSettings: LanguageVersionSettings + ) { val fileAnnotationsToCheck = arrayListOf>() for (entry in entries) { if (entry.useSiteTarget?.getAnnotationUseSiteTarget() != AnnotationUseSiteTarget.FILE) continue diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/RepeatableAnnotationChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/RepeatableAnnotationChecker.kt index 621840289e2..aab2f1f384a 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/RepeatableAnnotationChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/RepeatableAnnotationChecker.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.resolve.jvm.checkers +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget @@ -19,7 +20,12 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm object RepeatableAnnotationChecker : AdditionalAnnotationChecker { - override fun checkEntries(entries: List, actualTargets: List, trace: BindingTrace) { + override fun checkEntries( + entries: List, + actualTargets: List, + trace: BindingTrace, + languageVersionSettings: LanguageVersionSettings + ) { val entryTypesWithAnnotations = hashMapOf>() for (entry in entries) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 8a2dfbb9824..876175d2dd4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -292,6 +292,7 @@ public interface Errors { DiagnosticFactory1 EXPERIMENTAL_ANNOTATION_ON_WRONG_TARGET = DiagnosticFactory1.create(ERROR); DiagnosticFactory0 EXPERIMENTAL_ANNOTATION_ON_OVERRIDE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 EXPERIMENTAL_ANNOTATION_ON_OVERRIDE_WARNING = DiagnosticFactory0.create(WARNING); DiagnosticFactory1 EXPERIMENTAL_UNSIGNED_LITERALS = DiagnosticFactory1.create(WARNING); DiagnosticFactory1 EXPERIMENTAL_UNSIGNED_LITERALS_ERROR = DiagnosticFactory1.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index fd3ef54139e..8de583bed62 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -174,6 +174,7 @@ public class DefaultErrorMessages { MAP.put(EXPERIMENTAL_ANNOTATION_ON_WRONG_TARGET, "Opt-in requirement marker annotation cannot be used on {0}", STRING); MAP.put(EXPERIMENTAL_ANNOTATION_ON_OVERRIDE, "Opt-in requirement marker annotation on override requires the same marker on base declaration"); + MAP.put(EXPERIMENTAL_ANNOTATION_ON_OVERRIDE_WARNING, "Opt-in requirement marker annotation on override requires the same marker on base declaration (will be an error in 1.6)"); MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS, "{0}", STRING); MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS_ERROR, "{0}", STRING); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt index 90edae59e18..ee733314a51 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt @@ -230,7 +230,7 @@ class AnnotationChecker( } for (checker in additionalCheckers) { - checker.checkEntries(entries, actualTargets.defaultTargets, trace) + checker.checkEntries(entries, actualTargets.defaultTargets, trace, languageVersionSettings) } } @@ -381,5 +381,10 @@ private typealias TargetLists = AnnotationTargetLists private typealias TargetList = AnnotationTargetList interface AdditionalAnnotationChecker { - fun checkEntries(entries: List, actualTargets: List, trace: BindingTrace) + fun checkEntries( + entries: List, + actualTargets: List, + trace: BindingTrace, + languageVersionSettings: LanguageVersionSettings + ) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalMarkerDeclarationAnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalMarkerDeclarationAnnotationChecker.kt index ad2170d39ed..f5d50827742 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalMarkerDeclarationAnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalMarkerDeclarationAnnotationChecker.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.resolve.checkers import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -37,7 +39,8 @@ class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleD override fun checkEntries( entries: List, actualTargets: List, - trace: BindingTrace + trace: BindingTrace, + languageVersionSettings: LanguageVersionSettings ) { var isAnnotatedWithExperimental = false @@ -88,7 +91,11 @@ class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleD if (descriptor is CallableMemberDescriptor && !descriptor.hasExperimentalOverriddenDescriptors(annotationClass.fqNameSafe) ) { - trace.report(Errors.EXPERIMENTAL_ANNOTATION_ON_OVERRIDE.on(entry)) + if (languageVersionSettings.supportsFeature(LanguageFeature.OptInOnOverrideForbidden)) { + trace.report(Errors.EXPERIMENTAL_ANNOTATION_ON_OVERRIDE.on(entry)) + } else { + trace.report(Errors.EXPERIMENTAL_ANNOTATION_ON_OVERRIDE_WARNING.on(entry)) + } } } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.fir.kt new file mode 100644 index 00000000000..fde98977ead --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.fir.kt @@ -0,0 +1,12 @@ +// !USE_EXPERIMENTAL: kotlin.RequiresOptIn +// !LANGUAGE: -OptInOnOverrideForbidden + +@RequiresOptIn(level = RequiresOptIn.Level.WARNING) +@Retention(AnnotationRetention.BINARY) +annotation class E + +class My { + @E + override fun hashCode() = 0 +} + diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.kt new file mode 100644 index 00000000000..cc142f2a45b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.kt @@ -0,0 +1,12 @@ +// !USE_EXPERIMENTAL: kotlin.RequiresOptIn +// !LANGUAGE: -OptInOnOverrideForbidden + +@RequiresOptIn(level = RequiresOptIn.Level.WARNING) +@Retention(AnnotationRetention.BINARY) +annotation class E + +class My { + @E + override fun hashCode() = 0 +} + diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.txt new file mode 100644 index 00000000000..9a115317780 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.txt @@ -0,0 +1,15 @@ +package + +@kotlin.RequiresOptIn(level = Level.WARNING) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class E : kotlin.Annotation { + public constructor E() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class My { + public constructor My() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + @E public open override /*1*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.fir.kt index a1632a96fbb..87afaeab41f 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.fir.kt @@ -1,4 +1,5 @@ // !USE_EXPERIMENTAL: kotlin.RequiresOptIn +// !LANGUAGE: +OptInOnOverrideForbidden // FILE: api.kt package api diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.kt index 8c3225d4e8c..8e2a288c8c6 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.kt @@ -1,4 +1,5 @@ // !USE_EXPERIMENTAL: kotlin.RequiresOptIn +// !LANGUAGE: +OptInOnOverrideForbidden // FILE: api.kt package api 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 516031c659d..8603cc652a4 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 @@ -34963,6 +34963,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalIsNotEnabled.kt"); } + @Test + @TestMetadata("experimentalOnOverrideWarning.kt") + public void testExperimentalOnOverrideWarning() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.kt"); + } + @Test @TestMetadata("experimentalSetter.kt") public void testExperimentalSetter() throws Exception { diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index f52ce96ac3f..36ee4ccef05 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -216,6 +216,7 @@ enum class LanguageFeature( TypeInferenceOnCallsWithSelfTypes(KOTLIN_1_6), WarnAboutNonExhaustiveWhenOnAlgebraicTypes(KOTLIN_1_6, kind = BUG_FIX), InstantiationOfAnnotationClasses(KOTLIN_1_6), + OptInOnOverrideForbidden(KOTLIN_1_6, kind = BUG_FIX), // 1.7 diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 062d926ca60..d4d470039c9 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -34867,6 +34867,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalIsNotEnabled.kt"); } + @Test + @TestMetadata("experimentalOnOverrideWarning.kt") + public void testExperimentalOnOverrideWarning() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalOnOverrideWarning.kt"); + } + @Test @TestMetadata("experimentalSetter.kt") public void testExperimentalSetter() throws Exception { diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsQualifierChecker.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsQualifierChecker.kt index 5b1b62fbcb3..9f298d5d279 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsQualifierChecker.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsQualifierChecker.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.js.resolve.diagnostics +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils import org.jetbrains.kotlin.psi.KtAnnotationEntry @@ -24,7 +25,12 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace object JsQualifierChecker : AdditionalAnnotationChecker { - override fun checkEntries(entries: List, actualTargets: List, trace: BindingTrace) { + override fun checkEntries( + entries: List, + actualTargets: List, + trace: BindingTrace, + languageVersionSettings: LanguageVersionSettings + ) { val bindingContext = trace.bindingContext for (entry in entries) { val annotation = bindingContext[BindingContext.ANNOTATION, entry] ?: continue