diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrInlineReferenceLocator.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrInlineReferenceLocator.kt new file mode 100644 index 00000000000..fdcead3d5b5 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrInlineReferenceLocator.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.jvm.ir + +import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.codegen.isInlineFunctionCall +import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid + +internal class IrInlineReferenceLocator(private val context: JvmBackendContext) : IrElementVisitorVoidWithContext() { + val inlineReferences = mutableSetOf() + + // For crossinline lambdas, the call site is null as it's probably in a separate class somewhere. + // All other lambdas are guaranteed to be inlined into the scope they are declared in. + val lambdaToCallSite = mutableMapOf() + + override fun visitElement(element: IrElement) = element.acceptChildrenVoid(this) + + override fun visitFunctionAccess(expression: IrFunctionAccessExpression) { + val function = expression.symbol.owner + if (function.isInlineFunctionCall(context)) { + for (parameter in function.valueParameters) { + if (!parameter.isInlineParameter()) + continue + + val valueArgument = expression.getValueArgument(parameter.index) ?: continue + if (!isInlineIrExpression(valueArgument)) + continue + + if (valueArgument is IrPropertyReference) { + inlineReferences.add(valueArgument) + continue + } + + val reference = when (valueArgument) { + is IrFunctionReference -> valueArgument + is IrBlock -> valueArgument.statements.filterIsInstance().singleOrNull() + else -> null + } ?: continue + + inlineReferences.add(reference) + if (valueArgument is IrBlock && valueArgument.origin.isLambda) { + lambdaToCallSite[reference.symbol.owner] = + if (parameter.isCrossinline) null else currentScope!!.irElement as IrDeclaration + } + } + } + return super.visitFunctionAccess(expression) + } + + companion object { + fun scan(context: JvmBackendContext, element: IrElement) = + IrInlineReferenceLocator(context).apply { element.accept(this, null) } + } +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt index 5d95bf63685..2fbc01b59a2 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext -import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.ir.isSuspend @@ -15,15 +14,10 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin -import org.jetbrains.kotlin.backend.jvm.codegen.isInlineFunctionCall -import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression -import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder -import org.jetbrains.kotlin.backend.jvm.ir.irArray -import org.jetbrains.kotlin.backend.jvm.ir.isInlineParameter -import org.jetbrains.kotlin.backend.jvm.ir.isLambda +import org.jetbrains.kotlin.backend.jvm.ir.* +import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.addConstructor @@ -33,12 +27,10 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildClass import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames @@ -49,52 +41,12 @@ internal val callableReferencePhase = makeIrFilePhase( description = "Handle callable references" ) -internal class InlineReferenceLocator(private val context: JvmBackendContext) : IrElementVisitorVoidWithContext() { - val inlineReferences = mutableSetOf() - // For crossinline lambdas, the call site is null as it's probably in a separate class somewhere. - // All other lambdas are guaranteed to be inlined into the scope they are declared in. - val lambdaToCallSite = mutableMapOf() - - override fun visitElement(element: IrElement) = element.acceptChildrenVoid(this) - - override fun visitFunctionAccess(expression: IrFunctionAccessExpression) { - val function = expression.symbol.owner - if (function.isInlineFunctionCall(context)) { - for (parameter in function.valueParameters) { - if (!parameter.isInlineParameter()) - continue - - val valueArgument = expression.getValueArgument(parameter.index) ?: continue - if (!isInlineIrExpression(valueArgument)) - continue - - val reference = when (valueArgument) { - is IrFunctionReference -> valueArgument - is IrBlock -> valueArgument.statements.filterIsInstance().singleOrNull() - else -> null - } ?: continue - - inlineReferences.add(reference) - if (valueArgument is IrBlock && valueArgument.origin.isLambda) { - lambdaToCallSite[reference.symbol.owner] = - if (parameter.isCrossinline) null else currentScope!!.irElement as IrDeclaration - } - } - } - return super.visitFunctionAccess(expression) - } - - companion object { - fun scan(context: JvmBackendContext, element: IrElement) = - InlineReferenceLocator(context).apply { element.accept(this, null) } - } -} // Originally copied from K/Native internal class CallableReferenceLowering(private val context: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoidWithContext() { // This pass ignores suspend function references and function references used in inline arguments to inline functions. - private val ignoredFunctionReferences = mutableSetOf() + private val ignoredFunctionReferences = mutableSetOf() private val IrFunctionReference.isIgnored: Boolean get() = (!type.isFunctionOrKFunction() || ignoredFunctionReferences.contains(this)) && !isSuspendCallableReference() @@ -103,7 +55,7 @@ internal class CallableReferenceLowering(private val context: JvmBackendContext) private fun IrFunctionReference.isSuspendCallableReference(): Boolean = isSuspend && origin == null override fun lower(irFile: IrFile) { - ignoredFunctionReferences.addAll(InlineReferenceLocator.scan(context, irFile).inlineReferences) + ignoredFunctionReferences.addAll(IrInlineReferenceLocator.scan(context, irFile).inlineReferences) irFile.transformChildrenVoid(this) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InlineCallableReferenceToLambda.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InlineCallableReferenceToLambda.kt index 1bb024d79ee..25129f8e04d 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InlineCallableReferenceToLambda.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InlineCallableReferenceToLambda.kt @@ -7,18 +7,16 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext -import org.jetbrains.kotlin.backend.common.ScopeWithIr -import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom -import org.jetbrains.kotlin.backend.common.ir.copyValueParametersToStatic -import org.jetbrains.kotlin.backend.jvm.ir.isInlineParameter import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlock import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin -import org.jetbrains.kotlin.backend.jvm.codegen.isInlineFunctionCall -import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression +import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator +import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder +import org.jetbrains.kotlin.backend.jvm.ir.irArray +import org.jetbrains.kotlin.backend.jvm.ir.isLambda import org.jetbrains.kotlin.codegen.AsmUtil.BOUND_REFERENCE_RECEIVER import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.builders.* @@ -28,9 +26,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl import org.jetbrains.kotlin.ir.types.IrSimpleType -import org.jetbrains.kotlin.ir.types.classOrNull -import org.jetbrains.kotlin.ir.types.isSubtypeOf -import org.jetbrains.kotlin.ir.types.isSubtypeOfClass +import org.jetbrains.kotlin.ir.types.IrTypeProjection import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name @@ -49,187 +45,139 @@ internal val inlineCallableReferenceToLambdaPhase = makeIrFilePhase( // // foo(::smth) -> foo { a -> smth(a) } // -internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendContext) : FileLoweringPass { - private val inlinableCR = mutableSetOf() +internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendContext) : FileLoweringPass, + IrElementTransformerVoidWithContext() { + + private var inlinableReferences = mutableSetOf() override fun lower(irFile: IrFile) { - irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() { - - override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression { - val callee = expression.symbol.owner - if (callee.isInlineFunctionCall(context)) { - for (valueParameter in callee.valueParameters) { - if (valueParameter.isInlineParameter()) { - expression.getValueArgument(valueParameter.index)?.let { argument -> - if (argument is IrCallableReference && isInlineIrExpression(argument)) { - inlinableCR.add(argument) - } - } - } - } - } - - return super.visitFunctionAccess(expression) - } - - - override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { - if (expression !in inlinableCR) { - return super.visitPropertyReference(expression) - } - - //Use getter if field is absent... - val field = - expression.field?.owner ?: return functionReferenceToLambda(currentScope!!, expression, expression.getter!!.owner) - - //..else use field itself - val irBuilder = - context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset) - val boundReceiver = expression.dispatchReceiver ?: expression.extensionReceiver - return irBuilder.irBlock(expression, IrStatementOrigin.LAMBDA) { - lateinit var variableForBoundReceiver: IrVariable - if (boundReceiver != null) { - variableForBoundReceiver = createTmpVariable(boundReceiver, BOUND_REFERENCE_RECEIVER) - } - - val newLambda = buildFun { - setSourceRange(expression) - origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL - name = Name.identifier("stub_for_inline") - visibility = Visibilities.LOCAL - returnType = field.type - isSuspend = false - }.apply { - - val receiver = - when { - field.isStatic -> null - boundReceiver != null -> variableForBoundReceiver - else -> addValueParameter("receiver", field.parentAsClass.defaultType) - } - - val lambdaBodyBuilder = this@InlineCallableReferenceToLambdaPhase.context.createIrBuilder(this.symbol) - body = lambdaBodyBuilder.irBlockBody(startOffset, endOffset) { - +irReturn(irGetField(if (receiver != null) irGet(receiver) else null, field)) - } - } - +newLambda - - +IrFunctionReferenceImpl( - expression.startOffset, expression.endOffset, field.type, - newLambda.symbol, newLambda.symbol.descriptor, 0, - IrStatementOrigin.LAMBDA - ).apply { - copyAttributes(expression) - } - } - } - - override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { - if (inlinableCR.contains(expression)) { - val referencedFunction = expression.symbol.owner - return functionReferenceToLambda(currentScope!!, expression, referencedFunction) - } - - return super.visitFunctionReference(expression) - } - }) + IrInlineReferenceLocator.scan(context, irFile).let { + inlinableReferences.addAll(it.inlineReferences) + } + irFile.transformChildrenVoid(this) } - private fun functionReferenceToLambda( - scope: ScopeWithIr, - expression: IrCallableReference, - referencedFunction: IrFunction - ): IrExpression { - val irBuilder = - context.createIrBuilder(scope.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset) + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + if (expression !in inlinableReferences || expression.origin.isLambda) return expression + return expandInlineFunctionReferenceToLambda(expression, expression.symbol.owner) + } - val boundReceiver = expression.dispatchReceiver ?: expression.extensionReceiver + override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { + if (expression !in inlinableReferences) return expression - val expectedType = expression.type - var expectedNumValueParameters: Int - if (expectedType.isFunctionOrKFunction() || expectedType.isSuspendFunction() || expectedType.isKSuspendFunction()) { // TODO: handle subtypes - expectedNumValueParameters = (expectedType as IrSimpleType).arguments.size - 1 // In ...Function classes, the last argument is return type - referencedFunction.dispatchReceiverParameter?.let { expectedNumValueParameters-- } - referencedFunction.extensionReceiverParameter?.let { expectedNumValueParameters-- } - boundReceiver?.let { expectedNumValueParameters++ } - assert(referencedFunction.valueParameters.subList(expectedNumValueParameters, referencedFunction.valueParameters.size).all { - it.defaultValue != null - }) + return if (expression.field?.owner == null) { + // Use getter if field is absent ... + expandInlineFunctionReferenceToLambda(expression, expression.getter!!.owner) } else { - assert(expectedType.classOrNull?.isSubtypeOfClass(context.irBuiltIns.kPropertyClass) == true) - expectedNumValueParameters = 0 + // ... else use field itself + expandInlineFieldReferenceToLambda(expression, expression.field!!.owner) } + } + private fun expandInlineFieldReferenceToLambda(expression: IrPropertyReference, field: IrField): IrExpression { + val irBuilder = context.createJvmIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset) return irBuilder.irBlock(expression, IrStatementOrigin.LAMBDA) { - lateinit var variableForBoundReceiver: IrVariable - if (boundReceiver != null) { - variableForBoundReceiver = createTmpVariable(boundReceiver, BOUND_REFERENCE_RECEIVER) - } - - val newLambda = buildFun { + val function = buildFun { setSourceRange(expression) origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL name = Name.identifier("stub_for_inline") visibility = Visibilities.LOCAL + returnType = field.type + isSuspend = false + }.apply { + val boundReceiver = expression.dispatchReceiver ?: expression.extensionReceiver + + val receiver = + when { + field.isStatic -> null + boundReceiver != null -> irGet(irTemporary(boundReceiver, BOUND_REFERENCE_RECEIVER)) + else -> irGet(addValueParameter("receiver", field.parentAsClass.defaultType)) + } + + body = this@InlineCallableReferenceToLambdaPhase.context.createIrBuilder(symbol).run { + irExprBody(irGetField(receiver, field)) + } + } + + +function + +IrFunctionReferenceImpl( + expression.startOffset, + expression.endOffset, + field.type, + function.symbol, + function.symbol.descriptor, + typeArgumentsCount = 0, + origin = IrStatementOrigin.LAMBDA + ).apply { + copyAttributes(expression) + } + } + } + + private fun expandInlineFunctionReferenceToLambda(expression: IrCallableReference, referencedFunction: IrFunction): IrExpression { + val irBuilder = context.createJvmIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset) + return irBuilder.irBlock(expression, IrStatementOrigin.LAMBDA) { + + val parameterTypes = (expression.type as IrSimpleType).arguments.map { (it as IrTypeProjection).type } + val argumentTypes = parameterTypes.dropLast(1) + + val boundReceiver: Pair? = expression.getArgumentsWithIr().singleOrNull() + + val function = buildFun { + setSourceRange(expression) + origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL + name = Name.identifier("stub_for_inlining") + visibility = Visibilities.LOCAL returnType = referencedFunction.returnType isSuspend = false }.apply { - if (referencedFunction is IrConstructor) { - copyTypeParametersFrom(referencedFunction.parentAsClass) - } - copyTypeParametersFrom(referencedFunction) - if (boundReceiver == null) { - copyValueParametersToStatic(referencedFunction, origin, numValueParametersToCopy = expectedNumValueParameters) - } else { - for (oldValueParameter in referencedFunction.valueParameters) { - if (oldValueParameter.index >= expectedNumValueParameters) break - valueParameters.add( - oldValueParameter.copyTo( - this, - origin = origin, - index = oldValueParameter.index - ) - ) + for ((index, argumentType) in argumentTypes.withIndex()) { + addValueParameter { + name = Name.identifier("p$index") + type = argumentType } } - val lambdaBodyBuilder = this@InlineCallableReferenceToLambdaPhase.context.createIrBuilder(this.symbol) - body = lambdaBodyBuilder.irBlockBody(startOffset, endOffset) { - var shift = 0 - val irCall = - if (expression is IrPropertyReference) - irGet(referencedFunction.returnType, null, referencedFunction.symbol) - else irCall(referencedFunction.symbol) - +irReturn( - irCall.also { call -> - for (it in this@apply.typeParameters) { - call.putTypeArgument(it.index, expression.getTypeArgument(it.index)) - } - - referencedFunction.dispatchReceiverParameter?.let { - call.dispatchReceiver = - irGet(if (expression.dispatchReceiver != null) variableForBoundReceiver else valueParameters[shift++]) - } - referencedFunction.extensionReceiverParameter?.let { - call.extensionReceiver = - irGet(if (expression.extensionReceiver != null) variableForBoundReceiver else valueParameters[shift++]) - } - - for (it in referencedFunction.valueParameters.indices) { - if (it >= expectedNumValueParameters) break - call.putValueArgument(it, irGet(valueParameters[shift++])) - } + body = this@InlineCallableReferenceToLambdaPhase.context.createJvmIrBuilder( + this.symbol, + expression.startOffset, + expression.endOffset + ).run { + irExprBody(irCall(referencedFunction).apply { + this@apply.descriptor.typeParameters.forEach { + putTypeArgument(it.index, expression.getTypeArgument(it.index)) } - ) + + var unboundIndex = 0 + for (parameter in referencedFunction.explicitParameters) { + when { + boundReceiver?.first == parameter -> + irGet(irTemporary(boundReceiver.second)) + parameter.isVararg && unboundIndex < argumentTypes.size && parameter.type == valueParameters[unboundIndex].type -> + irGet(valueParameters[unboundIndex++]) + parameter.isVararg && (unboundIndex < argumentTypes.size || !parameter.hasDefaultValue()) -> + irArray(parameter.type) { + (unboundIndex until argumentTypes.size).forEach { +irGet(valueParameters[unboundIndex++]) } + } + unboundIndex >= argumentTypes.size -> + null + else -> + irGet(valueParameters[unboundIndex++]) + }?.let { putArgument(referencedFunction, parameter, it) } + } + }) } } - +newLambda + +function +IrFunctionReferenceImpl( - expression.startOffset, expression.endOffset, referencedFunction.returnType, - newLambda.symbol, newLambda.symbol.descriptor, referencedFunction.typeParameters.size, + expression.startOffset, + expression.endOffset, + referencedFunction.returnType, + function.symbol, + function.symbol.descriptor, + referencedFunction.typeParameters.size, IrStatementOrigin.LAMBDA ).apply { copyAttributes(expression) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt index ba7f883a238..af78f84a71a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.backend.common.ir.remapTypeParameters import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.intrinsics.receiverAndArgs +import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator import org.jetbrains.kotlin.backend.jvm.ir.isLambda import org.jetbrains.kotlin.backend.jvm.ir.shouldBeHidden import org.jetbrains.kotlin.descriptors.Modality @@ -46,7 +47,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle private val inlineLambdaToCallSite = mutableMapOf() override fun lower(irFile: IrFile) { - inlineLambdaToCallSite.putAll(InlineReferenceLocator.scan(context, irFile).lambdaToCallSite) + inlineLambdaToCallSite.putAll(IrInlineReferenceLocator.scan(context, irFile).lambdaToCallSite) irFile.transformChildrenVoid(this) pendingTransformations.forEach { it() } } 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 99809550e2e..85e1e604b5b 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 @@ -91,6 +91,10 @@ fun IrMemberAccessExpression.getArgumentsWithIr(): List this.symbol.owner is IrFunctionReference -> this.symbol.owner + is IrPropertyReference -> { + assert(this.field == null) { "Field should be null to use `getArgumentsWithIr` on IrPropertyReference: ${this.dump()}}" } + this.getter!!.owner + } else -> error(this) } diff --git a/compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineDefault.kt b/compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineDefault.kt new file mode 100644 index 00000000000..7120302b724 --- /dev/null +++ b/compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineDefault.kt @@ -0,0 +1,11 @@ +// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType +// WITH_RUNTIME +// IGNORE_BACKEND: JS_IR + +inline fun foo(mkString: () -> String): String = + mkString() + +fun bar (xs: CharArray = charArrayOf('O','K')) = + String(xs) + +fun box(): String = foo(::bar) diff --git a/compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVararg.kt b/compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVararg.kt new file mode 100644 index 00000000000..8b2d6cb287f --- /dev/null +++ b/compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVararg.kt @@ -0,0 +1,12 @@ +// !LANGUAGE: +NewInference +// WITH_RUNTIME +// IGNORE_BACKEND: JS, JS_IR + +inline fun foo(mkString: (Char, Char) -> String): String = + mkString('O','K') + +fun bar (vararg xs: Char) = + String(xs) + +fun box(): String = foo(::bar) +// -> { a, b -> bar(a, b) } \ No newline at end of file diff --git a/compiler/testData/codegen/box/callableReference/varargAndDefaults/inline.kt b/compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargAndDefault.kt similarity index 86% rename from compiler/testData/codegen/box/callableReference/varargAndDefaults/inline.kt rename to compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargAndDefault.kt index 1a179ba51d1..2f366cb4c98 100644 --- a/compiler/testData/codegen/box/callableReference/varargAndDefaults/inline.kt +++ b/compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargAndDefault.kt @@ -1,5 +1,5 @@ // !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType -// IGNORE_BACKEND: JS, JVM_IR, JS_IR +// IGNORE_BACKEND: JS, JS_IR fun foo(vararg l: Long, s: String = "OK"): String = if (l.size == 0) s else "Fail" diff --git a/compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargInts.kt b/compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargInts.kt new file mode 100644 index 00000000000..1ad1c26f788 --- /dev/null +++ b/compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargInts.kt @@ -0,0 +1,12 @@ +// !LANGUAGE: +NewInference +// WITH_RUNTIME +// IGNORE_BACKEND: JS, JS_IR + +inline fun foo(x: (Int, Int) -> Int): Int = + x(120,3) + +fun bar(vararg x: Int): Int = + x.sum() + +fun box(): String = + if (foo(::bar) == 123) "OK" else "FAIL" diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index e7e71bfb0fc..95e1d728707 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -2632,9 +2632,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/emptyVarargAndDefault.kt"); } - @TestMetadata("inline.kt") - public void testInline() throws Exception { - runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inline.kt"); + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineDefault.kt"); + } + + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVararg.kt"); + } + + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargAndDefault.kt"); + } + + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargInts.kt"); } @TestMetadata("innerConstructorWithVararg.kt") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index df891fa691a..0fec85b4c8b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -2632,9 +2632,24 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/emptyVarargAndDefault.kt"); } - @TestMetadata("inline.kt") - public void testInline() throws Exception { - runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inline.kt"); + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineDefault.kt"); + } + + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVararg.kt"); + } + + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargAndDefault.kt"); + } + + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargInts.kt"); } @TestMetadata("innerConstructorWithVararg.kt") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index bd835a6a5ad..ca6af2cf39c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -2612,9 +2612,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/emptyVarargAndDefault.kt"); } - @TestMetadata("inline.kt") - public void testInline() throws Exception { - runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inline.kt"); + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineDefault.kt"); + } + + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVararg.kt"); + } + + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargAndDefault.kt"); + } + + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargInts.kt"); } @TestMetadata("innerConstructorWithVararg.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 46c2005d0dd..d30d4489136 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 @@ -2072,9 +2072,24 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/emptyVarargAndDefault.kt"); } - @TestMetadata("inline.kt") - public void testInline() throws Exception { - runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inline.kt"); + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineDefault.kt"); + } + + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVararg.kt"); + } + + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargAndDefault.kt"); + } + + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargInts.kt"); } @TestMetadata("innerConstructorWithVararg.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 3db3cc5fa0f..1c6f30ae625 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 @@ -2072,9 +2072,24 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/emptyVarargAndDefault.kt"); } - @TestMetadata("inline.kt") - public void testInline() throws Exception { - runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inline.kt"); + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineDefault.kt"); + } + + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVararg.kt"); + } + + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargAndDefault.kt"); + } + + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/inlineVarargInts.kt"); } @TestMetadata("innerConstructorWithVararg.kt")