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 4dc4392336f..a53a5ec3f90 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 @@ -34891,6 +34891,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.kt"); } + @Test + @TestMetadata("implicitUsagesFuture.kt") + public void testImplicitUsagesFuture() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.kt"); + } + @Test @TestMetadata("importStatement.kt") public void testImportStatement() 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 03234b87d46..5b37c62803a 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 @@ -34891,6 +34891,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.kt"); } + @Test + @TestMetadata("implicitUsagesFuture.kt") + public void testImplicitUsagesFuture() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.kt"); + } + @Test @TestMetadata("importStatement.kt") public void testImportStatement() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 876175d2dd4..f88023b82c9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -276,6 +276,7 @@ public interface Errors { DiagnosticFactory2 EXPERIMENTAL_API_USAGE = DiagnosticFactory2.create(WARNING); DiagnosticFactory2 EXPERIMENTAL_API_USAGE_ERROR = DiagnosticFactory2.create(ERROR); + DiagnosticFactory2 EXPERIMENTAL_API_USAGE_FUTURE_ERROR = DiagnosticFactory2.create(WARNING); DiagnosticFactory2 EXPERIMENTAL_OVERRIDE = DiagnosticFactory2.create(WARNING); DiagnosticFactory2 EXPERIMENTAL_OVERRIDE_ERROR = DiagnosticFactory2.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 8de583bed62..6c24ae624a3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -159,6 +159,7 @@ public class DefaultErrorMessages { MAP.put(EXPERIMENTAL_API_USAGE, "{1}", TO_STRING, STRING); MAP.put(EXPERIMENTAL_API_USAGE_ERROR, "{1}", TO_STRING, STRING); + MAP.put(EXPERIMENTAL_API_USAGE_FUTURE_ERROR, "{1}", TO_STRING, STRING); MAP.put(EXPERIMENTAL_OVERRIDE, "{1}", TO_STRING, STRING); MAP.put(EXPERIMENTAL_OVERRIDE_ERROR, "{1}", TO_STRING, STRING); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt index 6a8a0155347..aca457d393a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt @@ -79,7 +79,8 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { data class ExperimentalityDiagnostics( val warning: ExperimentalityDiagnostic, - val error: ExperimentalityDiagnostic + val error: ExperimentalityDiagnostic, + val futureError: ExperimentalityDiagnostic ) override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { @@ -131,7 +132,11 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { error = ExperimentalityDiagnostic2( Errors.EXPERIMENTAL_API_USAGE_ERROR, getDefaultDiagnosticMessage("This declaration is experimental and its usage must be marked") - ) + ), + futureError = ExperimentalityDiagnostic2( + Errors.EXPERIMENTAL_API_USAGE_FUTURE_ERROR, + getDefaultDiagnosticMessage("This declaration is experimental due to signature types and its usage must be marked (will become an error in 1.6)") + ), ) fun reportNotAcceptedExperimentalities( @@ -154,6 +159,7 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { val diagnostic = when (severity) { Experimentality.Severity.WARNING -> diagnostics.warning Experimentality.Severity.ERROR -> diagnostics.error + Experimentality.Severity.FUTURE_ERROR -> diagnostics.futureError } diagnostic.report(trace, element, annotationFqName, message) } @@ -163,19 +169,20 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { fun DeclarationDescriptor.loadExperimentalities( moduleAnnotationsResolver: ModuleAnnotationsResolver, languageVersionSettings: LanguageVersionSettings, - visited: MutableSet = mutableSetOf() + visited: MutableSet = mutableSetOf(), + useFutureError: Boolean = false ): Set { if (!visited.add(this)) return emptySet() val result = SmartSet.create() if (this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { for (overridden in overriddenDescriptors) { - result.addAll(overridden.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visited)) + result.addAll(overridden.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visited, useFutureError)) } return result } for (annotation in annotations) { - result.addIfNotNull(annotation.annotationClass?.loadExperimentalityForMarkerAnnotation()) + result.addIfNotNull(annotation.annotationClass?.loadExperimentalityForMarkerAnnotation(useFutureError)) } if (this is CallableDescriptor && this !is ClassConstructorDescriptor) { @@ -211,7 +218,7 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { val container = containingDeclaration if (container is ClassDescriptor && this !is ConstructorDescriptor) { - result.addAll(container.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visited)) + result.addAll(container.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visited, useFutureError)) } for (moduleAnnotationClassId in moduleAnnotationsResolver.getAnnotationsOnContainingModule(this)) { @@ -230,19 +237,21 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { when { this?.isError != false -> emptySet() this is AbbreviatedType -> abbreviation.constructor.declarationDescriptor?.loadExperimentalities( - moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers + moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers, + useFutureError = !languageVersionSettings.supportsFeature(LanguageFeature.OptInContagiousSignatures) ).orEmpty() + expandedType.loadExperimentalities( moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers ) else -> constructor.declarationDescriptor?.loadExperimentalities( - moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers + moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers, + useFutureError = !languageVersionSettings.supportsFeature(LanguageFeature.OptInContagiousSignatures) ).orEmpty() + arguments.flatMap { if (it.isStarProjection) emptySet() else it.type.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers) } } - internal fun ClassDescriptor.loadExperimentalityForMarkerAnnotation(): Experimentality? { + internal fun ClassDescriptor.loadExperimentalityForMarkerAnnotation(useFutureError: Boolean = false): Experimentality? { val experimental = annotations.findAnnotation(REQUIRES_OPT_IN_FQ_NAME) ?: annotations.findAnnotation(OLD_EXPERIMENTAL_FQ_NAME) @@ -251,8 +260,12 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { val arguments = experimental.allValueArguments val severity = when ((arguments[LEVEL] as? EnumValue)?.enumEntryName) { WARNING_LEVEL -> Experimentality.Severity.WARNING - ERROR_LEVEL -> Experimentality.Severity.ERROR - else -> Experimentality.DEFAULT_SEVERITY + ERROR_LEVEL -> if (useFutureError) Experimentality.Severity.FUTURE_ERROR else Experimentality.Severity.ERROR + else -> if (Experimentality.DEFAULT_SEVERITY == Experimentality.Severity.ERROR && useFutureError) { + Experimentality.Severity.FUTURE_ERROR + } else { + Experimentality.DEFAULT_SEVERITY + } } val message = (arguments[MESSAGE] as? StringValue)?.value @@ -457,6 +470,7 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { val (diagnostic, defaultMessageVerb) = when (experimentality.severity) { Experimentality.Severity.WARNING -> Errors.EXPERIMENTAL_OVERRIDE to "should" Experimentality.Severity.ERROR -> Errors.EXPERIMENTAL_OVERRIDE_ERROR to "must" + Experimentality.Severity.FUTURE_ERROR -> Errors.EXPERIMENTAL_OVERRIDE_ERROR to "must" } val message = experimentality.message ?: "This declaration overrides experimental member of supertype " + 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 d8243843b82..9215191f8cb 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 @@ -342,7 +342,8 @@ class ConstantExpressionEvaluator( private val EXPERIMENTAL_UNSIGNED_LITERALS_DIAGNOSTICS = ExperimentalUsageChecker.ExperimentalityDiagnostics( warning = ExperimentalityDiagnostic1(Errors.EXPERIMENTAL_UNSIGNED_LITERALS, "should"), - error = ExperimentalityDiagnostic1(Errors.EXPERIMENTAL_UNSIGNED_LITERALS_ERROR, "must") + error = ExperimentalityDiagnostic1(Errors.EXPERIMENTAL_UNSIGNED_LITERALS_ERROR, "must"), + futureError = ExperimentalityDiagnostic1(Errors.EXPERIMENTAL_UNSIGNED_LITERALS_ERROR, "must"), ) @JvmStatic diff --git a/compiler/testData/diagnostics/tests/smartCasts/kt32358_2.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/kt32358_2.fir.kt index 95a8dd74db7..4959f2d5cd5 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/kt32358_2.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/kt32358_2.fir.kt @@ -1,5 +1,5 @@ // !LANGUAGE: +NewInference -// !DIAGNOSTICS: -EXPERIMENTAL_API_USAGE_ERROR -UNUSED_PARAMETER +// !DIAGNOSTICS: -EXPERIMENTAL_API_USAGE_ERROR -EXPERIMENTAL_API_USAGE_FUTURE_ERROR -UNUSED_PARAMETER import kotlin.contracts.* diff --git a/compiler/testData/diagnostics/tests/smartCasts/kt32358_2.kt b/compiler/testData/diagnostics/tests/smartCasts/kt32358_2.kt index d05d0c98b10..88609e0d526 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/kt32358_2.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/kt32358_2.kt @@ -1,5 +1,5 @@ // !LANGUAGE: +NewInference -// !DIAGNOSTICS: -EXPERIMENTAL_API_USAGE_ERROR -UNUSED_PARAMETER +// !DIAGNOSTICS: -EXPERIMENTAL_API_USAGE_ERROR -EXPERIMENTAL_API_USAGE_FUTURE_ERROR -UNUSED_PARAMETER import kotlin.contracts.* diff --git a/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByAtLeastOnce.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByAtLeastOnce.fir.kt index 91dfeece9fd..4d87696a9bb 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByAtLeastOnce.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByAtLeastOnce.fir.kt @@ -1,6 +1,6 @@ import kotlin.contracts.* -@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +@Suppress("EXPERIMENTAL_API_USAGE_ERROR", "EXPERIMENTAL_API_USAGE_FUTURE_ERROR") inline fun atLeastOnce(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.AT_LEAST_ONCE) @@ -8,7 +8,7 @@ inline fun atLeastOnce(block: () -> Unit) { block() } -@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +@Suppress("EXPERIMENTAL_API_USAGE_ERROR", "EXPERIMENTAL_API_USAGE_FUTURE_ERROR") inline fun atMostOnce(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) @@ -16,7 +16,7 @@ inline fun atMostOnce(block: () -> Unit) { block() } -@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +@Suppress("EXPERIMENTAL_API_USAGE_ERROR", "EXPERIMENTAL_API_USAGE_FUTURE_ERROR") inline fun exactlyOnce(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) diff --git a/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByAtLeastOnce.kt b/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByAtLeastOnce.kt index fcd45a203a7..3ad3ff7ab04 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByAtLeastOnce.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByAtLeastOnce.kt @@ -1,6 +1,6 @@ import kotlin.contracts.* -@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +@Suppress("EXPERIMENTAL_API_USAGE_ERROR", "EXPERIMENTAL_API_USAGE_FUTURE_ERROR") inline fun atLeastOnce(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.AT_LEAST_ONCE) @@ -8,7 +8,7 @@ inline fun atLeastOnce(block: () -> Unit) { block() } -@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +@Suppress("EXPERIMENTAL_API_USAGE_ERROR", "EXPERIMENTAL_API_USAGE_FUTURE_ERROR") inline fun atMostOnce(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) @@ -16,7 +16,7 @@ inline fun atMostOnce(block: () -> Unit) { block() } -@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +@Suppress("EXPERIMENTAL_API_USAGE_ERROR", "EXPERIMENTAL_API_USAGE_FUTURE_ERROR") inline fun exactlyOnce(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) diff --git a/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByAtLeastOnce.txt b/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByAtLeastOnce.txt index 2f2d89feb94..7a4723aa814 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByAtLeastOnce.txt +++ b/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByAtLeastOnce.txt @@ -1,12 +1,12 @@ package -@kotlin.Suppress(names = {"EXPERIMENTAL_API_USAGE_ERROR"}) public inline fun atLeastOnce(/*0*/ block: () -> kotlin.Unit): kotlin.Unit +@kotlin.Suppress(names = {"EXPERIMENTAL_API_USAGE_ERROR", "EXPERIMENTAL_API_USAGE_FUTURE_ERROR"}) public inline fun atLeastOnce(/*0*/ block: () -> kotlin.Unit): kotlin.Unit CallsInPlace(block, AT_LEAST_ONCE) -@kotlin.Suppress(names = {"EXPERIMENTAL_API_USAGE_ERROR"}) public inline fun atMostOnce(/*0*/ block: () -> kotlin.Unit): kotlin.Unit +@kotlin.Suppress(names = {"EXPERIMENTAL_API_USAGE_ERROR", "EXPERIMENTAL_API_USAGE_FUTURE_ERROR"}) public inline fun atMostOnce(/*0*/ block: () -> kotlin.Unit): kotlin.Unit CallsInPlace(block, AT_MOST_ONCE) -@kotlin.Suppress(names = {"EXPERIMENTAL_API_USAGE_ERROR"}) public inline fun exactlyOnce(/*0*/ block: () -> kotlin.Unit): kotlin.Unit +@kotlin.Suppress(names = {"EXPERIMENTAL_API_USAGE_ERROR", "EXPERIMENTAL_API_USAGE_FUTURE_ERROR"}) public inline fun exactlyOnce(/*0*/ block: () -> kotlin.Unit): kotlin.Unit CallsInPlace(block, EXACTLY_ONCE) public fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByMultipleLambdas.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByMultipleLambdas.fir.kt index e5a352a9525..bf1062c0255 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByMultipleLambdas.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByMultipleLambdas.fir.kt @@ -1,6 +1,6 @@ import kotlin.contracts.* -@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +@Suppress("EXPERIMENTAL_API_USAGE_ERROR", "EXPERIMENTAL_API_USAGE_FUTURE_ERROR") fun foo(f1: () -> Unit, f2: () -> Unit) { contract { callsInPlace(f1, InvocationKind.EXACTLY_ONCE) diff --git a/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByMultipleLambdas.kt b/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByMultipleLambdas.kt index 6024e25e3bd..cfaa3cb98a5 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByMultipleLambdas.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByMultipleLambdas.kt @@ -1,6 +1,6 @@ import kotlin.contracts.* -@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +@Suppress("EXPERIMENTAL_API_USAGE_ERROR", "EXPERIMENTAL_API_USAGE_FUTURE_ERROR") fun foo(f1: () -> Unit, f2: () -> Unit) { contract { callsInPlace(f1, InvocationKind.EXACTLY_ONCE) diff --git a/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByMultipleLambdas.txt b/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByMultipleLambdas.txt index c81dccc5b73..e209bfdf4b7 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByMultipleLambdas.txt +++ b/compiler/testData/diagnostics/tests/smartCasts/variables/capturedByMultipleLambdas.txt @@ -1,6 +1,6 @@ package -@kotlin.Suppress(names = {"EXPERIMENTAL_API_USAGE_ERROR"}) public fun foo(/*0*/ f1: () -> kotlin.Unit, /*1*/ f2: () -> kotlin.Unit): kotlin.Unit +@kotlin.Suppress(names = {"EXPERIMENTAL_API_USAGE_ERROR", "EXPERIMENTAL_API_USAGE_FUTURE_ERROR"}) public fun foo(/*0*/ f1: () -> kotlin.Unit, /*1*/ f2: () -> kotlin.Unit): kotlin.Unit CallsInPlace(f1, EXACTLY_ONCE) CallsInPlace(f2, EXACTLY_ONCE) diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.fir.kt index 158810509e3..ed293ced957 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.fir.kt @@ -1,4 +1,5 @@ // !USE_EXPERIMENTAL: kotlin.RequiresOptIn +// LANGUAGE: +OptInContagiousSignatures @RequiresOptIn @Retention(AnnotationRetention.BINARY) diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.kt index 97b427ebe0d..11ee92f7dfe 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.kt @@ -1,4 +1,5 @@ // !USE_EXPERIMENTAL: kotlin.RequiresOptIn +// LANGUAGE: +OptInContagiousSignatures @RequiresOptIn @Retention(AnnotationRetention.BINARY) diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.fir.kt new file mode 100644 index 00000000000..2ba316add2e --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.fir.kt @@ -0,0 +1,124 @@ +// !USE_EXPERIMENTAL: kotlin.RequiresOptIn +// LANGUAGE: -OptInContagiousSignatures + +@RequiresOptIn +@Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS) +annotation class Marker + +@Marker +interface Some + +abstract class User { + abstract fun createSome(): Some + fun Some?.onSome() {} + fun withSome(some: Some? = null) {} + + fun use() { + val something = createSome() + val somethingOther: Some = createSome() + null.onSome() + withSome() + } +} + +data class DataClass(@property:Marker val x: Int) + +fun useDataClass(d: DataClass) { + // Should have error in both + d.x + val (x) = d +} + +typealias My = Some + +fun my(my: My) {} + +fun your(my: Some) {} + +@Marker +interface ExperimentalType { + fun foo() {} + fun bar() {} +} + +@OptIn(Marker::class) +interface NotExperimentalExtension : ExperimentalType { + override fun foo() {} +} + +fun use(arg: NotExperimentalExtension) { + arg.foo() + arg.bar() +} + +@Marker +interface I + +@OptIn(Marker::class) +class A : I + +@OptIn(Marker::class) +class B : I + +@OptIn(Marker::class) +typealias MyList = ArrayList + +@Marker +typealias YourList = ArrayList + +fun main() { + val x = listOf(A(), B()) + val y = MyList() + val z = YourList() + YourList().add("") +} + +@Marker +class C { + operator fun getValue(x: Any?, y: Any?): String = "" +} + +object O { + @OptIn(Marker::class) + operator fun provideDelegate(x: Any?, y: Any?): C = C() +} + +val x: String by O + +@Marker +class OperatorContainer : Comparable { + @OptIn(Marker::class) + override fun compareTo(other: OperatorContainer): Int { + return 0 + } +} + +@OptIn(Marker::class) +class AnotherContainer : Iterable { + @OptIn(Marker::class) + override fun iterator(): Iterator { + return object : Iterator { + override fun hasNext(): Boolean { + return false + } + + override fun next(): C { + throw java.util.NoSuchElementException() + } + } + } +} + +@OptIn(Marker::class) +operator fun String.minus(s: String) = OperatorContainer() + +@OptIn(Marker::class) +operator fun String.invoke() = OperatorContainer() + +fun operatorContainerUsage(s: String, a: AnotherContainer) { + val res1 = s - s + val res2 = s() + val res3 = res1 > res2 + for (c in a) {} +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.kt new file mode 100644 index 00000000000..5b18aeeb765 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.kt @@ -0,0 +1,124 @@ +// !USE_EXPERIMENTAL: kotlin.RequiresOptIn +// LANGUAGE: -OptInContagiousSignatures + +@RequiresOptIn +@Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS) +annotation class Marker + +@Marker +interface Some + +abstract class User { + abstract fun createSome(): Some + fun Some?.onSome() {} + fun withSome(some: Some? = null) {} + + fun use() { + val something = createSome() + val somethingOther: Some = createSome() + null.onSome() + withSome() + } +} + +data class DataClass(@property:Marker val x: Int) + +fun useDataClass(d: DataClass) { + // Should have error in both + d.x + val (x) = d +} + +typealias My = Some + +fun my(my: My) {} + +fun your(my: Some) {} + +@Marker +interface ExperimentalType { + fun foo() {} + fun bar() {} +} + +@OptIn(Marker::class) +interface NotExperimentalExtension : ExperimentalType { + override fun foo() {} +} + +fun use(arg: NotExperimentalExtension) { + arg.foo() + arg.bar() +} + +@Marker +interface I + +@OptIn(Marker::class) +class A : I + +@OptIn(Marker::class) +class B : I + +@OptIn(Marker::class) +typealias MyList = ArrayList + +@Marker +typealias YourList = ArrayList + +fun main() { + val x = listOf(A(), B()) + val y = MyList() + val z = YourList() + YourList().add("") +} + +@Marker +class C { + operator fun getValue(x: Any?, y: Any?): String = "" +} + +object O { + @OptIn(Marker::class) + operator fun provideDelegate(x: Any?, y: Any?): C = C() +} + +val x: String by O + +@Marker +class OperatorContainer : Comparable { + @OptIn(Marker::class) + override fun compareTo(other: OperatorContainer): Int { + return 0 + } +} + +@OptIn(Marker::class) +class AnotherContainer : Iterable { + @OptIn(Marker::class) + override fun iterator(): Iterator { + return object : Iterator { + override fun hasNext(): Boolean { + return false + } + + override fun next(): C { + throw java.util.NoSuchElementException() + } + } + } +} + +@OptIn(Marker::class) +operator fun String.minus(s: String) = OperatorContainer() + +@OptIn(Marker::class) +operator fun String.invoke() = OperatorContainer() + +fun operatorContainerUsage(s: String, a: AnotherContainer) { + val res1 = s - s + val res2 = s() + val res3 = res1 > res2 + for (c in a) {} +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.txt new file mode 100644 index 00000000000..2eaa4b76944 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.txt @@ -0,0 +1,116 @@ +package + +public val x: kotlin.String +public fun main(): kotlin.Unit +public fun my(/*0*/ my: My /* = Some */): kotlin.Unit +public fun operatorContainerUsage(/*0*/ s: kotlin.String, /*1*/ a: AnotherContainer): kotlin.Unit +public fun use(/*0*/ arg: NotExperimentalExtension): kotlin.Unit +public fun useDataClass(/*0*/ d: DataClass): kotlin.Unit +public fun your(/*0*/ my: Some): kotlin.Unit +@kotlin.OptIn(markerClass = {Marker::class}) public operator fun kotlin.String.invoke(): OperatorContainer +@kotlin.OptIn(markerClass = {Marker::class}) public operator fun kotlin.String.minus(/*0*/ s: kotlin.String): OperatorContainer + +@kotlin.OptIn(markerClass = {Marker::class}) public final class A : I { + public constructor A() + 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 +} + +@kotlin.OptIn(markerClass = {Marker::class}) public final class AnotherContainer : kotlin.collections.Iterable { + public constructor AnotherContainer() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + @kotlin.OptIn(markerClass = {Marker::class}) public open override /*1*/ fun iterator(): kotlin.collections.Iterator + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.OptIn(markerClass = {Marker::class}) public final class B : I { + public constructor B() + 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 +} + +@Marker public final class C { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final operator fun getValue(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final data class DataClass { + public constructor DataClass(/*0*/ x: kotlin.Int) + @Marker public final val x: kotlin.Int + public final operator /*synthesized*/ fun component1(): kotlin.Int + public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ...): DataClass + public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String +} + +@Marker public interface ExperimentalType { + public open fun bar(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@Marker public interface I { + 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 +} + +@kotlin.RequiresOptIn @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public final annotation class Marker : kotlin.Annotation { + public constructor Marker() + 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 +} + +@kotlin.OptIn(markerClass = {Marker::class}) public interface NotExperimentalExtension : ExperimentalType { + public open override /*1*/ /*fake_override*/ fun bar(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public object O { + private constructor O() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + @kotlin.OptIn(markerClass = {Marker::class}) public final operator fun provideDelegate(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?): C + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@Marker public final class OperatorContainer : kotlin.Comparable { + public constructor OperatorContainer() + @kotlin.OptIn(markerClass = {Marker::class}) public open override /*1*/ fun compareTo(/*0*/ other: OperatorContainer): kotlin.Int + 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 +} + +@Marker public interface Some { + 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 abstract class User { + public constructor User() + public abstract fun createSome(): Some + 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 fun use(): kotlin.Unit + public final fun withSome(/*0*/ some: Some? = ...): kotlin.Unit + public final fun Some?.onSome(): kotlin.Unit +} +public typealias My = Some +@kotlin.OptIn(markerClass = {Marker::class}) public typealias MyList = kotlin.collections.ArrayList +@Marker public typealias YourList = kotlin.collections.ArrayList 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 8603cc652a4..a05458e5be4 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 @@ -34987,6 +34987,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.kt"); } + @Test + @TestMetadata("implicitUsagesFuture.kt") + public void testImplicitUsagesFuture() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.kt"); + } + @Test @TestMetadata("importStatement.kt") public void testImportStatement() 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 36ee4ccef05..0abaa0c6389 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -217,6 +217,7 @@ enum class LanguageFeature( WarnAboutNonExhaustiveWhenOnAlgebraicTypes(KOTLIN_1_6, kind = BUG_FIX), InstantiationOfAnnotationClasses(KOTLIN_1_6), OptInOnOverrideForbidden(KOTLIN_1_6, kind = BUG_FIX), + OptInContagiousSignatures(KOTLIN_1_6, kind = BUG_FIX), // 1.7 diff --git a/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/Experimentality.kt b/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/Experimentality.kt index 49e3fce825e..b4da1798664 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/Experimentality.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/Experimentality.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.name.FqName data class Experimentality(val annotationFqName: FqName, val severity: Severity, val message: String?) { - enum class Severity { WARNING, ERROR } + enum class Severity { WARNING, ERROR, FUTURE_ERROR } companion object { val DEFAULT_SEVERITY = Severity.ERROR 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 d4d470039c9..ff24d9938b6 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 @@ -34891,6 +34891,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.kt"); } + @Test + @TestMetadata("implicitUsagesFuture.kt") + public void testImplicitUsagesFuture() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsagesFuture.kt"); + } + @Test @TestMetadata("importStatement.kt") public void testImportStatement() throws Exception {