diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt index fcbb7f679d5..a128687a79b 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt @@ -190,7 +190,7 @@ class InlineClassLowering(val context: BackendContext) { return expression } - return irCall(expression, getOrCreateStaticMethod(function), dispatchReceiverAsFirstArgument = false) + return irCall(expression, getOrCreateStaticMethod(function), dispatchReceiverAsArgument = false) } override fun visitCall(expression: IrCall): IrExpression { @@ -208,7 +208,7 @@ class InlineClassLowering(val context: BackendContext) { return irCall( expression, getOrCreateStaticMethod(function), - dispatchReceiverAsFirstArgument = (function is IrSimpleFunction) + dispatchReceiverAsArgument = (function is IrSimpleFunction) ) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLoweringUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLoweringUtils.kt index e91dbd8a4a5..e3db4ca8ac3 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLoweringUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLoweringUtils.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.ir.backend.js.lower.calls import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol @@ -48,7 +47,7 @@ internal fun MutableMap IrExpression>.add internal typealias MemberToTransformer = HashMap IrExpression> internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunctionSymbol) { - add(type, name) { irCall(it, v, dispatchReceiverAsFirstArgument = true) } + add(type, name) { irCall(it, v, dispatchReceiverAsArgument = true) } } internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunction) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/EqualityAndComparisonCallsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/EqualityAndComparisonCallsTransformer.kt index 3421e4c3ba5..d68d478934d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/EqualityAndComparisonCallsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/EqualityAndComparisonCallsTransformer.kt @@ -53,7 +53,7 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls comparator.owner.returnType, comparator ).apply { - putValueArgument(0, irCall(call, intrinsics.longCompareToLong, firstArgumentAsDispatchReceiver = true)) + putValueArgument(0, irCall(call, intrinsics.longCompareToLong, argumentAsDispatchReceiver = true)) putValueArgument(1, JsIrBuilder.buildInt(irBuiltIns.intType, 0)) } } @@ -95,7 +95,7 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls chooseEqualityOperatorForPrimitiveTypes(call) !isLhsPrimitive && !lhs.type.isNullable() && equalsMethod != null -> - irCall(call, equalsMethod.symbol, firstArgumentAsDispatchReceiver = true) + irCall(call, equalsMethod.symbol, argumentAsDispatchReceiver = true) else -> irCall(call, intrinsics.jsEquals) @@ -127,7 +127,7 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls // Use runtime function call in case when receiverType is a primitive JS type that doesn't have `compareTo` method, // or has a potential to be primitive type (being fake overridden from `Comparable`) function.isMethodOfPrimitiveJSType() || function.isFakeOverriddenFromComparable() -> - irCall(call, intrinsics.jsCompareTo, dispatchReceiverAsFirstArgument = true) + irCall(call, intrinsics.jsCompareTo, dispatchReceiverAsArgument = true) // Valid `compareTo` method must be present at this point else -> @@ -144,12 +144,12 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls // `Any.equals` works as identity operator call.isSuperToAny() -> - irCall(call, intrinsics.jsEqeqeq, dispatchReceiverAsFirstArgument = true) + irCall(call, intrinsics.jsEqeqeq, dispatchReceiverAsArgument = true) // Use runtime function call in case when receiverType is a primitive JS type that doesn't have `equals` method, // or has a potential to be primitive type (being fake overridden from `Any`) function.isMethodOfPotentiallyPrimitiveJSType() -> - irCall(call, intrinsics.jsEquals, dispatchReceiverAsFirstArgument = true) + irCall(call, intrinsics.jsEquals, dispatchReceiverAsArgument = true) // Valid `equals` method must be present at this point else -> call diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/MethodsOfAnyCallsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/MethodsOfAnyCallsTransformer.kt index 6ab3ca69855..445e5127b18 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/MethodsOfAnyCallsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/MethodsOfAnyCallsTransformer.kt @@ -15,7 +15,6 @@ import org.jetbrains.kotlin.ir.types.isAny import org.jetbrains.kotlin.ir.types.isArray import org.jetbrains.kotlin.ir.types.isString import org.jetbrains.kotlin.ir.util.isFakeOverriddenFromAny -import org.jetbrains.kotlin.ir.util.isNullable import org.jetbrains.kotlin.ir.util.isSuperToAny import org.jetbrains.kotlin.name.Name @@ -30,9 +29,9 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform put(Name.identifier("toString")) { call -> if (shouldReplaceToStringWithRuntimeCall(call)) { if ((call as IrCall).isSuperToAny()) { - irCall(call, intrinsics.jsAnyToString, dispatchReceiverAsFirstArgument = true) + irCall(call, intrinsics.jsAnyToString, dispatchReceiverAsArgument = true) } else { - irCall(call, intrinsics.jsToString, dispatchReceiverAsFirstArgument = true) + irCall(call, intrinsics.jsToString, dispatchReceiverAsArgument = true) } } else { call @@ -42,9 +41,9 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform put(Name.identifier("hashCode")) { call -> if (call.symbol.owner.isFakeOverriddenFromAny()) { if ((call as IrCall).isSuperToAny()) { - irCall(call, intrinsics.jsGetObjectHashCode, dispatchReceiverAsFirstArgument = true) + irCall(call, intrinsics.jsGetObjectHashCode, dispatchReceiverAsArgument = true) } else { - irCall(call, intrinsics.jsHashCode, dispatchReceiverAsFirstArgument = true) + irCall(call, intrinsics.jsHashCode, dispatchReceiverAsArgument = true) } } else { call diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberOperatorCallsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberOperatorCallsTransformer.kt index 5f1549fc79d..ce2f09db5e2 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberOperatorCallsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberOperatorCallsTransformer.kt @@ -46,9 +46,9 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo irBuiltIns.booleanType.let { // These operators are not short-circuit -- using bitwise operators '&', '|', '^' followed by coercion to boolean - add(it, OperatorNames.AND) { call -> toBoolean(irCall(call, intrinsics.jsBitAnd, dispatchReceiverAsFirstArgument = true)) } - add(it, OperatorNames.OR) { call -> toBoolean(irCall(call, intrinsics.jsBitOr, dispatchReceiverAsFirstArgument = true)) } - add(it, OperatorNames.XOR) { call -> toBoolean(irCall(call, intrinsics.jsBitXor, dispatchReceiverAsFirstArgument = true)) } + add(it, OperatorNames.AND) { call -> toBoolean(irCall(call, intrinsics.jsBitAnd, dispatchReceiverAsArgument = true)) } + add(it, OperatorNames.OR) { call -> toBoolean(irCall(call, intrinsics.jsBitOr, dispatchReceiverAsArgument = true)) } + add(it, OperatorNames.XOR) { call -> toBoolean(irCall(call, intrinsics.jsBitXor, dispatchReceiverAsArgument = true)) } add(it, OperatorNames.NOT, intrinsics.jsNot) } @@ -88,9 +88,9 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo return with(call.symbol.owner.valueParameters[0].type) { when { isByte() || isShort() || isInt() -> - irCall(call, intrinsics.jsNumberRangeToNumber, dispatchReceiverAsFirstArgument = true) + irCall(call, intrinsics.jsNumberRangeToNumber, dispatchReceiverAsArgument = true) isLong() -> - irCall(call, intrinsics.jsNumberRangeToLong, dispatchReceiverAsFirstArgument = true) + irCall(call, intrinsics.jsNumberRangeToLong, dispatchReceiverAsArgument = true) else -> call } } @@ -101,7 +101,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo intrinsic: IrFunctionSymbol, toInt32: Boolean = false ): IrExpression { - val newCall = irCall(call, intrinsic, dispatchReceiverAsFirstArgument = true) + val newCall = irCall(call, intrinsic, dispatchReceiverAsArgument = true) if (toInt32) return toInt32(newCall) return newCall @@ -152,7 +152,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo transformCrement(call, intrinsics.jsMinus) private fun transformCrement(call: IrFunctionAccessExpression, correspondingBinaryOp: IrFunctionSymbol): IrExpression { - val operation = irCall(call, correspondingBinaryOp, dispatchReceiverAsFirstArgument = true).apply { + val operation = irCall(call, correspondingBinaryOp, dispatchReceiverAsArgument = true).apply { putValueArgument(1, buildInt(1)) } @@ -161,7 +161,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo private fun transformUnaryMinus(call: IrFunctionAccessExpression) = convertResultToPrimitiveType( - irCall(call, intrinsics.jsUnaryMinus, dispatchReceiverAsFirstArgument = true), + irCall(call, intrinsics.jsUnaryMinus, dispatchReceiverAsArgument = true), call.type ) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 84975e1baaf..e8bba0c9bc9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -20,7 +20,12 @@ import org.jetbrains.kotlin.name.NameUtils private fun makePatchParentsPhase(number: Int) = namedIrFilePhase( lower = object : SameTypeCompilerPhase { - override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: CommonBackendContext, input: IrFile): IrFile { + override fun invoke( + phaseConfig: PhaseConfig, + phaserState: PhaserState, + context: CommonBackendContext, + input: IrFile + ): IrFile { input.acceptVoid(PatchDeclarationParentsVisitor()) return input } @@ -59,12 +64,6 @@ private val propertiesPhase = makeIrFilePhase( stickyPostconditions = setOf((PropertiesLowering)::checkNoProperties) ) -private val defaultArgumentStubPhase = makeIrFilePhase( - { context -> DefaultArgumentStubGenerator(context, false) }, - name = "DefaultArgumentsStubGenerator", - description = "Generate synthetic stubs for functions with default parameter values" -) - private val localDeclarationsPhase = makeIrFilePhase( { context -> LocalDeclarationsLowering(context, object : LocalNameProvider { @@ -77,6 +76,13 @@ private val localDeclarationsPhase = makeIrFilePhase( prerequisite = setOf(sharedVariablesPhase) ) +private val defaultArgumentStubPhase = makeIrFilePhase( + { context -> DefaultArgumentStubGenerator(context, false) }, + name = "DefaultArgumentsStubGenerator", + description = "Generate synthetic stubs for functions with default parameter values", + prerequisite = setOf(localDeclarationsPhase) +) + private val innerClassesPhase = makeIrFilePhase( ::InnerClassesLowering, name = "InnerClasses", @@ -105,11 +111,7 @@ val jvmPhases = namedIrFilePhase( tailrecPhase then jvmInlineClassPhase then - defaultArgumentStubPhase then - interfacePhase then - interfaceDelegationPhase then - interfaceSuperCallsPhase then sharedVariablesPhase then makePatchParentsPhase(1) then @@ -117,6 +119,12 @@ val jvmPhases = namedIrFilePhase( enumWhenPhase then singletonReferencesPhase then localDeclarationsPhase then + defaultArgumentStubPhase then + + interfacePhase then + interfaceDelegationPhase then + interfaceSuperCallsPhase then + singleAbstractMethodPhase then addContinuationPhase then callableReferencePhase then diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt index 3ff459788c5..c212d74a7da 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt @@ -205,7 +205,7 @@ private class InterfaceSuperCallsLowering(val context: JvmBackendContext) : IrEl if (superCallee.isDefinitelyNotDefaultImplsMethod()) return super.visitCall(expression) val redirectTarget = context.declarationFactory.getDefaultImplsFunction(superCallee) - val newCall = irCall(expression, redirectTarget, dispatchReceiverAsFirstArgument = true) + val newCall = irCall(expression, redirectTarget, dispatchReceiverAsArgument = true, extensionReceiverAsArgument = true) return super.visitCall(newCall) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt index 055c9bc5db4..8d9913e12e4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt @@ -22,11 +22,15 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.expressions.IrCall -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionReference +import org.jetbrains.kotlin.ir.expressions.IrReturn +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.copyTypeAndValueArgumentsFrom +import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.ir.util.isInterface import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid @@ -42,6 +46,7 @@ internal val interfacePhase = makeIrFilePhase( private class InterfaceLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), ClassLoweringPass { val state = context.state + val removedFunctions = hashMapOf() override fun lower(irClass: IrClass) { if (!irClass.isInterface) return @@ -54,7 +59,10 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans if (function !is IrSimpleFunction) continue if (function.modality != Modality.ABSTRACT && function.origin != IrDeclarationOrigin.FAKE_OVERRIDE) { - val element = context.declarationFactory.getDefaultImplsFunction(function) + val element = context.declarationFactory.getDefaultImplsFunction(function).also { + if (shouldRemoveFunction(function)) + removedFunctions[function.symbol] = it.symbol + } members.add(element) element.body = function.body?.patchDeclarationParents(element) if (function.hasJvmDefault() && @@ -69,10 +77,11 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans } } + // Update IrElements (e.g., IrCalls) to point to the new functions. irClass.transformChildrenVoid(this) irClass.declarations.removeAll { - it is IrFunction && shouldRemoveFunction(it) + it is IrFunction && removedFunctions.containsKey(it.symbol) } } @@ -85,7 +94,7 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans val startOffset = interfaceMethod.startOffset val endOffset = interfaceMethod.endOffset - return IrCallImpl(interfaceMethod.startOffset, interfaceMethod.endOffset, interfaceMethod.returnType, defaultImpls.symbol).apply { + return IrCallImpl(startOffset, endOffset, interfaceMethod.returnType, defaultImpls.symbol).apply { passTypeArgumentsFrom(interfaceMethod) var offset = 0 @@ -100,6 +109,53 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans } } } + + override fun visitReturn(expression: IrReturn): IrExpression { + val newFunction = removedFunctions[expression.returnTargetSymbol]?.owner + return super.visitReturn( + if (newFunction != null) { + with(expression) { + IrReturnImpl(startOffset, endOffset, type, newFunction.symbol, value) + } + } else { + expression + } + ) + } + + override fun visitCall(expression: IrCall): IrExpression { + val newFunction = removedFunctions[expression.symbol]?.owner + return super.visitCall( + if (newFunction != null) { + irCall(expression, newFunction, dispatchReceiverAsArgument = true, extensionReceiverAsArgument = true) + } else { + expression + } + ) + } + + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + val newFunction = removedFunctions[expression.symbol]?.owner + return super.visitFunctionReference( + if (newFunction != null) { + with(expression) { + IrFunctionReferenceImpl( + startOffset, + endOffset, + type, + newFunction.symbol, + newFunction.descriptor, + typeArgumentsCount, + origin + ).apply { + copyTypeAndValueArgumentsFrom(expression, dispatchReceiverAsArgument = true, extensionReceiverAsArgument = true) + } + } + } else { + expression + } + ) + } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index 0e069a97496..83116a30349 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -349,6 +349,7 @@ fun IrDeclaration.isEffectivelyExternal(): Boolean { is IrSimpleFunction -> correspondingProperty ?: parent as? IrDeclaration else -> parent as? IrDeclaration } + val parent = parent return when (this) { is IrFunction -> isExternal || (effectiveParentDeclaration()?.isEffectivelyExternal() ?: false) @@ -418,7 +419,7 @@ fun ReferenceSymbolTable.referenceFunction(callable: CallableDescriptor): IrFunc */ fun irConstructorCall( - call: IrMemberAccessExpression, + call: IrFunctionAccessExpression, newFunction: IrConstructor, dispatchReceiverAsFirstArgument: Boolean = false, firstArgumentAsDispatchReceiver: Boolean = false @@ -426,7 +427,7 @@ fun irConstructorCall( irConstructorCall(call, newFunction.symbol, dispatchReceiverAsFirstArgument, firstArgumentAsDispatchReceiver) fun irConstructorCall( - call: IrMemberAccessExpression, + call: IrFunctionAccessExpression, newSymbol: IrConstructorSymbol, dispatchReceiverAsFirstArgument: Boolean = false, firstArgumentAsDispatchReceiver: Boolean = false @@ -452,18 +453,29 @@ fun irConstructorCall( } fun irCall( - call: IrMemberAccessExpression, + call: IrFunctionAccessExpression, newFunction: IrFunction, - dispatchReceiverAsFirstArgument: Boolean = false, - firstArgumentAsDispatchReceiver: Boolean = false + dispatchReceiverAsArgument: Boolean = false, + argumentAsDispatchReceiver: Boolean = false, + extensionReceiverAsArgument: Boolean = false, + argumentAsExtensionReceiver: Boolean = false ): IrCall = - irCall(call, newFunction.symbol, dispatchReceiverAsFirstArgument, firstArgumentAsDispatchReceiver) + irCall( + call, + newFunction.symbol, + dispatchReceiverAsArgument, + argumentAsDispatchReceiver, + extensionReceiverAsArgument, + argumentAsExtensionReceiver + ) fun irCall( - call: IrMemberAccessExpression, + call: IrFunctionAccessExpression, newSymbol: IrFunctionSymbol, - dispatchReceiverAsFirstArgument: Boolean = false, - firstArgumentAsDispatchReceiver: Boolean = false + dispatchReceiverAsArgument: Boolean = false, + argumentAsDispatchReceiver: Boolean = false, + extensionReceiverAsArgument: Boolean = false, + argumentAsExtensionReceiver: Boolean = false ): IrCall = call.run { IrCallImpl( @@ -477,46 +489,95 @@ fun irCall( ).apply { copyTypeAndValueArgumentsFrom( call, - dispatchReceiverAsFirstArgument, - firstArgumentAsDispatchReceiver + dispatchReceiverAsArgument, + argumentAsDispatchReceiver, + extensionReceiverAsArgument, + argumentAsExtensionReceiver ) } } -private fun IrMemberAccessExpression.copyTypeAndValueArgumentsFrom( - call: IrMemberAccessExpression, - dispatchReceiverAsFirstArgument: Boolean = false, - firstArgumentAsDispatchReceiver: Boolean = false -) { - copyTypeArgumentsFrom(call) +fun IrFunctionAccessExpression.copyTypeAndValueArgumentsFrom( + src: IrFunctionAccessExpression, + dispatchReceiverAsArgument: Boolean = false, + argumentAsDispatchReceiver: Boolean = false, + extensionReceiverAsArgument: Boolean = false, + argumentAsExtensionReceiver: Boolean = false +) = copyTypeAndValueArgumentsFrom( + src, + src.symbol.owner, + symbol.owner, + dispatchReceiverAsArgument, + argumentAsDispatchReceiver, + extensionReceiverAsArgument, + argumentAsExtensionReceiver +) - var toValueArgumentIndex = 0 - var fromValueArgumentIndex = 0 +fun IrFunctionReference.copyTypeAndValueArgumentsFrom( + src: IrFunctionReference, + dispatchReceiverAsArgument: Boolean = false, + argumentAsDispatchReceiver: Boolean = false, + extensionReceiverAsArgument: Boolean = false, + argumentAsExtensionReceiver: Boolean = false +) = copyTypeAndValueArgumentsFrom( + src, + src.symbol.owner, + symbol.owner, + dispatchReceiverAsArgument, + argumentAsDispatchReceiver, + extensionReceiverAsArgument, + argumentAsExtensionReceiver +) + +private fun IrMemberAccessExpression.copyTypeAndValueArgumentsFrom( + src: IrMemberAccessExpression, + srcFunction: IrFunction, + destFunction: IrFunction, + dispatchReceiverAsArgument: Boolean = false, + argumentAsDispatchReceiver: Boolean = false, + extensionReceiverAsArgument: Boolean = false, + argumentAsExtensionReceiver: Boolean = false +) { + copyTypeArgumentsFrom(src) + + var destValueArgumentIndex = 0 + var srcValueArgumentIndex = 0 when { - dispatchReceiverAsFirstArgument -> { - putValueArgument(toValueArgumentIndex++, call.dispatchReceiver) + dispatchReceiverAsArgument && srcFunction.dispatchReceiverParameter != null -> { + putValueArgument(destValueArgumentIndex++, src.dispatchReceiver) } - firstArgumentAsDispatchReceiver -> { - dispatchReceiver = call.getValueArgument(fromValueArgumentIndex++) + argumentAsDispatchReceiver && destFunction.dispatchReceiverParameter != null -> { + dispatchReceiver = src.getValueArgument(srcValueArgumentIndex++) } else -> { - dispatchReceiver = call.dispatchReceiver + dispatchReceiver = src.dispatchReceiver } } - extensionReceiver = call.extensionReceiver + when { + extensionReceiverAsArgument && srcFunction.extensionReceiverParameter != null -> { + putValueArgument(destValueArgumentIndex++, src.extensionReceiver) + } + argumentAsExtensionReceiver && destFunction.extensionReceiverParameter != null -> { + extensionReceiver = src.getValueArgument(srcValueArgumentIndex++) + } + else -> { + extensionReceiver = src.extensionReceiver + } + } - while (fromValueArgumentIndex < call.valueArgumentsCount) { - putValueArgument(toValueArgumentIndex++, call.getValueArgument(fromValueArgumentIndex++)) + while (srcValueArgumentIndex < src.valueArgumentsCount) { + putValueArgument(destValueArgumentIndex++, src.getValueArgument(srcValueArgumentIndex++)) } } -val IrDeclaration.file: IrFile get() = parent.let { - when (it) { - is IrFile -> it - is IrPackageFragment -> TODO("Unknown file") - is IrDeclaration -> it.file - else -> TODO("Unexpected declaration parent") +val IrDeclaration.file: IrFile + get() = parent.let { + when (it) { + is IrFile -> it + is IrPackageFragment -> TODO("Unknown file") + is IrDeclaration -> it.file + else -> TODO("Unexpected declaration parent") + } } -} diff --git a/compiler/testData/codegen/box/callableReference/varargAndDefaults/localFunctionWithDefault.kt b/compiler/testData/codegen/box/callableReference/varargAndDefaults/localFunctionWithDefault.kt index 9f22847c7b0..c86b24af117 100644 --- a/compiler/testData/codegen/box/callableReference/varargAndDefaults/localFunctionWithDefault.kt +++ b/compiler/testData/codegen/box/callableReference/varargAndDefaults/localFunctionWithDefault.kt @@ -1,5 +1,5 @@ // !LANGUAGE: +NewInference -// IGNORE_BACKEND: JVM_IR, JS +// IGNORE_BACKEND: JS fun call0(f: (String) -> String, x: String): String = f(x) fun call1(f: (String, String) -> String, x: String, y: String): String = f(x, y) diff --git a/compiler/testData/codegen/box/closures/kt5589.kt b/compiler/testData/codegen/box/closures/kt5589.kt index 229f63ecee9..3b3a27d91ca 100644 --- a/compiler/testData/codegen/box/closures/kt5589.kt +++ b/compiler/testData/codegen/box/closures/kt5589.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR fun box(): String { val x = "OK" fun bar(y: String = x): String = y diff --git a/compiler/testData/codegen/box/functions/localFunctions/kt3978.kt b/compiler/testData/codegen/box/functions/localFunctions/kt3978.kt index 379209d16fc..71295ca6f4c 100644 --- a/compiler/testData/codegen/box/functions/localFunctions/kt3978.kt +++ b/compiler/testData/codegen/box/functions/localFunctions/kt3978.kt @@ -1,11 +1,10 @@ -// IGNORE_BACKEND: JVM_IR fun box() : String { - - fun local(i: Int = 1) : Int { return i } - return if (local() != 1) "fail" else "OK" -} + if (local() != 1) return "Fail 1" + if (local(2) != 2) return "Fail 2" + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/functions/localFunctions/kt3978_2.kt b/compiler/testData/codegen/box/functions/localFunctions/kt3978_2.kt new file mode 100644 index 00000000000..603a93a2951 --- /dev/null +++ b/compiler/testData/codegen/box/functions/localFunctions/kt3978_2.kt @@ -0,0 +1,12 @@ +class C() { + fun box(): Int { + fun local(i: Int = 1): Int { + return i + } + return local() + } +} + +fun box(): String { + return if (C().box() != 1) "fail" else "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/functions/localFunctions/parameterAsDefaultValue.kt b/compiler/testData/codegen/box/functions/localFunctions/parameterAsDefaultValue.kt index b06651fffe6..e90fe97fede 100644 --- a/compiler/testData/codegen/box/functions/localFunctions/parameterAsDefaultValue.kt +++ b/compiler/testData/codegen/box/functions/localFunctions/parameterAsDefaultValue.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR fun foo(): String { fun bar(x: String, y: String = x): String { return y diff --git a/compiler/testData/codegen/box/jvm8/defaults/accessor.kt b/compiler/testData/codegen/box/jvm8/defaults/accessor.kt index e93ef3b6488..c6bcff77dec 100644 --- a/compiler/testData/codegen/box/jvm8/defaults/accessor.kt +++ b/compiler/testData/codegen/box/jvm8/defaults/accessor.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: enable -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // JVM_TARGET: 1.8 // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/jvm8/defaults/accessorFromCompanion.kt b/compiler/testData/codegen/box/jvm8/defaults/accessorFromCompanion.kt index 4556388b36f..80e774ed6b7 100644 --- a/compiler/testData/codegen/box/jvm8/defaults/accessorFromCompanion.kt +++ b/compiler/testData/codegen/box/jvm8/defaults/accessorFromCompanion.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: enable -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // JVM_TARGET: 1.8 // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/jvm8/defaults/accessorsFromDefaultImpls.kt b/compiler/testData/codegen/box/jvm8/defaults/accessorsFromDefaultImpls.kt index 9ceb2820dca..7973d8e6b39 100644 --- a/compiler/testData/codegen/box/jvm8/defaults/accessorsFromDefaultImpls.kt +++ b/compiler/testData/codegen/box/jvm8/defaults/accessorsFromDefaultImpls.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: enable -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // JVM_TARGET: 1.8 // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/jvm8/defaults/inline.kt b/compiler/testData/codegen/box/jvm8/defaults/inline.kt index 8b5b706a284..02357f8346a 100644 --- a/compiler/testData/codegen/box/jvm8/defaults/inline.kt +++ b/compiler/testData/codegen/box/jvm8/defaults/inline.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: enable -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // JVM_TARGET: 1.8 // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/jvm8/defaults/privateDefaultFromDefaultImpl.kt b/compiler/testData/codegen/box/jvm8/defaults/privateDefaultFromDefaultImpl.kt index 3b0aebee624..393c52f6718 100644 --- a/compiler/testData/codegen/box/jvm8/defaults/privateDefaultFromDefaultImpl.kt +++ b/compiler/testData/codegen/box/jvm8/defaults/privateDefaultFromDefaultImpl.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: enable -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // JVM_TARGET: 1.8 // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/localClasses/kt3584.kt b/compiler/testData/codegen/box/localClasses/kt3584.kt index 758694b6b17..21cdb764faa 100644 --- a/compiler/testData/codegen/box/localClasses/kt3584.kt +++ b/compiler/testData/codegen/box/localClasses/kt3584.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR fun box(): String { val s = "captured"; diff --git a/compiler/testData/codegen/boxInline/trait/trait.kt b/compiler/testData/codegen/boxInline/trait/trait.kt index c130e697467..cd85fac3b3e 100644 --- a/compiler/testData/codegen/boxInline/trait/trait.kt +++ b/compiler/testData/codegen/boxInline/trait/trait.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index eead5ac848e..1e8b6772dfc 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -11504,6 +11504,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/functions/localFunctions/kt3978.kt"); } + @TestMetadata("kt3978_2.kt") + public void testKt3978_2() throws Exception { + runTest("compiler/testData/codegen/box/functions/localFunctions/kt3978_2.kt"); + } + @TestMetadata("kt4119.kt") public void testKt4119() throws Exception { runTest("compiler/testData/codegen/box/functions/localFunctions/kt4119.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index f8f995e5a43..fd348b896c2 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -11504,6 +11504,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/functions/localFunctions/kt3978.kt"); } + @TestMetadata("kt3978_2.kt") + public void testKt3978_2() throws Exception { + runTest("compiler/testData/codegen/box/functions/localFunctions/kt3978_2.kt"); + } + @TestMetadata("kt4119.kt") public void testKt4119() throws Exception { runTest("compiler/testData/codegen/box/functions/localFunctions/kt4119.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 9ce5a4de111..5ba2c17ea71 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -10394,6 +10394,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/functions/localFunctions/kt3978.kt"); } + @TestMetadata("kt3978_2.kt") + public void testKt3978_2() throws Exception { + runTest("compiler/testData/codegen/box/functions/localFunctions/kt3978_2.kt"); + } + @TestMetadata("kt4119.kt") public void testKt4119() throws Exception { runTest("compiler/testData/codegen/box/functions/localFunctions/kt4119.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index c53452e7ee8..8fd302a195e 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -9019,6 +9019,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/functions/localFunctions/kt3978.kt"); } + @TestMetadata("kt3978_2.kt") + public void testKt3978_2() throws Exception { + runTest("compiler/testData/codegen/box/functions/localFunctions/kt3978_2.kt"); + } + @TestMetadata("kt4119.kt") public void testKt4119() throws Exception { runTest("compiler/testData/codegen/box/functions/localFunctions/kt4119.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 72fbf3a4cf7..04dad9de18f 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -10104,6 +10104,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/functions/localFunctions/kt3978.kt"); } + @TestMetadata("kt3978_2.kt") + public void testKt3978_2() throws Exception { + runTest("compiler/testData/codegen/box/functions/localFunctions/kt3978_2.kt"); + } + @TestMetadata("kt4119.kt") public void testKt4119() throws Exception { runTest("compiler/testData/codegen/box/functions/localFunctions/kt4119.kt");