[JVM IR] KTIJ-24335 Fix stub generation of deduplicated built-ins
- Some built-in symbols like `OptIn` haven't been created yet by the time `irBuiltIns` is bound to `SymbolTableWithBuiltInsDeduplication`. This caused an issue where `DeclarationStubGenerator` would get the built-in symbol from `referenceClass`, but still stub for the original duplicate `descriptor` and its associated own symbol. Because `generateClassStub` would check `referenceClass.isBound` for the built-in symbol, `isBound` was never checked for the duplicate symbol and thus a "symbol already bound" exception occurred if `generateClassStub` was invoked twice for a duplicate `descriptor`. - The solution takes the descriptor from the `IrClassSymbol` returned by `referenceClass`.
This commit is contained in:
committed by
Space Team
parent
f11ea92601
commit
d1df6391db
+10
-2
@@ -31,8 +31,8 @@ class SymbolTableWithBuiltInsDeduplication(
|
||||
irFactory: IrFactory,
|
||||
) : SymbolTable(signaturer, irFactory) {
|
||||
/**
|
||||
* As long as [IrBuiltIns] aren't bound, the symbol table will operate like [SymbolTable], as it must be assumed that built-ins are
|
||||
* still being created.
|
||||
* As long as [IrBuiltIns] aren't bound, the symbol table will operate like [SymbolTable], as the initialization of built-ins requires
|
||||
* a symbol table.
|
||||
*/
|
||||
private var irBuiltIns: IrBuiltInsOverDescriptors? = null
|
||||
|
||||
@@ -44,6 +44,14 @@ class SymbolTableWithBuiltInsDeduplication(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets or creates the [IrClassSymbol] for [descriptor], or for the built-in descriptor with the same name if [descriptor] is a
|
||||
* duplicate built-in.
|
||||
*
|
||||
* Note that not all built-in symbols may have been bound or created by the time [irBuiltIns] has been bound. However, [referenceClass]
|
||||
* will create a symbol in such a case (via `super.referenceClass`) and [org.jetbrains.kotlin.ir.util.DeclarationStubGenerator] will
|
||||
* create a stub for the symbol if [referenceClass] was invoked from the stub generator.
|
||||
*/
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
override fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol {
|
||||
val irBuiltIns = this.irBuiltIns ?: return super.referenceClass(descriptor)
|
||||
|
||||
@@ -254,26 +254,33 @@ abstract class DeclarationStubGenerator(
|
||||
classDescriptor.modality
|
||||
|
||||
fun generateClassStub(descriptor: ClassDescriptor): IrClass {
|
||||
val referenceClass = symbolTable.referenceClass(descriptor)
|
||||
if (referenceClass.isBound) {
|
||||
return referenceClass.owner
|
||||
val irClassSymbol = symbolTable.referenceClass(descriptor)
|
||||
if (irClassSymbol.isBound) {
|
||||
return irClassSymbol.owner
|
||||
}
|
||||
val origin = computeOrigin(descriptor)
|
||||
return symbolTable.declareClass(descriptor) {
|
||||
IrLazyClass(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin,
|
||||
it, descriptor,
|
||||
descriptor.name, descriptor.kind, descriptor.visibility, getEffectiveModality(descriptor),
|
||||
isCompanion = descriptor.isCompanionObject,
|
||||
isInner = descriptor.isInner,
|
||||
isData = descriptor.isData,
|
||||
isExternal = descriptor.isEffectivelyExternal(),
|
||||
isValue = descriptor.isValueClass(),
|
||||
isExpect = descriptor.isExpect,
|
||||
isFun = descriptor.isFun,
|
||||
stubGenerator = this,
|
||||
typeTranslator = typeTranslator
|
||||
)
|
||||
|
||||
// `irClassSymbol` may have a different descriptor than `descriptor`. For example, a `SymbolTableWithBuiltInsDeduplication` might
|
||||
// return a built-in symbol that hasn't been bound yet (e.g. `OptIn`). If the stub generator calls `declareClass` with the incorrect
|
||||
// `descriptor`, a symbol created for `descriptor` will be bound, not the built-in symbol which should be. If `generateClassStub` is
|
||||
// called twice for such a `descriptor`, an exception will occur because `descriptor`'s symbol will already have been bound.
|
||||
with(irClassSymbol.descriptor) {
|
||||
val origin = computeOrigin(this)
|
||||
return symbolTable.declareClass(this) {
|
||||
IrLazyClass(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin,
|
||||
it, this,
|
||||
name, kind, visibility, getEffectiveModality(this),
|
||||
isCompanion = isCompanionObject,
|
||||
isInner = isInner,
|
||||
isData = isData,
|
||||
isExternal = isEffectivelyExternal(),
|
||||
isValue = isValueClass(),
|
||||
isExpect = isExpect,
|
||||
isFun = isFun,
|
||||
stubGenerator = this@DeclarationStubGenerator,
|
||||
typeTranslator = typeTranslator
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user