Obtain reification marker on default lambda extraction.
Add reification tests.
This commit is contained in:
@@ -522,7 +522,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
private void generateClosuresBodies() {
|
||||
for (LambdaInfo info : expressionMap.values()) {
|
||||
info.generateLambdaBody(codegen);
|
||||
info.generateLambdaBody(codegen, reifiedTypeInliner);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean, @JvmField val is
|
||||
|
||||
lateinit var node: SMAPAndMethodNode
|
||||
|
||||
abstract fun generateLambdaBody(codegen: ExpressionCodegen)
|
||||
abstract fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner)
|
||||
|
||||
fun addAllParameters(remapper: FieldRemapper): Parameters {
|
||||
val builder = ParametersBuilder.initializeBuilderFrom(AsmTypes.OBJECT_TYPE, invokeMethod.descriptor, this)
|
||||
@@ -81,7 +81,8 @@ class DefaultLambda(
|
||||
override val lambdaClassType: Type,
|
||||
val capturedArgs: Array<Type>,
|
||||
val parameterDescriptor: ValueParameterDescriptor,
|
||||
val offset: Int
|
||||
val offset: Int,
|
||||
val needReification: Boolean
|
||||
) : LambdaInfo(parameterDescriptor.isCrossinline, false) {
|
||||
|
||||
val parameterOffsetsInDefault: MutableList<Int> = arrayListOf()
|
||||
@@ -99,7 +100,7 @@ class DefaultLambda(
|
||||
|
||||
override fun isMyLabel(name: String): Boolean = false
|
||||
|
||||
override fun generateLambdaBody(codegen: ExpressionCodegen) {
|
||||
override fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) {
|
||||
val classReader = InlineCodegenUtil.buildClassReaderByInternalName(codegen.state, lambdaClassType.internalName)
|
||||
|
||||
val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
|
||||
@@ -129,6 +130,11 @@ class DefaultLambda(
|
||||
invokeMethod.name,
|
||||
invokeMethod.descriptor,
|
||||
lambdaClassType.internalName)!!
|
||||
|
||||
if (needReification) {
|
||||
//nested classes could also require reification
|
||||
reifiedTypeInliner.reifyInstructions(node.node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +229,7 @@ class ExpressionLambda(
|
||||
val isPropertyReference: Boolean
|
||||
get() = propertyReferenceInfo != null
|
||||
|
||||
override fun generateLambdaBody(codegen: ExpressionCodegen) {
|
||||
override fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) {
|
||||
val closureContext =
|
||||
if (isPropertyReference)
|
||||
codegen.getContext().intoAnonymousClass(classDescriptor, codegen, OwnerKind.IMPLEMENTATION)
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.DEFAULT_LAMBDA_FAKE_CALL
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.getConstant
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.isNeedClassReificationMarker
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.insnText
|
||||
@@ -153,7 +154,7 @@ private fun extractDefaultLambdasInfo(
|
||||
instanceInstuction = instanceInstuction.previous
|
||||
}
|
||||
|
||||
val (owner, argTypes) = when (instanceInstuction) {
|
||||
val (owner, argTypes, needReification) = when (instanceInstuction) {
|
||||
is MethodInsnNode -> {
|
||||
assert(instanceInstuction.name == "<init>") { "Expected constructor call for default lambda, but $instanceInstuction" }
|
||||
val ownerInternalName = instanceInstuction.owner
|
||||
@@ -170,20 +171,23 @@ private fun extractDefaultLambdasInfo(
|
||||
addAll(InsnSequence(instanceInstuction, varAssignmentInstruction.next).toList())
|
||||
}
|
||||
|
||||
Type.getObjectType(instanceInstuction.owner) to Type.getArgumentTypes(instanceInstuction.desc)
|
||||
val needReification = instanceCreation.previous.takeIf { isNeedClassReificationMarker(it) }?.let { toDelete.add(it) } != null
|
||||
Triple(Type.getObjectType(instanceInstuction.owner), Type.getArgumentTypes(instanceInstuction.desc), needReification)
|
||||
}
|
||||
|
||||
is FieldInsnNode -> {
|
||||
toDelete.addAll(InsnSequence(instanceInstuction, varAssignmentInstruction.next).toList())
|
||||
|
||||
Type.getObjectType(instanceInstuction.owner) to emptyArray<Type>()
|
||||
val needReification = instanceInstuction.previous.takeIf { isNeedClassReificationMarker(it) }?.let { toDelete.add(it) } != null
|
||||
|
||||
Triple(Type.getObjectType(instanceInstuction.owner), emptyArray<Type>(), needReification)
|
||||
}
|
||||
else -> throw RuntimeException("Can't extract default lambda info $it.\n Unknown instruction: ${instanceInstuction.insnText}")
|
||||
}
|
||||
|
||||
toInsert.add(varAssignmentInstruction to defaultLambdaFakeCallStub(argTypes, it.varIndex))
|
||||
|
||||
DefaultLambda(owner, argTypes, defaultLambdas[it.varIndex]!!, it.varIndex)
|
||||
DefaultLambda(owner, argTypes, defaultLambdas[it.varIndex]!!, it.varIndex, needReification)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
//WITH_RUNTIME
|
||||
package test
|
||||
|
||||
class OK
|
||||
class FAIL
|
||||
|
||||
@Suppress("NOT_YET_SUPPORTED_IN_INLINE")
|
||||
inline fun <reified T> inlineFun(lambda: () -> String = { T::class.java.simpleName }): String {
|
||||
return lambda()
|
||||
}
|
||||
|
||||
inline fun <reified T> inlineFun2(): String {
|
||||
return inlineFun<OK>()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun2<FAIL>()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
//WITH_RUNTIME
|
||||
package test
|
||||
|
||||
@Suppress("NOT_YET_SUPPORTED_IN_INLINE")
|
||||
inline fun <reified T> inlineFun(p: String, lambda: () -> String = { { p + T::class.java.simpleName } () }): String {
|
||||
return lambda()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
class K
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun<OK>("O")
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
//WITH_RUNTIME
|
||||
package test
|
||||
|
||||
@Suppress("NOT_YET_SUPPORTED_IN_INLINE")
|
||||
inline fun <reified T> inlineFun(p: String, crossinline lambda: () -> String = { { p + T::class.java.simpleName } () }): String {
|
||||
return {
|
||||
lambda()
|
||||
} ()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
class OK
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun<OK>()
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
//WITH_RUNTIME
|
||||
package test
|
||||
|
||||
@Suppress("NOT_YET_SUPPORTED_IN_INLINE")
|
||||
inline fun <reified T> inlineFun(crossinline lambda: () -> String = { { T::class.java.simpleName } () }): String {
|
||||
return {
|
||||
lambda()
|
||||
} ()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
class OK
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun<OK>()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
//WITH_RUNTIME
|
||||
package test
|
||||
|
||||
@Suppress("NOT_YET_SUPPORTED_IN_INLINE")
|
||||
inline fun <reified T> inlineFun(lambda: () -> String = { { T::class.java.simpleName } () }): String {
|
||||
return lambda()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
class OK
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun<OK>()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
//WITH_RUNTIME
|
||||
package test
|
||||
|
||||
@Suppress("NOT_YET_SUPPORTED_IN_INLINE")
|
||||
inline fun <reified T> inlineFun(lambda: () -> String = { T::class.java.simpleName }): String {
|
||||
return lambda()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
class OK
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun<OK>()
|
||||
}
|
||||
@@ -2141,6 +2141,51 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class DefaultLambda extends AbstractBlackBoxInlineCodegenTest {
|
||||
public void testAllFilesPresentInDefaultLambda() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/reified/defaultLambda"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("chain.kt")
|
||||
public void testChain() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/chain.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/nested.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nested2.kt")
|
||||
public void testNested2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/nested2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nested2Static.kt")
|
||||
public void testNested2Static() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/nested2Static.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nestedStatic.kt")
|
||||
public void testNestedStatic() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/nestedStatic.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/simple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/reified/isCheck")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+45
@@ -2141,6 +2141,51 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class DefaultLambda extends AbstractCompileKotlinAgainstInlineKotlinTest {
|
||||
public void testAllFilesPresentInDefaultLambda() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/reified/defaultLambda"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("chain.kt")
|
||||
public void testChain() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/chain.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/nested.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nested2.kt")
|
||||
public void testNested2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/nested2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nested2Static.kt")
|
||||
public void testNested2Static() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/nested2Static.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nestedStatic.kt")
|
||||
public void testNestedStatic() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/nestedStatic.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/simple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/reified/isCheck")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user