From e54ef3bdb84a1bbc3f2185e6c1cd1a12794f1705 Mon Sep 17 00:00:00 2001 From: pyos Date: Mon, 16 Dec 2019 16:20:24 +0100 Subject: [PATCH] PSI2IR: ignore enum annotation arguments of error type Similar to references to error type, this may happen if library A uses an entity from library B annotated with an annotation from C, but A is compiled without C on the classpath. --- .../kotlin/ir/util/ConstantValueGenerator.kt | 14 ++++++++++++-- .../library/a.kt | 9 +++++++++ .../library/b.kt | 11 +++++++++++ .../output.txt | 1 + .../source.kt | 7 +++++++ .../CompileKotlinAgainstCustomBinariesTest.kt | 4 ++++ 6 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/library/a.kt create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/library/b.kt create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/output.txt create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/source.kt diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ConstantValueGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ConstantValueGenerator.kt index 02810dcd83d..a86d0ea0087 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ConstantValueGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ConstantValueGenerator.kt @@ -77,8 +77,8 @@ class ConstantValueGenerator( startOffset, endOffset, constantType, arrayElementType.toIrType(), - constantValue.value.map { - generateConstantValueAsExpression(startOffset, endOffset, it, null) + constantValue.value.mapNotNull { + generateConstantOrAnnotationValueAsExpression(startOffset, endOffset, it, null) } ) } @@ -90,6 +90,14 @@ class ConstantValueGenerator( if (enumEntryDescriptor !is ClassDescriptor) { throw AssertionError("Enum entry $enumEntryDescriptor should be a ClassDescriptor") } + if (!DescriptorUtils.isEnumEntry(enumEntryDescriptor)) { + // Error class descriptor for an unresolved entry. + // TODO this `null` may actually reach codegen if the annotation is on an interface member's default implementation, + // as any bridge generated in an implementation of that interface will have a copy of the annotation. See + // `missingEnumReferencedInAnnotationArgumentIr` in `testData/compileKotlinAgainstCustomBinaries`: replace + // `open class B` with `interface B` and watch things break. (`KClassValue` below likely has a similar problem.) + return null + } IrGetEnumValueImpl( startOffset, endOffset, constantType, @@ -115,6 +123,8 @@ class ConstantValueGenerator( } } + is ErrorValue -> null + else -> TODO("Unexpected constant value: ${constantValue.javaClass.simpleName} $constantValue") } } diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/library/a.kt new file mode 100644 index 00000000000..e4504d6fa12 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/library/a.kt @@ -0,0 +1,9 @@ +package a + +enum class E { ENTRY } + +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE_PARAMETER) +annotation class Anno(val e: E) + +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE_PARAMETER) +annotation class Anno2(val e: Array) diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/library/b.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/library/b.kt new file mode 100644 index 00000000000..5946628010d --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/library/b.kt @@ -0,0 +1,11 @@ +package b + +import a.* + +@Anno(E.ENTRY) +@Anno2(arrayOf(E.ENTRY)) +open class B { + @Anno(E.ENTRY) + @Anno2(arrayOf(E.ENTRY)) + fun <@Anno(E.ENTRY) @Anno2(arrayOf(E.ENTRY)) T> foo(t: T) = t +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/output.txt new file mode 100644 index 00000000000..a0aba9318ad --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/output.txt @@ -0,0 +1 @@ +OK \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/source.kt new file mode 100644 index 00000000000..4ab06f33a2a --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingEnumReferencedInAnnotationArgumentIr/source.kt @@ -0,0 +1,7 @@ +package c + +import b.B + +class C : B() { + fun bar() = foo("") +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt index 321ad961c48..537e9c6bdc3 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -172,6 +172,10 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration doTestWithTxt(copyJarFileWithoutEntry(compileLibrary("library"), "test/E.class")) } + fun testMissingEnumReferencedInAnnotationArgumentIr() { + doTestBrokenLibrary("library", "a/E.class", additionalOptions = listOf("-Xuse-ir")) + } + fun testNoWarningsOnJavaKotlinInheritance() { // This test checks that there are no PARAMETER_NAME_CHANGED_ON_OVERRIDE or DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES // warnings when subclassing in Kotlin from Java binaries (in case when no parameter names are available for Java classes)