From 0b2943d34c37cd9845fe85dc20638e23c0afcb4e Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 8 Apr 2021 16:07:45 +0300 Subject: [PATCH] Prohibit using annotations without TYPE target in several type positions #KT-8325 Fixed #KT-19455 Fixed #KT-25876 Fixed #KT-28449 Fixed --- ...irOldFrontendDiagnosticsTestGenerated.java | 34 +++++++++++ .../kotlin/fir/types/ConeTypeParameterType.kt | 1 - .../kotlin/resolve/AnnotationChecker.kt | 60 +++++++++++++++---- .../BasicExpressionTypingVisitor.java | 3 + .../ExpressionTypingComponents.java | 6 ++ .../PatternMatchingTypingVisitor.kt | 4 ++ .../tests/annotations/typeUse/kt19455.kt | 14 +++++ .../tests/annotations/typeUse/kt19455.txt | 26 ++++++++ .../tests/annotations/typeUse/kt25876.fir.kt | 13 ++++ .../tests/annotations/typeUse/kt25876.kt | 13 ++++ .../tests/annotations/typeUse/kt25876.txt | 37 ++++++++++++ .../tests/annotations/typeUse/kt8325.fir.kt | 6 ++ .../tests/annotations/typeUse/kt8325.kt | 6 ++ .../tests/annotations/typeUse/kt8325.txt | 3 + .../typeUse/nonTypeUseAnnotationOnType.fir.kt | 22 +++++++ .../typeUse/nonTypeUseAnnotationOnType.kt | 22 +++++++ .../typeUse/nonTypeUseAnnotationOnType.txt | 35 +++++++++++ .../test/runners/DiagnosticTestGenerated.java | 34 +++++++++++ .../kotlin/config/LanguageVersionSettings.kt | 1 + 19 files changed, 328 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/annotations/typeUse/kt19455.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/typeUse/kt19455.txt create mode 100644 compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.fir.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.txt create mode 100644 compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.fir.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.txt create mode 100644 compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.fir.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.txt diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 011fac1aa16..425de6aa440 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -1813,6 +1813,40 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti } } + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/annotations/typeUse") + @TestDataPath("$PROJECT_ROOT") + public class TypeUse { + @Test + public void testAllFilesPresentInTypeUse() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/annotations/typeUse"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Test + @TestMetadata("kt19455.kt") + public void testKt19455() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/typeUse/kt19455.kt"); + } + + @Test + @TestMetadata("kt25876.kt") + public void testKt25876() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.kt"); + } + + @Test + @TestMetadata("kt8325.kt") + public void testKt8325() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.kt"); + } + + @Test + @TestMetadata("nonTypeUseAnnotationOnType.kt") + public void testNonTypeUseAnnotationOnType() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.kt"); + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeTypeParameterType.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeTypeParameterType.kt index 711a9238049..238f48f31bb 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeTypeParameterType.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeTypeParameterType.kt @@ -10,4 +10,3 @@ import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag abstract class ConeTypeParameterType : ConeLookupTagBasedType() { abstract override val lookupTag: ConeTypeParameterLookupTag } - diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt index 1c89a9d2d55..77fc30cc3a6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.resolve import org.jetbrains.kotlin.builtins.StandardNames -import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageFeature.* import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor @@ -41,7 +41,7 @@ class AnnotationChecker( if (annotated is KtProperty) { checkPropertyUseSiteTargetAnnotations(annotated, trace) } - if (annotated is KtClass) { + if (annotated is KtClassOrObject) { checkSuperTypeAnnotations(annotated, trace) } if (annotated is KtCallableDeclaration) { @@ -51,12 +51,31 @@ class AnnotationChecker( if (annotated is KtTypeAlias) { annotated.getTypeReference()?.let { check(it, trace) } } - if (annotated is KtTypeParameterListOwner && annotated is KtCallableDeclaration) { - // TODO: support type parameter annotations for type parameters on classes and properties + if ( + annotated is KtTypeParameterListOwner && + (annotated is KtCallableDeclaration || languageVersionSettings.supportsFeature(ProperCheckAnnotationsTargetInTypeUsePositions)) + ) { annotated.typeParameters.forEach { check(it, trace) } + for (typeParameter in annotated.typeParameters) { + typeParameter.extendsBound?.let { + checkTypeReference( + it, + trace, + shouldCheckReferenceItself = true, + checkWithoutLanguageFeature = annotated is KtCallableDeclaration + ) + } + } + for (typeConstraint in annotated.typeConstraints) { + typeConstraint.boundTypeReference?.let { checkTypeReference(it, trace, shouldCheckReferenceItself = true) } + } } if (annotated is KtTypeReference) { - annotated.typeElement?.typeArgumentsAsTypes?.filterNotNull()?.forEach { check(it, trace) } + if (languageVersionSettings.supportsFeature(ProperCheckAnnotationsTargetInTypeUsePositions)) { + checkTypeReference(annotated, trace) + } else { + annotated.typeElement?.typeArgumentsAsTypes?.filterNotNull()?.forEach { check(it, trace) } + } } if (annotated is KtDeclarationWithBody) { // JetFunction or JetPropertyAccessor @@ -83,7 +102,7 @@ class AnnotationChecker( private fun checkPropertyUseSiteTargetAnnotations(property: KtProperty, trace: BindingTrace) { fun List?.getDescriptors() = this?.mapNotNull { trace.get(BindingContext.ANNOTATION, it)?.annotationClass } ?: listOf() - val reportError = languageVersionSettings.supportsFeature(LanguageFeature.ProhibitRepeatedUseSiteTargetAnnotations) + val reportError = languageVersionSettings.supportsFeature(ProhibitRepeatedUseSiteTargetAnnotations) val propertyAnnotations = mapOf( AnnotationUseSiteTarget.PROPERTY_GETTER to property.getter?.annotationEntries.getDescriptors(), @@ -107,21 +126,40 @@ class AnnotationChecker( } } - private fun checkSuperTypeAnnotations(annotated: KtClass, trace: BindingTrace) { - val reportError = languageVersionSettings.supportsFeature(LanguageFeature.ProhibitUseSiteTargetAnnotationsOnSuperTypes) - + private fun checkSuperTypeAnnotations(annotated: KtClassOrObject, trace: BindingTrace) { for (superType in annotated.superTypeListEntries.mapNotNull { it.typeReference }) { - for (entry in superType.annotationEntries) { - if (entry.useSiteTarget != null) { + checkTypeReference(superType, trace, isSuperType = true) + } + } + + private fun checkTypeReference( + reference: KtTypeReference, + trace: BindingTrace, + isSuperType: Boolean = false, + shouldCheckReferenceItself: Boolean = false, + checkWithoutLanguageFeature: Boolean = false + ) { + val shouldRunCheck = isSuperType || shouldCheckReferenceItself + if (shouldRunCheck) { + for (entry in reference.annotationEntries) { + val actualTargets = getActualTargetList(reference, null, trace.bindingContext) + if (entry.useSiteTarget != null && isSuperType) { + val reportError = languageVersionSettings.supportsFeature(ProhibitUseSiteTargetAnnotationsOnSuperTypes) val diagnostic = if (reportError) { Errors.ANNOTATION_ON_SUPERCLASS.on(entry) } else { Errors.ANNOTATION_ON_SUPERCLASS_WARNING.on(entry) } trace.report(diagnostic) + } else if (shouldRunCheck && (languageVersionSettings.supportsFeature(ProperCheckAnnotationsTargetInTypeUsePositions) || checkWithoutLanguageFeature)) { + checkAnnotationEntry(entry, actualTargets, trace) } } } + val typeArguments = reference.typeElement?.typeArgumentsAsTypes ?: return + for (typeArgument in typeArguments) { + typeArgument?.let { checkTypeReference(it, trace, shouldCheckReferenceItself = true) } + } } private fun KtAnnotated?.getImplicitUseSiteTargetList(): List = when (this) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 055504cbee4..4970b3b4538 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -344,6 +344,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return; } checkForCastImpossibilityOrRedundancy(expression, actualType, targetType, context); + if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProperCheckAnnotationsTargetInTypeUsePositions)) { + components.annotationChecker.check(expression.getRight(), context.trace, null); + } } private void checkForCastImpossibilityOrRedundancy( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java index 4cc05e7b387..feaa3e4c32b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java @@ -67,6 +67,7 @@ public class ExpressionTypingComponents { /*package*/ NewKotlinTypeChecker kotlinTypeChecker; /*package*/ TypeResolutionInterceptor typeResolutionInterceptor; /*package*/ MissingSupertypesResolver missingSupertypesResolver; + /*package*/ AnnotationChecker annotationChecker; @Inject @@ -258,4 +259,9 @@ public class ExpressionTypingComponents { public void setMissingSupertypesResolver(@NotNull MissingSupertypesResolver missingSupertypesResolver) { this.missingSupertypesResolver = missingSupertypesResolver; } + + @Inject + public void setAnnotationChecker(@NotNull AnnotationChecker annotationChecker) { + this.annotationChecker = annotationChecker; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt index 4fbeade41d2..5a54e421271 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt @@ -642,6 +642,10 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping detectRedundantIs(context, subjectType, targetType, isCheck, negated, subjectDataFlowValue) + if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProperCheckAnnotationsTargetInTypeUsePositions)) { + components.annotationChecker.check(typeReferenceAfterIs, context.trace) + } + if (CastDiagnosticsUtil.isCastErased(subjectType, targetType, KotlinTypeChecker.DEFAULT)) { context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(typeReferenceAfterIs, targetType)) } diff --git a/compiler/testData/diagnostics/tests/annotations/typeUse/kt19455.kt b/compiler/testData/diagnostics/tests/annotations/typeUse/kt19455.kt new file mode 100644 index 00000000000..ad8331aedff --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/typeUse/kt19455.kt @@ -0,0 +1,14 @@ +// FIR_IDENTICAL +// !LANGUAGE: +ProperCheckAnnotationsTargetInTypeUsePositions +// ISSUE: KT-19455 + +package test + +@Target(AnnotationTarget.TYPE) +annotation class TypeAnn + +open class TypeToken + +object Test : TypeToken<@TypeAnn String>() // (1) + +val test = object : TypeToken<@TypeAnn String>() {} // (2) diff --git a/compiler/testData/diagnostics/tests/annotations/typeUse/kt19455.txt b/compiler/testData/diagnostics/tests/annotations/typeUse/kt19455.txt new file mode 100644 index 00000000000..71bd8e88f70 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/typeUse/kt19455.txt @@ -0,0 +1,26 @@ +package + +package test { + public val test: test.TypeToken<@test.TypeAnn kotlin.String> + + public object Test : test.TypeToken<@test.TypeAnn kotlin.String> { + private constructor Test() + 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.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class TypeAnn : kotlin.Annotation { + public constructor TypeAnn() + 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 open class TypeToken { + public constructor TypeToken() + 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/tests/annotations/typeUse/kt25876.fir.kt b/compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.fir.kt new file mode 100644 index 00000000000..a7b1fb3f5f0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.fir.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: +ProperCheckAnnotationsTargetInTypeUsePositions +// ISSUE: KT-25876 + +@Target(AnnotationTarget.TYPE) +annotation class Anno(val value: String) + +fun foo(x: String): @Anno(Lorem, ipsum::class, "dolor", sit-amet) String { // OK + return x +} + +abstract class Foo : @Anno(o_O) Throwable() // OK + +abstract class Bar // OK diff --git a/compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.kt b/compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.kt new file mode 100644 index 00000000000..6a05d14e120 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: +ProperCheckAnnotationsTargetInTypeUsePositions +// ISSUE: KT-25876 + +@Target(AnnotationTarget.TYPE) +annotation class Anno(val value: String) + +fun foo(x: String): @Anno(Lorem, ipsum::class, "dolor", sit-amet) String { // OK + return x +} + +abstract class Foo : @Anno(o_O) Throwable() // OK + +abstract class BarO_o) Any> // OK diff --git a/compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.txt b/compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.txt new file mode 100644 index 00000000000..47876385b77 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.txt @@ -0,0 +1,37 @@ +package + +public fun foo(/*0*/ x: kotlin.String): @Anno kotlin.String + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class Anno : kotlin.Annotation { + public constructor Anno(/*0*/ value: kotlin.String) + public final val value: 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 +} + +public abstract class Bar { + public constructor Bar() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class Foo : @Anno kotlin.Throwable { + public constructor Foo() + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public open override /*1*/ /*fake_override*/ val message: kotlin.String? + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.fir.kt b/compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.fir.kt new file mode 100644 index 00000000000..d4fc6913762 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.fir.kt @@ -0,0 +1,6 @@ +// !LANGUAGE: +ProperCheckAnnotationsTargetInTypeUsePositions +// ISSUE: KT-8325 + +fun foo() { + object : @__UNRESOLVED__ Any() {} +} diff --git a/compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.kt b/compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.kt new file mode 100644 index 00000000000..1d6ed561160 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.kt @@ -0,0 +1,6 @@ +// !LANGUAGE: +ProperCheckAnnotationsTargetInTypeUsePositions +// ISSUE: KT-8325 + +fun foo() { + object : @__UNRESOLVED__ Any() {} +} diff --git a/compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.txt b/compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.txt new file mode 100644 index 00000000000..65a6ac47e1f --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.txt @@ -0,0 +1,3 @@ +package + +public fun foo(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.fir.kt b/compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.fir.kt new file mode 100644 index 00000000000..8bf69fa81ce --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.fir.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +ProperCheckAnnotationsTargetInTypeUsePositions +// ISSUE: KT-28449 + +@Target(AnnotationTarget.PROPERTY_GETTER) +annotation class Ann + +abstract class Foo : @Ann Any() + +abstract class Bar + +fun test_1(a: Any) { + if (a is @Ann String) return +} + +open class TypeToken +val test_2 = object : TypeToken<@Ann String>() {} + +fun test_3(a: Any) { + a as @Ann Int +} + +fun test_4() where T : @Ann Any, T : @Ann CharSequence {} diff --git a/compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.kt b/compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.kt new file mode 100644 index 00000000000..9420a410dbb --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +ProperCheckAnnotationsTargetInTypeUsePositions +// ISSUE: KT-28449 + +@Target(AnnotationTarget.PROPERTY_GETTER) +annotation class Ann + +abstract class Foo : @Ann Any() + +abstract class Bar@Ann Any> + +fun test_1(a: Any) { + if (a is @Ann String) return +} + +open class TypeToken +val test_2 = object : TypeToken<@Ann String>() {} + +fun test_3(a: Any) { + a as @Ann Int +} + +fun test_4() where T : @Ann Any, T : @Ann CharSequence {} diff --git a/compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.txt b/compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.txt new file mode 100644 index 00000000000..ebb5fac4297 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.txt @@ -0,0 +1,35 @@ +package + +public val test_2: TypeToken<@Ann kotlin.String> +public fun test_1(/*0*/ a: kotlin.Any): kotlin.Unit +public fun test_3(/*0*/ a: kotlin.Any): kotlin.Unit +public fun test_4(): kotlin.Unit where T : @Ann kotlin.CharSequence + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY_GETTER}) public final annotation class Ann : kotlin.Annotation { + public constructor Ann() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class Bar { + public constructor Bar() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class 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 open class TypeToken { + public constructor TypeToken() + 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/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 793776c06b2..6f0000a8e8a 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -1819,6 +1819,40 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { } } + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/annotations/typeUse") + @TestDataPath("$PROJECT_ROOT") + public class TypeUse { + @Test + public void testAllFilesPresentInTypeUse() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/annotations/typeUse"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Test + @TestMetadata("kt19455.kt") + public void testKt19455() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/typeUse/kt19455.kt"); + } + + @Test + @TestMetadata("kt25876.kt") + public void testKt25876() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/typeUse/kt25876.kt"); + } + + @Test + @TestMetadata("kt8325.kt") + public void testKt8325() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/typeUse/kt8325.kt"); + } + + @Test + @TestMetadata("nonTypeUseAnnotationOnType.kt") + public void testNonTypeUseAnnotationOnType() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/typeUse/nonTypeUseAnnotationOnType.kt"); + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 2867d9d2177..80fc20e0dd2 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -168,6 +168,7 @@ enum class LanguageFeature( ForbidUsingExtensionPropertyTypeParameterInDelegate(KOTLIN_1_6, kind = BUG_FIX), ProhibitSelfCallsInNestedObjects(KOTLIN_1_6, kind = BUG_FIX), ApproximateIntegerLiteralTypesInReceiverPosition(KOTLIN_1_6), + ProperCheckAnnotationsTargetInTypeUsePositions(KOTLIN_1_6, kind = BUG_FIX), // Temporarily disabled, see KT-27084/KT-22379 SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX),