From 99d4d934887c84f1bbe28fcd8c80a95bfaffe6eb Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Mon, 19 Nov 2018 19:23:15 +0300 Subject: [PATCH] Fixed copying of default args of expect functions Fixes issue https://github.com/JetBrains/kotlin-native/issues/2343 --- .../konan/lower/ExpectDeclarationsRemoving.kt | 127 +++++++++++++----- 1 file changed, 91 insertions(+), 36 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ExpectDeclarationsRemoving.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ExpectDeclarationsRemoving.kt index 84f615c9ce0..44c81321e84 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ExpectDeclarationsRemoving.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ExpectDeclarationsRemoving.kt @@ -8,16 +8,16 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember +import org.jetbrains.kotlin.backend.konan.descriptors.propertyIfAccessor import org.jetbrains.kotlin.descriptors.MemberDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrGetValue -import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl -import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol -import org.jetbrains.kotlin.ir.symbols.IrValueSymbol +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols +import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper +import org.jetbrains.kotlin.ir.util.DeepCopyTypeRemapper import org.jetbrains.kotlin.ir.util.referenceFunction -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid @@ -73,8 +73,8 @@ internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPa }) } - private fun IrFunction.findActualForExpected(): IrFunction = - context.ir.symbols.symbolTable.referenceFunction(descriptor.findActualForExpect()).owner + private inline fun T.findActualForExpected(): T = + context.ir.symbols.symbolTable.referenceFunction(descriptor.findActualForExpect()).owner as T private fun IrClass.findActualForExpected(): IrClass = context.ir.symbols.symbolTable.referenceClass(descriptor.findActualForExpect()).owner @@ -88,22 +88,75 @@ internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPa } as T private fun IrExpression.remapExpectValueSymbols(): IrExpression { - return this.transform(object : IrElementTransformerVoid() { + class SymbolRemapper : DeepCopySymbolRemapper() { + override fun getReferencedClass(symbol: IrClassSymbol) = + if (symbol.descriptor.isExpect) + symbol.owner.findActualForExpected().symbol + else super.getReferencedClass(symbol) - override fun visitGetValue(expression: IrGetValue): IrExpression { - expression.transformChildrenVoid() - val newValue = remapExpectValue(expression.symbol) - ?: return expression + override fun getReferencedClassOrNull(symbol: IrClassSymbol?) = + symbol?.let { getReferencedClass(it) } - return IrGetValueImpl( - expression.startOffset, - expression.endOffset, - newValue.type, - newValue.symbol, - expression.origin - ) + override fun getReferencedClassifier(symbol: IrClassifierSymbol): IrClassifierSymbol = when (symbol) { + is IrClassSymbol -> getReferencedClass(symbol) + is IrTypeParameterSymbol -> remapExpectTypeParameter(symbol).symbol + else -> error("Unexpected symbol $symbol ${symbol.descriptor}") } - }, data = null) + + override fun getReferencedConstructor(symbol: IrConstructorSymbol) = + if (symbol.descriptor.isExpect) + symbol.owner.findActualForExpected().symbol + else super.getReferencedConstructor(symbol) + + override fun getReferencedFunction(symbol: IrFunctionSymbol): IrFunctionSymbol = when (symbol) { + is IrSimpleFunctionSymbol -> getReferencedSimpleFunction(symbol) + is IrConstructorSymbol -> getReferencedConstructor(symbol) + else -> error("Unexpected symbol $symbol ${symbol.descriptor}") + } + + override fun getReferencedSimpleFunction(symbol: IrSimpleFunctionSymbol) = when { + symbol.descriptor.isExpect -> symbol.owner.findActualForExpected().symbol + + symbol.descriptor.propertyIfAccessor.isExpect -> { + val property = symbol.owner.correspondingProperty!! + val actualPropertyDescriptor = property.descriptor.findActualForExpect() + val accessorDescriptor = when (symbol.owner) { + property.getter -> actualPropertyDescriptor.getter!! + property.setter -> actualPropertyDescriptor.setter!! + else -> error("Unexpected accessor of $symbol ${symbol.descriptor}") + } + context.ir.symbols.symbolTable.referenceFunction(accessorDescriptor) as IrSimpleFunctionSymbol + } + + else -> super.getReferencedSimpleFunction(symbol) + } + + override fun getReferencedValue(symbol: IrValueSymbol) = + remapExpectValue(symbol)?.symbol ?: super.getReferencedValue(symbol) + } + + val symbolRemapper = SymbolRemapper() + acceptVoid(symbolRemapper) + return transform(DeepCopyIrTreeWithSymbols(symbolRemapper, DeepCopyTypeRemapper(symbolRemapper)), data = null) + } + + private fun remapExpectTypeParameter(symbol: IrTypeParameterSymbol): IrTypeParameter { + val parameter = symbol.owner + val parent = parameter.parent + + return when (parent) { + is IrClass -> + if (!parent.descriptor.isExpect) + parameter + else parent.findActualForExpected().typeParameters[parameter.index] + + is IrFunction -> + if (!parent.descriptor.isExpect) + parameter + else parent.findActualForExpected().typeParameters[parameter.index] + + else -> error(parent) + } } private fun remapExpectValue(symbol: IrValueSymbol): IrValueParameter? { @@ -115,23 +168,25 @@ internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPa val parent = parameter.parent return when (parent) { - is IrClass -> { - assert(parameter == parent.thisReceiver) - parent.findActualForExpected().thisReceiver!! - } - - is IrFunction -> when { - parameter == parent.dispatchReceiverParameter -> - parent.findActualForExpected().dispatchReceiverParameter!! - - parameter == parent.extensionReceiverParameter -> - parent.findActualForExpected().extensionReceiverParameter!! - - else -> { - assert(parent.valueParameters[parameter.index] == parameter) - parent.findActualForExpected().valueParameters[parameter.index] + is IrClass -> + if (!parent.descriptor.isExpect) + null + else { + assert(parameter == parent.thisReceiver) + parent.findActualForExpected().thisReceiver!! + } + + is IrFunction -> + if (!parent.descriptor.isExpect) + null + else when (parameter) { + parent.dispatchReceiverParameter -> parent.findActualForExpected().dispatchReceiverParameter!! + parent.extensionReceiverParameter -> parent.findActualForExpected().extensionReceiverParameter!! + else -> { + assert(parent.valueParameters[parameter.index] == parameter) + parent.findActualForExpected().valueParameters[parameter.index] + } } - } else -> error(parent) }