From eb9c658c1cbc883be0a0faa4e121c680d933e84c Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 3 Jun 2021 18:16:35 +0300 Subject: [PATCH] OptIn: handle usages via type aliases properly --- .../checkers/ExperimentalUsageChecker.kt | 20 +++++++++++++------ .../experimental/implicitUsages.fir.kt | 10 ++++++++++ .../experimental/implicitUsages.kt | 10 ++++++++++ .../experimental/implicitUsages.txt | 4 +++- .../testsWithStdLib/experimental/topLevel.kt | 2 +- 5 files changed, 38 insertions(+), 8 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt index e6cf338644b..72f1a35feef 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt @@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.storage.LockBasedStorageManager +import org.jetbrains.kotlin.types.AbbreviatedType import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.utils.SmartSet @@ -237,12 +238,19 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { languageVersionSettings: LanguageVersionSettings, visitedClassifiers: MutableSet ): Set = - if (this?.isError != false) emptySet() - else constructor.declarationDescriptor?.loadExperimentalities( - moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers - ).orEmpty() + arguments.flatMap { - if (it.isStarProjection) emptySet() - else it.type.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers) + when { + this?.isError != false -> emptySet() + this is AbbreviatedType -> abbreviation.constructor.declarationDescriptor?.loadExperimentalities( + moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers + ).orEmpty() + expandedType.loadExperimentalities( + moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers + ) + else -> constructor.declarationDescriptor?.loadExperimentalities( + moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers + ).orEmpty() + arguments.flatMap { + if (it.isStarProjection) emptySet() + else it.type.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers) + } } internal fun ClassDescriptor.loadExperimentalityForMarkerAnnotation(): Experimentality? { diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.fir.kt index 94442c9201f..472f2a470d1 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.fir.kt @@ -2,6 +2,7 @@ @RequiresOptIn @Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS) annotation class Marker @Marker @@ -59,8 +60,17 @@ class A : I @OptIn(Marker::class) class B : I +@OptIn(Marker::class) +typealias MyList = ArrayList + +@Marker +typealias YourList = ArrayList + fun main() { val x = listOf(A(), B()) + val y = MyList() + val z = YourList() + YourList().add("") } @Marker diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.kt index 27bc48e8bbd..97b427ebe0d 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.kt @@ -2,6 +2,7 @@ @RequiresOptIn @Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS) annotation class Marker @Marker @@ -59,8 +60,17 @@ class A : I @OptIn(Marker::class) class B : I +@OptIn(Marker::class) +typealias MyList = ArrayList + +@Marker +typealias YourList = ArrayList + fun main() { val x = listOf(A(), B()) + val y = MyList() + val z = YourList() + YourList().add("") } @Marker diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.txt index 3fb030697dd..8f2848bd6be 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.txt +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/implicitUsages.txt @@ -64,7 +64,7 @@ public final data class DataClass { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -@kotlin.RequiresOptIn @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class Marker : kotlin.Annotation { +@kotlin.RequiresOptIn @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public final annotation class Marker : kotlin.Annotation { public constructor Marker() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @@ -112,4 +112,6 @@ public abstract class User { public final fun Some?.onSome(): kotlin.Unit } public typealias My = Some +@kotlin.OptIn(markerClass = {Marker::class}) public typealias MyList = kotlin.collections.ArrayList +@Marker public typealias YourList = kotlin.collections.ArrayList diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt index 22c337d5788..895efd21684 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt @@ -75,5 +75,5 @@ fun use() { function() property val s: Typealias = "" - s.hashCode() + s.hashCode() }