diff --git a/.idea/dictionaries/dzharkov.xml b/.idea/dictionaries/dzharkov.xml
index 91938406f8b..6a38863e835 100644
--- a/.idea/dictionaries/dzharkov.xml
+++ b/.idea/dictionaries/dzharkov.xml
@@ -3,6 +3,8 @@
checkcast
coroutine
+ experimentalities
+ experimentality
insn
liveness
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java
index fb2c7275087..89785af9329 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java
@@ -226,6 +226,9 @@ public interface Errors {
DiagnosticFactory1 ILLEGAL_KOTLIN_VERSION_STRING_VALUE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1 NEWER_VERSION_IN_SINCE_KOTLIN = DiagnosticFactory1.create(WARNING);
+ DiagnosticFactory2 EXPERIMENTAL_API_USAGE = DiagnosticFactory2.create(WARNING);
+ DiagnosticFactory2 EXPERIMENTAL_API_USAGE_ERROR = DiagnosticFactory2.create(ERROR);
+
// Const
DiagnosticFactory0 CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0 CONST_VAL_WITH_GETTER = DiagnosticFactory0.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 145c47a3ffc..c280a0ee44f 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.config.LanguageVersion;
import org.jetbrains.kotlin.diagnostics.Diagnostic;
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
import org.jetbrains.kotlin.diagnostics.Errors;
+import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.resolve.VarianceConflictDiagnosticData;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.VersionRequirement;
import org.jetbrains.kotlin.types.KotlinTypeKt;
@@ -22,6 +23,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.ServiceLoader;
@@ -138,6 +140,17 @@ public class DefaultErrorMessages {
MAP.put(ILLEGAL_KOTLIN_VERSION_STRING_VALUE, "Invalid @{0} annotation value (should be ''major.minor'' or ''major.minor.patch'')", TO_STRING);
MAP.put(NEWER_VERSION_IN_SINCE_KOTLIN, "The version is greater than the specified API version {0}", STRING);
+ RenderingContext.Key getExperimentalFqName = new RenderingContext.Key("getExperimentalFqName") {
+ @Override
+ public FqName compute(@NotNull Collection> objectsToRender) {
+ return (FqName) CollectionsKt.first(objectsToRender);
+ }
+ };
+ DiagnosticParameterRenderer renderUseExperimental = (useExperimentalAllowed, c) ->
+ useExperimentalAllowed ? " or ''@UseExperimental(" + c.get(getExperimentalFqName) + "::class)''" : "";
+ MAP.put(EXPERIMENTAL_API_USAGE, "This declaration is experimental and its usage should be marked with ''@{0}''{1}", TO_STRING, renderUseExperimental);
+ MAP.put(EXPERIMENTAL_API_USAGE_ERROR, "This declaration is experimental and its usage must be marked with ''@{0}''{1}", TO_STRING, renderUseExperimental);
+
MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING);
MAP.put(REDUNDANT_OPEN_IN_INTERFACE, "Modifier 'open' is redundant for abstract interface members");
MAP.put(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter");
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/RenderingContext.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/RenderingContext.kt
index c946cc5625f..ff7304fa24d 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/RenderingContext.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/RenderingContext.kt
@@ -29,17 +29,12 @@ sealed class RenderingContext {
class Impl(private val objectsToRender: Collection) : RenderingContext() {
private val data = linkedMapOf, Any?>()
+ @Suppress("UNCHECKED_CAST")
override fun get(key: Key): T {
- if (!data.containsKey(key)) {
- val result = key.compute(objectsToRender)
- data[key] = result
- return result
- }
- return data[key] as T
+ return data[key] as? T ?: key.compute(objectsToRender).also { data[key] = it }
}
}
-
object Empty : RenderingContext() {
override fun get(key: Key): T {
return key.compute(emptyList())
@@ -65,4 +60,4 @@ sealed class RenderingContext {
return Impl(parameters)
}
}
-}
\ No newline at end of file
+}
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt
index 17f15357021..e1e6c409aef 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt
@@ -91,12 +91,14 @@ private val DEFAULT_CALL_CHECKERS = listOf(
CoroutineSuspendCallChecker, BuilderFunctionsCallChecker, DslScopeViolationCallChecker, MissingDependencyClassChecker,
CallableReferenceCompatibilityChecker(), LateinitIntrinsicApplicabilityChecker,
UnderscoreUsageChecker, AssigningNamedArgumentToVarargChecker(),
- PrimitiveNumericComparisonCallChecker, LambdaWithSuspendModifierCallChecker
+ PrimitiveNumericComparisonCallChecker, LambdaWithSuspendModifierCallChecker, ExperimentalUsageChecker
)
private val DEFAULT_TYPE_CHECKERS = emptyList()
private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(
- DeprecatedClassifierUsageChecker(), ApiVersionClassifierUsageChecker, MissingDependencyClassChecker.ClassifierUsage
+ DeprecatedClassifierUsageChecker(), ApiVersionClassifierUsageChecker, MissingDependencyClassChecker.ClassifierUsage,
+ ExperimentalUsageChecker.ClassifierUsage
)
+private val DEFAULT_ANNOTATION_CHECKERS = emptyList()
abstract class PlatformConfigurator(
@@ -105,7 +107,7 @@ abstract class PlatformConfigurator(
additionalCallCheckers: List,
additionalTypeCheckers: List,
additionalClassifierUsageCheckers: List,
- private val additionalAnnotationCheckers: List,
+ additionalAnnotationCheckers: List,
private val identifierChecker: IdentifierChecker,
private val overloadFilter: OverloadFilter,
private val platformToKotlinClassMap: PlatformToKotlinClassMap,
@@ -118,6 +120,7 @@ abstract class PlatformConfigurator(
private val typeCheckers: List = DEFAULT_TYPE_CHECKERS + additionalTypeCheckers
private val classifierUsageCheckers: List =
DEFAULT_CLASSIFIER_USAGE_CHECKERS + additionalClassifierUsageCheckers
+ private val annotationCheckers: List = DEFAULT_ANNOTATION_CHECKERS + additionalAnnotationCheckers
abstract fun configureModuleComponents(container: StorageComponentContainer)
@@ -127,7 +130,7 @@ abstract class PlatformConfigurator(
callCheckers.forEach { useInstance(it) }
typeCheckers.forEach { useInstance(it) }
classifierUsageCheckers.forEach { useInstance(it) }
- additionalAnnotationCheckers.forEach { useInstance(it) }
+ annotationCheckers.forEach { useInstance(it) }
useInstance(identifierChecker)
useInstance(overloadFilter)
useInstance(platformToKotlinClassMap)
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt
new file mode 100644
index 00000000000..ae471a7fba9
--- /dev/null
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2010-2017 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.kotlin.resolve.checkers
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
+import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
+import org.jetbrains.kotlin.diagnostics.Errors
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.BindingTrace
+import org.jetbrains.kotlin.resolve.DescriptorUtils
+import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
+import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
+import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
+import org.jetbrains.kotlin.resolve.constants.ArrayValue
+import org.jetbrains.kotlin.resolve.constants.EnumValue
+import org.jetbrains.kotlin.resolve.constants.KClassValue
+import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+import org.jetbrains.kotlin.utils.SmartSet
+import org.jetbrains.kotlin.utils.addIfNotNull
+
+object ExperimentalUsageChecker : CallChecker {
+ private val EXPERIMENTAL_FQ_NAME = FqName("kotlin.Experimental")
+ private val USE_EXPERIMENTAL_FQ_NAME = FqName("kotlin.UseExperimental")
+ private val USE_EXPERIMENTAL_ANNOTATION_CLASS = Name.identifier("markerClass")
+
+ private val LEVEL = Name.identifier("level")
+ private val WARNING_LEVEL = Name.identifier("WARNING")
+ private val ERROR_LEVEL = Name.identifier("ERROR")
+
+ private val IMPACT = Name.identifier("changesMayBreak")
+ private val COMPILATION_IMPACT = Name.identifier("COMPILATION")
+ private val LINKAGE_IMPACT = Name.identifier("LINKAGE")
+ private val RUNTIME_IMPACT = Name.identifier("RUNTIME")
+
+ private data class Experimentality(val annotationFqName: FqName, val severity: Severity, val impact: List) {
+ val isCompilationOnly: Boolean get() = impact.all(Impact.COMPILATION::equals)
+
+ enum class Severity { WARNING, ERROR }
+ enum class Impact { COMPILATION, LINKAGE_OR_RUNTIME }
+
+ companion object {
+ val DEFAULT_SEVERITY = Severity.ERROR
+ val DEFAULT_IMPACT = listOf(Impact.COMPILATION, Impact.LINKAGE_OR_RUNTIME)
+ }
+ }
+
+ override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
+ checkExperimental(resolvedCall.resultingDescriptor, reportOn, context.trace)
+ }
+
+ private fun checkExperimental(descriptor: DeclarationDescriptor, element: PsiElement, trace: BindingTrace) {
+ for (experimentality in descriptor.loadExperimentalities()) {
+ val (annotationFqName, severity, impact) = experimentality
+ val isBodyUsageOfCompilationExperimentality =
+ experimentality.isCompilationOnly && element.isBodyUsage()
+
+ val isExperimentalityAccepted =
+ (isBodyUsageOfCompilationExperimentality &&
+ element.hasContainerAnnotatedWithUseExperimental(annotationFqName, trace.bindingContext)) ||
+ element.propagates(annotationFqName, trace.bindingContext)
+
+ if (!isExperimentalityAccepted) {
+ val diagnostic = when (severity) {
+ ExperimentalUsageChecker.Experimentality.Severity.WARNING -> Errors.EXPERIMENTAL_API_USAGE
+ ExperimentalUsageChecker.Experimentality.Severity.ERROR -> Errors.EXPERIMENTAL_API_USAGE_ERROR
+ }
+ trace.report(diagnostic.on(element, annotationFqName, isBodyUsageOfCompilationExperimentality))
+ }
+ }
+ }
+
+ private fun DeclarationDescriptor.loadExperimentalities(): Set {
+ val result = SmartSet.create()
+
+ for (annotation in annotations) {
+ result.addIfNotNull(annotation.loadExperimentalityForMarkerAnnotation())
+ }
+
+ val container = containingDeclaration
+ if (container is ClassDescriptor && this !is ConstructorDescriptor) {
+ for (annotation in container.annotations) {
+ result.addIfNotNull(annotation.loadExperimentalityForMarkerAnnotation())
+ }
+ }
+
+ return result
+ }
+
+ private fun AnnotationDescriptor.loadExperimentalityForMarkerAnnotation(): Experimentality? {
+ val experimental = annotationClass?.annotations?.findAnnotation(EXPERIMENTAL_FQ_NAME) ?: return null
+ val annotationFqName = fqName ?: return null
+
+ val severity = when ((experimental.allValueArguments[LEVEL] as? EnumValue)?.enumEntryName) {
+ WARNING_LEVEL -> Experimentality.Severity.WARNING
+ ERROR_LEVEL -> Experimentality.Severity.ERROR
+ else -> Experimentality.DEFAULT_SEVERITY
+ }
+
+ val impact = (experimental.allValueArguments[IMPACT] as? ArrayValue)?.value?.mapNotNull { impact ->
+ when ((impact as? EnumValue)?.enumEntryName) {
+ COMPILATION_IMPACT -> Experimentality.Impact.COMPILATION
+ LINKAGE_IMPACT, RUNTIME_IMPACT -> Experimentality.Impact.LINKAGE_OR_RUNTIME
+ else -> null
+ }
+ } ?: Experimentality.DEFAULT_IMPACT
+
+ return Experimentality(annotationFqName, severity, impact)
+ }
+
+ // Returns true if this element appears in the body of some function and is not visible in any non-local declaration signature.
+ // If that's the case, one can opt-in to using the corresponding experimental API by annotating this element (or any of its
+ // enclosing declarations) with @UseExperimental(X::class), not requiring propagation of the experimental annotation to the call sites.
+ // (Note that this is allowed only if X's impact is [COMPILATION].)
+ private fun PsiElement.isBodyUsage(): Boolean {
+ return anyParentMatches { element, parent ->
+ element == (parent as? KtDeclarationWithBody)?.bodyExpression ||
+ element == (parent as? KtDeclarationWithInitializer)?.initializer ||
+ element == (parent as? KtClassInitializer)?.body ||
+ element == (parent as? KtParameter)?.defaultValue ||
+ element == (parent as? KtSuperTypeCallEntry)?.valueArgumentList ||
+ element == (parent as? KtDelegatedSuperTypeEntry)?.delegateExpression ||
+ element == (parent as? KtPropertyDelegate)?.expression
+ }
+ }
+
+ // Checks whether any of the non-local enclosing declarations is annotated with annotationFqName, effectively requiring
+ // propagation for the experimental annotation to the call sites
+ private fun PsiElement.propagates(annotationFqName: FqName, bindingContext: BindingContext): Boolean {
+ return anyParentMatches { element, _ ->
+ if (element is KtDeclaration) {
+ val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element)
+ descriptor != null && !DescriptorUtils.isLocal(descriptor) && descriptor.annotations.hasAnnotation(annotationFqName)
+ } else false
+ }
+ }
+
+ // Checks whether there's an element lexically above the tree, that is annotated with `@UseExperimental(X::class)`
+ // where annotationFqName is the FQ name of X
+ private fun PsiElement.hasContainerAnnotatedWithUseExperimental(annotationFqName: FqName, bindingContext: BindingContext): Boolean {
+ return anyParentMatches { element, _ ->
+ element is KtAnnotated && element.annotationEntries.any { entry ->
+ bindingContext.get(BindingContext.ANNOTATION, entry)?.isUseExperimental(annotationFqName) == true
+ }
+ }
+ }
+
+ private inline fun PsiElement.anyParentMatches(predicate: (element: PsiElement, parent: PsiElement?) -> Boolean): Boolean {
+ var element = this
+ while (true) {
+ val parent = element.parent
+ if (predicate(element, parent)) return true
+ element = parent ?: return false
+ }
+ }
+
+ private fun AnnotationDescriptor.isUseExperimental(annotationFqName: FqName): Boolean {
+ if (fqName != USE_EXPERIMENTAL_FQ_NAME) return false
+
+ val annotationClasses = allValueArguments[USE_EXPERIMENTAL_ANNOTATION_CLASS]
+ return annotationClasses is ArrayValue && annotationClasses.value.any { annotationClass ->
+ (annotationClass as? KClassValue)?.value?.constructor?.declarationDescriptor?.fqNameSafe == annotationFqName
+ }
+ }
+
+ object ClassifierUsage : ClassifierUsageChecker {
+ override fun check(targetDescriptor: ClassifierDescriptor, element: PsiElement, context: ClassifierUsageCheckerContext) {
+ checkExperimental(targetDescriptor, element, context.trace)
+ }
+ }
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/annotation.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/annotation.kt
new file mode 100644
index 00000000000..2918dd74429
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/annotation.kt
@@ -0,0 +1,136 @@
+// !API_VERSION: 1.3
+// !DIAGNOSTICS: -UNUSED_PARAMETER
+// FILE: api.kt
+
+package api
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
+@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
+ AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
+annotation class ExperimentalAPI
+
+@ExperimentalAPI
+@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
+ AnnotationTarget.VALUE_PARAMETER)
+annotation class EAnno
+
+// FILE: usage-propagate.kt
+
+package usage1
+
+import api.*
+
+@ExperimentalAPI
+@EAnno fun function() {}
+
+@ExperimentalAPI
+fun parameter(@EAnno p: String) {}
+
+@ExperimentalAPI
+fun parameterType(p: @EAnno String) {}
+
+@ExperimentalAPI
+fun returnType(): @EAnno Unit {}
+
+@ExperimentalAPI
+@EAnno val property = ""
+
+@ExperimentalAPI
+@EAnno typealias Typealias = Unit
+
+@ExperimentalAPI
+@EAnno class Klass
+
+@ExperimentalAPI
+annotation class AnnotationArgument(val p: EAnno)
+
+@ExperimentalAPI
+fun insideBody() {
+ @EAnno fun local() {}
+}
+
+@ExperimentalAPI
+fun inDefaultArgument(f: () -> Unit = @EAnno fun() {}) {}
+
+@ExperimentalAPI
+val inProperty = @EAnno fun() {}
+
+@ExperimentalAPI
+val inPropertyAccessor: () -> Unit
+ get() = @EAnno fun() {}
+
+// FILE: usage-use.kt
+
+package usage2
+
+import api.*
+
+@UseExperimental(ExperimentalAPI::class)
+@EAnno fun function() {}
+
+@UseExperimental(ExperimentalAPI::class)
+fun parameter(@EAnno p: String) {}
+
+@UseExperimental(ExperimentalAPI::class)
+fun parameterType(p: @EAnno String) {}
+
+@UseExperimental(ExperimentalAPI::class)
+fun returnType(): @EAnno Unit {}
+
+@UseExperimental(ExperimentalAPI::class)
+@EAnno val property = ""
+
+@UseExperimental(ExperimentalAPI::class)
+@EAnno typealias Typealias = Unit
+
+@UseExperimental(ExperimentalAPI::class)
+@EAnno class Klass
+
+@UseExperimental(ExperimentalAPI::class)
+annotation class AnnotationArgument(val p: EAnno)
+
+fun insideBody() {
+ @UseExperimental(ExperimentalAPI::class) @EAnno fun local() {}
+}
+
+fun inDefaultArgument(@UseExperimental(ExperimentalAPI::class) f: () -> Unit = @EAnno fun() {}) {}
+
+@UseExperimental(ExperimentalAPI::class)
+val inProperty = @EAnno fun() {}
+
+val inPropertyAccessor: () -> Unit
+ @UseExperimental(ExperimentalAPI::class)
+ get() = @EAnno fun() {}
+
+// FILE: usage-none.kt
+
+package usage3
+
+import api.*
+
+@EAnno fun function() {}
+
+fun parameter(@EAnno p: String) {}
+
+fun parameterType(p: @EAnno String) {}
+
+fun returnType(): @EAnno Unit {}
+
+@EAnno val property = ""
+
+@EAnno typealias Typealias = Unit
+
+@EAnno class Klass
+
+annotation class AnnotationArgument(val p: EAnno)
+
+fun insideBody() {
+ @EAnno fun local() {}
+}
+
+fun inDefaultArgument(f: () -> Unit = @EAnno fun() {}) {}
+
+val inProperty = @EAnno fun() {}
+
+val inPropertyAccessor: () -> Unit
+ get() = @EAnno fun() {}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/annotation.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/annotation.txt
new file mode 100644
index 00000000000..34f11bd2c47
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/annotation.txt
@@ -0,0 +1,102 @@
+package
+
+package api {
+
+ @api.ExperimentalAPI @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS, AnnotationTarget.VALUE_PARAMETER}) public final annotation class EAnno : kotlin.Annotation {
+ public constructor EAnno()
+ 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.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION}) public final annotation class ExperimentalAPI : kotlin.Annotation {
+ public constructor ExperimentalAPI()
+ 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
+ }
+}
+
+package usage1 {
+ @api.ExperimentalAPI public val inProperty: () -> kotlin.Unit
+ @api.ExperimentalAPI public val inPropertyAccessor: () -> kotlin.Unit
+ @api.ExperimentalAPI @api.EAnno public val property: kotlin.String = ""
+ @api.ExperimentalAPI @api.EAnno public fun function(): kotlin.Unit
+ @api.ExperimentalAPI public fun inDefaultArgument(/*0*/ f: () -> kotlin.Unit = ...): kotlin.Unit
+ @api.ExperimentalAPI public fun insideBody(): kotlin.Unit
+ @api.ExperimentalAPI public fun parameter(/*0*/ @api.EAnno p: kotlin.String): kotlin.Unit
+ @api.ExperimentalAPI public fun parameterType(/*0*/ p: @api.EAnno kotlin.String): kotlin.Unit
+ @api.ExperimentalAPI public fun returnType(): @api.EAnno kotlin.Unit
+
+ @api.ExperimentalAPI public final annotation class AnnotationArgument : kotlin.Annotation {
+ public constructor AnnotationArgument(/*0*/ p: api.EAnno)
+ public final val p: api.EAnno
+ 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
+ }
+
+ @api.ExperimentalAPI @api.EAnno public final class Klass {
+ public constructor Klass()
+ 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
+ }
+ @api.ExperimentalAPI @api.EAnno public typealias Typealias = kotlin.Unit
+}
+
+package usage2 {
+ @kotlin.UseExperimental(markerClass = {api.ExperimentalAPI::class}) public val inProperty: () -> kotlin.Unit
+ public val inPropertyAccessor: () -> kotlin.Unit
+ @kotlin.UseExperimental(markerClass = {api.ExperimentalAPI::class}) @api.EAnno public val property: kotlin.String = ""
+ @kotlin.UseExperimental(markerClass = {api.ExperimentalAPI::class}) @api.EAnno public fun function(): kotlin.Unit
+ public fun inDefaultArgument(/*0*/ @kotlin.UseExperimental(markerClass = {api.ExperimentalAPI::class}) f: () -> kotlin.Unit = ...): kotlin.Unit
+ public fun insideBody(): kotlin.Unit
+ @kotlin.UseExperimental(markerClass = {api.ExperimentalAPI::class}) public fun parameter(/*0*/ @api.EAnno p: kotlin.String): kotlin.Unit
+ @kotlin.UseExperimental(markerClass = {api.ExperimentalAPI::class}) public fun parameterType(/*0*/ p: @api.EAnno kotlin.String): kotlin.Unit
+ @kotlin.UseExperimental(markerClass = {api.ExperimentalAPI::class}) public fun returnType(): @api.EAnno kotlin.Unit
+
+ @kotlin.UseExperimental(markerClass = {api.ExperimentalAPI::class}) public final annotation class AnnotationArgument : kotlin.Annotation {
+ public constructor AnnotationArgument(/*0*/ p: api.EAnno)
+ public final val p: api.EAnno
+ 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.UseExperimental(markerClass = {api.ExperimentalAPI::class}) @api.EAnno public final class Klass {
+ public constructor Klass()
+ 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.UseExperimental(markerClass = {api.ExperimentalAPI::class}) @api.EAnno public typealias Typealias = kotlin.Unit
+}
+
+package usage3 {
+ public val inProperty: () -> kotlin.Unit
+ public val inPropertyAccessor: () -> kotlin.Unit
+ @api.EAnno public val property: kotlin.String = ""
+ @api.EAnno public fun function(): kotlin.Unit
+ public fun inDefaultArgument(/*0*/ f: () -> kotlin.Unit = ...): kotlin.Unit
+ public fun insideBody(): kotlin.Unit
+ public fun parameter(/*0*/ @api.EAnno p: kotlin.String): kotlin.Unit
+ public fun parameterType(/*0*/ p: @api.EAnno kotlin.String): kotlin.Unit
+ public fun returnType(): @api.EAnno kotlin.Unit
+
+ public final annotation class AnnotationArgument : kotlin.Annotation {
+ public constructor AnnotationArgument(/*0*/ p: api.EAnno)
+ public final val p: api.EAnno
+ 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
+ }
+
+ @api.EAnno public final class Klass {
+ public constructor Klass()
+ 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
+ }
+ @api.EAnno public typealias Typealias = kotlin.Unit
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/bodyUsages.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/bodyUsages.kt
new file mode 100644
index 00000000000..f1a8a249a7e
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/bodyUsages.kt
@@ -0,0 +1,30 @@
+// !API_VERSION: 1.3
+// FILE: api.kt
+
+package api
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
+annotation class ExperimentalCompilationAPI
+
+interface I
+
+@ExperimentalCompilationAPI
+class Impl : I
+
+// FILE: usage.kt
+
+package usage
+
+import api.*
+
+open class Base(val i: I)
+
+@UseExperimental(ExperimentalCompilationAPI::class)
+class Derived : Base(Impl())
+
+@UseExperimental(ExperimentalCompilationAPI::class)
+class Delegated : I by Impl()
+
+@UseExperimental(ExperimentalCompilationAPI::class)
+val delegatedProperty by Impl()
+operator fun I.getValue(x: Any?, y: Any?) = null
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/bodyUsages.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/bodyUsages.txt
new file mode 100644
index 00000000000..1cd8553d863
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/bodyUsages.txt
@@ -0,0 +1,52 @@
+package
+
+package api {
+
+ @kotlin.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) public final annotation class ExperimentalCompilationAPI : kotlin.Annotation {
+ public constructor ExperimentalCompilationAPI()
+ 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 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
+ }
+
+ @api.ExperimentalCompilationAPI public final class Impl : api.I {
+ public constructor Impl()
+ 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
+ }
+}
+
+package usage {
+ @kotlin.UseExperimental(markerClass = {api.ExperimentalCompilationAPI::class}) public val delegatedProperty: kotlin.Nothing?
+ public operator fun api.I.getValue(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?): kotlin.Nothing?
+
+ public open class Base {
+ public constructor Base(/*0*/ i: api.I)
+ public final val i: api.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.UseExperimental(markerClass = {api.ExperimentalCompilationAPI::class}) public final class Delegated : api.I {
+ public constructor Delegated()
+ 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.UseExperimental(markerClass = {api.ExperimentalCompilationAPI::class}) public final class Derived : usage.Base {
+ public constructor Derived()
+ public final override /*1*/ /*fake_override*/ val i: api.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
+ }
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/classMembers.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/classMembers.kt
new file mode 100644
index 00000000000..528f8f00a10
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/classMembers.kt
@@ -0,0 +1,88 @@
+// !API_VERSION: 1.3
+// FILE: api.kt
+
+package api
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
+@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
+annotation class ExperimentalAPI
+
+@ExperimentalAPI
+class C {
+ fun function(): String = ""
+ val property: String = ""
+ class Nested
+ inner class Inner
+}
+
+@ExperimentalAPI
+fun C.extension() {}
+
+// FILE: usage-propagate.kt
+
+package usage1
+
+import api.*
+
+@ExperimentalAPI
+fun useAll() {
+ val c: C = C()
+ c.function()
+ c.property
+ C.Nested()
+ c.Inner()
+ c.extension()
+}
+
+@ExperimentalAPI
+class Use {
+ fun useAll(c: C) {
+ c.function()
+ c.property
+ C.Nested()
+ c.Inner()
+ c.extension()
+ }
+}
+
+// FILE: usage-use.kt
+
+package usage2
+
+import api.*
+
+@UseExperimental(ExperimentalAPI::class)
+fun useAll() {
+ val c: C = C()
+ c.function()
+ c.property
+ C.Nested()
+ c.Inner()
+ c.extension()
+}
+
+@UseExperimental(ExperimentalAPI::class)
+class Use {
+ fun useAll(c: C) {
+ c.function()
+ c.property
+ C.Nested()
+ c.Inner()
+ c.extension()
+ }
+}
+
+// FILE: usage-none.kt
+
+package usage3
+
+import api.*
+
+fun use() {
+ val c: C = C()
+ c.function()
+ c.property
+ C.Nested()
+ c.Inner()
+ c.extension()
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/classMembers.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/classMembers.txt
new file mode 100644
index 00000000000..8b754e9dd7c
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/classMembers.txt
@@ -0,0 +1,63 @@
+package
+
+package api {
+ @api.ExperimentalAPI public fun api.C.extension(): kotlin.Unit
+
+ @api.ExperimentalAPI public final class C {
+ public constructor C()
+ public final val property: kotlin.String = ""
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public final fun function(): kotlin.String
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+
+ public final inner class Inner {
+ public constructor Inner()
+ 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 Nested {
+ public constructor Nested()
+ 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.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FUNCTION}) public final annotation class ExperimentalAPI : kotlin.Annotation {
+ public constructor ExperimentalAPI()
+ 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
+ }
+}
+
+package usage1 {
+ @api.ExperimentalAPI public fun useAll(): kotlin.Unit
+
+ @api.ExperimentalAPI public final class Use {
+ public constructor Use()
+ 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 useAll(/*0*/ c: api.C): kotlin.Unit
+ }
+}
+
+package usage2 {
+ @kotlin.UseExperimental(markerClass = {api.ExperimentalAPI::class}) public fun useAll(): kotlin.Unit
+
+ @kotlin.UseExperimental(markerClass = {api.ExperimentalAPI::class}) public final class Use {
+ public constructor Use()
+ 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 useAll(/*0*/ c: api.C): kotlin.Unit
+ }
+}
+
+package usage3 {
+ public fun use(): kotlin.Unit
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/classMembersOverlyExperimental.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/classMembersOverlyExperimental.kt
new file mode 100644
index 00000000000..3e82f7c156d
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/classMembersOverlyExperimental.kt
@@ -0,0 +1,36 @@
+// !API_VERSION: 1.3
+// FILE: api.kt
+
+package api
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
+@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
+annotation class ExperimentalAPI
+
+@ExperimentalAPI
+class C {
+ @ExperimentalAPI
+ fun function() {}
+
+ @ExperimentalAPI
+ val property: String = ""
+
+ @ExperimentalAPI
+ class Nested {
+ @ExperimentalAPI
+ fun nestedFunction() {}
+ }
+}
+
+// FILE: usage.kt
+
+package usage
+
+import api.*
+
+fun use() {
+ val c: C = C()
+ c.function()
+ c.property
+ C.Nested().nestedFunction()
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/classMembersOverlyExperimental.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/classMembersOverlyExperimental.txt
new file mode 100644
index 00000000000..f8f3b3cc81f
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/classMembersOverlyExperimental.txt
@@ -0,0 +1,32 @@
+package
+
+package api {
+
+ @api.ExperimentalAPI public final class C {
+ public constructor C()
+ @api.ExperimentalAPI public final val property: kotlin.String = ""
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ @api.ExperimentalAPI public final fun function(): kotlin.Unit
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+
+ @api.ExperimentalAPI public final class Nested {
+ public constructor Nested()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ @api.ExperimentalAPI public final fun nestedFunction(): kotlin.Unit
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+ }
+ }
+
+ @kotlin.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public final annotation class ExperimentalAPI : kotlin.Annotation {
+ public constructor ExperimentalAPI()
+ 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
+ }
+}
+
+package usage {
+ public fun use(): kotlin.Unit
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/compilationVsLinkageVsRuntime.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/compilationVsLinkageVsRuntime.kt
new file mode 100644
index 00000000000..0a96a42bb52
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/compilationVsLinkageVsRuntime.kt
@@ -0,0 +1,73 @@
+// !API_VERSION: 1.3
+// FILE: api.kt
+
+package api
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
+annotation class ExperimentalCompilationAPI
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.LINKAGE])
+annotation class ExperimentalLinkageAPI
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.RUNTIME])
+annotation class ExperimentalRuntimeAPI
+
+@ExperimentalCompilationAPI
+fun compilation() {}
+
+@ExperimentalLinkageAPI
+fun linkage() {}
+
+@ExperimentalRuntimeAPI
+fun runtime() {}
+
+// FILE: usage.kt
+
+package usage1
+
+import api.*
+
+@UseExperimental(ExperimentalCompilationAPI::class)
+@ExperimentalLinkageAPI
+@ExperimentalRuntimeAPI
+fun use() {
+ compilation()
+ linkage()
+ runtime()
+}
+
+@ExperimentalLinkageAPI
+@ExperimentalRuntimeAPI
+fun useUse() {
+ use()
+}
+
+@ExperimentalCompilationAPI
+@ExperimentalLinkageAPI
+@ExperimentalRuntimeAPI
+fun recursiveUse() {
+ compilation()
+ linkage()
+ runtime()
+ recursiveUse()
+}
+
+// FILE: usage-no-annotation.txt
+
+package usage2
+
+import api.*
+
+fun use1() {
+ usage1.use()
+}
+
+@ExperimentalLinkageAPI
+fun use2() {
+ usage1.use()
+}
+
+@ExperimentalRuntimeAPI
+fun use3() {
+ usage1.use()
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/compilationVsLinkageVsRuntime.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/compilationVsLinkageVsRuntime.txt
new file mode 100644
index 00000000000..ead6bb7ff73
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/compilationVsLinkageVsRuntime.txt
@@ -0,0 +1,40 @@
+package
+
+package api {
+ @api.ExperimentalCompilationAPI public fun compilation(): kotlin.Unit
+ @api.ExperimentalLinkageAPI public fun linkage(): kotlin.Unit
+ @api.ExperimentalRuntimeAPI public fun runtime(): kotlin.Unit
+
+ @kotlin.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) public final annotation class ExperimentalCompilationAPI : kotlin.Annotation {
+ public constructor ExperimentalCompilationAPI()
+ 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.Experimental(changesMayBreak = {Impact.LINKAGE}, level = Level.WARNING) public final annotation class ExperimentalLinkageAPI : kotlin.Annotation {
+ public constructor ExperimentalLinkageAPI()
+ 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.Experimental(changesMayBreak = {Impact.RUNTIME}, level = Level.WARNING) public final annotation class ExperimentalRuntimeAPI : kotlin.Annotation {
+ public constructor ExperimentalRuntimeAPI()
+ 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
+ }
+}
+
+package usage1 {
+ @api.ExperimentalCompilationAPI @api.ExperimentalLinkageAPI @api.ExperimentalRuntimeAPI public fun recursiveUse(): kotlin.Unit
+ @kotlin.UseExperimental(markerClass = {api.ExperimentalCompilationAPI::class}) @api.ExperimentalLinkageAPI @api.ExperimentalRuntimeAPI public fun use(): kotlin.Unit
+ @api.ExperimentalLinkageAPI @api.ExperimentalRuntimeAPI public fun useUse(): kotlin.Unit
+}
+
+package usage2 {
+ public fun use1(): kotlin.Unit
+ @api.ExperimentalLinkageAPI public fun use2(): kotlin.Unit
+ @api.ExperimentalRuntimeAPI public fun use3(): kotlin.Unit
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt
new file mode 100644
index 00000000000..8568cca1bae
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt
@@ -0,0 +1,78 @@
+// !API_VERSION: 1.3
+// !DIAGNOSTICS: -UNUSED_VARIABLE
+// FILE: api.kt
+
+package api
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
+@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
+ AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
+annotation class ExperimentalAPI
+
+@ExperimentalAPI
+fun function(): String = ""
+
+@ExperimentalAPI
+val property: String = ""
+
+@ExperimentalAPI
+typealias Typealias = String
+
+// FILE: usage-propagate.kt
+
+package usage1
+
+import api.*
+
+@ExperimentalAPI
+fun useAll() {
+ function()
+ property
+ val s: Typealias = ""
+}
+
+@ExperimentalAPI
+class Use {
+ fun useAll() {
+ function()
+ property
+ val s: Typealias = ""
+ }
+}
+
+// FILE: usage-use.kt
+
+package usage2
+
+import api.*
+
+fun useAll() {
+ @UseExperimental(ExperimentalAPI::class)
+ {
+ function()
+ property
+ val s: Typealias = ""
+ }()
+}
+
+@UseExperimental(ExperimentalAPI::class)
+class Use {
+ fun useAll() {
+ function()
+ property
+ val s: Typealias = ""
+ }
+}
+
+// FILE: usage-none.kt
+
+package usage3
+
+import api.*
+
+fun use() {
+ function()
+ property
+ val s: Typealias = ""
+ s.hashCode()
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.txt
new file mode 100644
index 00000000000..671c5cf634f
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.txt
@@ -0,0 +1,42 @@
+package
+
+package api {
+ @api.ExperimentalAPI public val property: kotlin.String = ""
+ @api.ExperimentalAPI public fun function(): kotlin.String
+
+ @kotlin.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION}) public final annotation class ExperimentalAPI : kotlin.Annotation {
+ public constructor ExperimentalAPI()
+ 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
+ }
+ @api.ExperimentalAPI public typealias Typealias = kotlin.String
+}
+
+package usage1 {
+ @api.ExperimentalAPI public fun useAll(): kotlin.Unit
+
+ @api.ExperimentalAPI public final class Use {
+ public constructor Use()
+ 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 useAll(): kotlin.Unit
+ }
+}
+
+package usage2 {
+ public fun useAll(): kotlin.Unit
+
+ @kotlin.UseExperimental(markerClass = {api.ExperimentalAPI::class}) public final class Use {
+ public constructor Use()
+ 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 useAll(): kotlin.Unit
+ }
+}
+
+package usage3 {
+ public fun use(): kotlin.Unit
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/typealias.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/typealias.kt
new file mode 100644
index 00000000000..a0ad16616da
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/typealias.kt
@@ -0,0 +1,13 @@
+// !API_VERSION: 1.3
+// FILE: api.kt
+
+package api
+
+@Experimental
+@Target(AnnotationTarget.CLASS)
+annotation class ExperimentalAPI
+
+@ExperimentalAPI
+class Foo
+
+typealias Bar = Foo
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/typealias.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/typealias.txt
new file mode 100644
index 00000000000..770d6360eab
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/typealias.txt
@@ -0,0 +1,19 @@
+package
+
+package api {
+
+ @kotlin.Experimental @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS}) public final annotation class ExperimentalAPI : kotlin.Annotation {
+ public constructor ExperimentalAPI()
+ 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
+ }
+
+ @api.ExperimentalAPI public final class Foo {
+ public constructor Foo()
+ 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 typealias Bar = api.Foo
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalOnFile.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalOnFile.kt
new file mode 100644
index 00000000000..ba1b643b3db
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalOnFile.kt
@@ -0,0 +1,37 @@
+// !API_VERSION: 1.3
+// FILE: api.kt
+
+package api
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
+@Target(AnnotationTarget.FUNCTION)
+annotation class CompilationExperimentalAPI
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.RUNTIME])
+@Target(AnnotationTarget.FUNCTION)
+annotation class RuntimeExperimentalAPI
+
+@CompilationExperimentalAPI
+fun compilation() {}
+
+@RuntimeExperimentalAPI
+fun runtime() {}
+
+// FILE: usage.kt
+
+@file:UseExperimental(CompilationExperimentalAPI::class)
+package usage
+
+import api.*
+
+fun use() {
+ compilation()
+ runtime()
+}
+
+class Use {
+ fun use() {
+ compilation()
+ runtime()
+ }
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalOnFile.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalOnFile.txt
new file mode 100644
index 00000000000..f19ec327ceb
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalOnFile.txt
@@ -0,0 +1,32 @@
+package
+
+package api {
+ @api.CompilationExperimentalAPI public fun compilation(): kotlin.Unit
+ @api.RuntimeExperimentalAPI public fun runtime(): kotlin.Unit
+
+ @kotlin.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FUNCTION}) public final annotation class CompilationExperimentalAPI : kotlin.Annotation {
+ public constructor CompilationExperimentalAPI()
+ 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.Experimental(changesMayBreak = {Impact.RUNTIME}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FUNCTION}) public final annotation class RuntimeExperimentalAPI : kotlin.Annotation {
+ public constructor RuntimeExperimentalAPI()
+ 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
+ }
+}
+
+package usage {
+ public fun use(): kotlin.Unit
+
+ public final class Use {
+ public constructor Use()
+ 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
+ }
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalTargets.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalTargets.kt
new file mode 100644
index 00000000000..397945a4f15
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalTargets.kt
@@ -0,0 +1,54 @@
+// !API_VERSION: 1.3
+// !DIAGNOSTICS: -UNUSED_PARAMETER
+// FILE: api.kt
+
+package api
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
+@Target(AnnotationTarget.CLASS)
+annotation class E
+
+@E
+open class Foo(val s: String = "")
+
+// FILE: usage.kt
+
+import api.*
+
+@UseExperimental(E::class)
+class Klass {
+ init {
+ Foo()
+ }
+}
+
+class Constructor {
+ @UseExperimental(E::class) constructor() {
+ Foo()
+ }
+}
+
+@UseExperimental(E::class)
+val property = Foo().s
+
+@UseExperimental(E::class)
+fun function() {
+ Foo()
+}
+
+fun valueParameter(@UseExperimental(E::class) p: String = Foo().s): String {
+ @UseExperimental(E::class)
+ val localVariable: String = Foo().s
+ return localVariable
+}
+
+var propertyAccessors: String
+ @UseExperimental(E::class)
+ get() = Foo().s
+ @UseExperimental(E::class)
+ set(value) { Foo() }
+
+fun expression(): String {
+ val s = @UseExperimental(E::class) Foo().s
+ return s
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalTargets.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalTargets.txt
new file mode 100644
index 00000000000..dc75ed386f2
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalTargets.txt
@@ -0,0 +1,39 @@
+package
+
+@kotlin.UseExperimental(markerClass = {api.E::class}) public val property: kotlin.String
+public var propertyAccessors: kotlin.String
+public fun expression(): kotlin.String
+@kotlin.UseExperimental(markerClass = {api.E::class}) public fun function(): kotlin.Unit
+public fun valueParameter(/*0*/ @kotlin.UseExperimental(markerClass = {api.E::class}) p: kotlin.String = ...): kotlin.String
+
+public final class Constructor {
+ @kotlin.UseExperimental(markerClass = {api.E::class}) public constructor Constructor()
+ 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.UseExperimental(markerClass = {api.E::class}) public final class Klass {
+ public constructor Klass()
+ 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
+}
+
+package api {
+
+ @kotlin.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS}) 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
+ }
+
+ @api.E public open class Foo {
+ public constructor Foo(/*0*/ s: kotlin.String = ...)
+ public final val s: kotlin.String
+ 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
+ }
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalWithSeveralAnnotations.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalWithSeveralAnnotations.kt
new file mode 100644
index 00000000000..0d56ce82407
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalWithSeveralAnnotations.kt
@@ -0,0 +1,52 @@
+// !API_VERSION: 1.3
+// FILE: api.kt
+
+package api
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
+@Target(AnnotationTarget.FUNCTION)
+annotation class E1
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
+@Target(AnnotationTarget.FUNCTION)
+annotation class E2
+
+@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
+@Target(AnnotationTarget.FUNCTION)
+annotation class E3
+
+@E1
+fun e1() {}
+
+@E2
+fun e2() {}
+
+@E3
+fun e3() {}
+
+// FILE: usage.kt
+
+package usage
+
+import api.*
+
+@UseExperimental(E1::class, E2::class, E3::class)
+fun use1() {
+ e1()
+ e2()
+ e3()
+}
+
+@UseExperimental(E1::class, E3::class)
+fun use2() {
+ e1()
+ @UseExperimental(E2::class) e2()
+ e3()
+}
+
+@UseExperimental(E1::class, E2::class)
+fun use3() {
+ e1()
+ e2()
+ e3()
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalWithSeveralAnnotations.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalWithSeveralAnnotations.txt
new file mode 100644
index 00000000000..a2be94a9946
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalWithSeveralAnnotations.txt
@@ -0,0 +1,34 @@
+package
+
+package api {
+ @api.E1 public fun e1(): kotlin.Unit
+ @api.E2 public fun e2(): kotlin.Unit
+ @api.E3 public fun e3(): kotlin.Unit
+
+ @kotlin.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FUNCTION}) public final annotation class E1 : kotlin.Annotation {
+ public constructor E1()
+ 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.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FUNCTION}) public final annotation class E2 : kotlin.Annotation {
+ public constructor E2()
+ 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.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FUNCTION}) public final annotation class E3 : kotlin.Annotation {
+ public constructor E3()
+ 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
+ }
+}
+
+package usage {
+ @kotlin.UseExperimental(markerClass = {api.E1::class, api.E2::class, api.E3::class}) public fun use1(): kotlin.Unit
+ @kotlin.UseExperimental(markerClass = {api.E1::class, api.E3::class}) public fun use2(): kotlin.Unit
+ @kotlin.UseExperimental(markerClass = {api.E1::class, api.E2::class}) public fun use3(): kotlin.Unit
+}
diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java
index de27fce9e47..741a1571c16 100644
--- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java
+++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java
@@ -1795,6 +1795,75 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
}
}
+ @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class Experimental extends AbstractDiagnosticsTestWithStdLib {
+ public void testAllFilesPresentInExperimental() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/experimental"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("annotation.kt")
+ public void testAnnotation() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/annotation.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("bodyUsages.kt")
+ public void testBodyUsages() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/bodyUsages.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("classMembers.kt")
+ public void testClassMembers() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/classMembers.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("classMembersOverlyExperimental.kt")
+ public void testClassMembersOverlyExperimental() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/classMembersOverlyExperimental.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("compilationVsLinkageVsRuntime.kt")
+ public void testCompilationVsLinkageVsRuntime() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/compilationVsLinkageVsRuntime.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("topLevel.kt")
+ public void testTopLevel() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("typealias.kt")
+ public void testTypealias() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/typealias.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("useExperimentalOnFile.kt")
+ public void testUseExperimentalOnFile() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalOnFile.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("useExperimentalTargets.kt")
+ public void testUseExperimentalTargets() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalTargets.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("useExperimentalWithSeveralAnnotations.kt")
+ public void testUseExperimentalWithSeveralAnnotations() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalWithSeveralAnnotations.kt");
+ doTest(fileName);
+ }
+ }
+
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/forInArrayLoop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java
index e65650545c5..9c18a301e18 100644
--- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java
+++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java
@@ -1795,6 +1795,75 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
}
}
+ @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class Experimental extends AbstractDiagnosticsTestWithStdLibUsingJavac {
+ public void testAllFilesPresentInExperimental() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/experimental"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("annotation.kt")
+ public void testAnnotation() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/annotation.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("bodyUsages.kt")
+ public void testBodyUsages() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/bodyUsages.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("classMembers.kt")
+ public void testClassMembers() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/classMembers.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("classMembersOverlyExperimental.kt")
+ public void testClassMembersOverlyExperimental() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/classMembersOverlyExperimental.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("compilationVsLinkageVsRuntime.kt")
+ public void testCompilationVsLinkageVsRuntime() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/compilationVsLinkageVsRuntime.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("topLevel.kt")
+ public void testTopLevel() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("typealias.kt")
+ public void testTypealias() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/typealias.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("useExperimentalOnFile.kt")
+ public void testUseExperimentalOnFile() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalOnFile.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("useExperimentalTargets.kt")
+ public void testUseExperimentalTargets() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalTargets.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("useExperimentalWithSeveralAnnotations.kt")
+ public void testUseExperimentalWithSeveralAnnotations() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/useExperimentalWithSeveralAnnotations.kt");
+ doTest(fileName);
+ }
+ }
+
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/forInArrayLoop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
diff --git a/libraries/stdlib/src/kotlin/annotations/Experimental.kt b/libraries/stdlib/src/kotlin/annotations/Experimental.kt
new file mode 100644
index 00000000000..70a01dc9c84
--- /dev/null
+++ b/libraries/stdlib/src/kotlin/annotations/Experimental.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2010-2017 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package kotlin
+
+import kotlin.annotation.AnnotationRetention.BINARY
+import kotlin.annotation.AnnotationRetention.SOURCE
+import kotlin.annotation.AnnotationTarget.*
+import kotlin.reflect.KClass
+
+/**
+ * Signals that the annotated annotation class is a marker of an experimental API. Any declaration annotated with that marker is thus
+ * considered an experimental declaration and its call sites must accept the experimental aspect of it either by using [UseExperimental],
+ * or by being annotated with that marker themselves, effectively causing further propagation of that experimental aspect.
+ */
+@Target(ANNOTATION_CLASS)
+@Retention(BINARY)
+@SinceKotlin("1.3")
+@Suppress("ANNOTATION_CLASS_WITH_BODY", "ANNOTATION_CLASS_MEMBER", "ReplaceArrayOfWithLiteral")
+annotation class Experimental(
+ val level: Level = Level.ERROR,
+ val changesMayBreak: Array = arrayOf(Impact.COMPILATION, Impact.LINKAGE, Impact.RUNTIME) // arrayOf, not [] because of KT-22578
+) {
+ /**
+ * Severity of the diagnostic that should be reported on usages of experimental API which did not explicitly accept the experimental aspect
+ * of that API either by using [UseExperimental] or by being annotated with the corresponding marker annotation.
+ */
+ enum class Level {
+ /** Specifies that a warning should be reported on incorrect usages of this experimental API. */
+ WARNING,
+ /** Specifies that an error should be reported on incorrect usages of this experimental API. */
+ ERROR,
+ }
+
+ /**
+ * Impact of the experimental API specifies what aspects may break after that API is changed.
+ */
+ enum class Impact {
+ /**
+ * Signifies that changes in this experimental API can cause compilation errors or warnings in the client code.
+ *
+ * Non-signature usages (inside a function body, variable initializer, default argument value, etc.) of compilation-affecting
+ * experimental API are allowed either if the containing declaration is annotated with the experimental annotation marker
+ * and thus propagates the experimental aspect to its clients, or if there's a [UseExperimental] annotation entry with
+ * the corresponding annotation marker somewhere above that usage in the parse tree. Signature usages of compilation-affecting
+ * experimental API always require propagation (as long as the experimental API is declared in another module).
+ */
+ COMPILATION,
+ /**
+ * Signifies that changes in this experimental API can cause linkage errors, i.e. exceptions at runtime
+ * if the client code was not recompiled after the change.
+ *
+ * Any usage of a linkage-affecting experimental API requires its containing declaration to be annotated with
+ * the corresponding annotation marker (except non-signature usages in annotation marker's module).
+ */
+ LINKAGE,
+ /**
+ * Signifies that changes in this experimental API can cause changes in runtime behavior, including exceptions at runtime.
+ *
+ * Any usage of a runtime-affecting experimental API requires its containing declaration to be annotated with
+ * the corresponding annotation marker (except non-signature usages in the annotation marker's module).
+ */
+ RUNTIME,
+ }
+}
+
+/**
+ * Allows to use experimental API denoted by the given markers in the annotated file, declaration, or expression. Each of the given markers
+ * must be an annotation class, whose impact ([Experimental.changesMayBreak]) is [Experimental.Impact.COMPILATION].
+ * Any other given annotation classes have no effect and are ignored.
+ *
+ * Only allows non-signature usages of the experimental API, i.e. inside a function body, variable initializer, default argument value, etc.
+ * (Usages in declaration signatures must be propagated by annotating the affected signature with the marker annotation itself.)
+ */
+@Target(CLASS, PROPERTY, LOCAL_VARIABLE, VALUE_PARAMETER, CONSTRUCTOR, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, EXPRESSION, FILE)
+@Retention(SOURCE)
+@SinceKotlin("1.3")
+annotation class UseExperimental(
+ vararg val markerClass: KClass
+)
diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt
index 6d153e2b4f5..a190731f1a2 100644
--- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt
+++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt
@@ -20,6 +20,26 @@ public final class kotlin/ExceptionsKt {
public static final fun getStackTrace (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement;
}
+public abstract interface annotation class kotlin/Experimental : java/lang/annotation/Annotation {
+ public abstract fun changesMayBreak ()[Lkotlin/Experimental$Impact;
+ public abstract fun level ()Lkotlin/Experimental$Level;
+}
+
+public final class kotlin/Experimental$Impact : java/lang/Enum {
+ public static final field COMPILATION Lkotlin/Experimental$Impact;
+ public static final field LINKAGE Lkotlin/Experimental$Impact;
+ public static final field RUNTIME Lkotlin/Experimental$Impact;
+ public static fun valueOf (Ljava/lang/String;)Lkotlin/Experimental$Impact;
+ public static fun values ()[Lkotlin/Experimental$Impact;
+}
+
+public final class kotlin/Experimental$Level : java/lang/Enum {
+ public static final field ERROR Lkotlin/Experimental$Level;
+ public static final field WARNING Lkotlin/Experimental$Level;
+ public static fun valueOf (Ljava/lang/String;)Lkotlin/Experimental$Level;
+ public static fun values ()[Lkotlin/Experimental$Level;
+}
+
public abstract interface annotation class kotlin/ExtensionFunctionType : java/lang/annotation/Annotation {
}
@@ -159,6 +179,10 @@ public final class kotlin/Unit {
public abstract interface annotation class kotlin/UnsafeVariance : java/lang/annotation/Annotation {
}
+public abstract interface annotation class kotlin/UseExperimental : java/lang/annotation/Annotation {
+ public abstract fun markerClass ()[Ljava/lang/Class;
+}
+
public final class kotlin/_Assertions {
public static final field INSTANCE Lkotlin/_Assertions;
}
diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt
index 445b7b58177..2ae9c56e4f5 100644
--- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt
+++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt
@@ -3,6 +3,26 @@ public final class kotlin/ExceptionsKt {
public static final fun getStackTrace (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement;
}
+public abstract interface annotation class kotlin/Experimental : java/lang/annotation/Annotation {
+ public abstract fun changesMayBreak ()[Lkotlin/Experimental$Impact;
+ public abstract fun level ()Lkotlin/Experimental$Level;
+}
+
+public final class kotlin/Experimental$Impact : java/lang/Enum {
+ public static final field COMPILATION Lkotlin/Experimental$Impact;
+ public static final field LINKAGE Lkotlin/Experimental$Impact;
+ public static final field RUNTIME Lkotlin/Experimental$Impact;
+ public static fun valueOf (Ljava/lang/String;)Lkotlin/Experimental$Impact;
+ public static fun values ()[Lkotlin/Experimental$Impact;
+}
+
+public final class kotlin/Experimental$Level : java/lang/Enum {
+ public static final field ERROR Lkotlin/Experimental$Level;
+ public static final field WARNING Lkotlin/Experimental$Level;
+ public static fun valueOf (Ljava/lang/String;)Lkotlin/Experimental$Level;
+ public static fun values ()[Lkotlin/Experimental$Level;
+}
+
public final class kotlin/KotlinVersion : java/lang/Comparable {
public static final field CURRENT Lkotlin/KotlinVersion;
public static final field Companion Lkotlin/KotlinVersion$Companion;
@@ -84,6 +104,10 @@ public final class kotlin/TuplesKt {
public static final fun toList (Lkotlin/Triple;)Ljava/util/List;
}
+public abstract interface annotation class kotlin/UseExperimental : java/lang/annotation/Annotation {
+ public abstract fun markerClass ()[Ljava/lang/Class;
+}
+
public final class kotlin/_Assertions {
public static final field INSTANCE Lkotlin/_Assertions;
}