[FakeOverrideBuilder] Fix referencing a local type from a return type

Copying tree part happens in two stages.
1. Collect all symbols to copy and create new version of them
2. Do copy tree, replacing collected symbols

For f/o builder 1-st stage traversed more nodes, than seconds.
This led to unbound symbols in tree.

^KT-65273 Fixed
This commit is contained in:
Pavel Kunyavskiy
2024-02-06 15:15:19 +01:00
committed by Space Team
parent 90db7cd685
commit 831ef0f909
19 changed files with 509 additions and 22 deletions
@@ -5,10 +5,11 @@
package org.jetbrains.kotlin.ir.overrides
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrOverridableMember
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
@@ -98,6 +99,17 @@ class CopyIrTreeWithSymbolsForFakeOverrides(
private val typeArguments: Map<IrTypeParameterSymbol, IrType>,
descriptorsRemapper: DescriptorsRemapper
) : DeepCopySymbolRemapper(descriptorsRemapper) {
// We need to avoid visiting parts of the tree that would not be visited by [FakeOverrideCopier]
// Otherwise, we can record symbols inside them for rebinding, but would not actually copy them.
// Normally, this is not important, as these local symbols would not be used anyway
// But they can be used in return values of functions/accessors if it is effectively a private declaration,
// e.g. public declaration inside a private class.
override fun visitField(declaration: IrField) {} // don't visit property backing field
override fun visitBlockBody(body: IrBlockBody) {} // don't visit function body and parameter default values
override fun visitExpressionBody(body: IrExpressionBody) {} // don't visit function body and parameter default values
override fun getReferencedClassifier(symbol: IrClassifierSymbol): IrClassifierSymbol {
val result = super.getReferencedClassifier(symbol)
if (result !is IrTypeParameterSymbol)
@@ -53,10 +53,6 @@ open class DeepCopySymbolRemapper(
element.acceptChildrenVoid(this)
}
override fun visitCall(expression: IrCall) {
expression.acceptChildrenVoid(this)
}
protected inline fun <D : DeclarationDescriptor, B : IrSymbolOwner, reified S : IrBindableSymbol<D, B>>
remapSymbol(map: MutableMap<S, S>, owner: B, createNewSymbol: (S) -> S) {
val symbol = owner.symbol as S
@@ -67,98 +63,98 @@ open class DeepCopySymbolRemapper(
remapSymbol(classes, declaration) {
IrClassSymbolImpl(descriptorsRemapper.remapDeclaredClass(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitClass(declaration)
}
override fun visitScript(declaration: IrScript) {
remapSymbol(scripts, declaration) {
IrScriptSymbolImpl(descriptorsRemapper.remapDeclaredScript(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitScript(declaration)
}
override fun visitConstructor(declaration: IrConstructor) {
remapSymbol(constructors, declaration) {
IrConstructorSymbolImpl(descriptorsRemapper.remapDeclaredConstructor(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitConstructor(declaration)
}
override fun visitEnumEntry(declaration: IrEnumEntry) {
remapSymbol(enumEntries, declaration) {
IrEnumEntrySymbolImpl(descriptorsRemapper.remapDeclaredEnumEntry(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitEnumEntry(declaration)
}
override fun visitExternalPackageFragment(declaration: IrExternalPackageFragment) {
remapSymbol(externalPackageFragments, declaration) {
IrExternalPackageFragmentSymbolImpl(descriptorsRemapper.remapDeclaredExternalPackageFragment(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitExternalPackageFragment(declaration)
}
override fun visitField(declaration: IrField) {
remapSymbol(fields, declaration) {
IrFieldSymbolImpl(descriptorsRemapper.remapDeclaredField(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitField(declaration)
}
override fun visitFile(declaration: IrFile) {
remapSymbol(files, declaration) {
IrFileSymbolImpl(descriptorsRemapper.remapDeclaredFilePackageFragment(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitFile(declaration)
}
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
remapSymbol(functions, declaration) {
IrSimpleFunctionSymbolImpl(descriptorsRemapper.remapDeclaredSimpleFunction(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitSimpleFunction(declaration)
}
override fun visitProperty(declaration: IrProperty) {
remapSymbol(properties, declaration) {
IrPropertySymbolImpl(descriptorsRemapper.remapDeclaredProperty(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitProperty(declaration)
}
override fun visitTypeParameter(declaration: IrTypeParameter) {
remapSymbol(typeParameters, declaration) {
IrTypeParameterSymbolImpl(descriptorsRemapper.remapDeclaredTypeParameter(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitTypeParameter(declaration)
}
override fun visitValueParameter(declaration: IrValueParameter) {
remapSymbol(valueParameters, declaration) {
IrValueParameterSymbolImpl(descriptorsRemapper.remapDeclaredValueParameter(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitValueParameter(declaration)
}
override fun visitVariable(declaration: IrVariable) {
remapSymbol(variables, declaration) {
IrVariableSymbolImpl(descriptorsRemapper.remapDeclaredVariable(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitVariable(declaration)
}
override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty) {
remapSymbol(localDelegatedProperties, declaration) {
IrLocalDelegatedPropertySymbolImpl(descriptorsRemapper.remapDeclaredLocalDelegatedProperty(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitLocalDelegatedProperty(declaration)
}
override fun visitTypeAlias(declaration: IrTypeAlias) {
remapSymbol(typeAliases, declaration) {
IrTypeAliasSymbolImpl(descriptorsRemapper.remapDeclaredTypeAlias(it.descriptor))
}
declaration.acceptChildrenVoid(this)
super.visitTypeAlias(declaration)
}
override fun visitBlock(expression: IrBlock) {
@@ -167,7 +163,7 @@ open class DeepCopySymbolRemapper(
IrReturnableBlockSymbolImpl()
}
}
expression.acceptChildrenVoid(this)
super.visitBlock(expression)
}
private fun <T : IrSymbol> Map<T, T>.getDeclared(symbol: T) =