[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,
|
irFactory: IrFactory,
|
||||||
) : SymbolTable(signaturer, 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
|
* As long as [IrBuiltIns] aren't bound, the symbol table will operate like [SymbolTable], as the initialization of built-ins requires
|
||||||
* still being created.
|
* a symbol table.
|
||||||
*/
|
*/
|
||||||
private var irBuiltIns: IrBuiltInsOverDescriptors? = null
|
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
|
@ObsoleteDescriptorBasedAPI
|
||||||
override fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol {
|
override fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol {
|
||||||
val irBuiltIns = this.irBuiltIns ?: return super.referenceClass(descriptor)
|
val irBuiltIns = this.irBuiltIns ?: return super.referenceClass(descriptor)
|
||||||
|
|||||||
@@ -254,26 +254,33 @@ abstract class DeclarationStubGenerator(
|
|||||||
classDescriptor.modality
|
classDescriptor.modality
|
||||||
|
|
||||||
fun generateClassStub(descriptor: ClassDescriptor): IrClass {
|
fun generateClassStub(descriptor: ClassDescriptor): IrClass {
|
||||||
val referenceClass = symbolTable.referenceClass(descriptor)
|
val irClassSymbol = symbolTable.referenceClass(descriptor)
|
||||||
if (referenceClass.isBound) {
|
if (irClassSymbol.isBound) {
|
||||||
return referenceClass.owner
|
return irClassSymbol.owner
|
||||||
}
|
}
|
||||||
val origin = computeOrigin(descriptor)
|
|
||||||
return symbolTable.declareClass(descriptor) {
|
// `irClassSymbol` may have a different descriptor than `descriptor`. For example, a `SymbolTableWithBuiltInsDeduplication` might
|
||||||
IrLazyClass(
|
// return a built-in symbol that hasn't been bound yet (e.g. `OptIn`). If the stub generator calls `declareClass` with the incorrect
|
||||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin,
|
// `descriptor`, a symbol created for `descriptor` will be bound, not the built-in symbol which should be. If `generateClassStub` is
|
||||||
it, descriptor,
|
// called twice for such a `descriptor`, an exception will occur because `descriptor`'s symbol will already have been bound.
|
||||||
descriptor.name, descriptor.kind, descriptor.visibility, getEffectiveModality(descriptor),
|
with(irClassSymbol.descriptor) {
|
||||||
isCompanion = descriptor.isCompanionObject,
|
val origin = computeOrigin(this)
|
||||||
isInner = descriptor.isInner,
|
return symbolTable.declareClass(this) {
|
||||||
isData = descriptor.isData,
|
IrLazyClass(
|
||||||
isExternal = descriptor.isEffectivelyExternal(),
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin,
|
||||||
isValue = descriptor.isValueClass(),
|
it, this,
|
||||||
isExpect = descriptor.isExpect,
|
name, kind, visibility, getEffectiveModality(this),
|
||||||
isFun = descriptor.isFun,
|
isCompanion = isCompanionObject,
|
||||||
stubGenerator = this,
|
isInner = isInner,
|
||||||
typeTranslator = typeTranslator
|
isData = isData,
|
||||||
)
|
isExternal = isEffectivelyExternal(),
|
||||||
|
isValue = isValueClass(),
|
||||||
|
isExpect = isExpect,
|
||||||
|
isFun = isFun,
|
||||||
|
stubGenerator = this@DeclarationStubGenerator,
|
||||||
|
typeTranslator = typeTranslator
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user