From 70c4bdf32e68cde9d125224b073e5be4065102e6 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 24 Dec 2020 11:46:19 +0300 Subject: [PATCH] [FE] Detect recursion when typealias referenced as annotation in its RHS #KT-14612 Fixed --- ...irOldFrontendDiagnosticsTestGenerated.java | 6 +++++ .../lazy/descriptors/LazyAnnotations.kt | 25 ++++++++++++++++--- .../tests/typealias/kt14612.fir.kt | 3 +++ .../diagnostics/tests/typealias/kt14612.kt | 3 +++ .../diagnostics/tests/typealias/kt14612.txt | 4 +++ .../test/runners/DiagnosticTestGenerated.java | 6 +++++ .../descriptors/annotations/Annotations.kt | 17 +++++++++++++ 7 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/typealias/kt14612.fir.kt create mode 100644 compiler/testData/diagnostics/tests/typealias/kt14612.kt create mode 100644 compiler/testData/diagnostics/tests/typealias/kt14612.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 49046ad1589..f1d7aeaf79f 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 @@ -28743,6 +28743,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/typealias/kt14518.kt"); } + @Test + @TestMetadata("kt14612.kt") + public void testKt14612() throws Exception { + runTest("compiler/testData/diagnostics/tests/typealias/kt14612.kt"); + } + @Test @TestMetadata("kt14641.kt") public void testKt14641() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt index 4606e054a07..4e37ce2acb5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt @@ -19,6 +19,8 @@ package org.jetbrains.kotlin.resolve.lazy.descriptors import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.annotations.FilteredByPredicateAnnotations +import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.resolve.AnnotationResolver @@ -32,6 +34,8 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.getValue +import org.jetbrains.kotlin.types.AbbreviatedType +import org.jetbrains.kotlin.types.ErrorUtils abstract class LazyAnnotationsContext( val annotationResolver: AnnotationResolver, @@ -77,9 +81,24 @@ class LazyAnnotationDescriptor( c.trace.record(BindingContext.ANNOTATION, annotationEntry, this) } - override val type by c.storageManager.createLazyValue { - c.annotationResolver.resolveAnnotationType(scope, annotationEntry, c.trace) - } + override val type by c.storageManager.createLazyValue( + computable = lazy@{ + val annotationType = c.annotationResolver.resolveAnnotationType(scope, annotationEntry, c.trace) + if (annotationType is AbbreviatedType) { + // This is needed to prevent recursion in cases like this: typealias S = @S Ann + if (annotationType.annotations.any { it == this }) { + annotationType.abbreviation.constructor.declarationDescriptor?.let { typeAliasDescriptor -> + c.trace.report(Errors.RECURSIVE_TYPEALIAS_EXPANSION.on(annotationEntry, typeAliasDescriptor)) + } + return@lazy annotationType.replaceAnnotations(FilteredByPredicateAnnotations(annotationType.annotations) { it != this }) + } + } + annotationType + }, + onRecursiveCall = { + ErrorUtils.createErrorType("Recursion in type of annotation detected") + } + ) override val source = annotationEntry.toSourceElement() diff --git a/compiler/testData/diagnostics/tests/typealias/kt14612.fir.kt b/compiler/testData/diagnostics/tests/typealias/kt14612.fir.kt new file mode 100644 index 00000000000..3aa32a7624f --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/kt14612.fir.kt @@ -0,0 +1,3 @@ +// ISSUE: KT-14612 + +typealias S = @S Suppress diff --git a/compiler/testData/diagnostics/tests/typealias/kt14612.kt b/compiler/testData/diagnostics/tests/typealias/kt14612.kt new file mode 100644 index 00000000000..54de5c038a0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/kt14612.kt @@ -0,0 +1,3 @@ +// ISSUE: KT-14612 + +typealias S = @S Suppress diff --git a/compiler/testData/diagnostics/tests/typealias/kt14612.txt b/compiler/testData/diagnostics/tests/typealias/kt14612.txt new file mode 100644 index 00000000000..71b154ca6f0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/kt14612.txt @@ -0,0 +1,4 @@ +package + +public typealias S = @S /* = kotlin.Suppress */(names = {}) kotlin.Suppress + 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 0ee8b1da93d..6702ff74293 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 @@ -28839,6 +28839,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/typealias/kt14518.kt"); } + @Test + @TestMetadata("kt14612.kt") + public void testKt14612() throws Exception { + runTest("compiler/testData/diagnostics/tests/typealias/kt14612.kt"); + } + @Test @TestMetadata("kt14641.kt") public void testKt14641() throws Exception { diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt index 44a5838c22b..90beb46f1ac 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt @@ -79,6 +79,23 @@ class FilteredAnnotations( } } +class FilteredByPredicateAnnotations( + private val delegate: Annotations, + private val filter: (AnnotationDescriptor) -> Boolean +) : Annotations { + override fun isEmpty(): Boolean { + return !iterator().hasNext() + } + + override fun iterator(): Iterator { + return delegate.filter(filter).iterator() + } + + override fun findAnnotation(fqName: FqName): AnnotationDescriptor? { + return super.findAnnotation(fqName)?.takeIf(filter) + } +} + class CompositeAnnotations( private val delegates: List ) : Annotations {