From 5ec9cb31718cd3caa8124e36e146ba805a9ef44b Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Fri, 21 Apr 2017 14:12:53 +0300 Subject: [PATCH] OldDeepCopyIrTree: old DeepCopyIrTree working with new IrElement hierarchy --- .../backend/jvm/lower/InitializersLowering.kt | 6 +- .../ir/declarations/impl/IrEnumEntryImpl.kt | 2 +- .../kotlin/ir/expressions/IrReturn.kt | 4 +- .../kotlin/ir/expressions/impl/IrCallImpl.kt | 20 +- .../expressions/impl/IrClassReferenceImpl.kt | 21 +- .../impl/IrDelegatingConstructorCallImpl.kt | 2 +- .../impl/IrEnumConstructorCallImpl.kt | 11 +- .../ir/expressions/impl/IrGetEnumValueImpl.kt | 9 + .../expressions/impl/IrGetObjectValueImpl.kt | 9 + .../impl/IrInstanceInitializerCallImpl.kt | 8 + .../ir/expressions/impl/IrReturnImpl.kt | 9 +- .../ir/expressions/impl/IrSetVariableImpl.kt | 9 + .../kotlin/ir/symbols/impl/IrSymbolBase.kt | 4 +- ...IrTree.kt => DeepCopyIrTreeWithSymbols.kt} | 9 +- .../kotlin/ir/util/OldDeepCopyIrTree.kt | 577 ++++++++++++++++++ .../kotlin/ir/AbstractIrTextTestCase.kt | 13 +- 16 files changed, 689 insertions(+), 24 deletions(-) rename compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/{DeepCopyIrTree.kt => DeepCopyIrTreeWithSymbols.kt} (98%) create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/OldDeepCopyIrTree.kt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InitializersLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InitializersLowering.kt index 8c0edc3f082..b3b69fdc08b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InitializersLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InitializersLowering.kt @@ -37,7 +37,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl -import org.jetbrains.kotlin.ir.util.deepCopy +import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -127,7 +127,7 @@ class InitializersLowering(val context: JvmBackendContext) : ClassLoweringPass { companion object { val clinitName = Name.special("") - fun IrStatement.copy() = deepCopy() - fun IrExpression.copy() = deepCopy() + fun IrStatement.copy() = deepCopyWithSymbols() + fun IrExpression.copy() = deepCopyWithSymbols() } } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrEnumEntryImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrEnumEntryImpl.kt index 7dce0432400..858b0115b14 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrEnumEntryImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrEnumEntryImpl.kt @@ -38,7 +38,7 @@ class IrEnumEntryImpl( constructor( startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor, - correspondingClass: IrClass?, initializerExpression: IrExpression + correspondingClass: IrClass?, initializerExpression: IrExpression? ) : this(startOffset, endOffset, origin, descriptor) { this.correspondingClass = correspondingClass this.initializerExpression = initializerExpression diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturn.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturn.kt index 006d656bed2..df11c277f8c 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturn.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturn.kt @@ -16,13 +16,13 @@ package org.jetbrains.kotlin.ir.expressions -import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol interface IrReturn : IrExpression { var value: IrExpression - val returnTarget: CallableDescriptor + val returnTarget: FunctionDescriptor val returnTargetSymbol: IrFunctionSymbol } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrCallImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrCallImpl.kt index b0fe3f7d5a8..dd9bd44b9d8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrCallImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrCallImpl.kt @@ -40,6 +40,24 @@ class IrCallImpl( ) : IrCall, IrCallWithIndexedArgumentsBase(startOffset, endOffset, type, symbol.descriptor.valueParameters.size, typeArguments) { + @Deprecated("Creates unbound symbols") + constructor( + startOffset: Int, + endOffset: Int, + type: KotlinType, + calleeDescriptor: FunctionDescriptor, + typeArguments: Map? = null, + origin: IrStatementOrigin? = null, + superQualifierDescriptor: ClassDescriptor? = null + ) : this( + startOffset, endOffset, + type, + createFunctionSymbol(calleeDescriptor), + calleeDescriptor, + typeArguments, origin, + createClassSymbolOrNull(superQualifierDescriptor) + ) + @Deprecated("Creates unbound symbols") constructor( startOffset: Int, @@ -51,7 +69,7 @@ class IrCallImpl( ) : this( startOffset, endOffset, calleeDescriptor.returnType!!, - createFunctionSymbol(calleeDescriptor.original), + createFunctionSymbol(calleeDescriptor), calleeDescriptor, typeArguments, origin, createClassSymbolOrNull(superQualifierDescriptor) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrClassReferenceImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrClassReferenceImpl.kt index dd38ef056c9..8d20edf5b25 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrClassReferenceImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrClassReferenceImpl.kt @@ -16,9 +16,13 @@ package org.jetbrains.kotlin.ir.expressions.impl +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.expressions.IrClassReference import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType @@ -33,8 +37,23 @@ class IrClassReferenceImpl( symbol, symbol.descriptor ) { + @Deprecated("Creates unbound symbols") + constructor( + startOffset: Int, + endOffset: Int, + type: KotlinType, + descriptor: ClassifierDescriptor + ) : this(startOffset, endOffset, type, createClassifierSymbolForClassReference(descriptor)) + override val descriptor: ClassifierDescriptor get() = symbol.descriptor override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitClassReference(this, data) -} \ No newline at end of file +} + +internal fun createClassifierSymbolForClassReference(descriptor: ClassifierDescriptor): IrClassifierSymbol = + when (descriptor) { + is ClassDescriptor -> IrClassSymbolImpl(descriptor) + is TypeParameterDescriptor -> IrTypeParameterSymbolImpl(descriptor) + else -> throw IllegalArgumentException("Unexpected referenced classifier: $descriptor") + } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrDelegatingConstructorCallImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrDelegatingConstructorCallImpl.kt index 11f119f6c4c..0ee8fffb076 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrDelegatingConstructorCallImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrDelegatingConstructorCallImpl.kt @@ -46,7 +46,7 @@ class IrDelegatingConstructorCallImpl( constructorDescriptor: ClassConstructorDescriptor, typeArguments: Map? = null ) : this(startOffset, endOffset, - IrConstructorSymbolImpl(constructorDescriptor), + IrConstructorSymbolImpl(constructorDescriptor.original), constructorDescriptor, typeArguments) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt index 6eb965e3647..954fc3a7398 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.ir.expressions.impl import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.ir.expressions.IrEnumConstructorCall import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns @@ -32,7 +33,15 @@ class IrEnumConstructorCallImpl( symbol.descriptor.builtIns.unitType, symbol.descriptor.valueParameters.size, null - ) { + ) +{ + @Deprecated("Creates unbound symbols") + constructor( + startOffset: Int, + endOffset: Int, + descriptor: ClassConstructorDescriptor + ) : this(startOffset, endOffset, IrConstructorSymbolImpl(descriptor)) + override val descriptor: ClassConstructorDescriptor get() = symbol.descriptor override fun accept(visitor: IrElementVisitor, data: D): R { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetEnumValueImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetEnumValueImpl.kt index 1e5ed87dc50..b08d48cd4f8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetEnumValueImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetEnumValueImpl.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.ir.expressions.impl import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrEnumEntrySymbolImpl import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType @@ -30,6 +31,14 @@ class IrGetEnumValueImpl( ) : IrGetEnumValue, IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, symbol, symbol.descriptor) { + @Deprecated("Creates unbound symbol") + constructor( + startOffset: Int, + endOffset: Int, + type: KotlinType, + descriptor: ClassDescriptor + ) : this(startOffset, endOffset, type, IrEnumEntrySymbolImpl(descriptor)) + override fun accept(visitor: IrElementVisitor, data: D): R { return visitor.visitGetEnumValue(this, data) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetObjectValueImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetObjectValueImpl.kt index 040e578183d..b136635eb21 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetObjectValueImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetObjectValueImpl.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.ir.expressions.impl import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType @@ -30,6 +31,14 @@ class IrGetObjectValueImpl( ) : IrGetObjectValue, IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, symbol, symbol.descriptor) { + @Deprecated("Creates unbound symbol") + constructor( + startOffset: Int, + endOffset: Int, + type: KotlinType, + descriptor: ClassDescriptor + ) : this(startOffset, endOffset, type, IrClassSymbolImpl(descriptor)) + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitGetObjectValue(this, data) } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrInstanceInitializerCallImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrInstanceInitializerCallImpl.kt index 4b2a95a8812..934783f0664 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrInstanceInitializerCallImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrInstanceInitializerCallImpl.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.ir.expressions.impl import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns @@ -27,6 +28,13 @@ class IrInstanceInitializerCallImpl( endOffset: Int, override val classSymbol: IrClassSymbol ) : IrTerminalExpressionBase(startOffset, endOffset, classSymbol.descriptor.builtIns.unitType), IrInstanceInitializerCall { + @Deprecated("Creates unbound symbol") + constructor( + startOffset: Int, + endOffset: Int, + descriptor: ClassDescriptor + ) : this(startOffset, endOffset, IrClassSymbolImpl(descriptor)) + override val classDescriptor: ClassDescriptor get() = classSymbol.descriptor override fun accept(visitor: IrElementVisitor, data: D): R { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrReturnImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrReturnImpl.kt index 47314f5bb13..76b67be7e4d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrReturnImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrReturnImpl.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.ir.expressions.impl -import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrReturn @@ -37,13 +36,19 @@ class IrReturnImpl( constructor(startOffset: Int, endOffset: Int, returnTargetSymbol: IrFunctionSymbol, value: IrExpression) : this(startOffset, endOffset, returnTargetSymbol.descriptor.builtIns.nothingType, returnTargetSymbol, value) + @Deprecated("Creates unbound symbol") + constructor(startOffset: Int, endOffset: Int, type: KotlinType, returnTargetDescriptor: FunctionDescriptor, value: IrExpression) : + this(startOffset, endOffset, type, + createFunctionSymbol(returnTargetDescriptor), + value) + @Deprecated("Creates unbound symbol") constructor(startOffset: Int, endOffset: Int, returnTargetDescriptor: FunctionDescriptor, value: IrExpression) : this(startOffset, endOffset, returnTargetDescriptor.builtIns.nothingType, createFunctionSymbol(returnTargetDescriptor), value) - override val returnTarget: CallableDescriptor get() = returnTargetSymbol.descriptor + override val returnTarget: FunctionDescriptor get() = returnTargetSymbol.descriptor override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitReturn(this, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrSetVariableImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrSetVariableImpl.kt index 59fcb9e204e..8b65a0f8ee9 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrSetVariableImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrSetVariableImpl.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrSetVariable import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns @@ -39,6 +40,14 @@ class IrSetVariableImpl( this.value = value } + @Deprecated("Creates unbound symbol") + constructor( + startOffset: Int, endOffset: Int, + descriptor: VariableDescriptor, + value: IrExpression, + origin: IrStatementOrigin? + ) : this(startOffset, endOffset, IrVariableSymbolImpl(descriptor), value, origin) + override val descriptor: VariableDescriptor get() = symbol.descriptor override lateinit var value: IrExpression diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt index d543a0bb7f6..4a3737e690d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt @@ -107,7 +107,7 @@ class IrConstructorSymbolImpl(descriptor: ClassConstructorDescriptor) : fun createFunctionSymbol(descriptor: CallableMemberDescriptor): IrFunctionSymbol = when (descriptor) { - is ClassConstructorDescriptor -> IrConstructorSymbolImpl(descriptor) - is FunctionDescriptor -> IrSimpleFunctionSymbolImpl(descriptor) + is ClassConstructorDescriptor -> IrConstructorSymbolImpl(descriptor.original) + is FunctionDescriptor -> IrSimpleFunctionSymbolImpl(descriptor.original) else -> throw IllegalArgumentException("Unexpected descriptor kind: $descriptor") } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt similarity index 98% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt index a276cb296d7..db5f9f543fd 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt @@ -29,19 +29,19 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.types.KotlinType import java.util.* -inline fun T.deepCopy(): T { +inline fun T.deepCopyWithSymbols(): T { val remapper = DeepCopySymbolsRemapper() acceptVoid(remapper) - return transform(DeepCopyIrTree(remapper), null) as T + return transform(DeepCopyIrTreeWithSymbols(remapper), null) as T } -class DeepCopyIrTree(private val symbolsRemapper: DeepCopySymbolsRemapper) : IrElementTransformerVoid() { +class DeepCopyIrTreeWithSymbols(private val symbolsRemapper: DeepCopySymbolsRemapper) : IrElementTransformerVoid() { private fun mapDeclarationOrigin(origin: IrDeclarationOrigin) = origin private fun mapStatementOrigin(origin: IrStatementOrigin?) = origin private inline fun T.transform() = - transform(this@DeepCopyIrTree, null) as T + transform(this@DeepCopyIrTreeWithSymbols, null) as T private inline fun List.transform() = map { it.transform() } @@ -539,3 +539,4 @@ class DeepCopyIrTree(private val symbolsRemapper: DeepCopySymbolsRemapper) : IrE } } + diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/OldDeepCopyIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/OldDeepCopyIrTree.kt new file mode 100644 index 00000000000..b79643c0b57 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/OldDeepCopyIrTree.kt @@ -0,0 +1,577 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.ir.util + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.SourceManager +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.types.KotlinType +import java.util.HashMap + +inline fun T.deepCopyOld() = + transform(OldDeepCopyIrTree(), null) as T + +open class OldDeepCopyIrTree : IrElementTransformerVoid() { + protected open fun mapDeclarationOrigin(declarationOrigin: IrDeclarationOrigin) = declarationOrigin + protected open fun mapStatementOrigin(statementOrigin: IrStatementOrigin?) = statementOrigin + protected open fun mapFileEntry(fileEntry: SourceManager.FileEntry) = fileEntry + + protected open fun mapModuleDescriptor(descriptor: ModuleDescriptor) = descriptor + protected open fun mapPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor) = descriptor + protected open fun mapClassDeclaration(descriptor: ClassDescriptor) = descriptor + protected open fun mapTypeAliasDeclaration(descriptor: TypeAliasDescriptor) = descriptor + protected open fun mapFunctionDeclaration(descriptor: FunctionDescriptor) = descriptor + protected open fun mapConstructorDeclaration(descriptor: ClassConstructorDescriptor) = descriptor + protected open fun mapPropertyDeclaration(descriptor: PropertyDescriptor) = descriptor + protected open fun mapLocalPropertyDeclaration(descriptor: VariableDescriptorWithAccessors) = descriptor + protected open fun mapEnumEntryDeclaration(descriptor: ClassDescriptor) = descriptor + protected open fun mapVariableDeclaration(descriptor: VariableDescriptor) = descriptor + protected open fun mapErrorDeclaration(descriptor: DeclarationDescriptor) = descriptor + + protected open fun mapSuperQualifier(qualifier: ClassDescriptor?) = qualifier + protected open fun mapClassReference(descriptor: ClassDescriptor) = descriptor + protected open fun mapValueReference(descriptor: ValueDescriptor) = descriptor + protected open fun mapVariableReference(descriptor: VariableDescriptor) = descriptor + protected open fun mapPropertyReference(descriptor: PropertyDescriptor) = descriptor + protected open fun mapCallee(descriptor: FunctionDescriptor) = descriptor + protected open fun mapDelegatedConstructorCallee(descriptor: ClassConstructorDescriptor) = descriptor + protected open fun mapEnumConstructorCallee(descriptor: ClassConstructorDescriptor) = descriptor + protected open fun mapLocalPropertyReference(descriptor: VariableDescriptorWithAccessors) = descriptor + protected open fun mapClassifierReference(descriptor: ClassifierDescriptor) = descriptor + protected open fun mapReturnTarget(descriptor: FunctionDescriptor) = mapCallee(descriptor) + + private inline fun T.transform() = transform(this@OldDeepCopyIrTree, null) as T + + override fun visitElement(element: IrElement): IrElement = + throw IllegalArgumentException("Unsupported element type: $element") + + override fun visitModuleFragment(declaration: IrModuleFragment): IrModuleFragment = + IrModuleFragmentImpl( + mapModuleDescriptor(declaration.descriptor), + declaration.irBuiltins, + declaration.files.map { it.transform() } + ) + + override fun visitFile(declaration: IrFile): IrFile = + IrFileImpl( + mapFileEntry(declaration.fileEntry), + mapPackageFragmentDescriptor(declaration.packageFragmentDescriptor), + declaration.fileAnnotations.toMutableList(), + declaration.declarations.map { it.transform() } + ) + + override fun visitDeclaration(declaration: IrDeclaration): IrStatement = + throw IllegalArgumentException("Unsupported declaration type: $declaration") + + override fun visitClass(declaration: IrClass): IrClass = + IrClassImpl( + declaration.startOffset, declaration.endOffset, + mapDeclarationOrigin(declaration.origin), + mapClassDeclaration(declaration.descriptor), + declaration.declarations.map { it.transform() } + ).apply { + transformTypeParameters(declaration, descriptor.declaredTypeParameters) + } + + override fun visitTypeAlias(declaration: IrTypeAlias): IrTypeAlias = + IrTypeAliasImpl( + declaration.startOffset, declaration.endOffset, + mapDeclarationOrigin(declaration.origin), + mapTypeAliasDeclaration(declaration.descriptor) + ) + + override fun visitFunction(declaration: IrFunction): IrFunction = + IrFunctionImpl( + declaration.startOffset, declaration.endOffset, + mapDeclarationOrigin(declaration.origin), + mapFunctionDeclaration(declaration.descriptor), + declaration.body?.transform() + ).transformParameters(declaration) + + override fun visitConstructor(declaration: IrConstructor): IrConstructor = + IrConstructorImpl( + declaration.startOffset, declaration.endOffset, + mapDeclarationOrigin(declaration.origin), + mapConstructorDeclaration(declaration.descriptor), + declaration.body!!.transform() + ).transformParameters(declaration) + + private fun T.transformTypeParameters(original: T, myTypeParameters: List): T = + apply { + original.typeParameters.mapTo(typeParameters) { originalTypeParameter -> + copyTypeParameter(originalTypeParameter, myTypeParameters[originalTypeParameter.descriptor.index]) + } + } + + private fun T.transformParameters(original: T): T = + apply { + transformTypeParameters(original, descriptor.typeParameters) + transformValueParameters(original) + } + + private fun T.transformValueParameters(original: T) = + apply { + dispatchReceiverParameter = original.dispatchReceiverParameter?.let { + copyValueParameter(it, descriptor.dispatchReceiverParameter ?: throw AssertionError("No dispatch receiver in $descriptor")) + } + + extensionReceiverParameter = original.extensionReceiverParameter?.let { + copyValueParameter(it, descriptor.extensionReceiverParameter ?: throw AssertionError("No extension receiver in $descriptor")) + } + + original.valueParameters.mapIndexedTo(valueParameters) { i, originalValueParameter -> + copyValueParameter(originalValueParameter, descriptor.valueParameters[i]) + } + } + + private fun copyTypeParameter( + originalTypeParameter: IrTypeParameter, + newTypeParameterDescriptor: TypeParameterDescriptor + ): IrTypeParameterImpl = + IrTypeParameterImpl( + originalTypeParameter.startOffset, originalTypeParameter.endOffset, + mapDeclarationOrigin(originalTypeParameter.origin), + newTypeParameterDescriptor + ) + + private fun copyValueParameter( + originalValueParameter: IrValueParameter, + newParameterDescriptor: ParameterDescriptor + ): IrValueParameterImpl = + IrValueParameterImpl( + originalValueParameter.startOffset, originalValueParameter.endOffset, + mapDeclarationOrigin(originalValueParameter.origin), + newParameterDescriptor, + originalValueParameter.defaultValue?.transform() + ) + + // TODO visitTypeParameter + // TODO visitValueParameter + + override fun visitProperty(declaration: IrProperty): IrProperty = + IrPropertyImpl( + declaration.startOffset, declaration.endOffset, + mapDeclarationOrigin(declaration.origin), + declaration.isDelegated, + mapPropertyDeclaration(declaration.descriptor), + declaration.backingField?.transform(), + declaration.getter?.transform(), + declaration.setter?.transform() + ) + + override fun visitField(declaration: IrField): IrField = + IrFieldImpl( + declaration.startOffset, declaration.endOffset, + mapDeclarationOrigin(declaration.origin), + mapPropertyDeclaration(declaration.descriptor), + declaration.initializer?.transform() + ) + + override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty): IrLocalDelegatedProperty = + IrLocalDelegatedPropertyImpl( + declaration.startOffset, declaration.endOffset, + mapDeclarationOrigin(declaration.origin), + mapLocalPropertyDeclaration(declaration.descriptor), + declaration.delegate.transform(), + declaration.getter.transform(), + declaration.setter?.transform() + ) + + override fun visitEnumEntry(declaration: IrEnumEntry): IrEnumEntry = + IrEnumEntryImpl( + declaration.startOffset, declaration.endOffset, + mapDeclarationOrigin(declaration.origin), + mapEnumEntryDeclaration(declaration.descriptor), + declaration.correspondingClass?.transform(), + declaration.initializerExpression?.transform() + ) + + override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer): IrAnonymousInitializer = + IrAnonymousInitializerImpl( + declaration.startOffset, declaration.endOffset, + mapDeclarationOrigin(declaration.origin), + mapClassDeclaration(declaration.descriptor), + declaration.body.transform() + ) + + override fun visitVariable(declaration: IrVariable): IrVariable = + IrVariableImpl( + declaration.startOffset, declaration.endOffset, + mapDeclarationOrigin(declaration.origin), + mapVariableDeclaration(declaration.descriptor), + declaration.initializer?.transform() + ) + + override fun visitBody(body: IrBody): IrBody = + throw IllegalArgumentException("Unsupported body type: $body") + + override fun visitExpressionBody(body: IrExpressionBody): IrExpressionBody = + IrExpressionBodyImpl(body.expression.transform()) + + override fun visitBlockBody(body: IrBlockBody): IrBlockBody = + IrBlockBodyImpl( + body.startOffset, body.endOffset, + body.statements.map { it.transform() } + ) + + override fun visitSyntheticBody(body: IrSyntheticBody): IrSyntheticBody = + IrSyntheticBodyImpl(body.startOffset, body.endOffset, body.kind) + + override fun visitExpression(expression: IrExpression): IrExpression = + throw IllegalArgumentException("Unsupported expression type: $expression") + + override fun visitConst(expression: IrConst): IrConst = + expression.copy() + + override fun visitVararg(expression: IrVararg): IrVararg = + IrVarargImpl( + expression.startOffset, expression.endOffset, + expression.type, expression.varargElementType, + expression.elements.map { it.transform() } + ) + + override fun visitSpreadElement(spread: IrSpreadElement): IrSpreadElement = + IrSpreadElementImpl( + spread.startOffset, spread.endOffset, + spread.expression.transform() + ) + + override fun visitBlock(expression: IrBlock): IrBlock = + IrBlockImpl( + expression.startOffset, expression.endOffset, + expression.type, + mapStatementOrigin(expression.origin), + expression.statements.map { it.transform() } + ) + + override fun visitComposite(expression: IrComposite): IrComposite = + IrCompositeImpl( + expression.startOffset, expression.endOffset, + expression.type, + mapStatementOrigin(expression.origin), + expression.statements.map { it.transform() } + ) + + override fun visitStringConcatenation(expression: IrStringConcatenation): IrStringConcatenation = + IrStringConcatenationImpl( + expression.startOffset, expression.endOffset, + expression.type, + expression.arguments.map { it.transform() } + ) + + override fun visitGetObjectValue(expression: IrGetObjectValue): IrGetObjectValue = + IrGetObjectValueImpl( + expression.startOffset, expression.endOffset, + expression.type, + mapClassReference(expression.descriptor) + ) + + override fun visitGetEnumValue(expression: IrGetEnumValue): IrGetEnumValue = + IrGetEnumValueImpl( + expression.startOffset, expression.endOffset, + expression.type, + mapClassReference(expression.descriptor) + ) + + override fun visitGetValue(expression: IrGetValue): IrGetValue = + IrGetValueImpl( + expression.startOffset, expression.endOffset, + mapValueReference(expression.descriptor), + mapStatementOrigin(expression.origin) + ) + + override fun visitSetVariable(expression: IrSetVariable): IrSetVariable = + IrSetVariableImpl( + expression.startOffset, expression.endOffset, + mapVariableReference(expression.descriptor), + expression.value.transform(), + mapStatementOrigin(expression.origin) + ) + + override fun visitGetField(expression: IrGetField): IrGetField = + IrGetFieldImpl( + expression.startOffset, expression.endOffset, + mapPropertyReference(expression.descriptor), + expression.receiver?.transform(), + mapStatementOrigin(expression.origin), + mapSuperQualifier(expression.superQualifier) + ) + + override fun visitSetField(expression: IrSetField): IrSetField = + IrSetFieldImpl( + expression.startOffset, expression.endOffset, + mapPropertyReference(expression.descriptor), + expression.receiver?.transform(), + expression.value.transform(), + mapStatementOrigin(expression.origin), + mapSuperQualifier(expression.superQualifier) + ) + + override fun visitCall(expression: IrCall): IrCall = + shallowCopyCall(expression).transformValueArguments(expression) + + protected fun shallowCopyCall(expression: IrCall) = + when (expression) { + is IrCallWithShallowCopy -> + expression.shallowCopy( + mapStatementOrigin(expression.origin), + mapCallee(expression.descriptor), + mapSuperQualifier(expression.superQualifier) + ) + else -> { + val newCallee = mapCallee(expression.descriptor) + IrCallImpl( + expression.startOffset, expression.endOffset, + expression.type, + newCallee, + expression.transformTypeArguments(newCallee), + mapStatementOrigin(expression.origin), + mapSuperQualifier(expression.superQualifier) + ) + } + } + + protected fun T.transformValueArguments(original: IrMemberAccessExpression): T = + apply { + dispatchReceiver = original.dispatchReceiver?.transform() + extensionReceiver = original.extensionReceiver?.transform() + mapValueParameters { valueParameter -> + original.getValueArgument(valueParameter)?.transform() + } + Unit + } + + protected fun IrMemberAccessExpression.transformTypeArguments(newCallee: CallableDescriptor): Map? { + if (this is IrMemberAccessExpressionBase) return typeArguments + + val typeParameters = descriptor.original.typeParameters + return if (typeParameters.isEmpty()) + null + else + typeParameters.associateBy( + { newCallee.typeParameters[it.index] }, + { getTypeArgument(it)!! } + ) + } + + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrDelegatingConstructorCall { + val newCallee = mapDelegatedConstructorCallee(expression.descriptor) + return IrDelegatingConstructorCallImpl( + expression.startOffset, expression.endOffset, + newCallee, + expression.transformTypeArguments(newCallee) + ).transformValueArguments(expression) + } + + override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrEnumConstructorCall = + IrEnumConstructorCallImpl( + expression.startOffset, expression.endOffset, + mapEnumConstructorCallee(expression.descriptor) + ).transformValueArguments(expression) + + override fun visitGetClass(expression: IrGetClass): IrGetClass = + IrGetClassImpl( + expression.startOffset, expression.endOffset, + expression.type, + expression.argument.transform() + ) + + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + val newCallee = mapCallee(expression.descriptor) + return IrFunctionReferenceImpl( + expression.startOffset, expression.endOffset, + expression.type, + expression.descriptor, + expression.transformTypeArguments(newCallee), + mapStatementOrigin(expression.origin) + ).transformValueArguments(expression) + } + + override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { + val newProperty = mapPropertyReference(expression.descriptor) + val newFieldSymbol = if (newProperty.getter == null) IrFieldSymbolImpl(newProperty) else null + val newGetterSymbol = newProperty.getter?.let { IrSimpleFunctionSymbolImpl(it) } + val newSetterSymbol = newProperty.setter?.let { IrSimpleFunctionSymbolImpl(it) } + return IrPropertyReferenceImpl( + expression.startOffset, expression.endOffset, expression.type, + newProperty, newFieldSymbol, newGetterSymbol, newSetterSymbol, + expression.transformTypeArguments(newProperty), + mapStatementOrigin(expression.origin) + ) + } + + override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression { + val newLocalDelegatedProperty = mapLocalPropertyReference(expression.descriptor) + val newDelegateDescriptor = mapVariableReference(expression.delegate.descriptor) + val newDelegateSymbol = IrVariableSymbolImpl(newDelegateDescriptor) + val newGetterSymbol = newLocalDelegatedProperty.getter!!.let { IrSimpleFunctionSymbolImpl(it) } + val newSetterSymbol = newLocalDelegatedProperty.setter?.let { IrSimpleFunctionSymbolImpl(it) } + return IrLocalDelegatedPropertyReferenceImpl( + expression.startOffset, expression.endOffset, expression.type, + newLocalDelegatedProperty, + newDelegateSymbol, newGetterSymbol, newSetterSymbol, + mapStatementOrigin(expression.origin) + ) + } + + override fun visitClassReference(expression: IrClassReference): IrClassReference = + IrClassReferenceImpl( + expression.startOffset, expression.endOffset, + expression.type, + mapClassifierReference(expression.descriptor) + ) + + override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrInstanceInitializerCall = + IrInstanceInitializerCallImpl( + expression.startOffset, expression.endOffset, + mapClassReference(expression.classDescriptor) + ) + + override fun visitTypeOperator(expression: IrTypeOperatorCall): IrTypeOperatorCall = + IrTypeOperatorCallImpl( + expression.startOffset, expression.endOffset, + expression.type, + expression.operator, + expression.typeOperand, + expression.argument.transform() + ) + + override fun visitWhen(expression: IrWhen): IrWhen = + IrWhenImpl( + expression.startOffset, expression.endOffset, + expression.type, + mapStatementOrigin(expression.origin), + expression.branches.map { it.transform() } + ) + + override fun visitBranch(branch: IrBranch): IrBranch = + IrBranchImpl( + branch.startOffset, branch.endOffset, + branch.condition.transform(), + branch.result.transform() + ) + + override fun visitElseBranch(branch: IrElseBranch): IrElseBranch = + IrElseBranchImpl( + branch.startOffset, branch.endOffset, + branch.condition.transform(), + branch.result.transform() + ) + + private val transformedLoops = HashMap() + + private fun getTransformedLoop(irLoop: IrLoop): IrLoop = + transformedLoops.getOrElse(irLoop) { getNonTransformedLoop(irLoop) } + + protected open fun getNonTransformedLoop(irLoop: IrLoop): IrLoop = + throw AssertionError("Outer loop was not transformed: ${irLoop.render()}") + + override fun visitWhileLoop(loop: IrWhileLoop): IrWhileLoop { + val newLoop = IrWhileLoopImpl(loop.startOffset, loop.endOffset, loop.type, mapStatementOrigin(loop.origin)) + transformedLoops[loop] = newLoop + newLoop.label = loop.label + newLoop.condition = loop.condition.transform() + newLoop.body = loop.body?.transform() + return newLoop + } + + override fun visitDoWhileLoop(loop: IrDoWhileLoop): IrDoWhileLoop { + val newLoop = IrDoWhileLoopImpl(loop.startOffset, loop.endOffset, loop.type, mapStatementOrigin(loop.origin)) + transformedLoops[loop] = newLoop + newLoop.label = loop.label + newLoop.condition = loop.condition.transform() + newLoop.body = loop.body?.transform() + return newLoop + } + + override fun visitBreak(jump: IrBreak): IrBreak = + IrBreakImpl( + jump.startOffset, jump.endOffset, + jump.type, + getTransformedLoop(jump.loop) + ).apply { label = jump.label } + + override fun visitContinue(jump: IrContinue): IrContinue = + IrContinueImpl( + jump.startOffset, jump.endOffset, + jump.type, + getTransformedLoop(jump.loop) + ).apply { label = jump.label } + + override fun visitTry(aTry: IrTry): IrTry = + IrTryImpl( + aTry.startOffset, aTry.endOffset, + aTry.type, + aTry.tryResult.transform(), + aTry.catches.map { it.transform() }, + aTry.finallyExpression?.transform() + ) + + override fun visitCatch(aCatch: IrCatch): IrCatch = + IrCatchImpl( + aCatch.startOffset, aCatch.endOffset, + aCatch.catchParameter.transform(), + aCatch.result.transform() + ) + + override fun visitReturn(expression: IrReturn): IrReturn = + IrReturnImpl( + expression.startOffset, expression.endOffset, + expression.type, + mapReturnTarget(expression.returnTarget), + expression.value.transform() + ) + + override fun visitThrow(expression: IrThrow): IrThrow = + IrThrowImpl( + expression.startOffset, expression.endOffset, + expression.type, + expression.value.transform() + ) + + override fun visitErrorDeclaration(declaration: IrErrorDeclaration): IrErrorDeclaration = + IrErrorDeclarationImpl( + declaration.startOffset, declaration.endOffset, + mapErrorDeclaration(declaration.descriptor) + ) + + override fun visitErrorExpression(expression: IrErrorExpression): IrErrorExpression = + IrErrorExpressionImpl( + expression.startOffset, expression.endOffset, + expression.type, + expression.description + ) + + override fun visitErrorCallExpression(expression: IrErrorCallExpression): IrErrorCallExpression = + IrErrorCallExpressionImpl( + expression.startOffset, expression.endOffset, + expression.type, + expression.description + ).apply { + explicitReceiver = expression.explicitReceiver?.transform() + expression.arguments.mapTo(arguments) { it.transform() } + } +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/ir/AbstractIrTextTestCase.kt b/compiler/tests/org/jetbrains/kotlin/ir/AbstractIrTextTestCase.kt index dceb15239ef..d9b62432989 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/AbstractIrTextTestCase.kt +++ b/compiler/tests/org/jetbrains/kotlin/ir/AbstractIrTextTestCase.kt @@ -26,10 +26,7 @@ import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.expressions.IrLocalDelegatedPropertyReference import org.jetbrains.kotlin.ir.expressions.IrPropertyReference import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.util.deepCopy -import org.jetbrains.kotlin.ir.util.dump -import org.jetbrains.kotlin.ir.util.dumpTreesFromLineNumber -import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.test.KotlinTestUtils @@ -79,10 +76,14 @@ abstract class AbstractIrTextTestCase : AbstractIrGeneratorTestCase() { verify(irFile) // Check that deep copy produces an equivalent result - val irFileCopy = irFile.deepCopy() + val irFileCopy = irFile.deepCopyWithSymbols() val copiedTrees = irFileCopy.dumpTreesFromLineNumber(irTreeFileLabel.lineNumber) - TestCase.assertEquals("IR dump mismatch after deep copy", actualTrees, copiedTrees) + TestCase.assertEquals("IR dump mismatch after deep copy with symbols", actualTrees, copiedTrees) verify(irFileCopy) + + val irFileCopyOld = irFile.deepCopyOld() + val copiedTreesOld = irFileCopyOld.dumpTreesFromLineNumber(irTreeFileLabel.lineNumber) + TestCase.assertEquals("IR dump mismatch after old deep copy", actualTrees, copiedTrees) } try {