diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalMarkerDeclarationAnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalMarkerDeclarationAnnotationChecker.kt index f6f930a2e5c..3830e95f30c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalMarkerDeclarationAnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalMarkerDeclarationAnnotationChecker.kt @@ -115,6 +115,13 @@ class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleD if (overridden.annotations.any { it.fqName == experimentalFqName }) { return true } + var containingDeclaration = overridden.containingDeclaration + while (containingDeclaration is ClassDescriptor) { + if (containingDeclaration.annotations.any { it.fqName == experimentalFqName }) { + return true + } + containingDeclaration = containingDeclaration.containingDeclaration + } if (overridden.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE && overridden.hasExperimentalOverriddenDescriptors(experimentalFqName) ) { diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.fir.kt index 7471e7605ea..9f20ba0f013 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.fir.kt @@ -42,7 +42,7 @@ annotation class E4 annotation class E5 @RequiresOptIn(level = RequiresOptIn.Level.WARNING) -@Target(PROPERTY, FUNCTION, PROPERTY_SETTER, VALUE_PARAMETER, FIELD, LOCAL_VARIABLE) +@Target(PROPERTY, FUNCTION, PROPERTY_SETTER, VALUE_PARAMETER, FIELD, LOCAL_VARIABLE, CLASS) @Retention(AnnotationRetention.BINARY) annotation class E6 @@ -84,6 +84,27 @@ class Derived : Base { override fun @receiver:E6 String.withReceiver() {} } +@E6 +interface BaseMarked { + val bar: Int +} + +@E6 +class Outer { + interface Nested { + val baz: Int + } +} + +@OptIn(E6::class) +class DerivedOptIn : BaseMarked, Outer.Nested { + @E6 + override val bar: Int = 42 // Ok + + @E6 + override val baz: Int = 24 // Ok +} + abstract class Another(@param:E6 val x: String) : Base { @delegate:E6 override val bar: Int by lazy { 42 } diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.kt index f208a6bf4f7..0f2cd36d4e1 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.kt @@ -42,7 +42,7 @@ annotation class E4 annotation class E5 @RequiresOptIn(level = RequiresOptIn.Level.WARNING) -@Target(PROPERTY, FUNCTION, PROPERTY_SETTER, VALUE_PARAMETER, FIELD, LOCAL_VARIABLE) +@Target(PROPERTY, FUNCTION, PROPERTY_SETTER, VALUE_PARAMETER, FIELD, LOCAL_VARIABLE, CLASS) @Retention(AnnotationRetention.BINARY) annotation class E6 @@ -84,6 +84,27 @@ class Derived : Base { override fun @receiver:E6 String.withReceiver() {} } +@E6 +interface BaseMarked { + val bar: Int +} + +@E6 +class Outer { + interface Nested { + val baz: Int + } +} + +@OptIn(E6::class) +class DerivedOptIn : BaseMarked, Outer.Nested { + @E6 + override val bar: Int = 42 // Ok + + @E6 + override val baz: Int = 24 // Ok +} + abstract class Another(@param:E6 val x: String) : Base { @delegate:E6 override val bar: Int by lazy { 42 } diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.txt b/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.txt index 271fa2ba27c..f00063d4105 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.txt +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.txt @@ -41,6 +41,13 @@ package api { public abstract fun kotlin.String.withReceiver(): kotlin.Unit } + @api.E6 public interface BaseMarked { + public abstract val bar: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + public interface C1 : api.A, api.B { public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public abstract override /*2*/ /*fake_override*/ fun f(): kotlin.Unit @@ -66,6 +73,15 @@ package api { public open override /*1*/ fun @receiver:api.E6 kotlin.String.withReceiver(): kotlin.Unit } + @kotlin.OptIn(markerClass = {api.E6::class}) public final class DerivedOptIn : api.BaseMarked, api.Outer.Nested { + public constructor DerivedOptIn() + @api.E6 public open override /*1*/ val bar: kotlin.Int = 42 + @api.E6 public open override /*1*/ val baz: kotlin.Int = 24 + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + } + @kotlin.RequiresOptIn(level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FIELD, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.TYPEALIAS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class E1 : kotlin.Annotation { public constructor E1() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean @@ -115,7 +131,7 @@ package api { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } - @kotlin.RequiresOptIn(level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FIELD, AnnotationTarget.LOCAL_VARIABLE}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class E6 : kotlin.Annotation { + @kotlin.RequiresOptIn(level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FIELD, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.CLASS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class E6 : kotlin.Annotation { public constructor E6() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @@ -129,6 +145,20 @@ package api { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + @api.E6 public final class Outer { + public constructor Outer() + 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 Nested { + public abstract val baz: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } + public final class X1 : api.C1 { public constructor X1() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean