FIR: add EXPERIMENTAL_API_USAGE reporting

This commit is contained in:
Mikhail Glukhikh
2021-07-08 15:50:53 +03:00
parent 3235b09a92
commit 82f268d611
81 changed files with 520 additions and 650 deletions
@@ -7,7 +7,7 @@ interface FirFunctionCall : FirBase
fun foo(statements: List<FirBase>, arguments: List<FirBase>, explicitReceiver: FirBase): List<FirFunctionCall> {
val firstCalls = with(statements.last() as FirFunctionCall) setCall@{
buildList {
<!EXPERIMENTAL_API_USAGE_ERROR!>buildList<!> {
add(this@setCall)
with(arguments.last() as FirFunctionCall) plusCall@{
add(this@plusCall)
@@ -1,4 +1,4 @@
fun <T> foo(@BuilderInference block: MutableList<T>.() -> Unit): T = null!!
fun <T> foo(@<!EXPERIMENTAL_API_USAGE_ERROR!>BuilderInference<!> block: MutableList<T>.() -> Unit): T = null!!
fun takeString(s: String) {}
@@ -2,7 +2,7 @@ class DropDownComponent<T : Any>(val initialValues: List<T>)
fun test(strings: List<String>) {
val dropDown = DropDownComponent(
initialValues = buildList {
initialValues = <!EXPERIMENTAL_API_USAGE_ERROR!>buildList<!> {
addAll(strings)
}
)
@@ -1,5 +1,5 @@
fun test_1() {
val list = buildList {
val list = <!EXPERIMENTAL_API_USAGE_ERROR!>buildList<!> {
add("")
}
takeList(list)
@@ -12,7 +12,7 @@ fun test_2() {
takeList(list)
}
fun <E> myBuildList(@BuilderInference builderAction: MutableList<E>.() -> Unit): List<E> {
fun <E> myBuildList(@<!EXPERIMENTAL_API_USAGE_ERROR!>BuilderInference<!> builderAction: MutableList<E>.() -> Unit): List<E> {
return ArrayList<E>().apply(builderAction)
}
@@ -2,7 +2,7 @@ interface KtScope {
fun getAllNames(): Set<String>
}
inline fun <E> buildSet(@BuilderInference builderAction: MutableSet<E>.() -> Unit): Set<E> {
inline fun <E> buildSet(@<!EXPERIMENTAL_API_USAGE_ERROR!>BuilderInference<!> builderAction: MutableSet<E>.() -> Unit): Set<E> {
return null!!
}
@@ -34863,6 +34863,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalIsNotEnabled.kt");
}
@Test
@TestMetadata("experimentalSetter.kt")
public void testExperimentalSetter() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalSetter.kt");
}
@Test
@TestMetadata("fullFqNameUsage.kt")
public void testFullFqNameUsage() throws Exception {
@@ -34863,6 +34863,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalIsNotEnabled.kt");
}
@Test
@TestMetadata("experimentalSetter.kt")
public void testExperimentalSetter() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalSetter.kt");
}
@Test
@TestMetadata("fullFqNameUsage.kt")
public void testFullFqNameUsage() throws Exception {
@@ -23,6 +23,11 @@ object CommonExpressionCheckers : ExpressionCheckers() {
FirDeprecationChecker,
)
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
get() = setOf(
FirOptInUsageAccessChecker,
)
override val qualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker>
get() = setOf(
FirCallableReferenceChecker,
@@ -115,6 +120,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
override val resolvedQualifierCheckers: Set<FirResolvedQualifierChecker>
get() = setOf(
FirStandaloneQualifierChecker,
FirOptInUsageQualifierChecker,
)
override val equalityOperatorCallCheckers: Set<FirEqualityOperatorCallChecker>
@@ -12,5 +12,6 @@ object CommonTypeCheckers : TypeCheckers() {
FirTypeAnnotationChecker,
FirSuspendModifierChecker,
FirDeprecatedTypeChecker,
FirOptInUsageTypeRefChecker,
)
}
@@ -32,7 +32,7 @@ object FirClassLiteralChecker : FirGetClassCallChecker() {
val argument = expression.argument
if (argument is FirResolvedQualifier) {
val fqName = argument.classId?.asSingleFqName()
if (fqName in OptInNames.EXPERIMENTAL_FQ_NAMES || fqName in OptInNames.USE_EXPERIMENTAL_FQ_NAMES) {
if (fqName == OptInNames.REQUIRES_OPT_IN_FQ_NAME || fqName == OptInNames.OPT_IN_FQ_NAME) {
reporter.reportOn(argument.source, FirErrors.EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION, context)
}
}
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.ensureResolved
object FirOptInUsageAccessChecker : FirQualifiedAccessChecker() {
@OptIn(SymbolInternals::class)
override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) {
val sourceKind = expression.source?.kind
if (sourceKind is FirFakeSourceElementKind.DataClassGeneratedMembers ||
sourceKind is FirFakeSourceElementKind.PropertyFromParameter
) return
val reference = expression.calleeReference as? FirResolvedNamedReference ?: return
val resolvedSymbol = reference.resolvedSymbol
resolvedSymbol.ensureResolved(FirResolvePhase.STATUS)
val fir = resolvedSymbol.fir as? FirAnnotatedDeclaration ?: return
with(FirOptInUsageBaseChecker) {
if (expression is FirVariableAssignment && fir is FirProperty) {
val experimentalities = fir.loadExperimentalities(context, fromSetter = true) +
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
reportNotAcceptedExperimentalities(experimentalities, expression.lValue, context, reporter)
return
}
val experimentalities = fir.loadExperimentalities(context, fromSetter = false) +
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
}
}
}
@@ -5,6 +5,16 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.findArgumentByName
import org.jetbrains.kotlin.fir.declarations.getAnnotationByFqName
@@ -12,12 +22,22 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenProperties
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.checkers.Experimentality
import org.jetbrains.kotlin.resolve.checkers.OptInNames
import org.jetbrains.kotlin.utils.SmartSet
import org.jetbrains.kotlin.utils.addIfNotNull
internal object FirOptInUsageBaseChecker {
fun FirRegularClassSymbol.loadExperimentalityForMarkerAnnotation(): Experimentality? {
@@ -26,8 +46,140 @@ internal object FirOptInUsageBaseChecker {
return fir.loadExperimentalityForMarkerAnnotation()
}
fun loadExperimentalitiesFromTypeArguments(
context: CheckerContext,
typeArguments: List<FirTypeProjection>
): Set<Experimentality> {
if (typeArguments.isEmpty()) return emptySet()
return loadExperimentalitiesFromConeArguments(context, typeArguments.map { it.toConeTypeProjection() })
}
fun loadExperimentalitiesFromConeArguments(
context: CheckerContext,
typeArguments: List<ConeTypeProjection>
): Set<Experimentality> {
if (typeArguments.isEmpty()) return emptySet()
val result = SmartSet.create<Experimentality>()
typeArguments.forEach {
if (!it.isStarProjection) it.type?.addExperimentalities(context, result)
}
return result
}
fun FirAnnotatedDeclaration.loadExperimentalities(
context: CheckerContext, fromSetter: Boolean
): Set<Experimentality> = loadExperimentalities(
context, knownExperimentalities = null, visited = mutableSetOf(), fromSetter
)
@OptIn(SymbolInternals::class)
private fun FirAnnotatedDeclaration.loadExperimentalities(
context: CheckerContext,
knownExperimentalities: SmartSet<Experimentality>?,
visited: MutableSet<FirAnnotatedDeclaration>,
fromSetter: Boolean,
): Set<Experimentality> {
if (!visited.add(this)) return emptySet()
val result = knownExperimentalities ?: SmartSet.create()
val session = context.session
if (this is FirCallableDeclaration) {
val parentClass = containingClass()?.toFirRegularClass(session)
if (this.isSubstitutionOrIntersectionOverride) {
val parentClassScope = parentClass?.unsubstitutedScope(context)
if (this is FirSimpleFunction) {
parentClassScope?.processDirectlyOverriddenFunctions(symbol) {
it.fir.loadExperimentalities(context, result, visited, fromSetter = false)
ProcessorAction.NEXT
}
} else if (this is FirProperty) {
parentClassScope?.processDirectlyOverriddenProperties(symbol) {
it.fir.loadExperimentalities(context, result, visited, fromSetter)
ProcessorAction.NEXT
}
}
}
if (this !is FirConstructor) {
// Note: coneType here crashes on overridden members
returnTypeRef.coneTypeSafe<ConeKotlinType>().addExperimentalities(context, result, visited)
receiverTypeRef?.coneTypeSafe<ConeKotlinType>().addExperimentalities(context, result, visited)
if (this is FirSimpleFunction) {
valueParameters.forEach {
it.returnTypeRef.coneTypeSafe<ConeKotlinType>().addExperimentalities(context, result, visited)
}
}
}
parentClass?.loadExperimentalities(context, result, visited, fromSetter = false)
if (fromSetter && this is FirProperty) {
setter?.loadExperimentalities(context, result, visited, fromSetter = false)
}
} else if (this is FirRegularClass && !this.isLocal) {
val parentClassSymbol = symbol.outerClassSymbol(context)
parentClassSymbol?.fir?.loadExperimentalities(context, result, visited, fromSetter = false)
}
for (annotation in annotations) {
val annotationType = annotation.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()
if (annotation.useSiteTarget != AnnotationUseSiteTarget.PROPERTY_SETTER || fromSetter) {
result.addIfNotNull(
annotationType?.lookupTag?.toFirRegularClass(
session
)?.loadExperimentalityForMarkerAnnotation()
)
}
}
if (this is FirTypeAlias) {
expandedTypeRef.coneType.addExperimentalities(context, result, visited)
}
if (getAnnotationByFqName(OptInNames.WAS_EXPERIMENTAL_FQ_NAME) != null) {
val accessibility = checkSinceKotlinVersionAccessibility(context)
if (accessibility is FirSinceKotlinAccessibility.NotAccessibleButWasExperimental) {
accessibility.markerClasses.forEach {
it.ensureResolved(FirResolvePhase.STATUS)
result.addIfNotNull(it.fir.loadExperimentalityForMarkerAnnotation())
}
}
}
// TODO: getAnnotationsOnContainingModule
return result
}
@OptIn(SymbolInternals::class)
private fun ConeKotlinType?.addExperimentalities(
context: CheckerContext,
result: SmartSet<Experimentality>,
visited: MutableSet<FirAnnotatedDeclaration> = mutableSetOf()
) {
when (this) {
!is ConeClassLikeType -> return
else -> {
val expandedType = fullyExpandedType(context.session)
if (this === expandedType) {
expandedType.lookupTag.toFirRegularClass(context.session)?.loadExperimentalities(
context, result, visited, fromSetter = false
)
typeArguments.forEach {
if (!it.isStarProjection) it.type?.addExperimentalities(context, result, visited)
}
} else {
val symbol = lookupTag.toSymbol(context.session)
if (symbol != null) {
symbol.ensureResolved(FirResolvePhase.STATUS)
symbol.fir.loadExperimentalities(context, result, visited, fromSetter = false)
}
expandedType.typeArguments.forEach {
if (!it.isStarProjection) it.type?.addExperimentalities(context, result, visited)
}
}
}
}
}
private fun FirRegularClass.loadExperimentalityForMarkerAnnotation(): Experimentality? {
val experimental = getAnnotationByFqName(OptInNames.REQUIRES_OPT_IN_FQ_NAME) ?: return null
val experimental = getAnnotationByFqName(OptInNames.REQUIRES_OPT_IN_FQ_NAME)
?: return null
val levelArgument = experimental.findArgumentByName(LEVEL) as? FirQualifiedAccessExpression
val levelName = (levelArgument?.calleeReference as? FirResolvedNamedReference)?.name?.asString()
@@ -36,6 +188,73 @@ internal object FirOptInUsageBaseChecker {
return Experimentality(symbol.classId.asSingleFqName(), level.severity, message)
}
fun reportNotAcceptedExperimentalities(
experimentalities: Collection<Experimentality>,
element: FirElement,
context: CheckerContext,
reporter: DiagnosticReporter
) {
for ((annotationFqName, severity, message) in experimentalities) {
if (!isExperimentalityAcceptableInContext(annotationFqName, element, context)) {
val diagnostic = when (severity) {
Experimentality.Severity.WARNING -> FirErrors.EXPERIMENTAL_API_USAGE
Experimentality.Severity.ERROR -> FirErrors.EXPERIMENTAL_API_USAGE_ERROR
}
val reportedMessage = message ?: when (severity) {
Experimentality.Severity.WARNING -> "This declaration is experimental and its usage should be marked"
Experimentality.Severity.ERROR -> "This declaration is experimental and its usage must be marked"
}
reporter.reportOn(element.source, diagnostic, annotationFqName, reportedMessage, context)
}
}
}
private fun isExperimentalityAcceptableInContext(
annotationFqName: FqName,
element: FirElement,
context: CheckerContext
): Boolean {
val languageVersionSettings = context.session.languageVersionSettings
val fqNameAsString = annotationFqName.asString()
if (fqNameAsString in languageVersionSettings.getFlag(AnalysisFlags.useExperimental)) {
return true
}
for (declaration in context.containingDeclarations) {
if (declaration !is FirAnnotatedDeclaration) continue
if (declaration.isExperimentalityAcceptable(annotationFqName)) {
return true
}
}
for (accessOrAnnotation in context.qualifiedAccessOrAnnotationCalls) {
if (accessOrAnnotation.isExperimentalityAcceptable(annotationFqName)) {
return true
}
}
if (element !is FirAnnotationContainer) return false
return element.isExperimentalityAcceptable(annotationFqName)
}
private fun FirAnnotationContainer.isExperimentalityAcceptable(annotationFqName: FqName): Boolean {
return getAnnotationByFqName(annotationFqName) != null || isAnnotatedWithUseExperimentalOf(annotationFqName)
}
private fun FirAnnotationContainer.isAnnotatedWithUseExperimentalOf(annotationFqName: FqName): Boolean {
for (annotation in annotations) {
val coneType = annotation.annotationTypeRef.coneType as? ConeClassLikeType
if (coneType?.lookupTag?.classId?.asSingleFqName() != OptInNames.OPT_IN_FQ_NAME) {
continue
}
val annotationClasses = annotation.findArgumentByName(OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS) ?: continue
if (annotationClasses.extractClassesFromArgument().any {
it.classId.asSingleFqName() == annotationFqName
}
) {
return true
}
}
return false
}
private val LEVEL = Name.identifier("level")
private val MESSAGE = Name.identifier("message")
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.ensureResolved
object FirOptInUsageQualifierChecker : FirResolvedQualifierChecker() {
@OptIn(SymbolInternals::class)
override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) {
val symbol = expression.symbol ?: return
symbol.ensureResolved(FirResolvePhase.STATUS)
val fir = symbol.fir
with(FirOptInUsageBaseChecker) {
val experimentalities = fir.loadExperimentalities(context, fromSetter = false)
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
}
}
}
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.type
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.resolve.checkers.OptInNames
object FirOptInUsageTypeRefChecker : FirTypeRefChecker() {
@OptIn(SymbolInternals::class)
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
if (typeRef.source?.kind !is FirRealSourceElementKind) return
val coneType = typeRef.coneTypeSafe<ConeClassLikeType>() ?: return
val symbol = coneType.lookupTag.toSymbol(context.session) ?: return
symbol.ensureResolved(FirResolvePhase.STATUS)
val fqName = symbol.classId.asSingleFqName()
val lastAnnotationCall = context.qualifiedAccessOrAnnotationCalls.lastOrNull() as? FirAnnotationCall
if ((lastAnnotationCall == null || lastAnnotationCall.annotationTypeRef !== typeRef) &&
(fqName == OptInNames.REQUIRES_OPT_IN_FQ_NAME || fqName == OptInNames.OPT_IN_FQ_NAME)
) {
reporter.reportOn(typeRef.source, FirErrors.EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION, context)
}
with(FirOptInUsageBaseChecker) {
val experimentalities = symbol.fir.loadExperimentalities(context, fromSetter = false) +
loadExperimentalitiesFromConeArguments(context, coneType.typeArguments.toList())
reportNotAcceptedExperimentalities(experimentalities, typeRef, context, reporter)
}
}
}
@@ -57,6 +57,7 @@ class ValueParameter(
initializer = buildQualifiedAccessExpression {
source = propertySource
calleeReference = buildPropertyFromParameterResolvedNamedReference {
source = propertySource
this.name = name
resolvedSymbol = this@ValueParameter.firValueParameter.symbol
source = propertySource
@@ -5,7 +5,7 @@
// FILE: main.kt
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R> build(@BuilderInference block: TestInterface<R>.() -> Unit): R = TODO()
interface TestInterface<R> {
@@ -1,6 +1,6 @@
package
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R>.() -> kotlin.Unit): R
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R>.() -> kotlin.Unit): R
public fun main(): kotlin.Unit
public interface TestInterface</*0*/ R> {
@@ -3,7 +3,7 @@
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R> combined(
check: () -> Unit,
@BuilderInference block: TestInterface<R>.() -> Unit
@@ -3,7 +3,7 @@
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R> combined(
check: () -> Unit,
@BuilderInference block: TestInterface<R>.() -> Unit
@@ -1,6 +1,6 @@
package
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R> combined(/*0*/ check: () -> kotlin.Unit, /*1*/ @kotlin.BuilderInference block: TestInterface<R>.() -> kotlin.Unit): R
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R> combined(/*0*/ check: () -> kotlin.Unit, /*1*/ @kotlin.BuilderInference block: TestInterface<R>.() -> kotlin.Unit): R
public fun test(): kotlin.Unit
public interface TestInterface</*0*/ R> {
@@ -5,10 +5,10 @@
// FILE: main.kt
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R> build(@BuilderInference block: TestInterface<R>.() -> Unit): R = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R> build2(@BuilderInference block: TestInterface<R>.() -> Unit): R = TODO()
interface TestInterface<R> {
@@ -5,10 +5,10 @@
// FILE: main.kt
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R> build(@BuilderInference block: TestInterface<R>.() -> Unit): R = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R> build2(@BuilderInference block: TestInterface<R>.() -> Unit): R = TODO()
interface TestInterface<R> {
@@ -1,7 +1,7 @@
package
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R>.() -> kotlin.Unit): R
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R> build2(/*0*/ @kotlin.BuilderInference block: TestInterface<R>.() -> kotlin.Unit): R
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R>.() -> kotlin.Unit): R
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R> build2(/*0*/ @kotlin.BuilderInference block: TestInterface<R>.() -> kotlin.Unit): R
public fun </*0*/ K> capture(/*0*/ x: Inv<K>): K
public fun </*0*/ K> captureIn(/*0*/ x: Inv<out K>): K
public fun </*0*/ K> captureOut(/*0*/ x: Inv<out K>): K
@@ -11,10 +11,10 @@ class Test {
// FILE: main.kt
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1> build(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R2> build2(@BuilderInference block: TestInterface<R2>.() -> Unit): R2 = TODO()
class In<in K>
@@ -11,10 +11,10 @@ class Test {
// FILE: main.kt
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1> build(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R2> build2(@BuilderInference block: TestInterface<R2>.() -> Unit): R2 = TODO()
class In<in K>
@@ -1,7 +1,7 @@
package
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R2> build2(/*0*/ @kotlin.BuilderInference block: TestInterface<R2>.() -> kotlin.Unit): R2
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R2> build2(/*0*/ @kotlin.BuilderInference block: TestInterface<R2>.() -> kotlin.Unit): R2
public fun </*0*/ U> id(/*0*/ x: U): U?
public fun </*0*/ E> select1(/*0*/ x: E, /*1*/ y: In<E>): E?
public fun </*0*/ E> select2(/*0*/ x: E, /*1*/ y: In<E?>): E
@@ -11,10 +11,10 @@ class Test {
// FILE: main.kt
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1> build(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R2> build2(@BuilderInference block: TestInterface<R2>.() -> Unit): R2 = TODO()
class Inv<K>
@@ -11,10 +11,10 @@ class Test {
// FILE: main.kt
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1> build(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R2> build2(@BuilderInference block: TestInterface<R2>.() -> Unit): R2 = TODO()
class Inv<K>
@@ -1,7 +1,7 @@
package
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R2> build2(/*0*/ @kotlin.BuilderInference block: TestInterface<R2>.() -> kotlin.Unit): R2
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R2> build2(/*0*/ @kotlin.BuilderInference block: TestInterface<R2>.() -> kotlin.Unit): R2
public fun </*0*/ U> id(/*0*/ x: U): U?
public fun </*0*/ E> select1(/*0*/ x: E, /*1*/ y: Inv<E>): E?
public fun </*0*/ E> select2(/*0*/ x: E, /*1*/ y: Inv<E?>): E
@@ -11,10 +11,10 @@ class Test {
// FILE: main.kt
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1> build(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R2> build2(@BuilderInference block: TestInterface<R2>.() -> Unit): R2 = TODO()
class In<in K>
@@ -11,10 +11,10 @@ class Test {
// FILE: main.kt
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1> build(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R2> build2(@BuilderInference block: TestInterface<R2>.() -> Unit): R2 = TODO()
class In<in K>
@@ -1,7 +1,7 @@
package
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R2> build2(/*0*/ @kotlin.BuilderInference block: TestInterface<R2>.() -> kotlin.Unit): R2
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R2> build2(/*0*/ @kotlin.BuilderInference block: TestInterface<R2>.() -> kotlin.Unit): R2
public fun </*0*/ U> id(/*0*/ x: U): U
public fun </*0*/ E> intersect(/*0*/ vararg x: In<E> /*kotlin.Array<out In<E>>*/): E
public fun test(): kotlin.Unit
@@ -10,7 +10,7 @@ interface TestInterface<R> {
fun get(): R
}
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1> build(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
fun Any.test() {}
@@ -10,7 +10,7 @@ interface TestInterface<R> {
fun get(): R
}
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1> build(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
fun Any.test() {}
@@ -1,6 +1,6 @@
package
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
public fun test(): kotlin.Unit
public fun kotlin.Any.test(): kotlin.Unit
public fun kotlin.Any?.test2(): kotlin.Unit
@@ -10,16 +10,16 @@ interface TestInterface<R> {
fun get(): R
}
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1> build(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1 : Any> build2(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1 : R2, R2 : Any> build3(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1 : R2, R2> build4(x: R2, @BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
fun test(a: String?) {
@@ -10,16 +10,16 @@ interface TestInterface<R> {
fun get(): R
}
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1> build(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1 : Any> build2(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1 : R2, R2 : Any> build3(@BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R1 : R2, R2> build4(x: R2, @BuilderInference block: TestInterface<R1>.() -> Unit): R1 = TODO()
fun test(a: String?) {
@@ -1,9 +1,9 @@
package
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1 : kotlin.Any> build2(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1 : R2, /*1*/ R2 : kotlin.Any> build3(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1 : R2, /*1*/ R2> build4(/*0*/ x: R2, /*1*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1 : kotlin.Any> build2(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1 : R2, /*1*/ R2 : kotlin.Any> build3(/*0*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R1 : R2, /*1*/ R2> build4(/*0*/ x: R2, /*1*/ @kotlin.BuilderInference block: TestInterface<R1>.() -> kotlin.Unit): R1
public fun test(/*0*/ a: kotlin.String?): kotlin.Unit
public interface TestInterface</*0*/ R> {
@@ -4,7 +4,7 @@
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R> build(
@BuilderInference block: TestInterface<R>.() -> Unit
): R = TODO()
@@ -4,7 +4,7 @@
import kotlin.experimental.ExperimentalTypeInference
@UseExperimental(ExperimentalTypeInference::class)
@OptIn(ExperimentalTypeInference::class)
fun <R> build(
@BuilderInference block: TestInterface<R>.() -> Unit
): R = TODO()
@@ -1,6 +1,6 @@
package
@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R>.() -> kotlin.Unit): R
@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ R> build(/*0*/ @kotlin.BuilderInference block: TestInterface<R>.() -> kotlin.Unit): R
public fun </*0*/ U> id(/*0*/ x: U): U
public fun test(): kotlin.Unit
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun ubyte(vararg a: <!EXPERIMENTAL_API_USAGE!>UByte<!>) {}
fun ushort(vararg a: <!EXPERIMENTAL_API_USAGE!>UShort<!>) {}
fun uint(vararg a: <!EXPERIMENTAL_API_USAGE!>UInt<!>) {}
fun ulong(vararg a: <!EXPERIMENTAL_API_USAGE!>ULong<!>) {}
class ValueParam(vararg val a: <!EXPERIMENTAL_API_USAGE!>ULong<!>)
annotation class Ann(vararg val a: <!EXPERIMENTAL_API_USAGE!>UInt<!>)
fun array(<!FORBIDDEN_VARARG_PARAMETER_TYPE!>vararg<!> a: <!EXPERIMENTAL_API_USAGE!>UIntArray<!>) {}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun ubyte(vararg a: UByte) {}
@@ -33,7 +33,7 @@ fun takeUShort(@ImplicitIntegerCoercion u: UShort) {}
fun takeUInt(@ImplicitIntegerCoercion u: UInt) {}
fun takeULong(@ImplicitIntegerCoercion u: ULong) {}
fun takeUBytes(@ImplicitIntegerCoercion vararg u: UByte) {}
fun takeUBytes(@ImplicitIntegerCoercion vararg u: <!EXPERIMENTAL_API_USAGE!>UByte<!>) {}
fun takeLong(@ImplicitIntegerCoercion l: Long) {}
@@ -5,7 +5,7 @@ fun takeUShort(u: UShort) {}
fun takeUInt(u: UInt) {}
fun takeULong(u: ULong) {}
fun takeUBytes(vararg u: UByte) {}
fun takeUBytes(vararg u: <!EXPERIMENTAL_API_USAGE!>UByte<!>) {}
fun takeNullableUInt(u: UInt?) {}
@@ -1,7 +1,7 @@
fun ubyte(vararg a: UByte): UByteArray = a
fun ushort(vararg a: UShort): UShortArray = a
fun uint(vararg a: UInt): UIntArray = a
fun ulong(vararg a: ULong): ULongArray = a
fun ubyte(vararg a: <!EXPERIMENTAL_API_USAGE!>UByte<!>): <!EXPERIMENTAL_API_USAGE!>UByteArray<!> = <!EXPERIMENTAL_API_USAGE!>a<!>
fun ushort(vararg a: <!EXPERIMENTAL_API_USAGE!>UShort<!>): <!EXPERIMENTAL_API_USAGE!>UShortArray<!> = <!EXPERIMENTAL_API_USAGE!>a<!>
fun uint(vararg a: <!EXPERIMENTAL_API_USAGE!>UInt<!>): <!EXPERIMENTAL_API_USAGE!>UIntArray<!> = <!EXPERIMENTAL_API_USAGE!>a<!>
fun ulong(vararg a: <!EXPERIMENTAL_API_USAGE!>ULong<!>): <!EXPERIMENTAL_API_USAGE!>ULongArray<!> = <!EXPERIMENTAL_API_USAGE!>a<!>
fun rawUInt(vararg a: UInt): IntArray = <!RETURN_TYPE_MISMATCH!>a<!>
fun rawUInt(vararg a: <!EXPERIMENTAL_API_USAGE!>UInt<!>): IntArray = <!EXPERIMENTAL_API_USAGE, RETURN_TYPE_MISMATCH!>a<!>
@@ -1,4 +1,5 @@
// FIR_IDENTICAL
// ALLOW_KOTLIN_PACKAGE
// !LANGUAGE: +UnrestrictedBuilderInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: annotation.kt
@@ -1,4 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// ALLOW_KOTLIN_PACKAGE
// !WITH_NEW_INFERENCE
// FILE: annotation.kt
@@ -1,4 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// ALLOW_KOTLIN_PACKAGE
// !WITH_NEW_INFERENCE
// FILE: annotation.kt
@@ -1,4 +1,5 @@
// FIR_IDENTICAL
// ALLOW_KOTLIN_PACKAGE
// !LANGUAGE: +UnrestrictedBuilderInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
@@ -1,4 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// ALLOW_KOTLIN_PACKAGE
// FILE: annotation.kt
@@ -1,4 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// ALLOW_KOTLIN_PACKAGE
// FILE: annotation.kt
@@ -1,138 +0,0 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// !DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: api.kt
package api
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.BINARY)
annotation class ExperimentalAPI
@ExperimentalAPI
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.BINARY)
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: <!WRONG_ANNOTATION_TARGET!>@EAnno<!> String) {}
@ExperimentalAPI
fun returnType(): <!WRONG_ANNOTATION_TARGET!>@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.*
@OptIn(ExperimentalAPI::class)
@EAnno fun function() {}
@OptIn(ExperimentalAPI::class)
fun parameter(@EAnno p: String) {}
@OptIn(ExperimentalAPI::class)
fun parameterType(p: <!WRONG_ANNOTATION_TARGET!>@EAnno<!> String) {}
@OptIn(ExperimentalAPI::class)
fun returnType(): <!WRONG_ANNOTATION_TARGET!>@EAnno<!> Unit {}
@OptIn(ExperimentalAPI::class)
@EAnno val property = ""
@OptIn(ExperimentalAPI::class)
@EAnno typealias Typealias = Unit
@OptIn(ExperimentalAPI::class)
@EAnno class Klass
@OptIn(ExperimentalAPI::class)
annotation class AnnotationArgument(val p: EAnno)
fun insideBody() {
@OptIn(ExperimentalAPI::class) @EAnno fun local() {}
}
fun inDefaultArgument(@OptIn(ExperimentalAPI::class) f: () -> Unit = @EAnno fun() {}) {}
@OptIn(ExperimentalAPI::class)
val inProperty = @EAnno fun() {}
val inPropertyAccessor: () -> Unit
@OptIn(ExperimentalAPI::class)
get() = @EAnno fun() {}
// FILE: usage-none.kt
package usage3
import api.*
@EAnno fun function() {}
fun parameter(@EAnno p: String) {}
fun parameterType(p: <!WRONG_ANNOTATION_TARGET!>@EAnno<!> String) {}
fun returnType(): <!WRONG_ANNOTATION_TARGET!>@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() {}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// !DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: api.kt
@@ -1,84 +0,0 @@
// !DIAGNOSTICS: -NOTHING_TO_INLINE -UNUSED_PARAMETER
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// FILE: api.kt
package api
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Retention(AnnotationRetention.BINARY)
annotation class API
@API
fun f() {}
// FILE: usage.kt
package usage
import api.*
fun use1() {
f()
}
val use2 = f()
// FILE: inline-usage.kt
package usage
import api.*
inline fun inlineUse1() {
f()
}
inline var inlineUse2: Unit
get() {
f()
}
set(value) {
f()
}
var inlineUse3: Unit
inline get() {
f()
}
@API
inline set(value) {
f()
}
@API
inline fun inlineUse4() {
f()
}
// FILE: private-inline-usage.kt
package usage
import api.*
private inline fun privateInline1() {
f()
}
internal inline fun privateInline2() {
f()
}
private inline var privateInline3: Unit
get() {
f()
}
set(value) {
f()
}
internal class InternalClass {
inline fun privateInline4() {
f()
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -NOTHING_TO_INLINE -UNUSED_PARAMETER
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// FILE: api.kt
@@ -1,89 +0,0 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// FILE: api.kt
package api
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.BINARY)
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.*
@OptIn(ExperimentalAPI::class)
fun useAll() {
val c: C = C()
c.function()
c.property
C.Nested()
c.Inner()
c.extension()
}
@OptIn(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()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// FILE: api.kt
@@ -1,37 +0,0 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// FILE: api.kt
package api
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.BINARY)
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()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// FILE: api.kt
@@ -40,5 +40,5 @@ package usage3
import api.*
@Anno(MEANING)
@Anno(<!EXPERIMENTAL_API_USAGE!>MEANING<!>)
fun usage() {}
@@ -52,7 +52,7 @@ package usage3
import api.*
fun use1() {
C.D.E.F()
C.D.<!EXPERIMENTAL_API_USAGE!>E<!>.<!EXPERIMENTAL_API_USAGE!>F<!>()
}
fun use2(f: C.D.E.F) = f.hashCode()
fun use2(f: <!EXPERIMENTAL_API_USAGE!>C.D.E.F<!>) = <!EXPERIMENTAL_API_USAGE!>f<!>.hashCode()
@@ -23,5 +23,5 @@ class Derived : Base() {
}
fun test(b: Base) {
b.foo()
b.<!EXPERIMENTAL_API_USAGE_ERROR!>foo<!>()
}
@@ -1,24 +0,0 @@
// FILE: api.kt
@<!EXPERIMENTAL_IS_NOT_ENABLED!>RequiresOptIn<!>
@Retention(AnnotationRetention.BINARY)
annotation class Marker
@Marker
fun f() {}
// FILE: usage.kt
fun use1() {
f()
}
@Marker
fun use2() {
f()
}
@<!EXPERIMENTAL_IS_NOT_ENABLED!>OptIn<!>(Marker::class)
fun use3() {
f()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: api.kt
@<!EXPERIMENTAL_IS_NOT_ENABLED!>RequiresOptIn<!>
@@ -0,0 +1,24 @@
// FIR_IDENTICAL
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
@RequiresOptIn
@Retention(AnnotationRetention.BINARY)
annotation class E
@set:E
var x: Int = 42
@E
var y: Int = 24
var z: Int = 44
@E set(arg) {
field = arg
}
fun user(): Int {
<!EXPERIMENTAL_API_USAGE_ERROR!>x<!> = 10
<!EXPERIMENTAL_API_USAGE_ERROR!>y<!> = 5
<!EXPERIMENTAL_API_USAGE_ERROR!>x<!> = 15
return x + <!EXPERIMENTAL_API_USAGE_ERROR!>y<!> + z
}
@@ -0,0 +1,13 @@
package
@set:E public var x: kotlin.Int
@E public var y: kotlin.Int
@set:E public var z: kotlin.Int
public fun user(): kotlin.Int
@kotlin.RequiresOptIn @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class E : kotlin.Annotation {
public constructor E()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -9,15 +9,15 @@ annotation class Marker
interface Some
abstract class User {
abstract fun createSome(): Some
fun Some?.onSome() {}
fun withSome(some: Some? = null) {}
abstract fun createSome(): <!EXPERIMENTAL_API_USAGE_ERROR!>Some<!>
fun <!EXPERIMENTAL_API_USAGE_ERROR!>Some<!>?.onSome() {}
fun withSome(some: <!EXPERIMENTAL_API_USAGE_ERROR!>Some<!>? = null) {}
fun use() {
val something = createSome()
val somethingOther: Some = createSome()
null.onSome()
withSome()
val something = <!EXPERIMENTAL_API_USAGE_ERROR!>createSome<!>()
val somethingOther: <!EXPERIMENTAL_API_USAGE_ERROR!>Some<!> = <!EXPERIMENTAL_API_USAGE_ERROR!>createSome<!>()
null.<!EXPERIMENTAL_API_USAGE_ERROR!>onSome<!>()
<!EXPERIMENTAL_API_USAGE_ERROR!>withSome<!>()
}
}
@@ -25,15 +25,15 @@ data class DataClass(@property:Marker val x: Int)
fun useDataClass(d: DataClass) {
// Should have error in both
d.x
d.<!EXPERIMENTAL_API_USAGE_ERROR!>x<!>
val (x) = d
}
typealias My = Some
typealias My = <!EXPERIMENTAL_API_USAGE_ERROR!>Some<!>
fun my(my: My) {}
fun my(my: <!EXPERIMENTAL_API_USAGE_ERROR!>My<!>) {}
fun your(my: Some) {}
fun your(my: <!EXPERIMENTAL_API_USAGE_ERROR!>Some<!>) {}
@Marker
interface ExperimentalType {
@@ -48,7 +48,7 @@ interface NotExperimentalExtension : ExperimentalType {
fun use(arg: NotExperimentalExtension) {
arg.foo()
arg.bar()
arg.<!EXPERIMENTAL_API_USAGE_ERROR!>bar<!>()
}
@Marker
@@ -67,7 +67,7 @@ typealias MyList = ArrayList<I>
typealias YourList = ArrayList<String>
fun main() {
val x = listOf(A(), B())
val x = <!EXPERIMENTAL_API_USAGE_ERROR!>listOf<!>(A(), B())
val y = MyList()
val z = YourList()
YourList().add("")
@@ -83,7 +83,7 @@ object O {
operator fun provideDelegate(x: Any?, y: Any?): C = C()
}
val x: String by O
val x: String by <!EXPERIMENTAL_API_USAGE_ERROR!>O<!>
@Marker
class OperatorContainer : Comparable<OperatorContainer> {
@@ -116,8 +116,8 @@ operator fun String.minus(s: String) = OperatorContainer()
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) {}
val res1 = s <!EXPERIMENTAL_API_USAGE_ERROR!>-<!> s
val res2 = <!EXPERIMENTAL_API_USAGE_ERROR!>s<!>()
val res3 = <!EXPERIMENTAL_API_USAGE_ERROR!>res1<!> <!EXPERIMENTAL_API_USAGE_ERROR!>><!> <!EXPERIMENTAL_API_USAGE_ERROR!>res2<!>
<!EXPERIMENTAL_API_USAGE_ERROR, EXPERIMENTAL_API_USAGE_ERROR, EXPERIMENTAL_API_USAGE_ERROR, EXPERIMENTAL_API_USAGE_ERROR!>for (c in a) {}<!>
}
@@ -1,79 +0,0 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// !DIAGNOSTICS: -UNUSED_VARIABLE
// FILE: api.kt
package api
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.BINARY)
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() {
@OptIn(ExperimentalAPI::class)
{
function()
property
val s: Typealias = ""
}()
}
@OptIn(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()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// !DIAGNOSTICS: -UNUSED_VARIABLE
// FILE: api.kt
@@ -1,14 +0,0 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// FILE: api.kt
package api
@RequiresOptIn
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
annotation class ExperimentalAPI
@ExperimentalAPI
class Foo
typealias Bar = Foo
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// FILE: api.kt
@@ -21,11 +21,11 @@ annotation class M
// Usages as types should be errors
fun f1(e: RequiresOptIn) {}
fun f2(u: OptIn?) {}
fun f1(e: <!EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION!>RequiresOptIn<!>) {}
fun f2(u: <!EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION!>OptIn?<!>) {}
typealias Experimental0 = RequiresOptIn
typealias OptIn0 = OptIn
typealias Experimental0 = <!EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION!>RequiresOptIn<!>
typealias OptIn0 = <!EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION!>OptIn<!>
fun f3(e: Experimental0 /* TODO */) {}
fun f4(u: OptIn0 /* TODO */) {}
@@ -1,39 +0,0 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// FILE: api.kt
package api
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.BINARY)
annotation class ExperimentalAPI1
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.BINARY)
annotation class ExperimentalAPI2
@ExperimentalAPI1
fun compilation() {}
@ExperimentalAPI2
fun runtime() {}
// FILE: usage.kt
@file:OptIn(ExperimentalAPI1::class)
package usage
import api.*
fun use() {
compilation()
runtime()
}
class Use {
fun use() {
compilation()
runtime()
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// FILE: api.kt
@@ -1,4 +1,5 @@
// FIR_IDENTICAL
// FIR_IDE_IGNORE
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn api.ExperimentalAPI
// MODULE: api
// FILE: api.kt
@@ -1,55 +0,0 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// FILE: api.kt
package api
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.BINARY)
annotation class E1
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.BINARY)
annotation class E2
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.BINARY)
annotation class E3
@E1
fun e1() {}
@E2
fun e2() {}
@E3
fun e3() {}
// FILE: usage.kt
package usage
import api.*
@OptIn(E1::class, E2::class, E3::class)
fun use1() {
e1()
e2()
e3()
}
@OptIn(E1::class, E3::class)
fun use2() {
e1()
@OptIn(E2::class) e2()
e3()
}
@OptIn(E1::class, E2::class)
fun use3() {
e1()
e2()
e3()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// FILE: api.kt
@@ -2,9 +2,9 @@
fun main() {
val list = listOf(A())
list.forEach(A::foo)
list.forEach(A::<!EXPERIMENTAL_API_USAGE_ERROR!>foo<!>)
list.forEach {
it.foo()
it.<!EXPERIMENTAL_API_USAGE_ERROR!>foo<!>()
}
}
@@ -34959,6 +34959,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalIsNotEnabled.kt");
}
@Test
@TestMetadata("experimentalSetter.kt")
public void testExperimentalSetter() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalSetter.kt");
}
@Test
@TestMetadata("fullFqNameUsage.kt")
public void testFullFqNameUsage() throws Exception {
@@ -34863,6 +34863,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalIsNotEnabled.kt");
}
@Test
@TestMetadata("experimentalSetter.kt")
public void testExperimentalSetter() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalSetter.kt");
}
@Test
@TestMetadata("fullFqNameUsage.kt")
public void testFullFqNameUsage() throws Exception {