diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AnnotationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AnnotationGenerator.kt index cb25ffd884a..23e834d2396 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AnnotationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AnnotationGenerator.kt @@ -40,7 +40,7 @@ class AnnotationGenerator(context: GeneratorContext) : IrElementVisitorVoid { declaration.descriptor.backingField else declaration.descriptor - annotatedDescriptor?.annotations?.mapTo(declaration.annotations) { + annotatedDescriptor?.annotations?.mapNotNullTo(declaration.annotations) { constantValueGenerator.generateAnnotationConstructorCall(it) } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ModuleGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ModuleGenerator.kt index 939393471ce..6234c0a1f4f 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ModuleGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ModuleGenerator.kt @@ -73,7 +73,7 @@ class ModuleGenerator(override val context: GeneratorContext) : Generator { for (ktAnnotationEntry in ktFile.annotationEntries) { val annotationDescriptor = getOrFail(BindingContext.ANNOTATION, ktAnnotationEntry) - irFile.annotations.add(constantValueGenerator.generateAnnotationConstructorCall(annotationDescriptor)) + irFile.annotations.addIfNotNull(constantValueGenerator.generateAnnotationConstructorCall(annotationDescriptor)) } for (ktDeclaration in ktFile.declarations) { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt index 38fffa3547d..b55ce53b082 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt @@ -48,9 +48,7 @@ abstract class IrLazyDeclarationBase( } override val annotations: MutableList by lazy { - descriptor.annotations.map { - typeTranslator.constantValueGenerator.generateAnnotationConstructorCall(it) - }.toMutableList() + descriptor.annotations.mapNotNull(typeTranslator.constantValueGenerator::generateAnnotationConstructorCall).toMutableList() } override var metadata: Nothing? 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 88d05f17c58..1fe0977df3b 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 @@ -7,10 +7,10 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.NotFoundClasses import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.* @@ -38,7 +38,19 @@ class ConstantValueGenerator( endOffset: Int, constantValue: ConstantValue<*>, varargElementType: KotlinType? = null - ): IrExpression { + ): IrExpression = + // Assertion is safe here because annotation calls are not allowed in constant initializers + generateConstantOrAnnotationValueAsExpression(startOffset, endOffset, constantValue, varargElementType)!! + + /** + * @return null if the constant value is an unresolved annotation + */ + private fun generateConstantOrAnnotationValueAsExpression( + startOffset: Int, + endOffset: Int, + constantValue: ConstantValue<*>, + varargElementType: KotlinType? = null + ): IrExpression? { val constantKtType = constantValue.getType(moduleDescriptor) val constantType = constantKtType.toIrType() @@ -103,10 +115,11 @@ class ConstantValueGenerator( } } - fun generateAnnotationConstructorCall(annotationDescriptor: AnnotationDescriptor): IrConstructorCall { + fun generateAnnotationConstructorCall(annotationDescriptor: AnnotationDescriptor): IrConstructorCall? { val annotationType = annotationDescriptor.type - val annotationClassDescriptor = annotationType.constructor.declarationDescriptor as? ClassDescriptor - ?: throw AssertionError("No declaration descriptor for annotation $annotationDescriptor") + val annotationClassDescriptor = annotationType.constructor.declarationDescriptor + if (annotationClassDescriptor !is ClassDescriptor) return null + if (annotationClassDescriptor is NotFoundClasses.MockClassDescriptor) return null assert(DescriptorUtils.isAnnotationClass(annotationClassDescriptor)) { "Annotation class expected: $annotationClassDescriptor" @@ -143,4 +156,4 @@ class ConstantValueGenerator( } private fun KotlinType.getArrayElementType() = builtIns.getArrayElementType(this) -} \ No newline at end of file +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt index f85cefdb069..294a80d7963 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt @@ -130,9 +130,8 @@ class TypeTranslator( } - private fun translateTypeAnnotations(annotations: Annotations): List = - annotations.map(constantValueGenerator::generateAnnotationConstructorCall) + annotations.mapNotNull(constantValueGenerator::generateAnnotationConstructorCall) private fun translateTypeArguments(arguments: List) = arguments.map { diff --git a/compiler/testData/codegen/box/callableReference/property/kt6870_privatePropertyReference.kt b/compiler/testData/codegen/box/callableReference/property/kt6870_privatePropertyReference.kt index 6b17daedfa5..ab273e9919b 100644 --- a/compiler/testData/codegen/box/callableReference/property/kt6870_privatePropertyReference.kt +++ b/compiler/testData/codegen/box/callableReference/property/kt6870_privatePropertyReference.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // IGNORE_BACKEND: JS_IR // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS, NATIVE diff --git a/compiler/testData/codegen/box/objects/kt1136.kt b/compiler/testData/codegen/box/objects/kt1136.kt index a412502ccd5..9caf5855971 100644 --- a/compiler/testData/codegen/box/objects/kt1136.kt +++ b/compiler/testData/codegen/box/objects/kt1136.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM public object SomeObject { diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotationIr/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotationIr/library/a.kt new file mode 100644 index 00000000000..2cb3794ad4c --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotationIr/library/a.kt @@ -0,0 +1,6 @@ +package a + +interface A { + @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE_PARAMETER) + annotation class Anno(val value: String) +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotationIr/library/b.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotationIr/library/b.kt new file mode 100644 index 00000000000..fdac61bc93d --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotationIr/library/b.kt @@ -0,0 +1,9 @@ +package b + +import a.A + +@A.Anno("B") +interface B { + @A.Anno("foo") + fun <@A.Anno("T") T> foo(t: T) = t +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotationIr/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotationIr/output.txt new file mode 100644 index 00000000000..a0aba9318ad --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotationIr/output.txt @@ -0,0 +1 @@ +OK \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotationIr/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotationIr/source.kt new file mode 100644 index 00000000000..ad564297819 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotationIr/source.kt @@ -0,0 +1,8 @@ +package c + +import b.B + +// There should be _no_ error despite the fact that B and B#foo are annotated with an annotation which cannot be resolved +fun bar(b: B) { + b.foo("") +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt index eaae6a449d8..acf27121a8f 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -77,11 +77,11 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration private fun analyzeAndGetAllDescriptors(vararg extraClassPath: File): Collection = DescriptorUtils.getAllDescriptors(analyzeFileToPackageView(*extraClassPath).memberScope) - private fun doTestBrokenLibrary(libraryName: String, vararg pathsToDelete: String) { + private fun doTestBrokenLibrary(libraryName: String, vararg pathsToDelete: String, additionalOptions: List = emptyList()) { // This function compiles a library, then deletes one class file and attempts to compile a Kotlin source against // this broken library. The expected result is an error message from the compiler val library = copyJarFileWithoutEntry(compileLibrary(libraryName), *pathsToDelete) - compileKotlin("source.kt", tmpdir, listOf(library)) + compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = additionalOptions) } private fun doTestKotlinLibraryWithWrongMetadataVersion( @@ -215,6 +215,10 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration doTestBrokenLibrary("library", "a/A\$Anno.class") } + fun testMissingDependencyNestedAnnotationIr() { + doTestBrokenLibrary("library", "a/A\$Anno.class", additionalOptions = listOf("-Xuse-ir")) + } + fun testMissingDependencyConflictingLibraries() { val library1 = copyJarFileWithoutEntry( compileLibrary("library1"),