[FE] Detect recursion when typealias referenced as annotation in its RHS

#KT-14612 Fixed
This commit is contained in:
Dmitriy Novozhilov
2020-12-24 11:46:19 +03:00
parent d3349197ba
commit 70c4bdf32e
7 changed files with 61 additions and 3 deletions
@@ -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 {
@@ -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()
@@ -0,0 +1,3 @@
// ISSUE: KT-14612
typealias S = @S Suppress
@@ -0,0 +1,3 @@
// ISSUE: KT-14612
typealias S = <!RECURSIVE_TYPEALIAS_EXPANSION!>@S<!> Suppress
@@ -0,0 +1,4 @@
package
public typealias S = @S /* = kotlin.Suppress */(names = {}) kotlin.Suppress
@@ -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 {
@@ -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<AnnotationDescriptor> {
return delegate.filter(filter).iterator()
}
override fun findAnnotation(fqName: FqName): AnnotationDescriptor? {
return super.findAnnotation(fqName)?.takeIf(filter)
}
}
class CompositeAnnotations(
private val delegates: List<Annotations>
) : Annotations {