[K/N] Fix references for inline function

Corresponding lowering creating wrappers from JS Backend was used.

Also, the lowering was changed to create local function, instead of
normal one in outer scope, as a lot of logic from local declarations
lowering should be duplicated otherwise for correct type parameters
handling.

^KT-38535
This commit is contained in:
Pavel Kunyavskiy
2022-08-02 16:00:47 +02:00
committed by Space
parent 2f75ea585e
commit 5034581788
19 changed files with 235 additions and 42 deletions
@@ -45617,6 +45617,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFun.kt");
}
@Test
@TestMetadata("callableReferenceInlinedFunFromOtherModule.kt")
public void testCallableReferenceInlinedFunFromOtherModule() throws Exception {
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFunFromOtherModule.kt");
}
@Test
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
@@ -119,3 +119,5 @@ fun CommonBackendContext.createArrayOfExpression(
putValueArgument(0, arg0)
}
}
fun IrFunction.isInlineFunWithReifiedParameter() = isInline && typeParameters.any { it.isReified }
@@ -1,31 +1,29 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 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.
*/
/*
* Copyright 2010-2021 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.ir.backend.js.lower.inline
package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.ir.isInlineFunWithReifiedParameter
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.isInlineFunWithReifiedParameter
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.types.IrTypeArgument
import org.jetbrains.kotlin.ir.types.IrTypeSubstitutor
import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
import org.jetbrains.kotlin.ir.util.typeSubstitutionMap
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -59,48 +57,56 @@ class WrapInlineDeclarationsWithReifiedTypeParametersLowering(val context: Backe
context.irBuiltIns
)
val function = irFactory.addFunction(container.parent as IrDeclarationContainer) {
val function = irFactory.buildFun {
name = Name.identifier("${owner.name}${"$"}wrap")
returnType = owner.returnType
visibility = DescriptorVisibilities.PRIVATE
origin = JsIrBuilder.SYNTHESIZED_DECLARATION
}.also { function ->
returnType = typeSubstitutor.substitute(owner.returnType)
visibility = DescriptorVisibilities.LOCAL
origin = IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE
startOffset = SYNTHETIC_OFFSET
endOffset = SYNTHETIC_OFFSET
}.apply {
parent = container as IrDeclarationParent
val irBuilder = context.createIrBuilder(symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET)
owner.valueParameters.forEach { valueParameter ->
function.addValueParameter(
addValueParameter(
valueParameter.name,
typeSubstitutor.substitute(valueParameter.type)
)
}
function.body = irFactory.createBlockBody(
body = irFactory.createBlockBody(
expression.startOffset,
expression.endOffset
) {
statements.add(
JsIrBuilder.buildReturn(
function.symbol,
JsIrBuilder.buildCall(owner.symbol).also { call ->
irBuilder.irReturn(
irBuilder.irCall(owner.symbol).also { call ->
call.dispatchReceiver = expression.dispatchReceiver
call.extensionReceiver = expression.extensionReceiver
function.valueParameters.forEachIndexed { index, valueParameter ->
call.putValueArgument(index, JsIrBuilder.buildGetValue(valueParameter.symbol))
valueParameters.forEachIndexed { index, valueParameter ->
call.putValueArgument(index, irBuilder.irGet(valueParameter))
}
for (i in 0 until expression.typeArgumentsCount) {
call.putTypeArgument(i, expression.getTypeArgument(i))
}
},
owner.returnType
)
)
}
}
return IrFunctionReferenceImpl.fromSymbolOwner(
expression.startOffset,
expression.endOffset,
expression.type,
function.symbol,
function.typeParameters.size,
expression.reflectionTarget
)
return context.createIrBuilder(container.symbol).irBlock(
expression,
origin = IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE
) {
+function
+IrFunctionReferenceImpl.fromSymbolOwner(
expression.startOffset,
expression.endOffset,
expression.type,
function.symbol,
function.typeParameters.size,
expression.reflectionTarget
)
}
}
})
}
@@ -13,9 +13,7 @@ import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineFunc
import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineLambdasLowering
import org.jetbrains.kotlin.backend.common.lower.loops.ForLoopsLowering
import org.jetbrains.kotlin.backend.common.lower.optimizations.FoldConstantLowering
import org.jetbrains.kotlin.backend.common.lower.optimizations.PropertyAccessorInlineLowering
import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
import org.jetbrains.kotlin.ir.backend.js.lower.*
import org.jetbrains.kotlin.ir.backend.js.lower.calls.CallsLowering
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower.inline
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.isInlineFunWithReifiedParameter
import org.jetbrains.kotlin.backend.common.ir.isInlineFunWithReifiedParameter
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrProperty
@@ -118,5 +118,3 @@ fun invokeFunForLambda(call: IrCall) =
.type
.getClass()!!
.invokeFun!!
fun IrFunction.isInlineFunWithReifiedParameter() = isInline && typeParameters.any { it.isReified }
@@ -14,13 +14,11 @@ import org.jetbrains.kotlin.backend.common.lower.optimizations.PropertyAccessorI
import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.backend.common.toMultiModuleAction
import org.jetbrains.kotlin.backend.wasm.lower.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.lower.*
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.AddContinuationToFunctionCallsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.AddContinuationToNonLocalSuspendFunctionsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.JsSuspendFunctionsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.RemoveInlineDeclarationsWithReifiedTypeParametersLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.WrapInlineDeclarationsWithReifiedTypeParametersLowering
import org.jetbrains.kotlin.ir.backend.wasm.lower.generateMainFunctionCalls
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
@@ -1,5 +1,4 @@
// WITH_STDLIB
// IGNORE_BACKEND: NATIVE
inline fun <reified T> baz(value: T): String = "OK" + value
@@ -67,6 +66,21 @@ class F<T1> {
inline fun <reified T2> foo(x: T1, y: T2): Any? = "OK" + x + y
}
inline fun <reified T, K> bam(value1: K?, value2: T?): String = "OK" + value1.toString() + value2.toString()
fun <T> test10(): String {
val f: (T?, String?) -> String = ::bam
return f(null, "abc")
}
inline fun <T> test11Impl() : String {
val f: (T?, String?) -> String = ::bam
return f(null, "def")
}
fun <T> test11() = test11Impl<T>()
fun box(): String {
val test1 = test()
if (test1 != "OK1") return "fail1: $test1"
@@ -86,6 +100,10 @@ fun box(): String {
if (test8 != "OK56") return "fail8: $test8"
val test9 = F<Int>().foo(65, "hello")
if (test9 != "OK65hello") return "fail9: $test9"
val test10 = test10<Int>()
if (test10 != "OKnullabc") return "fail10: $test10"
val test11 = test11<Int>()
if (test11 != "OKnulldef") return "fail11: $test11"
return "OK"
}
@@ -0,0 +1,119 @@
// WITH_STDLIB
// MODULE: lib
// FILE: lib.kt
inline fun <reified T> baz(value: T): String = "OK" + value
object Foo {
val log = "123"
}
public inline fun <reified T> Foo.foo(value: T): String =
log + value
object Bar {
val log = "321"
public inline fun <reified T> bar(value: T): String =
log + value
}
class C {
inline fun <reified T: String> qux(value: T): String = "OK" + value
}
inline fun <reified T: Any> ((Any) -> String).cux(value: T): String = this(value)
inline fun <reified T, K, reified S> bak(value1: T, value2: K, value3: S): String = "OK" + value1 + value2 + value3
inline fun <reified T, K> bal(value1: Array<K>, value2: Array<T>): String = "OK" + value1.joinToString() + value2.joinToString()
class E<T>
public inline fun <reified T> E<T>.foo(value: T): String = "OK" + value
class F<T1> {
inline fun <reified T2> foo(x: T1, y: T2): Any? = "OK" + x + y
}
inline fun <reified T, K> bam(value1: K?, value2: T?): String = "OK" + value1.toString() + value2.toString()
inline fun <T> test11Impl() : String {
val f: (T?, String?) -> String = ::bam
return f(null, "def")
}
// MODULE: main(lib)
// FILE: main.kt
fun test(): String {
val f: (Any) -> String = ::baz
return f(1)
}
val test2 = { "OK".let(Foo::foo) }
val test3 = { "OK".let(Bar::bar) }
fun test4(): String {
val c = C()
val cr: (String) -> String = c::qux
return cr("456")
}
fun test5(): String {
val foo: (Any) -> String = ({ b: Any ->
val a: (Any) -> String = ::baz
a(b)
})::cux
return foo(3)
}
fun test6(): String {
val f: (Any, Int, String) -> String = ::bak
return f(1, 37, "joo")
}
fun test7(): String {
val f: (Array<Any>, Array<Int>) -> String = ::bal
return f(arrayOf("mer", "nas"), arrayOf(73, 37))
}
fun <T> test10(): String {
val f: (T?, String?) -> String = ::bam
return f(null, "abc")
}
fun <T> test11() = test11Impl<T>()
fun box(): String {
val test1 = test()
if (test1 != "OK1") return "fail1: $test1"
val test2 = test2()
if (test2 != "123OK") return "fail2: $test2"
val test3 = test3()
if (test3 != "321OK") return "fail3: $test3"
val test4 = test4()
if (test4 != "OK456") return "fail4: $test4"
val test5 = test5()
if (test5 != "OK3") return "fail5: $test5"
val test6 = test6()
if (test6 != "OK137joo") return "fail6: $test6"
val test7 = test7()
if (test7 != "OKmer, nas73, 37") return "fail7: $test7"
val test8 = E<Int>().foo(56)
if (test8 != "OK56") return "fail8: $test8"
val test9 = F<Int>().foo(65, "hello")
if (test9 != "OK65hello") return "fail9: $test9"
val test10 = test10<Int>()
if (test10 != "OKnullabc") return "fail10: $test10"
val test11 = test11<Int>()
if (test11 != "OKnulldef") return "fail11: $test11"
return "OK"
}
@@ -44195,6 +44195,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFun.kt");
}
@Test
@TestMetadata("callableReferenceInlinedFunFromOtherModule.kt")
public void testCallableReferenceInlinedFunFromOtherModule() throws Exception {
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFunFromOtherModule.kt");
}
@Test
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
@@ -45617,6 +45617,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFun.kt");
}
@Test
@TestMetadata("callableReferenceInlinedFunFromOtherModule.kt")
public void testCallableReferenceInlinedFunFromOtherModule() throws Exception {
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFunFromOtherModule.kt");
}
@Test
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
@@ -35616,6 +35616,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFun.kt");
}
@TestMetadata("callableReferenceInlinedFunFromOtherModule.kt")
public void testCallableReferenceInlinedFunFromOtherModule() throws Exception {
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFunFromOtherModule.kt");
}
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
runTest("compiler/testData/codegen/box/reified/checkcast.kt");
@@ -33199,6 +33199,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFun.kt");
}
@Test
@TestMetadata("callableReferenceInlinedFunFromOtherModule.kt")
public void testCallableReferenceInlinedFunFromOtherModule() throws Exception {
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFunFromOtherModule.kt");
}
@Test
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
@@ -33367,6 +33367,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFun.kt");
}
@Test
@TestMetadata("callableReferenceInlinedFunFromOtherModule.kt")
public void testCallableReferenceInlinedFunFromOtherModule() throws Exception {
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFunFromOtherModule.kt");
}
@Test
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
@@ -29876,6 +29876,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFun.kt");
}
@TestMetadata("callableReferenceInlinedFunFromOtherModule.kt")
public void testCallableReferenceInlinedFunFromOtherModule() throws Exception {
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFunFromOtherModule.kt");
}
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
runTest("compiler/testData/codegen/box/reified/checkcast.kt");
@@ -2,7 +2,6 @@ package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.lower.StringConcatenationLowering
import org.jetbrains.kotlin.backend.common.lower.inline.FunctionInlining
import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesExtractionFromInlineFunctionsLowering
import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineFunctionsLowering
@@ -160,6 +159,12 @@ internal val extractLocalClassesFromInlineBodies = makeKonanFileOpPhase(
prerequisite = setOf(sharedVariablesPhase), // TODO: add "soft" dependency on inventNamesForLocalClasses
)
internal val wrapInlineDeclarationsWithReifiedTypeParametersLowering = makeKonanFileLoweringPhase(
::WrapInlineDeclarationsWithReifiedTypeParametersLowering,
name = "WrapInlineDeclarationsWithReifiedTypeParameters",
description = "Wrap inline declarations with reified type parameters"
)
internal val inlinePhase = makeKonanFileOpPhase(
{ context, irFile ->
irFile.acceptChildrenVoid(object : IrElementVisitorVoid {
@@ -252,6 +252,7 @@ internal val allLoweringsPhase = NamedCompilerPhase(
sharedVariablesPhase,
inventNamesForLocalClasses,
extractLocalClassesFromInlineBodies,
wrapInlineDeclarationsWithReifiedTypeParametersLowering,
inlinePhase,
provisionalFunctionExpressionPhase,
postInlinePhase,
@@ -74,6 +74,8 @@ internal class NativeInlineFunctionResolver(override val context: Context) : Def
LocalClassesExtractionFromInlineFunctionsLowering(context).lower(body, notLoweredFunction)
}
WrapInlineDeclarationsWithReifiedTypeParametersLowering(context).lower(body, notLoweredFunction)
return notLoweredFunction
}
@@ -36410,6 +36410,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFun.kt");
}
@Test
@TestMetadata("callableReferenceInlinedFunFromOtherModule.kt")
public void testCallableReferenceInlinedFunFromOtherModule() throws Exception {
runTest("compiler/testData/codegen/box/reified/callableReferenceInlinedFunFromOtherModule.kt");
}
@Test
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {