JVM_IR KT-45103 optimize direct invoke for lambdas and callable refs

This commit is contained in:
Dmitry Petrov
2021-04-26 17:17:25 +03:00
committed by teamcityserver
parent bfb1a06f3d
commit 851980e36f
124 changed files with 1340 additions and 324 deletions
@@ -14171,6 +14171,76 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
} }
} }
@Nested
@TestMetadata("compiler/testData/codegen/box/directInvokeOptimization")
@TestDataPath("$PROJECT_ROOT")
public class DirectInvokeOptimization {
@Test
public void testAllFilesPresentInDirectInvokeOptimization() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/directInvokeOptimization"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("boundInnerContructorRef.kt")
public void testBoundInnerContructorRef() throws Exception {
runTest("compiler/testData/codegen/box/directInvokeOptimization/boundInnerContructorRef.kt");
}
@Test
@TestMetadata("boundMemberRef.kt")
public void testBoundMemberRef() throws Exception {
runTest("compiler/testData/codegen/box/directInvokeOptimization/boundMemberRef.kt");
}
@Test
@TestMetadata("capturingLambda.kt")
public void testCapturingLambda() throws Exception {
runTest("compiler/testData/codegen/box/directInvokeOptimization/capturingLambda.kt");
}
@Test
@TestMetadata("contructorRef.kt")
public void testContructorRef() throws Exception {
runTest("compiler/testData/codegen/box/directInvokeOptimization/contructorRef.kt");
}
@Test
@TestMetadata("nestedLambdas.kt")
public void testNestedLambdas() throws Exception {
runTest("compiler/testData/codegen/box/directInvokeOptimization/nestedLambdas.kt");
}
@Test
@TestMetadata("simpleAnonymousFun.kt")
public void testSimpleAnonymousFun() throws Exception {
runTest("compiler/testData/codegen/box/directInvokeOptimization/simpleAnonymousFun.kt");
}
@Test
@TestMetadata("simpleFunRef.kt")
public void testSimpleFunRef() throws Exception {
runTest("compiler/testData/codegen/box/directInvokeOptimization/simpleFunRef.kt");
}
@Test
@TestMetadata("simpleLambda.kt")
public void testSimpleLambda() throws Exception {
runTest("compiler/testData/codegen/box/directInvokeOptimization/simpleLambda.kt");
}
@Test
@TestMetadata("unboundInnerContructorRef.kt")
public void testUnboundInnerContructorRef() throws Exception {
runTest("compiler/testData/codegen/box/directInvokeOptimization/unboundInnerContructorRef.kt");
}
@Test
@TestMetadata("unboundMemberRef.kt")
public void testUnboundMemberRef() throws Exception {
runTest("compiler/testData/codegen/box/directInvokeOptimization/unboundMemberRef.kt");
}
}
@Nested @Nested
@TestMetadata("compiler/testData/codegen/box/elvis") @TestMetadata("compiler/testData/codegen/box/elvis")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ir.* import org.jetbrains.kotlin.backend.common.ir.*
import org.jetbrains.kotlin.backend.common.lower.SamEqualsHashCodeMethodsGenerator import org.jetbrains.kotlin.backend.common.lower.SamEqualsHashCodeMethodsGenerator
import org.jetbrains.kotlin.backend.common.lower.parents
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
@@ -27,10 +28,7 @@ import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
@@ -38,6 +36,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.util.OperatorNameConventions
internal val functionReferencePhase = makeIrFilePhase( internal val functionReferencePhase = makeIrFilePhase(
::FunctionReferenceLowering, ::FunctionReferenceLowering,
@@ -113,6 +112,104 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
return FunctionReferenceBuilder(reference).build() return FunctionReferenceBuilder(reference).build()
} }
override fun visitCall(expression: IrCall): IrExpression {
if (expression.symbol.owner.isInvokeOperator()) {
when (val receiver = expression.dispatchReceiver) {
is IrFunctionReference -> {
rewriteDirectInvokeToFunctionReference(expression, receiver)?.let {
it.transformChildrenVoid()
return it
}
}
is IrBlock -> {
val last = receiver.statements.last()
if (last is IrFunctionReference) {
rewriteDirectInvokeToLambda(expression, receiver, last)?.let {
it.transformChildrenVoid()
return it
}
}
}
}
}
expression.transformChildrenVoid(this)
return expression
}
private fun IrFunction.isInvokeOperator(): Boolean {
// For now, it's enough to check that the function name is 'invoke',
// because later we are looking at the dispatch receiver and check whether it's a function reference
// or a block returning a function reference.
return name == OperatorNameConventions.INVOKE
}
private fun rewriteDirectInvokeToLambda(irInvokeCall: IrCall, irBlock: IrBlock, lastFunRef: IrFunctionReference): IrExpression? {
val callee = lastFunRef.symbol.owner
if (callee.origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA && !callee.isAnonymousFunction)
return null
if (callee.parents.any { it is IrSimpleFunction && it.isInline }) {
// TODO investigate why inliner gets confused when we pass it a function with some optimized direct invoke.
return null
}
val irDirectCall = rewriteDirectInvokeToFunctionReference(irInvokeCall, lastFunRef)
?: return null
val newBlock = IrBlockImpl(irBlock.startOffset, irBlock.endOffset, irDirectCall.type)
newBlock.statements.addAll(irBlock.statements)
newBlock.statements[newBlock.statements.lastIndex] = irDirectCall
return newBlock
}
private fun rewriteDirectInvokeToFunctionReference(irInvokeCall: IrCall, irFunRef: IrFunctionReference): IrExpression? {
// TODO deal with type parameters somehow?
// It seems we can't encounter them in the code written by user,
// but this might be important later if we actually perform inlining and optimizations on IR.
return when (val irFun = irFunRef.symbol.owner) {
is IrSimpleFunction -> {
if (irFun.typeParameters.isNotEmpty()) return null
IrCallImpl(
irInvokeCall.startOffset, irInvokeCall.endOffset, irInvokeCall.type,
irFun.symbol,
typeArgumentsCount = irFun.typeParameters.size, valueArgumentsCount = irFun.valueParameters.size
).apply {
copyReceiverAndValueArgumentsForDirectInvoke(irFunRef, irInvokeCall)
}
}
is IrConstructor ->
IrConstructorCallImpl(
irInvokeCall.startOffset, irInvokeCall.endOffset, irInvokeCall.type,
irFun.symbol,
typeArgumentsCount = irFun.typeParameters.size,
constructorTypeArgumentsCount = 0,
valueArgumentsCount = irFun.valueParameters.size
).apply {
copyReceiverAndValueArgumentsForDirectInvoke(irFunRef, irInvokeCall)
}
else ->
throw AssertionError("Simple function or constructor expected: ${irFun.render()}")
}
}
private fun IrFunctionAccessExpression.copyReceiverAndValueArgumentsForDirectInvoke(
irFunRef: IrFunctionReference,
irInvokeCall: IrFunctionAccessExpression
) {
val irFun = irFunRef.symbol.owner
var invokeArgIndex = 0
if (irFun.dispatchReceiverParameter != null) {
dispatchReceiver = irFunRef.dispatchReceiver ?: irInvokeCall.getValueArgument(invokeArgIndex++)
}
if (irFun.extensionReceiverParameter != null) {
extensionReceiver = irFunRef.extensionReceiver ?: irInvokeCall.getValueArgument(invokeArgIndex++)
}
if (invokeArgIndex + valueArgumentsCount != irInvokeCall.valueArgumentsCount) {
throw AssertionError("Mismatching value arguments: $invokeArgIndex arguments used for receivers\n${irInvokeCall.dump()}")
}
for (i in 0 until valueArgumentsCount) {
putValueArgument(i, irInvokeCall.getValueArgument(invokeArgIndex++))
}
}
private fun wrapLambdaReferenceWithIndySamConversion( private fun wrapLambdaReferenceWithIndySamConversion(
expression: IrBlock, expression: IrBlock,
reference: IrFunctionReference, reference: IrFunctionReference,
@@ -131,6 +131,8 @@ val IrDeclaration.isTopLevelDeclaration get() =
val IrDeclaration.isAnonymousObject get() = this is IrClass && name == SpecialNames.NO_NAME_PROVIDED val IrDeclaration.isAnonymousObject get() = this is IrClass && name == SpecialNames.NO_NAME_PROVIDED
val IrDeclaration.isAnonymousFunction get() = this is IrSimpleFunction && name == SpecialNames.NO_NAME_PROVIDED
val IrDeclaration.isLocal: Boolean val IrDeclaration.isLocal: Boolean
get() { get() {
var current: IrElement = this var current: IrElement = this
@@ -0,0 +1,8 @@
public final class A /* p.A*/ {
public A(int);// .ctor(int)
public final int getProperty();// getProperty()
public final void memberFun();// memberFun()
}
+25
View File
@@ -0,0 +1,25 @@
// p.A
package p
class A {
init {
fun localFunInInit() {}
}
constructor(x: Int) {
fun localFunInConstructor() {}
}
fun memberFun() {
fun localFunInMemberFun() {}
}
val property: Int
get() {
fun localFunInPropertyAccessor() {}
return 1
}
}
// FIR_COMPARISON
@@ -1,6 +1,7 @@
class A { fun <T> eval(f: () -> T) = f()
private var foo = 1; class A {
private var foo = 1
fun `access$getFoo$p`(a: A): Int = 1 fun `access$getFoo$p`(a: A): Int = 1
fun `access$setFoo$p`(a: A, d: Int) {} fun `access$setFoo$p`(a: A, d: Int) {}
@@ -21,10 +22,10 @@ class A {
get() = field get() = field
fun test() { fun test() {
{ eval {
foo = 2; foo = 2
foo foo
}() }
} }
fun `access$getFoo$p`(p: A.Companion): Int = 1 fun `access$getFoo$p`(p: A.Companion): Int = 1
@@ -32,9 +33,9 @@ class A {
} }
fun test() { fun test() {
{ eval {
foo = 2; foo = 2;
foo + bar foo + bar
}() }
} }
} }
@@ -1,39 +1,39 @@
compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:1:7: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo$p(LA;)I): compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:3:7: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo$p(LA;)I):
fun `access$getFoo$p`(`$this`: A): Int defined in A fun `access$getFoo$p`(`$this`: A): Int defined in A
fun `access$getFoo$p`(a: A): Int defined in A fun `access$getFoo$p`(a: A): Int defined in A
class A { class A {
^ ^
compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:1:7: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo$p(LA;I)V): compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:3:7: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo$p(LA;I)V):
fun `access$setFoo$p`(`$this`: A, `<set-?>`: Int): Unit defined in A fun `access$setFoo$p`(`$this`: A, `<set-?>`: Int): Unit defined in A
fun `access$setFoo$p`(a: A, d: Int): Unit defined in A fun `access$setFoo$p`(a: A, d: Int): Unit defined in A
class A { class A {
^ ^
compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:1:7: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo$cp()I): compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:3:7: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo$cp()I):
fun `access$getFoo$cp`(): Int defined in A fun `access$getFoo$cp`(): Int defined in A
fun `access$getFoo$cp`(): Int defined in A fun `access$getFoo$cp`(): Int defined in A
class A { class A {
^ ^
compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:1:7: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo$cp(I)V): compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:3:7: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo$cp(I)V):
fun `access$setFoo$cp`(`<set-?>`: Int): Unit defined in A fun `access$setFoo$cp`(`<set-?>`: Int): Unit defined in A
fun `access$setFoo$cp`(d: Int): Unit defined in A fun `access$setFoo$cp`(d: Int): Unit defined in A
class A { class A {
^ ^
compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:5:5: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo$p(LA;)I): compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:6:5: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo$p(LA;)I):
fun `access$getFoo$p`(`$this`: A): Int defined in A fun `access$getFoo$p`(`$this`: A): Int defined in A
fun `access$getFoo$p`(a: A): Int defined in A fun `access$getFoo$p`(a: A): Int defined in A
fun `access$getFoo$p`(a: A): Int = 1 fun `access$getFoo$p`(a: A): Int = 1
^ ^
compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:6:5: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo$p(LA;I)V): compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:7:5: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo$p(LA;I)V):
fun `access$setFoo$p`(`$this`: A, `<set-?>`: Int): Unit defined in A fun `access$setFoo$p`(`$this`: A, `<set-?>`: Int): Unit defined in A
fun `access$setFoo$p`(a: A, d: Int): Unit defined in A fun `access$setFoo$p`(a: A, d: Int): Unit defined in A
fun `access$setFoo$p`(a: A, d: Int) {} fun `access$setFoo$p`(a: A, d: Int) {}
^ ^
compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:9:5: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo$cp()I): compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:10:5: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo$cp()I):
fun `access$getFoo$cp`(): Int defined in A fun `access$getFoo$cp`(): Int defined in A
fun `access$getFoo$cp`(): Int defined in A fun `access$getFoo$cp`(): Int defined in A
fun `access$getFoo$cp`(): Int = 1 fun `access$getFoo$cp`(): Int = 1
^ ^
compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:10:5: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo$cp(I)V): compiler/testData/cli/jvm/syntheticAccessorForPropertiesSignatureClash.kt:11:5: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo$cp(I)V):
fun `access$setFoo$cp`(`<set-?>`: Int): Unit defined in A fun `access$setFoo$cp`(`<set-?>`: Int): Unit defined in A
fun `access$setFoo$cp`(d: Int): Unit defined in A fun `access$setFoo$cp`(d: Int): Unit defined in A
fun `access$setFoo$cp`(d: Int) {} fun `access$setFoo$cp`(d: Int) {}
@@ -1,25 +1,25 @@
class A { fun <T> eval(f: () -> T) = f()
private var foo = 1; class A {
private var foo = 1
fun `access$getFoo$p`(a: A): Int = 1 fun `access$getFoo$p`(a: A): Int = 1
fun `access$setFoo$p`(a: A, d: Int) {} fun `access$setFoo$p`(a: A, d: Int) {}
private fun getFoo() = 1; private fun getFoo() = 1
private fun setFoo(i: Int) {} private fun setFoo(i: Int) {}
fun `access$getFoo`(a: A): Int = 1 fun `access$getFoo`(a: A): Int = 1
fun `access$setFoo`(a: A, d: Int) {} fun `access$setFoo`(a: A, d: Int) {}
fun test() { fun test() {
{ eval {
foo = 2; foo = 2
foo foo
}(); }
eval {
{
setFoo(2) setFoo(2)
getFoo(); getFoo()
}() }
} }
} }
@@ -1,39 +1,39 @@
compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:1:7: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo$p(LA;)I): compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:3:7: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo$p(LA;)I):
fun `access$getFoo$p`(`$this`: A): Int defined in A fun `access$getFoo$p`(`$this`: A): Int defined in A
fun `access$getFoo$p`(a: A): Int defined in A fun `access$getFoo$p`(a: A): Int defined in A
class A { class A {
^ ^
compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:1:7: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo$p(LA;I)V): compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:3:7: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo$p(LA;I)V):
fun `access$setFoo$p`(`$this`: A, `<set-?>`: Int): Unit defined in A fun `access$setFoo$p`(`$this`: A, `<set-?>`: Int): Unit defined in A
fun `access$setFoo$p`(a: A, d: Int): Unit defined in A fun `access$setFoo$p`(a: A, d: Int): Unit defined in A
class A { class A {
^ ^
compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:1:7: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo(LA;)I): compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:3:7: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo(LA;)I):
fun `access$getFoo`(`$this`: A): Int defined in A fun `access$getFoo`(`$this`: A): Int defined in A
fun `access$getFoo`(a: A): Int defined in A fun `access$getFoo`(a: A): Int defined in A
class A { class A {
^ ^
compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:1:7: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo(LA;I)V): compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:3:7: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo(LA;I)V):
fun `access$setFoo`(`$this`: A, i: Int): Unit defined in A fun `access$setFoo`(`$this`: A, i: Int): Unit defined in A
fun `access$setFoo`(a: A, d: Int): Unit defined in A fun `access$setFoo`(a: A, d: Int): Unit defined in A
class A { class A {
^ ^
compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:5:5: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo$p(LA;)I): compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:6:5: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo$p(LA;)I):
fun `access$getFoo$p`(`$this`: A): Int defined in A fun `access$getFoo$p`(`$this`: A): Int defined in A
fun `access$getFoo$p`(a: A): Int defined in A fun `access$getFoo$p`(a: A): Int defined in A
fun `access$getFoo$p`(a: A): Int = 1 fun `access$getFoo$p`(a: A): Int = 1
^ ^
compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:6:5: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo$p(LA;I)V): compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:7:5: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo$p(LA;I)V):
fun `access$setFoo$p`(`$this`: A, `<set-?>`: Int): Unit defined in A fun `access$setFoo$p`(`$this`: A, `<set-?>`: Int): Unit defined in A
fun `access$setFoo$p`(a: A, d: Int): Unit defined in A fun `access$setFoo$p`(a: A, d: Int): Unit defined in A
fun `access$setFoo$p`(a: A, d: Int) {} fun `access$setFoo$p`(a: A, d: Int) {}
^ ^
compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:11:5: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo(LA;)I): compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:12:5: error: platform declaration clash: The following declarations have the same JVM signature (access$getFoo(LA;)I):
fun `access$getFoo`(`$this`: A): Int defined in A fun `access$getFoo`(`$this`: A): Int defined in A
fun `access$getFoo`(a: A): Int defined in A fun `access$getFoo`(a: A): Int defined in A
fun `access$getFoo`(a: A): Int = 1 fun `access$getFoo`(a: A): Int = 1
^ ^
compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:12:5: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo(LA;I)V): compiler/testData/cli/jvm/syntheticAccessorPropertyAndFunSignatureClash.kt:13:5: error: platform declaration clash: The following declarations have the same JVM signature (access$setFoo(LA;I)V):
fun `access$setFoo`(`$this`: A, i: Int): Unit defined in A fun `access$setFoo`(`$this`: A, i: Int): Unit defined in A
fun `access$setFoo`(a: A, d: Int): Unit defined in A fun `access$setFoo`(a: A, d: Int): Unit defined in A
fun `access$setFoo`(a: A, d: Int) {} fun `access$setFoo`(a: A, d: Int) {}
@@ -26,4 +26,8 @@ class Kotlin {
fun foo4() = { foo2() }() fun foo4() = { foo2() }()
fun foo5() {
val lambda = { foo2() }
lambda()
}
} }
@@ -1,5 +1,5 @@
Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function0<Ljava/lang/String;>; Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function0<Ljava/lang/String;>;
final class foo/Kotlin$foo4$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 { final class foo/Kotlin$foo5$lambda$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
final foo.Kotlin this$0 final foo.Kotlin this$0
void <init>(foo.Kotlin $receiver) void <init>(foo.Kotlin $receiver)
@@ -29,6 +29,12 @@ public final class foo/Kotlin : java/lang/Object {
@Lorg/jetbrains/annotations/NotNull;([]) // invisible @Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null @Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible @Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
private final static java.lang.String foo4$lambda-0(foo.Kotlin this$0)
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
public final void foo5()
} }
public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation { public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation {
+4 -1
View File
@@ -4,7 +4,10 @@ fun Array<String>.test1(): Array<String> {
} }
fun Array<String>.test1Nested(): Array<String> { fun Array<String>.test1Nested(): Array<String> {
val func = { i: Int -> { this }()} val func = { i: Int ->
val lam = { this }
lam()
}
return func(1) return func(1)
} }
@@ -3,10 +3,12 @@ class C(val i: Int) {
operator fun component2() = i + 2 operator fun component2() = i + 2
} }
fun <T> eval(fn: () -> T) = fn()
fun doTest(l : Array<C>): String { fun doTest(l : Array<C>): String {
var s = "" var s = ""
for ((a, b) in l) { for ((a, b) in l) {
s += {"$a:$b;"}() s += eval {"$a:$b;"}
} }
return s return s
} }
@@ -1,10 +1,12 @@
operator fun Int.component1() = this + 1 operator fun Int.component1() = this + 1
operator fun Int.component2() = this + 2 operator fun Int.component2() = this + 2
fun <T> eval(fn: () -> T) = fn()
fun doTest(l : Array<Int>): String { fun doTest(l : Array<Int>): String {
var s = "" var s = ""
for ((a, b) in l) { for ((a, b) in l) {
s += {"$a:$b;"}() s += eval {"$a:$b;"}
} }
return s return s
} }
@@ -1,10 +1,12 @@
operator fun Long.component1() = this + 1 operator fun Long.component1() = this + 1
operator fun Long.component2() = this + 2 operator fun Long.component2() = this + 2
fun <T> eval(fn: () -> T) = fn()
fun doTest(l : Array<Long>): String { fun doTest(l : Array<Long>): String {
var s = "" var s = ""
for ((a, b) in l) { for ((a, b) in l) {
s += {"$a:$b;"}() s += eval { "$a:$b;" }
} }
return s return s
} }
@@ -15,10 +15,11 @@ interface Checker {
class Checker1 : Checker { class Checker1 : Checker {
override fun check(): Boolean { override fun check(): Boolean {
var result = true var result = true
assert(true, { val lam = {
result = false result = false
{ "Assertion failure" } { "Assertion failure" }
}()) }
assert(true, lam())
return result return result
} }
} }
@@ -26,10 +27,11 @@ class Checker1 : Checker {
class Checker2 : Checker { class Checker2 : Checker {
override fun check(): Boolean { override fun check(): Boolean {
var result = true var result = true
assert(true, { val lam = {
result = false result = false
{ "Assertion failure" } { "Assertion failure" }
}()) }
assert(true, lam())
return result return result
} }
} }
+2 -3
View File
@@ -1,8 +1,7 @@
fun box() : String { fun box() : String {
var i = 0 var i = 0
{ val lambda = { i++ }
i++ lambda()
}()
i++ //the problem is here i++ //the problem is here
// i = i + 1 //this way it works // i = i + 1 //this way it works
return if (i == 2) "OK" else "fail" return if (i == 2) "OK" else "fail"
@@ -1,5 +1,7 @@
fun <T> eval(fn: () -> T) = fn()
fun String.f(x: String): String { fun String.f(x: String): String {
fun String.g() = { this@f + this@g }() fun String.g() = eval { this@f + this@g }
return x.g() return x.g()
} }
@@ -3,7 +3,12 @@ open class Base(val callback: () -> String)
class Outer { class Outer {
val ok = "OK" val ok = "OK"
inner class Inner : Base({ { ok }() }) inner class Inner : Base(
{
val lambda = { ok }
lambda()
}
)
} }
fun box(): String = fun box(): String =
@@ -7,12 +7,14 @@
package test package test
val p = { "OK" }() fun <T> eval(lambda: () -> T) = lambda()
val p = eval { "OK" }
val getter: String val getter: String
get() = { "OK" }() get() = eval { "OK" }
fun f() = { "OK" }() fun f() = eval { "OK" }
val obj = object : Function0<String> { val obj = object : Function0<String> {
override fun invoke() = "OK" override fun invoke() = "OK"
@@ -5,12 +5,14 @@
// TODO: muted automatically, investigate should it be ran for JS or not // TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS // IGNORE_BACKEND: JS
val p = { "OK" }() fun <T> eval(lambda: () -> T) = lambda()
val p = eval { "OK" }
val getter: String val getter: String
get() = { "OK" }() get() = eval { "OK" }
fun f() = { "OK" }() fun f() = eval { "OK" }
val obj = object : Function0<String> { val obj = object : Function0<String> {
override fun invoke() = "OK" override fun invoke() = "OK"
+4 -6
View File
@@ -12,9 +12,8 @@ class Example : JClass {
var result: String? = null var result: String? = null
init { init {
{ val lambda = { result = obj?.test() }
result = obj?.test() lambda()
}()
} }
} }
@@ -26,9 +25,8 @@ class Example2 : JClass {
var result: String? = null var result: String? = null
init { init {
{ val lambda = { result = obj?.test() }
result = obj?.test() lambda()
}()
} }
} }
+4 -2
View File
@@ -1,8 +1,10 @@
fun <T> eval(fn: () -> T) = fn()
class Foo(private val s: String) { class Foo(private val s: String) {
inner class Inner { inner class Inner {
private val x = { private val x = eval {
this@Foo.s this@Foo.s
}() }
} }
val f = Inner() val f = Inner()
+3 -3
View File
@@ -1,7 +1,7 @@
fun <T> eval(fn: () -> T) = fn()
private const val z = "OK"; private const val z = "OK";
fun box(): String { fun box(): String {
return { return eval { z }
z
}()
} }
@@ -3,12 +3,14 @@
import kotlin.reflect.* import kotlin.reflect.*
fun <T> eval(fn: () -> T) = fn()
object E object E
operator fun E.getValue(receiver: Any?, property: KProperty<*>): String = operator fun E.getValue(receiver: Any?, property: KProperty<*>): String =
if (property.returnType.classifier == String::class) "OK" else "Fail" if (property.returnType.classifier == String::class) "OK" else "Fail"
fun box(): String = { fun box(): String = eval {
val x: String by E val x: String by E
x x
}() }
@@ -3,10 +3,8 @@ import kotlin.reflect.KProperty
operator fun Int.provideDelegate(thiz: Any?, property: KProperty<*>): String = property.name operator fun Int.provideDelegate(thiz: Any?, property: KProperty<*>): String = property.name
inline operator fun String.getValue(thiz: Any?, property: KProperty<*>): String = property.name inline operator fun String.getValue(thiz: Any?, property: KProperty<*>): String = property.name
fun box(): String = with(42) { fun <T> eval(fn: () -> T) = fn()
val O by this
O fun box(): String =
} + { with(42) { val O by this; O } + eval { val K by ""; K }
val K by ""
K
}()
@@ -0,0 +1,13 @@
// IGNORE_BACKEND: WASM
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
class Outer (val x: String) {
inner class Inner(val y: String) {
val yx = y + x
}
}
fun box() =
Outer("K")::Inner.invoke("O").yx
@@ -0,0 +1,11 @@
// IGNORE_BACKEND: WASM
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
class C(val x: String) {
fun foo(s: String) = x + s
}
fun box() =
C("O")::foo.invoke("K")
@@ -0,0 +1,11 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 invoke
fun box(): String {
var ok = "FAILED"
{ s: String ->
ok = s
}("OK")
return ok
}
@@ -0,0 +1,10 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
class C(x: String, y: String) {
val yx = y + x
}
fun box() =
::C.invoke("K", "O").yx
@@ -0,0 +1,12 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
fun box() =
{ k: String ->
{ o: String ->
var ok = o
ok += k
ok
}("O")
}("K")
@@ -0,0 +1,10 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
fun box() =
(fun (s: String): String {
var ok = "O"
ok += s
return ok
}).invoke("K")
@@ -0,0 +1,8 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
fun ok(s: String) = "O" + s
fun box() =
::ok.invoke("K")
@@ -0,0 +1,10 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
fun box() =
{ s: String ->
var ok = "O"
ok += s
ok
}.invoke("K")
@@ -0,0 +1,12 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
class Outer (val x: String) {
inner class Inner(val y: String) {
val yx = y + x
}
}
fun box() =
(Outer::Inner).invoke(Outer("K"), "O").yx
@@ -0,0 +1,2 @@
fun box(): String =
(String::plus)("O", "K")
@@ -1,3 +1,5 @@
fun <T> eval(fn: () -> T) = fn()
fun box(): String { fun box(): String {
var s = "" var s = ""
var foo = "K" var foo = "K"
@@ -11,10 +13,10 @@ fun box(): String {
s += x s += x
} }
{ eval {
foo("O") foo("O")
foo(foo, 1) foo(foo, 1)
}() }
} }
test() test()
@@ -1,7 +1,9 @@
// !LANGUAGE: +InlineClasses // !LANGUAGE: +InlineClasses
fun <T> eval(fn: () -> T) = fn()
inline class R(private val r: Int) { inline class R(private val r: Int) {
fun test() = { ok() }() fun test() = eval { ok() }
private fun ok() = "OK" private fun ok() = "OK"
} }
@@ -1,7 +1,9 @@
// !LANGUAGE: +InlineClasses // !LANGUAGE: +InlineClasses
fun <T> eval(fn: () -> T) = fn()
inline class R(private val r: Int) { inline class R(private val r: Int) {
fun test() = { "OK" }() fun test() = eval { "OK" }
} }
fun box() = R(0).test() fun box() = R(0).test()
+4 -2
View File
@@ -4,17 +4,19 @@
// !LANGUAGE: +InlineClasses // !LANGUAGE: +InlineClasses
// WITH_RUNTIME // WITH_RUNTIME
fun <T> eval(fn: () -> T) = fn()
fun box(): String { fun box(): String {
var uint1 = 1u var uint1 = 1u
var uint2 = 2u var uint2 = 2u
var uint3 = 3u var uint3 = 3u
val uintSet = mutableSetOf(uint1) val uintSet = mutableSetOf(uint1)
uintSet.add(uint2); uintSet.add(uint2);
{ eval {
uintSet.add(uint3) uintSet.add(uint3)
if (!uintSet.contains(1u)) throw AssertionError() if (!uintSet.contains(1u)) throw AssertionError()
if (!uintSet.contains(2u)) throw AssertionError() if (!uintSet.contains(2u)) throw AssertionError()
if (!uintSet.contains(3u)) throw AssertionError() if (!uintSet.contains(3u)) throw AssertionError()
}() }
return "OK" return "OK"
} }
@@ -1,13 +1,15 @@
fun <T> eval(fn: () -> T) = fn()
class A { class A {
fun bar(): Any { fun bar(): Any {
return { return eval {
{ eval {
class Local : Inner() { class Local : Inner() {
override fun toString() = foo() override fun toString() = foo()
} }
Local() Local()
}() }
}() }
} }
open inner class Inner open inner class Inner
@@ -1,12 +1,14 @@
fun <T> eval(fn: () -> T) = fn()
class A { class A {
fun bar(): Any { fun bar(): Any {
return { return eval {
{ eval {
object : Inner() { object : Inner() {
override fun toString() = foo() override fun toString() = foo()
} }
}() }
}() }
} }
open inner class Inner open inner class Inner
@@ -5,13 +5,13 @@
// CHECK_BYTECODE_TEXT // CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES // JVM_IR_TEMPLATES
// 0 java/lang/invoke/LambdaMetafactory\.metafactory // 0 java/lang/invoke/LambdaMetafactory\.metafactory
// 1 final class BigArityLambdaKt\$box\$1 // 1 final class BigArityLambdaKt\$box\$lam\$1
fun box() = fun box(): String {
{ p0: String, p1: String, p2: Int, p3: Int, p4: Int, p5: Int, p6: Int, p7: Int, p8: Int, p9: Int, val lam = { p0: String, p1: String, p2: Int, p3: Int, p4: Int, p5: Int, p6: Int, p7: Int, p8: Int, p9: Int,
p10: Int, p11: Int, p12: Int, p13: Int, p14: Int, p15: Int, p16: Int, p17: Int, p18: Int, p19: Int, p10: Int, p11: Int, p12: Int, p13: Int, p14: Int, p15: Int, p16: Int, p17: Int, p18: Int, p19: Int,
p20: Int, p21: Int, p22: Int, p23: Int, p24: Int, p25: Int, p26: Int, p27: Int, p28: Int, p29: Int p20: Int, p21: Int, p22: Int, p23: Int, p24: Int, p25: Int, p26: Int, p27: Int, p28: Int, p29: Int
-> p0 + p1 -> p0 + p1
}( }
"O", "K", 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 return lam("O", "K", 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29)
) }
@@ -8,5 +8,6 @@
fun box(): String { fun box(): String {
val ok = "OK" val ok = "OK"
return { ok }() val lam = { ok }
return lam()
} }
@@ -8,6 +8,7 @@
fun box(): String { fun box(): String {
var ok = "Failed" var ok = "Failed"
{ ok = "OK" }() val lam = { ok = "OK" }
lam()
return ok return ok
} }
@@ -6,4 +6,11 @@
// JVM_IR_TEMPLATES // JVM_IR_TEMPLATES
// 3 java/lang/invoke/LambdaMetafactory // 3 java/lang/invoke/LambdaMetafactory
fun box() = { { "O" }() + { "K" }() }() fun box(): String {
val lam1 = {
val lamO = { "O" }
val lamK = { "K" }
lamO() + lamK()
}
return lam1()
}
@@ -7,7 +7,8 @@
// 1 java/lang/invoke/LambdaMetafactory // 1 java/lang/invoke/LambdaMetafactory
fun box(): String { fun box(): String {
val test = { i: Int -> i + 40 }(2) val lam = { i: Int -> i + 40 }
val test = lam(2)
if (test != 42) return "Failed: test=$test" if (test != 42) return "Failed: test=$test"
return "OK" return "OK"
@@ -6,4 +6,7 @@
// JVM_IR_TEMPLATES // JVM_IR_TEMPLATES
// 1 java/lang/invoke/LambdaMetafactory // 1 java/lang/invoke/LambdaMetafactory
fun box() = { "OK" }() fun box(): String {
val lam = { "OK" }
return lam()
}
@@ -9,6 +9,7 @@
var ok = "Failed" var ok = "Failed"
fun box(): String { fun box(): String {
{ ok = "OK" }() val lam = { ok = "OK" }
lam()
return ok return ok
} }
@@ -5,12 +5,13 @@
@JvmField public val publicField = "1"; @JvmField public val publicField = "1";
@JvmField internal val internalField = "23"; @JvmField internal val internalField = "23";
fun test(): String { fun <T> eval(fn: () -> T) = fn()
return {
publicField + internalField
}()
}
fun test(): String {
return eval {
publicField + internalField
}
}
fun box(): String { fun box(): String {
return if (test() == "123") return "OK" else "fail" return if (test() == "123") return "OK" else "fail"
+5 -5
View File
@@ -1,16 +1,16 @@
package a.b package a.b
fun <T> eval(fn: () -> T) = fn()
interface Test { interface Test {
fun invoke(): String { fun invoke(): String {
return "OK" return "OK"
} }
} }
private val a : Test = { private val a : Test = eval {
object : Test { object : Test {}
}
}
}()
fun box(): String { fun box(): String {
return a.invoke(); return a.invoke();
@@ -1,5 +1,7 @@
fun <T> eval(fn: () -> T) = fn()
class A( class A(
val a: String = { val a: String = eval {
open class B() { open class B() {
open fun s() : String = "O" open fun s() : String = "O"
} }
@@ -9,7 +11,7 @@ class A(
} }
B().s() + o.s() B().s() + o.s()
}() }
) )
fun box() : String { fun box() : String {
@@ -1,12 +1,14 @@
// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField // !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField
fun <T> eval(fn: () -> T) = fn()
class Outer { class Outer {
private companion object { private companion object {
val result = "OK" val result = "OK"
} }
class Nested { class Nested {
fun foo() = { result }() fun foo() = eval { result }
} }
fun test() = Nested().foo() fun test() = Nested().foo()
@@ -1,12 +1,14 @@
interface T interface T
fun <T> eval(fn: () -> T) = fn()
object Foo { object Foo {
private fun foo(p: T) = p private fun foo(p: T) = p
private val v: Int = { private val v: Int = eval {
val x = foo(O) val x = foo(O)
42 42
}() }
private object O : T private object O : T
@@ -1,4 +1,6 @@
fun <T> eval(fn: () -> T) = fn()
private var x = "O" private var x = "O"
private fun f() = "K" private fun f() = "K"
fun box() = { x + f() }() fun box() = eval { x + f() }
@@ -1,7 +1,9 @@
fun <T> eval(fn: () -> T) = fn()
public open class Outer private constructor(val s: String) { public open class Outer private constructor(val s: String) {
companion object { companion object {
fun test () = { Outer("OK") }() fun test () = eval { Outer("OK") }
} }
} }
@@ -1,6 +1,8 @@
fun <T> eval(fn: () -> T) = fn()
class My { class My {
val my: String = "O" val my: String = "O"
get() = { field }() + "K" get() = eval { field } + "K"
} }
fun box() = My().my fun box() = My().my
@@ -1,6 +1,8 @@
fun <T> eval(fn: () -> T) = fn()
class My { class My {
var my: String = "U" var my: String = "U"
get() = { field }() get() = eval { field }
set(arg) { set(arg) {
class Local { class Local {
fun foo() { fun foo() {
@@ -1,6 +1,8 @@
fun <T> eval(fn: () -> T) = fn()
class My { class My {
val my: String = "O" val my: String = "O"
get() = { { field }() }() + "K" get() = eval { eval { field } } + "K"
} }
fun box() = My().my fun box() = My().my
@@ -1,6 +1,8 @@
fun <T> eval(fn: () -> T) = fn()
class My { class My {
val my: String = "O" val my: String = "O"
get() = { { { field }() }() }() + "K" get() = eval { eval { eval { field } } } + "K"
} }
fun box() = My().my fun box() = My().my
@@ -1,7 +1,9 @@
fun <T> eval(fn: () -> T) = fn()
class My { class My {
companion object { companion object {
val my: String = "O" val my: String = "O"
get() = { field }() + "K" get() = eval { field } + "K"
} }
} }
@@ -1,7 +1,9 @@
fun <T> eval(fn: () -> T) = fn()
class My { class My {
companion object { companion object {
private val my: String = "O" private val my: String = "O"
get() = { field }() + "K" get() = eval { field } + "K"
fun getValue() = my fun getValue() = my
} }
@@ -1,4 +1,6 @@
fun <T> eval(fn: () -> T) = fn()
val my: String = "O" val my: String = "O"
get() = { field }() + "K" get() = eval { field } + "K"
fun box() = my fun box() = my
+3 -1
View File
@@ -1,3 +1,5 @@
fun <T> eval(fn: () -> T) = fn()
class IntentionsBundle { class IntentionsBundle {
companion object { companion object {
fun message(key: String): String { fun message(key: String): String {
@@ -5,7 +7,7 @@ class IntentionsBundle {
} }
fun message2(key: String): String { fun message2(key: String): String {
return { key + BUNDLE }() return eval { key + BUNDLE }
} }
private const val BUNDLE = "K" private const val BUNDLE = "K"
+4 -6
View File
@@ -1,3 +1,5 @@
fun <T> eval(fn: () -> T) = fn()
class A { class A {
var result: Int = 0; var result: Int = 0;
@@ -12,15 +14,11 @@ class A {
} }
fun test(p: Int):Int { fun test(p: Int):Int {
return { return eval { p.times3 }
p.times3
}()
} }
fun test2(p: Int, s: Int):Int { fun test2(p: Int, s: Int):Int {
{ eval { p.times = s }
p.times = s
}()
return result return result
} }
} }
+3 -1
View File
@@ -1,10 +1,12 @@
fun <T> eval(fn: () -> T) = fn()
class A { class A {
public var prop = "OK" public var prop = "OK"
private set private set
fun test(): String { fun test(): String {
return { prop }() return eval { prop }
} }
} }
@@ -1,5 +1,7 @@
// DONT_TARGET_EXACT_BACKEND: WASM // DONT_TARGET_EXACT_BACKEND: WASM
// WASM_MUTE_REASON: EXCEPTIONS_NOT_IMPLEMENTED // WASM_MUTE_REASON: EXCEPTIONS_NOT_IMPLEMENTED
fun <T> eval(fn: () -> T) = fn()
public class A { public class A {
fun getFromClass(): Boolean { fun getFromClass(): Boolean {
try { try {
@@ -12,7 +14,7 @@ public class A {
fun getFromLambda(): Boolean { fun getFromLambda(): Boolean {
try { try {
val a = { str }() val a = eval { str }
return false return false
} catch (e: RuntimeException) { } catch (e: RuntimeException) {
return true return true
@@ -1,10 +1,12 @@
// WITH_RUNTIME // WITH_RUNTIME
fun <T> eval(fn: () -> T) = fn()
class Foo { class Foo {
private lateinit var foo: String private lateinit var foo: String
fun test(): Boolean { fun test(): Boolean {
val result = { ::foo.isInitialized }() val result = eval { ::foo.isInitialized }
foo = "" foo = ""
return result return result
} }
@@ -13,9 +13,11 @@ public class D {
import test.D import test.D
fun <T> eval(fn: () -> T) = fn()
class A : D() { class A : D() {
fun a(): String { fun a(): String {
return {field!!}() return eval { field!! }
} }
} }
@@ -4,16 +4,18 @@
fun box(): String { fun box(): String {
val classInLambda = { val lambda = {
class Z {} class Z {}
Z() Z()
}() }
val classInLambda = lambda()
val enclosingMethod = classInLambda.javaClass.getEnclosingMethod() val enclosingMethod = classInLambda.javaClass.getEnclosingMethod()
if (enclosingMethod?.getName() != "invoke") return "method: $enclosingMethod" if (enclosingMethod?.getName() != "invoke") return "method: $enclosingMethod"
val enclosingClass = classInLambda.javaClass.getEnclosingClass()!!.getName() val enclosingClass = classInLambda.javaClass.getEnclosingClass()!!.getName()
if (enclosingClass != "ClassInLambdaKt\$box\$classInLambda\$1") return "enclosing class: $enclosingClass" if (enclosingClass != "ClassInLambdaKt\$box\$lambda\$1") return "enclosing class: $enclosingClass"
val declaringClass = classInLambda.javaClass.getDeclaringClass() val declaringClass = classInLambda.javaClass.getDeclaringClass()
if (declaringClass != null) return "class has a declaring class" if (declaringClass != null) return "class has a declaring class"
@@ -3,16 +3,17 @@
// WITH_REFLECT // WITH_REFLECT
fun box(): String { fun box(): String {
val lambda = {
val objectInLambda = {
object : Any () {} object : Any () {}
}() }
val objectInLambda = lambda()
val enclosingMethod = objectInLambda.javaClass.getEnclosingMethod() val enclosingMethod = objectInLambda.javaClass.getEnclosingMethod()
if (enclosingMethod?.getName() != "invoke") return "method: $enclosingMethod" if (enclosingMethod?.getName() != "invoke") return "method: $enclosingMethod"
val enclosingClass = objectInLambda.javaClass.getEnclosingClass()!!.getName() val enclosingClass = objectInLambda.javaClass.getEnclosingClass()!!.getName()
if (enclosingClass != "ObjectInLambdaKt\$box\$objectInLambda\$1") return "enclosing class: $enclosingClass" if (enclosingClass != "ObjectInLambdaKt\$box\$lambda\$1") return "enclosing class: $enclosingClass"
val declaringClass = objectInLambda.javaClass.getDeclaringClass() val declaringClass = objectInLambda.javaClass.getDeclaringClass()
if (declaringClass != null) return "anonymous object has a declaring class" if (declaringClass != null) return "anonymous object has a declaring class"
@@ -2,10 +2,12 @@
// WITH_REFLECT // WITH_REFLECT
import kotlin.reflect.* import kotlin.reflect.*
fun <T> eval(fn: () -> T) = fn()
inline operator fun String.getValue(t:Any?, p: KProperty<*>): String = inline operator fun String.getValue(t:Any?, p: KProperty<*>): String =
if (p.returnType.classifier == String::class) this else "fail" if (p.returnType.classifier == String::class) this else "fail"
fun box() = { fun box() = eval {
val x by "OK" val x by "OK"
x x
}() }
@@ -1,7 +1,9 @@
inline fun myRun(x: () -> String) = x() inline fun myRun(x: () -> String) = x()
fun <T> eval(fn: () -> T) = fn()
class C { class C {
val x = myRun { { "OK" }() } val x = myRun { eval { "OK" } }
constructor(y: Int) constructor(y: Int)
constructor(y: String) constructor(y: String)
+3 -1
View File
@@ -1,3 +1,5 @@
fun <T> eval(fn: () -> T) = fn()
class C { class C {
companion object { companion object {
private val s: String private val s: String
@@ -17,5 +19,5 @@ class C {
} }
fun box(): String { fun box(): String {
return C.foo() + {C.bar2(); C.foo2()}() return C.foo() + eval { C.bar2(); C.foo2() }
} }
+12 -11
View File
@@ -32,24 +32,25 @@ package anotherPackage
import Base.Derived import Base.Derived
import Base import Base
fun <T> eval(fn: () -> T) = fn()
class Kotlin : Base.Derived() { class Kotlin : Base.Derived() {
fun doTest(): String { fun doTest(): String {
if ({ TEST }() != "DERIVED") return "fail 1" if (eval { TEST } != "DERIVED") return "fail 1"
if ({ test() }() != "DERIVED") return "fail 2" if (eval { test() } != "DERIVED") return "fail 2"
if ({ Derived.TEST }() != "DERIVED") return "fail 3" if (eval { Derived.TEST } != "DERIVED") return "fail 3"
if ({ Derived.test() }() != "DERIVED") return "fail 4" if (eval { Derived.test() } != "DERIVED") return "fail 4"
if ({ Base.TEST }() != "BASE") return "fail 5" if (eval { Base.TEST } != "BASE") return "fail 5"
if ({ Base.test() }() != "BASE") return "fail 6" if (eval { Base.test() } != "BASE") return "fail 6"
if (eval { Base.BASE_ONLY } != "BASE") return "fail 7"
if (eval { Base.baseOnly() } != "BASE") return "fail 8"
if ({ Base.BASE_ONLY }() != "BASE") return "fail 7" if (eval { BASE_ONLY } != "BASE") return "fail 9"
if ({ Base.baseOnly() }() != "BASE") return "fail 8" if (eval { baseOnly() } != "BASE") return "fail 10"
if ({ BASE_ONLY }() != "BASE") return "fail 9"
if ({ baseOnly() }() != "BASE") return "fail 10"
return "OK" return "OK"
} }
+5 -11
View File
@@ -1,20 +1,14 @@
open class C(s: Int) { fun <T> eval(fn: () -> T) = fn()
fun test() {
} open class C(s: Int) {
fun test() {}
} }
class B(var x: Int) { class B(var x: Int) {
fun foo() { fun foo() {
class A(val a: Int) : C({a}()) { class A(val a: Int) : C(eval { a })
}
A(11).test() A(11).test()
class B(val a: Int) : C(a)
class B(val a: Int) : C(a) {
}
B(11).test() B(11).test()
} }
} }
@@ -1,8 +1,10 @@
// FILE: 1.kt // FILE: 1.kt
import a.* import a.*
fun <T> eval(fn: () -> T) = fn()
abstract class B : A() { abstract class B : A() {
fun g() = { f() }() fun g() = eval { f() }
} }
fun box() = object : B() { fun box() = object : B() {
@@ -5,13 +5,15 @@ package test2
import test.Actor import test.Actor
import test.O2dScriptAction import test.O2dScriptAction
fun <T> eval(fn: () -> T) = fn()
class CompositeActor : Actor() class CompositeActor : Actor()
public open class O2dDialog : O2dScriptAction<CompositeActor>() { public open class O2dDialog : O2dScriptAction<CompositeActor>() {
fun test() = { owner }() fun test() = eval { owner }
fun test2() = { calc() }() fun test2() = eval { calc() }
} }
fun box(): String { fun box(): String {
@@ -1,6 +1,8 @@
fun <T> eval(fn: () -> T) = fn()
class Foo { class Foo {
private val fld: String = "O" private val fld: String = "O"
get() = { field }() + "K" get() = eval { field } + "K"
val indirectFldGetter: () -> String = { fld } val indirectFldGetter: () -> String = { fld }
} }
@@ -1,6 +1,8 @@
fun <T> eval(fn: () -> T) = fn()
class Foo { class Foo {
private val fld: String = "O" private val fld: String = "O"
get() = { field }() + "K" get() = eval { field } + "K"
val indirectFldGetter: () -> String = { fld } val indirectFldGetter: () -> String = { fld }
@@ -1,11 +1,11 @@
package test package test
fun <T> eval(fn: () -> T) = fn()
private val prop = "O" private val prop = "O"
private fun test() = "K" private fun test() = "K"
fun box(): String { fun box(): String {
return { return eval { prop + test() }
prop + test()
}()
} }
@@ -5,12 +5,12 @@
@file:kotlin.jvm.JvmName("TestKt") @file:kotlin.jvm.JvmName("TestKt")
package test package test
fun <T> eval(fn: () -> T) = fn()
private val prop = "O" private val prop = "O"
private fun test() = "K" private fun test() = "K"
fun box(): String { fun box(): String {
return { return eval { prop + test() }
prop + test()
}()
} }
@@ -19,16 +19,17 @@ object B {
// FILE: 2.kt // FILE: 2.kt
import test.* import test.*
fun <T> eval(f: () -> T) = f()
fun box(): String { fun box(): String {
var z = "fail" var z = "fail"
B.test2 { B.test2 {
{ // regenerated object in inline lambda eval { // regenerated object in inline lambda
A.test { A.test {
z = "OK" z = "OK"
} }
}() }
} }
return z; return z;
} }
@@ -11,14 +11,14 @@ _2Kt
+ 2 1.kt + 2 1.kt
test/B test/B
*L *L
1#1,36:1 1#1,37:1
15#2,2:37 15#2,2:38
*S KotlinDebug *S KotlinDebug
*F *F
+ 1 2.kt + 1 2.kt
_2Kt _2Kt
*L *L
26#1:37,2 27#1:38,2
*E *E
SMAP SMAP
@@ -31,13 +31,13 @@ _2Kt$box$1$1
+ 2 1.kt + 2 1.kt
test/A test/A
*L *L
1#1,36:1 1#1,37:1
9#2,2:37 9#2,2:38
*S KotlinDebug *S KotlinDebug
*F *F
+ 1 2.kt + 1 2.kt
_2Kt$box$1$1 _2Kt$box$1$1
*L *L
28#1:37,2 29#1:38,2
*E *E
@@ -18,15 +18,17 @@ inline fun test2(s: () -> String): String {
import test.* import test.*
fun <T> eval(f: () -> T) = f()
fun box(): String { fun box(): String {
var result = "fail" var result = "fail"
test { test {
{ eval {
result = test2 { result = test2 {
"OK" "OK"
} }
}() }
} }
return result return result
@@ -11,14 +11,14 @@ _2Kt
+ 2 1.kt + 2 1.kt
test/_1Kt test/_1Kt
*L *L
1#1,34:1 1#1,36:1
6#2,4:35 6#2,4:37
*S KotlinDebug *S KotlinDebug
*F *F
+ 1 2.kt + 1 2.kt
_2Kt _2Kt
*L *L
24#1:35,4 26#1:37,4
*E *E
SMAP SMAP
@@ -31,13 +31,13 @@ _2Kt$box$1$1
+ 2 1.kt + 2 1.kt
test/_1Kt test/_1Kt
*L *L
1#1,34:1 1#1,36:1
12#2,3:35 12#2,3:37
*S KotlinDebug *S KotlinDebug
*F *F
+ 1 2.kt + 1 2.kt
_2Kt$box$1$1 _2Kt$box$1$1
*L *L
26#1:35,3 28#1:37,3
*E *E
@@ -18,15 +18,17 @@ inline fun test2(s: () -> String): String {
return res return res
} }
fun <T> eval(f: () -> T) = f()
fun box(): String { fun box(): String {
var result = "fail" var result = "fail"
test { test {
{ eval {
result = test2 { result = test2 {
"OK" "OK"
} }
}() }
} }
return result return result
@@ -11,14 +11,14 @@ _2Kt
+ 2 1.kt + 2 1.kt
test/_1Kt test/_1Kt
*L *L
1#1,34:1 1#1,36:1
6#2,4:35 6#2,4:37
*S KotlinDebug *S KotlinDebug
*F *F
+ 1 2.kt + 1 2.kt
_2Kt _2Kt
*L *L
24#1:35,4 26#1:37,4
*E *E
SMAP SMAP
@@ -31,13 +31,13 @@ _2Kt$box$1$1
+ 2 2.kt + 2 2.kt
_2Kt _2Kt
*L *L
1#1,34:1 1#1,36:1
16#2,3:35 16#2,3:37
*S KotlinDebug *S KotlinDebug
*F *F
+ 1 2.kt + 1 2.kt
_2Kt$box$1$1 _2Kt$box$1$1
*L *L
26#1:35,3 28#1:37,3
*E *E
@@ -1,12 +1,14 @@
// FILE: C.kt // FILE: C.kt
package test package test
fun <T> eval(f: () -> T) = f()
class C: A.B() { class C: A.B() {
// For binary compatibility, two accessibility bridges should be generated in C: // For binary compatibility, two accessibility bridges should be generated in C:
// one for A.x and one for A.B.x. // one for A.x and one for A.B.x.
// Otherwise, if a static 'x' field is added to A.B either A.x or A.B.x will be ignored. // Otherwise, if a static 'x' field is added to A.B either A.x or A.B.x will be ignored.
// The JVM backend generates accessibility bridges for setters as well which is not necessary. // The JVM backend generates accessibility bridges for setters as well which is not necessary.
fun f() = ({ A.x + x })() fun f() = eval { A.x + x }
// Similarly for static functions. Two bridges should be generated for binary compatibility. // Similarly for static functions. Two bridges should be generated for binary compatibility.
fun g() = ({ A.h() + h() }) fun g() = ({ A.h() + h() })
} }
@@ -37,3 +37,9 @@ public final class test/C {
public final @org.jetbrains.annotations.NotNull method f(): java.lang.String public final @org.jetbrains.annotations.NotNull method f(): java.lang.String
public final @org.jetbrains.annotations.NotNull method g(): kotlin.jvm.functions.Function0 public final @org.jetbrains.annotations.NotNull method g(): kotlin.jvm.functions.Function0
} }
@kotlin.Metadata
public final class test/CKt {
// source: 'C.kt'
public final static method eval(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Object
}
@@ -35,3 +35,9 @@ public final class test/C {
public final @org.jetbrains.annotations.NotNull method f(): java.lang.String public final @org.jetbrains.annotations.NotNull method f(): java.lang.String
public final @org.jetbrains.annotations.NotNull method g(): kotlin.jvm.functions.Function0 public final @org.jetbrains.annotations.NotNull method g(): kotlin.jvm.functions.Function0
} }
@kotlin.Metadata
public final class test/CKt {
// source: 'C.kt'
public final static method eval(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Object
}
@@ -10,17 +10,19 @@ inline fun test(s: () -> Unit) {
import test.* import test.*
fun <T> eval(f: () -> T) = f()
fun box() { fun box() {
var s1 = "" var s1 = ""
var s2 = "" var s2 = ""
test { test {
{ eval {
val p = object {} val p = object {}
s1 = p.toString(); s1 = p.toString();
{ eval {
val q = object {} val q = object {}
s2 = q.toString() s2 = q.toString()
}() }
}() }
} }
} }
@@ -48,6 +48,7 @@ final class _2Kt$box$$inlined$test$lambda$1 {
public final class _2Kt { public final class _2Kt {
// source: '2.kt' // source: '2.kt'
public final static method box(): void public final static method box(): void
public final static method eval(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Object
} }
@kotlin.Metadata @kotlin.Metadata
@@ -49,6 +49,7 @@ public final class _2Kt {
// source: '2.kt' // source: '2.kt'
inner (anonymous) class _2Kt$box$1$1 inner (anonymous) class _2Kt$box$1$1
public final static method box(): void public final static method box(): void
public final static method eval(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Object
} }
@kotlin.Metadata @kotlin.Metadata
@@ -1,28 +1,31 @@
fun test() { fun test() {
fun local(){ fun local(){
{ val lam = {
//static instance access //static instance access
local() local()
}() }
lam()
} }
//static instance access //static instance access
{ val lam = {
//static instance access //static instance access
local() local()
}() }
lam()
//static instance access //static instance access
(::local)() val cr = ::local
cr()
} }
// JVM_TEMPLATES // JVM_TEMPLATES
// 3 GETSTATIC ConstClosureOptimizationKt\$test\$1\.INSTANCE // 3 GETSTATIC ConstClosureOptimizationKt\$test\$1\.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$2\.INSTANCE // 1 GETSTATIC ConstClosureOptimizationKt\$test\$lam\$1\.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$3\.INSTANCE // 1 GETSTATIC ConstClosureOptimizationKt\$test\$cr\$1\.INSTANCE
// JVM_IR_TEMPLATES // JVM_IR_TEMPLATES
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$1.INSTANCE // 1 GETSTATIC ConstClosureOptimizationKt\$test\$cr\$1.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$2.INSTANCE // 1 GETSTATIC ConstClosureOptimizationKt\$test\$lam\$1.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$local\$1.INSTANCE // 1 GETSTATIC ConstClosureOptimizationKt\$test\$local\$lam\$1.INSTANCE
@@ -3,7 +3,8 @@ class Z{
fun a(s: Int) {} fun a(s: Int) {}
fun b() { fun b() {
(Z::a)(Z(), 1) val cr = (Z::a)
cr(Z(), 1)
} }
} }
@@ -1,6 +1,6 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun test() { fun test() {
1.(fun Int.() = 2)() val fn = fun Int.() = 2
1.fn()
} }
// 1 invoke \(I\)I // 1 invoke \(I\)I
@@ -1,6 +1,7 @@
fun test() { fun test() {
{ {
{}() val lam = {}
lam()
}() }()
} }
@@ -11,16 +12,19 @@ inline fun ifun(s: () -> Unit) {
fun test2() { fun test2() {
var z = 1; var z = 1;
ifun { ifun {
{ z = 2 }() val lam = { z = 2 }
lam()
} }
} }
// 1 class DeleteClassOnTransformationKt\$test\$1\$1
// JVM_TEMPLATES: // JVM_TEMPLATES:
// 1 class DeleteClassOnTransformationKt\$test\$1 extends
// 1 class DeleteClassOnTransformationKt\$test\$1\$lam\$1 extends
// 0 class DeleteClassOnTransformationKt\$test2\$1\$1 // 0 class DeleteClassOnTransformationKt\$test2\$1\$1
// 1 class DeleteClassOnTransformationKt\$test2\$\$inlined\$ifun\$lambda\$1 // 1 class DeleteClassOnTransformationKt\$test2\$\$inlined\$ifun\$lambda\$1
// JVM_IR_TEMPLATES: // JVM_IR_TEMPLATES:
// 1 class DeleteClassOnTransformationKt\$test2\$1\$1 // 3 final class
// 0 class DeleteClassOnTransformationKt\$test2\$\$inlined // 1 class DeleteClassOnTransformationKt\$test\$1\$lam\$1
// 1 class DeleteClassOnTransformationKt\$test2\$1\$lam\$1
@@ -3,7 +3,14 @@
// JVM_TARGET: 1.8 // JVM_TARGET: 1.8
// LAMBDAS: INDY // LAMBDAS: INDY
fun test() = { { "O" }() + { "K" }() }() fun test(): String {
val lam = {
val lamO = { "O" }
val lamK = { "K" }
lamO() + lamK()
}
return lam()
}
// JVM_IR_TEMPLATES // JVM_IR_TEMPLATES
// 3 INVOKEDYNAMIC // 3 INVOKEDYNAMIC
+7 -9
View File
@@ -2,12 +2,12 @@ fun box(): String {
var encl1 = "fail" var encl1 = "fail"
var encl2 = "fail" var encl2 = "fail"
test { test {
{ val lam1 = {
encl1 = "OK" encl1 = "OK"
{ val lam2 = { encl2 = "OK" }
encl2 = "OK" lam2()
}() }
}() lam1()
} }
return "OK" return "OK"
@@ -28,7 +28,5 @@ inline fun test(s: () -> Unit) {
// JVM_IR_TEMPLATES // JVM_IR_TEMPLATES
// 5 INNERCLASS // 5 INNERCLASS
// 3 INNERCLASS Kt10259Kt\$box\$1\$1\s // 3 INNERCLASS Kt10259Kt\$box\$1\$lam1\$1 null null
// 2 INNERCLASS Kt10259Kt\$box\$1\$1\$1 // 2 INNERCLASS Kt10259Kt\$box\$1\$lam1\$1\$lam2\$1
// 1 class Kt10259Kt\$box\$1\$1\ extends
// 1 class Kt10259Kt\$box\$1\$1\$1 extends

Some files were not shown because too many files have changed in this diff Show More