diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt index 3f3dbdb5d46..028986d0b9a 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt @@ -64,7 +64,10 @@ class Psi2IrTranslator( extensions: GeneratorExtensions = GeneratorExtensions(), fragmentContext: FragmentContext? = null ): GeneratorContext { - val typeTranslator = TypeTranslatorImpl(symbolTable, languageVersionSettings, moduleDescriptor, extensions = extensions) + val typeTranslator = TypeTranslatorImpl( + symbolTable, languageVersionSettings, moduleDescriptor, extensions = extensions, + allowErrorTypeInAnnotations = configuration.skipBodies, + ) return GeneratorContext( configuration, moduleDescriptor, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ConstantValueGeneratorImpl.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ConstantValueGeneratorImpl.kt index ff81e3fdca9..ecfedc6d69b 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ConstantValueGeneratorImpl.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ConstantValueGeneratorImpl.kt @@ -22,7 +22,8 @@ class ConstantValueGeneratorImpl( moduleDescriptor: ModuleDescriptor, symbolTable: ReferenceSymbolTable, typeTranslator: TypeTranslator, -) : ConstantValueGenerator(moduleDescriptor, symbolTable, typeTranslator) { + allowErrorTypeInAnnotations: Boolean, +) : ConstantValueGenerator(moduleDescriptor, symbolTable, typeTranslator, allowErrorTypeInAnnotations) { override fun extractAnnotationOffsets(annotationDescriptor: AnnotationDescriptor): Pair = extractOffsets(annotationDescriptor.source) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt index 842fcd89e5c..be54f54971d 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt @@ -9,15 +9,11 @@ import org.jetbrains.kotlin.backend.common.SamTypeApproximator import org.jetbrains.kotlin.builtins.ReflectionTypes import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.NotFoundClasses import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.builders.IrGeneratorContext -import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.expressions.IrDeclarationReference -import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.TypeTranslator import org.jetbrains.kotlin.psi.KtFile @@ -83,7 +79,10 @@ class GeneratorContext private constructor( languageVersionSettings, symbolTable, extensions, - TypeTranslatorImpl(symbolTable, languageVersionSettings, moduleDescriptor, extensions = extensions, ktFile = ktFile), + TypeTranslatorImpl( + symbolTable, languageVersionSettings, moduleDescriptor, extensions = extensions, ktFile = ktFile, + allowErrorTypeInAnnotations = configuration.skipBodies, + ), irBuiltIns, callToSubstitutedDescriptorMap, fragmentContext, 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 0c5eef87824..9ab45ca2b82 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 @@ -18,7 +18,11 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor +import org.jetbrains.kotlin.ir.IrFileEntry import org.jetbrains.kotlin.ir.PsiIrFileEntry +import org.jetbrains.kotlin.ir.SourceRangeInfo +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.DescriptorMetadataSource import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl @@ -28,10 +32,12 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi2ir.transformations.insertImplicitCasts import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.lazy.descriptors.findPackageFragmentForFile +import org.jetbrains.kotlin.types.error.ErrorUtils import org.jetbrains.kotlin.utils.addIfNotNull open class ModuleGenerator( @@ -75,6 +81,13 @@ open class ModuleGenerator( IrSyntheticDeclarationGenerator(context).generateSyntheticDeclarations(irFile) + if (context.configuration.skipBodies) { + // In KAPT3 mode (skipBodies = true), we create stub IR for error class, so that it would be possible to have annotations + // with unresolved types in the IR and they could survive all transformations up until the codegen. + // This is a hack which should preferably be removed as soon as KAPT3 is no longer used. + createStubIrForErrorClass() + } + insertImplicitCasts(irFile, context) context.callToSubstitutedDescriptorMap.clear() @@ -85,11 +98,32 @@ open class ModuleGenerator( return irFile } - fun createEmptyIrFile(ktFile: KtFile, module: IrModuleFragment): IrFileImpl { + private fun createEmptyIrFile(ktFile: KtFile, module: IrModuleFragment): IrFileImpl { val fileEntry = PsiIrFileEntry(ktFile) val packageFragmentDescriptor = context.moduleDescriptor.findPackageFragmentForFile(ktFile)!! return IrFileImpl(fileEntry, packageFragmentDescriptor, module).apply { metadata = DescriptorMetadataSource.File(CodegenUtil.getMemberDescriptorsToGenerate(ktFile, context.bindingContext)) } } + + private fun createStubIrForErrorClass() { + val fakeFileEntry = object : IrFileEntry { + override val name: String = "" + override val maxOffset: Int = UNDEFINED_OFFSET + + override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int): SourceRangeInfo = TODO("Not yet implemented") + override fun getLineNumber(offset: Int): Int = TODO("Not yet implemented") + override fun getColumnNumber(offset: Int): Int = TODO("Not yet implemented") + } + val fakeFile = IrFileImpl( + fakeFileEntry, + EmptyPackageFragmentDescriptor(context.moduleDescriptor, FqName(fakeFileEntry.name)), + ) + val gen = SyntheticDeclarationsGenerator(context) + gen.visitClassDescriptor(ErrorUtils.errorClass, fakeFile) + gen.visitConstructorDescriptor( + ErrorUtils.errorClass.unsubstitutedPrimaryConstructor!!, + context.symbolTable.referenceClass(ErrorUtils.errorClass).owner, + ) + } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TypeTranslatorImpl.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TypeTranslatorImpl.kt index 4cfd4dd0b42..b57e4aac693 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TypeTranslatorImpl.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TypeTranslatorImpl.kt @@ -14,16 +14,18 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.types.* -open class TypeTranslatorImpl( +class TypeTranslatorImpl( symbolTable: ReferenceSymbolTable, languageVersionSettings: LanguageVersionSettings, moduleDescriptor: ModuleDescriptor, typeParametersResolverBuilder: () -> TypeParametersResolver = { ScopedTypeParametersResolver() }, enterTableScope: Boolean = false, extensions: StubGeneratorExtensions = StubGeneratorExtensions.EMPTY, - private val ktFile: KtFile? = null + private val ktFile: KtFile? = null, + allowErrorTypeInAnnotations: Boolean = false, ) : TypeTranslator(symbolTable, languageVersionSettings, typeParametersResolverBuilder, enterTableScope, extensions) { - override val constantValueGenerator: ConstantValueGenerator = ConstantValueGeneratorImpl(moduleDescriptor, symbolTable, this) + override val constantValueGenerator: ConstantValueGenerator = + ConstantValueGeneratorImpl(moduleDescriptor, symbolTable, this, allowErrorTypeInAnnotations) private val typeApproximatorForNI = TypeApproximator(moduleDescriptor.builtIns, languageVersionSettings) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBasedDescriptors.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBasedDescriptors.kt index d8b529bba88..02837768a2a 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBasedDescriptors.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBasedDescriptors.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.error.ErrorUtils /* Descriptors that serve purely as a view into IR structures. Created each time at the borderline between IR-based and descriptor-based code (such as inliner). @@ -44,11 +45,21 @@ abstract class IrBasedDeclarationDescriptor(val owner: T) : D } private fun IrConstructorCall.toAnnotationDescriptor(): AnnotationDescriptor { - assert(symbol.owner.parentAsClass.isAnnotationClass) { + val annotationClass = symbol.owner.parentAsClass + + @OptIn(ObsoleteDescriptorBasedAPI::class) + if (annotationClass.symbol.descriptor == ErrorUtils.errorClass) { + // This should be possible only in case of KAPT3 where IR generated by psi2ir can have annotations with unresolved types. + // Apparently annotations with unresolved types is a useful feature for KAPT3 in the "correct error types mode", see kt32596.kt. + // This is a hack which should preferably be removed as soon as KAPT3 is no longer used. + return AnnotationDescriptorImpl(type.toKotlinType(), emptyMap(), source) + } + + assert(annotationClass.isAnnotationClass) { "Expected call to constructor of annotation class but was: ${this.dump()}" } return AnnotationDescriptorImpl( - symbol.owner.parentAsClass.defaultType.toIrBasedKotlinType(), + annotationClass.defaultType.toIrBasedKotlinType(), symbol.owner.valueParameters.map { it.name to getValueArgument(it.index) } .filter { it.second != null } .associate { it.first to it.second!!.toConstantValue() }, 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 a735434b8ba..d13d551a903 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 @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.constants.* import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeConstructorSubstitution +import org.jetbrains.kotlin.types.error.ErrorClassDescriptor import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.typeUtil.builtIns @@ -28,6 +29,7 @@ abstract class ConstantValueGenerator( private val moduleDescriptor: ModuleDescriptor, private val symbolTable: ReferenceSymbolTable, private val typeTranslator: TypeTranslator, + private val allowErrorTypeInAnnotations: Boolean, ) { protected abstract fun extractAnnotationOffsets(annotationDescriptor: AnnotationDescriptor): Pair @@ -158,7 +160,10 @@ abstract class ConstantValueGenerator( if (annotationClassDescriptor !is ClassDescriptor) return null if (annotationClassDescriptor is NotFoundClasses.MockClassDescriptor) return null - assert(DescriptorUtils.isAnnotationClass(annotationClassDescriptor)) { + assert( + DescriptorUtils.isAnnotationClass(annotationClassDescriptor) || + (allowErrorTypeInAnnotations && annotationClassDescriptor is ErrorClassDescriptor) + ) { "Annotation class expected: $annotationClassDescriptor" } diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/kt32596.kt b/plugins/kapt3/kapt3-compiler/testData/converter/kt32596.kt index 6b456a12eab..01f77145bc6 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/kt32596.kt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/kt32596.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // CORRECT_ERROR_TYPES @file:Suppress("UNRESOLVED_REFERENCE", "ANNOTATION_ARGUMENT_MUST_BE_CONST") @@ -15,6 +14,6 @@ class ErrorSomeMissingAnnotations annotation class Anno(val klass: KClass<*>) -// EXPECTED_ERROR: (kotlin:10:1) cannot find symbol -// EXPECTED_ERROR: (kotlin:13:1) cannot find symbol -// EXPECTED_ERROR: (kotlin:7:1) cannot find symbol +// EXPECTED_ERROR: (kotlin:9:1) cannot find symbol +// EXPECTED_ERROR: (kotlin:12:1) cannot find symbol +// EXPECTED_ERROR: (kotlin:6:1) cannot find symbol