Properly process primitive receiver on inlining bound callable references

#KT-18728 Fixed
This commit is contained in:
Mikhael Bogdanov
2017-06-30 13:11:53 +02:00
parent fe17c4416e
commit 49252f6eec
17 changed files with 404 additions and 5 deletions
@@ -20,8 +20,7 @@ import com.intellij.psi.PsiElement
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
import org.jetbrains.kotlin.codegen.AsmUtil.*
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForSuspendCoroutineOrReturn
import org.jetbrains.kotlin.codegen.coroutines.isBuiltInSuspendCoroutineOrReturnInJvm
import org.jetbrains.kotlin.codegen.intrinsics.bytecode
@@ -657,7 +656,8 @@ class PsiInlineCodegen(
val receiver = getBoundCallableReferenceReceiver(argumentExpression)
if (receiver != null) {
putClosureParametersOnStack(lambdaInfo, codegen.gen(receiver))
val receiverValue = codegen.gen(receiver)
putClosureParametersOnStack(lambdaInfo, StackValue.coercion(receiverValue, receiverValue.type.boxReceiverForBoundReference()))
}
}
else {
@@ -105,6 +105,9 @@ class DefaultLambda(
override fun isMyLabel(name: String): Boolean = false
var originalBoundReceiverType: Type? = null
private set
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner) {
val classReader = buildClassReaderByInternalName(sourceCompiler.state, lambdaClassType.internalName)
var isPropertyReference = false
@@ -141,7 +144,8 @@ class DefaultLambda(
capturedVars =
if (isFunctionReference || isPropertyReference)
constructor?.desc?.let { Type.getArgumentTypes(it) }?.singleOrNull()?.let {
listOf(capturedParamDesc(AsmUtil.RECEIVER_NAME, it))
originalBoundReceiverType = it
listOf(capturedParamDesc(AsmUtil.RECEIVER_NAME, it.boxReceiverForBoundReference()))
} ?: emptyList()
else
constructor?.findCapturedFieldAssignmentInstructions()?.map {
@@ -169,6 +173,9 @@ class DefaultLambda(
}
}
fun Type.boxReceiverForBoundReference() = AsmUtil.boxType(this)
class ExpressionLambda(
expression: KtExpression,
private val typeMapper: KotlinTypeMapper,
@@ -237,7 +244,9 @@ class ExpressionLambda(
}
if (closure.captureReceiverType != null) {
val type = typeMapper.mapType(closure.captureReceiverType!!)
val type = typeMapper.mapType(closure.captureReceiverType!!).let {
if (isBoundCallableReference) it.boxReceiverForBoundReference() else it
}
val descriptor = EnclosedValueDescriptor(
AsmUtil.CAPTURED_RECEIVER_FIELD, null,
StackValue.field(type, lambdaClassType, AsmUtil.CAPTURED_RECEIVER_FIELD, false, StackValue.LOCAL_0),
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.ClosureCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
@@ -347,6 +348,10 @@ class MethodInliner(
val lambda = getLambdaIfExists(index) as DefaultLambda
lambda.parameterOffsetsInDefault.zip(lambda.capturedVars).asReversed().forEach {
(_, captured) ->
val originalBoundReceiverType = lambda.originalBoundReceiverType
if (lambda.isBoundCallableReference && AsmUtil.isPrimitive(originalBoundReceiverType)) {
StackValue.onStack(originalBoundReceiverType!!).put(captured.type, InstructionAdapter(this))
}
super.visitFieldInsn(
Opcodes.PUTSTATIC, captured.containingLambdaName, CAPTURED_FIELD_FOLD_PREFIX + captured.fieldName, captured.type.descriptor
)
@@ -0,0 +1,16 @@
// FILE: 1.kt
package test
inline fun <T, R> T.map(transform: (T) -> R): R {
return transform(this)
}
// FILE: 2.kt
import test.*
fun box(): String {
val result = 1.map(2::plus)
return if (result == 3) "OK" else "fail $result"
}
@@ -0,0 +1,16 @@
// FILE: 1.kt
package test
inline fun <T, R> T.map(transform: (T) -> R): R {
return transform(this)
}
// FILE: 2.kt
import test.*
fun box(): String {
val result = 1.map(3L::plus)
return if (result == 4L) "OK" else "fail $result"
}
@@ -0,0 +1,19 @@
// FILE: 1.kt
package test
inline fun <R> map(transform: () -> R): R {
return transform()
}
// FILE: 2.kt
import test.*
val Int.myInc
get() = this + 1
fun box(): String {
val result = map(2::myInc)
return if (result == 3) "OK" else "fail $result"
}
@@ -0,0 +1,18 @@
// FILE: 1.kt
package test
inline fun <R> map(transform: () -> R): R {
return transform()
}
// FILE: 2.kt
import test.*
val Long.myInc
get() = this + 1
fun box(): String {
val result = map(2L::myInc)
return if (result == 3L) "OK" else "fail $result"
}
@@ -0,0 +1,17 @@
// FILE: 1.kt
// LANGUAGE_VERSION: 1.2
// SKIP_INLINE_CHECK_IN: inlineFun$default
package test
inline fun inlineFun(a: Int, lambda: (Int) -> Int = 1::plus): Int {
return lambda(a)
}
// FILE: 2.kt
import test.*
fun box(): String {
val result = inlineFun(2)
return if (result == 3) return "OK" else "fail $result"
}
@@ -0,0 +1,17 @@
// FILE: 1.kt
// LANGUAGE_VERSION: 1.2
// SKIP_INLINE_CHECK_IN: inlineFun$default
package test
inline fun inlineFun(a: Int, lambda: (Int) -> Int = 1::plus): Int {
return lambda(a)
}
// FILE: 2.kt
import test.*
fun box(): String {
val result = inlineFun(2)
return if (result == 3) return "OK" else "fail $result"
}
@@ -0,0 +1,21 @@
// FILE: 1.kt
// LANGUAGE_VERSION: 1.2
// SKIP_INLINE_CHECK_IN: inlineFun$default
package test
val Int.myInc
get() = this + 1
inline fun inlineFun(lambda: () -> Int = 1::myInc): Int {
return lambda()
}
// FILE: 2.kt
import test.*
fun box(): String {
val result = inlineFun()
return if (result == 2) return "OK" else "fail $result"
}
@@ -0,0 +1,21 @@
// FILE: 1.kt
// LANGUAGE_VERSION: 1.2
// SKIP_INLINE_CHECK_IN: inlineFun$default
package test
val Long.myInc
get() = this + 1
inline fun inlineFun(lambda: () -> Long = 1L::myInc): Long {
return lambda()
}
// FILE: 2.kt
import test.*
fun box(): String {
val result = inlineFun()
return if (result == 2L) return "OK" else "fail $result"
}
@@ -736,6 +736,30 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
doTest(fileName);
}
@TestMetadata("kt18728.kt")
public void testKt18728() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728.kt");
doTest(fileName);
}
@TestMetadata("kt18728_2.kt")
public void testKt18728_2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_2.kt");
doTest(fileName);
}
@TestMetadata("kt18728_3.kt")
public void testKt18728_3() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_3.kt");
doTest(fileName);
}
@TestMetadata("kt18728_4.kt")
public void testKt18728_4() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_4.kt");
doTest(fileName);
}
@TestMetadata("map.kt")
public void testMap() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/map.kt");
@@ -1161,12 +1185,36 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
doTest(fileName);
}
@TestMetadata("boundFunctionReferenceOnInt.kt")
public void testBoundFunctionReferenceOnInt() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReferenceOnInt.kt");
doTest(fileName);
}
@TestMetadata("boundFunctionReferenceOnLong.kt")
public void testBoundFunctionReferenceOnLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReferenceOnLong.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReference.kt")
public void testBoundPropertyReference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReference.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReferenceOnInt.kt")
public void testBoundPropertyReferenceOnInt() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnInt.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReferenceOnLong.kt")
public void testBoundPropertyReferenceOnLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnLong.kt");
doTest(fileName);
}
@TestMetadata("constuctorReference.kt")
public void testConstuctorReference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/constuctorReference.kt");
@@ -736,6 +736,30 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
doTest(fileName);
}
@TestMetadata("kt18728.kt")
public void testKt18728() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728.kt");
doTest(fileName);
}
@TestMetadata("kt18728_2.kt")
public void testKt18728_2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_2.kt");
doTest(fileName);
}
@TestMetadata("kt18728_3.kt")
public void testKt18728_3() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_3.kt");
doTest(fileName);
}
@TestMetadata("kt18728_4.kt")
public void testKt18728_4() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_4.kt");
doTest(fileName);
}
@TestMetadata("map.kt")
public void testMap() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/map.kt");
@@ -1161,12 +1185,36 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
doTest(fileName);
}
@TestMetadata("boundFunctionReferenceOnInt.kt")
public void testBoundFunctionReferenceOnInt() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReferenceOnInt.kt");
doTest(fileName);
}
@TestMetadata("boundFunctionReferenceOnLong.kt")
public void testBoundFunctionReferenceOnLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReferenceOnLong.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReference.kt")
public void testBoundPropertyReference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReference.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReferenceOnInt.kt")
public void testBoundPropertyReferenceOnInt() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnInt.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReferenceOnLong.kt")
public void testBoundPropertyReferenceOnLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnLong.kt");
doTest(fileName);
}
@TestMetadata("constuctorReference.kt")
public void testConstuctorReference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/constuctorReference.kt");
@@ -736,6 +736,30 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
doTest(fileName);
}
@TestMetadata("kt18728.kt")
public void testKt18728() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728.kt");
doTest(fileName);
}
@TestMetadata("kt18728_2.kt")
public void testKt18728_2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_2.kt");
doTest(fileName);
}
@TestMetadata("kt18728_3.kt")
public void testKt18728_3() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_3.kt");
doTest(fileName);
}
@TestMetadata("kt18728_4.kt")
public void testKt18728_4() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_4.kt");
doTest(fileName);
}
@TestMetadata("map.kt")
public void testMap() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/map.kt");
@@ -1161,12 +1185,36 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
doTest(fileName);
}
@TestMetadata("boundFunctionReferenceOnInt.kt")
public void testBoundFunctionReferenceOnInt() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReferenceOnInt.kt");
doTest(fileName);
}
@TestMetadata("boundFunctionReferenceOnLong.kt")
public void testBoundFunctionReferenceOnLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReferenceOnLong.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReference.kt")
public void testBoundPropertyReference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReference.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReferenceOnInt.kt")
public void testBoundPropertyReferenceOnInt() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnInt.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReferenceOnLong.kt")
public void testBoundPropertyReferenceOnLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnLong.kt");
doTest(fileName);
}
@TestMetadata("constuctorReference.kt")
public void testConstuctorReference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/constuctorReference.kt");
@@ -736,6 +736,30 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
doTest(fileName);
}
@TestMetadata("kt18728.kt")
public void testKt18728() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728.kt");
doTest(fileName);
}
@TestMetadata("kt18728_2.kt")
public void testKt18728_2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_2.kt");
doTest(fileName);
}
@TestMetadata("kt18728_3.kt")
public void testKt18728_3() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_3.kt");
doTest(fileName);
}
@TestMetadata("kt18728_4.kt")
public void testKt18728_4() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_4.kt");
doTest(fileName);
}
@TestMetadata("map.kt")
public void testMap() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/map.kt");
@@ -1161,12 +1185,36 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
doTest(fileName);
}
@TestMetadata("boundFunctionReferenceOnInt.kt")
public void testBoundFunctionReferenceOnInt() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReferenceOnInt.kt");
doTest(fileName);
}
@TestMetadata("boundFunctionReferenceOnLong.kt")
public void testBoundFunctionReferenceOnLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReferenceOnLong.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReference.kt")
public void testBoundPropertyReference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReference.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReferenceOnInt.kt")
public void testBoundPropertyReferenceOnInt() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnInt.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReferenceOnLong.kt")
public void testBoundPropertyReferenceOnLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnLong.kt");
doTest(fileName);
}
@TestMetadata("constuctorReference.kt")
public void testConstuctorReference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/constuctorReference.kt");
@@ -140,6 +140,30 @@ public class CallableReferenceInlineTestsGenerated extends AbstractCallableRefer
doTest(fileName);
}
@TestMetadata("kt18728.kt")
public void testKt18728() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728.kt");
doTest(fileName);
}
@TestMetadata("kt18728_2.kt")
public void testKt18728_2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_2.kt");
doTest(fileName);
}
@TestMetadata("kt18728_3.kt")
public void testKt18728_3() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_3.kt");
doTest(fileName);
}
@TestMetadata("kt18728_4.kt")
public void testKt18728_4() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/kt18728_4.kt");
doTest(fileName);
}
@TestMetadata("map.kt")
public void testMap() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/map.kt");
@@ -274,12 +274,36 @@ public class InlineDefaultValuesTestsGenerated extends AbstractInlineDefaultValu
doTest(fileName);
}
@TestMetadata("boundFunctionReferenceOnInt.kt")
public void testBoundFunctionReferenceOnInt() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReferenceOnInt.kt");
doTest(fileName);
}
@TestMetadata("boundFunctionReferenceOnLong.kt")
public void testBoundFunctionReferenceOnLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReferenceOnLong.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReference.kt")
public void testBoundPropertyReference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReference.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReferenceOnInt.kt")
public void testBoundPropertyReferenceOnInt() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnInt.kt");
doTest(fileName);
}
@TestMetadata("boundPropertyReferenceOnLong.kt")
public void testBoundPropertyReferenceOnLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnLong.kt");
doTest(fileName);
}
@TestMetadata("constuctorReference.kt")
public void testConstuctorReference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/constuctorReference.kt");