diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml
index ca6e2ba2d81..fe55a91a572 100644
--- a/.idea/inspectionProfiles/idea_default.xml
+++ b/.idea/inspectionProfiles/idea_default.xml
@@ -236,6 +236,11 @@
+
+
+
+
+
diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt
index ccc82e2bb98..90daa68d620 100644
--- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt
+++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt
@@ -16,10 +16,12 @@
package org.jetbrains.kotlin.psi2ir.generators
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.psi.KtExpression
+import org.jetbrains.kotlin.psi.KtFunctionLiteral
import org.jetbrains.kotlin.psi.KtLoopExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
@@ -30,8 +32,6 @@ class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: Ge
private val loopTable = HashMap()
fun generateFunctionBody(ktBody: KtExpression): IrBody {
- resetInternalContext()
-
val statementGenerator = createStatementGenerator()
val irBlockBody = IrBlockBodyImpl(ktBody.startOffset, ktBody.endOffset)
@@ -42,21 +42,17 @@ class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: Ge
}
else {
val irBodyExpression = statementGenerator.generateExpression(ktBody)
- val irReturn = IrReturnImpl(ktBody.startOffset, ktBody.endOffset, context.builtIns.nothingType, scopeOwner, irBodyExpression)
- irBlockBody.addStatement(irReturn)
+ irBlockBody.addStatement(irBodyExpression.wrapWithReturn())
}
- postprocessFunctionBody()
-
return irBlockBody
}
- private fun resetInternalContext() {
- loopTable.clear()
- }
-
- private fun postprocessFunctionBody() {
- }
+ private fun IrExpression.wrapWithReturn() =
+ if (KotlinBuiltIns.isNothing(type))
+ this
+ else
+ IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, scopeOwner, this)
fun generatePropertyInitializerBody(ktInitializer: KtExpression): IrBody =
IrExpressionBodyImpl(ktInitializer.startOffset, ktInitializer.endOffset,
@@ -71,5 +67,24 @@ class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: Ge
fun getLoop(expression: KtExpression): IrLoop? =
loopTable[expression]
+
+ fun generateLambdaBody(ktFun: KtFunctionLiteral): IrBody {
+ val statementGenerator = createStatementGenerator()
+
+ val ktBody = ktFun.bodyExpression!!
+ val irBlockBody = IrBlockBodyImpl(ktBody.startOffset, ktBody.endOffset)
+ if (ktBody is KtBlockExpression) {
+ for (ktStatement in ktBody.statements.subList(0, ktBody.statements.size - 1)) {
+ irBlockBody.addStatement(statementGenerator.generateStatement(ktStatement))
+ }
+ val ktReturnedValue = ktBody.statements.last()
+ irBlockBody.addStatement(statementGenerator.generateExpression(ktReturnedValue).wrapWithReturn())
+ }
+ else {
+ irBlockBody.addStatement(statementGenerator.generateExpression(ktBody).wrapWithReturn())
+ }
+
+ return irBlockBody
+ }
}
diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LocalFunctionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LocalFunctionGenerator.kt
new file mode 100644
index 00000000000..28913c3e6be
--- /dev/null
+++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LocalFunctionGenerator.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.kotlin.psi2ir.generators
+
+import org.jetbrains.kotlin.ir.IrStatement
+import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
+import org.jetbrains.kotlin.ir.declarations.IrFunctionImpl
+import org.jetbrains.kotlin.ir.expressions.IrBlockImpl
+import org.jetbrains.kotlin.ir.expressions.IrCallableReferenceImpl
+import org.jetbrains.kotlin.ir.expressions.IrOperator
+import org.jetbrains.kotlin.psi.KtLambdaExpression
+import org.jetbrains.kotlin.psi.psiUtil.endOffset
+import org.jetbrains.kotlin.psi.psiUtil.startOffset
+import org.jetbrains.kotlin.resolve.BindingContext
+
+class LocalFunctionGenerator(val statementGenerator: StatementGenerator) : GeneratorWithScope {
+ override val scope: Scope get() = statementGenerator.scope
+ override val context: GeneratorContext get() = statementGenerator.context
+
+ fun generateLambda(ktLambda: KtLambdaExpression): IrStatement {
+ val ktFun = ktLambda.functionLiteral
+ val lambdaExpressionType = getInferredTypeWithSmartcastsOrFail(ktLambda)
+ val lambdaDescriptor = getOrFail(BindingContext.FUNCTION, ktFun)
+ val irBlock = IrBlockImpl(ktLambda.startOffset, ktLambda.endOffset, lambdaExpressionType, IrOperator.LAMBDA)
+
+ val irFun = IrFunctionImpl(ktFun.startOffset, ktFun.endOffset, IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA, lambdaDescriptor)
+ irFun.body = BodyGenerator(lambdaDescriptor, statementGenerator.context).generateLambdaBody(ktFun)
+ irBlock.addStatement(irFun)
+
+ irBlock.addStatement(IrCallableReferenceImpl(ktLambda.startOffset, ktLambda.endOffset, lambdaExpressionType, lambdaDescriptor))
+
+ return irBlock
+ }
+
+}
\ No newline at end of file
diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt
index 51c6b2dad5f..12e302549cf 100644
--- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt
+++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt
@@ -26,7 +26,9 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.deparenthesize
-import org.jetbrains.kotlin.psi2ir.intermediate.*
+import org.jetbrains.kotlin.psi2ir.intermediate.IntermediateValue
+import org.jetbrains.kotlin.psi2ir.intermediate.createRematerializableOrTemporary
+import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -40,10 +42,11 @@ import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
+import java.lang.AssertionError
class StatementGenerator(
override val context: GeneratorContext,
- val scopeOwner: DeclarationDescriptor,
+ val scopeOwner: CallableDescriptor,
val bodyGenerator: BodyGenerator,
override val scope: Scope
) : KtVisitor(), GeneratorWithScope {
@@ -316,4 +319,7 @@ class StatementGenerator(
override fun visitTryExpression(expression: KtTryExpression, data: Nothing?): IrStatement =
TryCatchExpressionGenerator(this).generateTryCatch(expression)
-}
\ No newline at end of file
+ override fun visitLambdaExpression(expression: KtLambdaExpression, data: Nothing?): IrStatement =
+ LocalFunctionGenerator(this).generateLambda(expression)
+}
+
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt
index 0bdf6565813..1e39c2b2b68 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt
@@ -42,6 +42,7 @@ enum class IrDeclarationKind {
enum class IrDeclarationOrigin {
DEFINED,
+ LOCAL_FUNCTION_FOR_LAMBDA,
IR_TEMPORARY_VARIABLE,
}
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallableReference.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallableReference.kt
new file mode 100644
index 00000000000..7ed5e257425
--- /dev/null
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallableReference.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.kotlin.ir.expressions
+
+import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import org.jetbrains.kotlin.ir.IrElement
+import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
+import org.jetbrains.kotlin.types.KotlinType
+
+
+interface IrCallableReference : IrDeclarationReference {
+ override val descriptor: CallableDescriptor
+
+ // TODO closure
+}
+
+class IrCallableReferenceImpl(
+ startOffset: Int,
+ endOffset: Int,
+ type: KotlinType,
+ descriptor: CallableDescriptor
+) : IrDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrCallableReference {
+ override fun accept(visitor: IrElementVisitor, data: D): R {
+ return visitor.visitCallableReference(this, data)
+ }
+
+ override fun acceptChildren(visitor: IrElementVisitor, data: D) {
+ // TODO
+ }
+
+ override fun getChild(slot: Int): IrElement? {
+ // TODO
+ return null
+ }
+
+ override fun replaceChild(slot: Int, newChild: IrElement) {
+ // TODO
+ }
+}
\ No newline at end of file
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt
index 0aa2938845e..5b6dae85946 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt
@@ -85,6 +85,9 @@ interface IrOperator {
object FOR_LOOP_HAS_NEXT : IrOperatorImpl("FOR_LOOP_HAS_NEXT")
object FOR_LOOP_NEXT : IrOperatorImpl("FOR_LOOP_NEXT")
+ object LAMBDA : IrOperatorImpl("LAMBDA")
+
+
data class COMPONENT_N private constructor(val index: Int) : IrOperatorImpl("COMPONENT_$index") {
companion object {
private val precreatedComponents = Array(32) { i -> COMPONENT_N(i + 1) }
@@ -97,8 +100,6 @@ interface IrOperator {
}
}
-
-
}
fun IrOperator.isAssignmentOperatorWithResult() =
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt
index 2760902b94d..20c13cea1fc 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt
@@ -67,10 +67,10 @@ class RenderIrElementVisitor : IrElementVisitor {
"BLOCK_BODY"
override fun visitExpression(expression: IrExpression, data: Nothing?): String =
- "? ${expression.javaClass.simpleName} type=${expression.renderType()}"
+ "? ${expression.javaClass.simpleName} type=${expression.type.render()}"
override fun visitConst(expression: IrConst, data: Nothing?): String =
- "CONST ${expression.kind} type=${expression.renderType()} value='${expression.value}'"
+ "CONST ${expression.kind} type=${expression.type.render()} value='${expression.value}'"
override fun visitVararg(expression: IrVararg, data: Nothing?): String =
"VARARG type=${expression.type} varargElementType=${expression.varargElementType}"
@@ -79,35 +79,35 @@ class RenderIrElementVisitor : IrElementVisitor {
"SPREAD_ELEMENT"
override fun visitBlock(expression: IrBlock, data: Nothing?): String =
- "BLOCK type=${expression.renderType()} operator=${expression.operator}"
+ "BLOCK type=${expression.type.render()} operator=${expression.operator}"
override fun visitReturn(expression: IrReturn, data: Nothing?): String =
- "RETURN type=${expression.renderType()}"
+ "RETURN type=${expression.type.render()}"
override fun visitGetExtensionReceiver(expression: IrGetExtensionReceiver, data: Nothing?): String =
- "\$RECEIVER of: ${expression.descriptor.containingDeclaration.name} type=${expression.renderType()}"
+ "\$RECEIVER of: ${expression.descriptor.containingDeclaration.name} type=${expression.type.render()}"
override fun visitThisReference(expression: IrThisReference, data: Nothing?): String =
- "THIS ${expression.classDescriptor.render()} type=${expression.renderType()}"
+ "THIS ${expression.classDescriptor.render()} type=${expression.type.render()}"
override fun visitCall(expression: IrCall, data: Nothing?): String =
"CALL .${expression.descriptor.name} " +
- "type=${expression.renderType()} operator=${expression.operator}"
+ "type=${expression.type.render()} operator=${expression.operator}"
override fun visitGetVariable(expression: IrGetVariable, data: Nothing?): String =
- "GET_VAR ${expression.descriptor.name} type=${expression.renderType()} operator=${expression.operator}"
+ "GET_VAR ${expression.descriptor.name} type=${expression.type.render()} operator=${expression.operator}"
override fun visitSetVariable(expression: IrSetVariable, data: Nothing?): String =
- "SET_VAR ${expression.descriptor.name} type=${expression.renderType()} operator=${expression.operator}"
+ "SET_VAR ${expression.descriptor.name} type=${expression.type.render()} operator=${expression.operator}"
override fun visitGetObjectValue(expression: IrGetObjectValue, data: Nothing?): String =
- "GET_OBJECT ${expression.descriptor.name} type=${expression.renderType()}"
+ "GET_OBJECT ${expression.descriptor.name} type=${expression.type.render()}"
override fun visitGetEnumValue(expression: IrGetEnumValue, data: Nothing?): String =
- "GET_ENUM_VALUE ${expression.descriptor.name} type=${expression.renderType()}"
+ "GET_ENUM_VALUE ${expression.descriptor.name} type=${expression.type.render()}"
override fun visitStringConcatenation(expression: IrStringConcatenation, data: Nothing?): String =
- "STRING_CONCATENATION type=${expression.renderType()}"
+ "STRING_CONCATENATION type=${expression.type.render()}"
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: Nothing?): String =
"TYPE_OP operator=${expression.operator} typeOperand=${expression.typeOperand.render()}"
@@ -128,16 +128,19 @@ class RenderIrElementVisitor : IrElementVisitor {
"CONTINUE label=${jump.label} depth=${jump.getDepth()}"
override fun visitThrow(expression: IrThrow, data: Nothing?): String =
- "THROW type=${expression.renderType()}"
+ "THROW type=${expression.type.render()}"
+
+ override fun visitCallableReference(expression: IrCallableReference, data: Nothing?): String =
+ "CALLABLE_REFERENCE ${expression.descriptor.render()} type=${expression.type.render()}"
override fun visitTryCatch(tryCatch: IrTryCatch, data: Nothing?): String =
- "TRY_CATCH type=${tryCatch.renderType()}"
+ "TRY_CATCH type=${tryCatch.type.render()}"
override fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: Nothing?): String =
"DUMMY ${declaration.descriptor.javaClass.simpleName} ${declaration.descriptor.name}"
override fun visitDummyExpression(expression: IrDummyExpression, data: Nothing?): String =
- "DUMMY ${expression.description} type=${expression.renderType()}"
+ "DUMMY ${expression.description} type=${expression.type.render()}"
companion object {
private val DESCRIPTOR_RENDERER = DescriptorRenderer.withOptions {
@@ -155,9 +158,6 @@ class RenderIrElementVisitor : IrElementVisitor {
internal fun DeclarationDescriptor?.render(): String =
this?.let { DESCRIPTOR_RENDERER.render(it) } ?: ""
- internal fun IrExpression.renderType(): String =
- type.render()
-
internal fun KotlinType?.render(): String =
this?.let { DESCRIPTOR_RENDERER.renderType(it) } ?: ""
}
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt
index 6063f67c0d0..9b9c5ca1ec0 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt
@@ -58,6 +58,7 @@ interface IrElementVisitor {
fun visitSetVariable(expression: IrSetVariable, data: D) = visitDeclarationReference(expression, data)
fun visitGetExtensionReceiver(expression: IrGetExtensionReceiver, data: D) = visitDeclarationReference(expression, data)
fun visitCall(expression: IrCall, data: D) = visitDeclarationReference(expression, data)
+ fun visitCallableReference(expression: IrCallableReference, data: D) = visitDeclarationReference(expression, data)
fun visitTypeOperator(expression: IrTypeOperatorCall, data: D) = visitExpression(expression, data)
diff --git a/compiler/testData/ir/irText/expressions/variableAsFunctionCall.txt b/compiler/testData/ir/irText/expressions/variableAsFunctionCall.txt
index fed6af9f412..9fd58a066af 100644
--- a/compiler/testData/ir/irText/expressions/variableAsFunctionCall.txt
+++ b/compiler/testData/ir/irText/expressions/variableAsFunctionCall.txt
@@ -2,7 +2,12 @@ FILE /variableAsFunctionCall.kt
FUN public fun kotlin.String.k(): () -> kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing
- DUMMY KtLambdaExpression type=() -> kotlin.String
+ BLOCK type=() -> kotlin.String operator=LAMBDA
+ FUN local final fun (): kotlin.String
+ BLOCK_BODY
+ RETURN type=kotlin.Nothing
+ $RECEIVER of: k type=kotlin.String
+ CALLABLE_REFERENCE local final fun (): kotlin.String type=() -> kotlin.String
FUN public fun test1(/*0*/ f: () -> kotlin.Unit): kotlin.Unit
BLOCK_BODY
RETURN type=kotlin.Nothing
diff --git a/compiler/testData/ir/irText/lambdas/extensionLambda.kt b/compiler/testData/ir/irText/lambdas/extensionLambda.kt
new file mode 100644
index 00000000000..2c3825f12a3
--- /dev/null
+++ b/compiler/testData/ir/irText/lambdas/extensionLambda.kt
@@ -0,0 +1 @@
+fun test1() = "42".run { length }
\ No newline at end of file
diff --git a/compiler/testData/ir/irText/lambdas/extensionLambda.txt b/compiler/testData/ir/irText/lambdas/extensionLambda.txt
new file mode 100644
index 00000000000..d9d07c53a3d
--- /dev/null
+++ b/compiler/testData/ir/irText/lambdas/extensionLambda.txt
@@ -0,0 +1,13 @@
+FILE /extensionLambda.kt
+ FUN public fun test1(): kotlin.Int
+ BLOCK_BODY
+ RETURN type=kotlin.Nothing
+ CALL .run type=kotlin.Int operator=null
+ $receiver: CONST String type=kotlin.String value='42'
+ block: BLOCK type=kotlin.String.() -> kotlin.Int operator=LAMBDA
+ FUN local final fun kotlin.String.(): kotlin.Int
+ BLOCK_BODY
+ RETURN type=kotlin.Nothing
+ CALL . type=kotlin.Int operator=GET_PROPERTY
+ $this: $RECEIVER of: type=kotlin.String
+ CALLABLE_REFERENCE local final fun kotlin.String.(): kotlin.Int type=kotlin.String.() -> kotlin.Int
diff --git a/compiler/testData/ir/irText/lambdas/justLambda.kt b/compiler/testData/ir/irText/lambdas/justLambda.kt
new file mode 100644
index 00000000000..201939c11a3
--- /dev/null
+++ b/compiler/testData/ir/irText/lambdas/justLambda.kt
@@ -0,0 +1 @@
+val lambda = { 42 }
\ No newline at end of file
diff --git a/compiler/testData/ir/irText/lambdas/justLambda.txt b/compiler/testData/ir/irText/lambdas/justLambda.txt
new file mode 100644
index 00000000000..cfc2a70ab88
--- /dev/null
+++ b/compiler/testData/ir/irText/lambdas/justLambda.txt
@@ -0,0 +1,9 @@
+FILE /justLambda.kt
+ PROPERTY public val lambda: () -> kotlin.Int getter=null setter=null
+ EXPRESSION_BODY
+ BLOCK type=() -> kotlin.Int operator=LAMBDA
+ FUN local final fun (): kotlin.Int
+ BLOCK_BODY
+ RETURN type=kotlin.Nothing
+ CONST Int type=kotlin.Int value='42'
+ CALLABLE_REFERENCE local final fun (): kotlin.Int type=() -> kotlin.Int
diff --git a/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.kt b/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.kt
new file mode 100644
index 00000000000..1e86fffb2d4
--- /dev/null
+++ b/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.kt
@@ -0,0 +1,20 @@
+object A
+object B
+
+interface IFoo {
+ val A.foo: B get() = B
+}
+
+interface IInvoke {
+ operator fun B.invoke() = 42
+}
+
+fun test(fooImpl: IFoo, invokeImpl: IInvoke) {
+ with(A) {
+ with(fooImpl) {
+ with(invokeImpl) {
+ foo()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.txt b/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.txt
new file mode 100644
index 00000000000..4f6f7b7edb6
--- /dev/null
+++ b/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.txt
@@ -0,0 +1,42 @@
+FILE /multipleImplicitReceivers.kt
+ CLASS OBJECT A
+ CLASS OBJECT B
+ CLASS INTERFACE IFoo
+ PROPERTY public open val A.foo: B getter= setter=null
+ PROPERTY_GETTER public open fun A.(): B property=foo
+ BLOCK_BODY
+ RETURN type=kotlin.Nothing
+ GET_OBJECT B type=B
+ CLASS INTERFACE IInvoke
+ FUN public open operator fun B.invoke(): kotlin.Int
+ BLOCK_BODY
+ RETURN type=kotlin.Nothing
+ CONST Int type=kotlin.Int value='42'
+ FUN public fun test(/*0*/ fooImpl: IFoo, /*1*/ invokeImpl: IInvoke): kotlin.Unit
+ BLOCK_BODY
+ CALL .with type=kotlin.Int operator=null
+ receiver: GET_OBJECT A type=A
+ block: BLOCK type=A.() -> kotlin.Int operator=LAMBDA
+ FUN local final fun A.(): kotlin.Int
+ BLOCK_BODY
+ RETURN type=kotlin.Nothing
+ CALL .with type=kotlin.Int operator=null
+ receiver: GET_VAR fooImpl type=IFoo operator=null
+ block: BLOCK type=IFoo.() -> kotlin.Int operator=LAMBDA
+ FUN local final fun IFoo.(): kotlin.Int
+ BLOCK_BODY
+ RETURN type=kotlin.Nothing
+ CALL .with type=kotlin.Int operator=null
+ receiver: GET_VAR invokeImpl type=IInvoke operator=null
+ block: BLOCK type=IInvoke.() -> kotlin.Int operator=LAMBDA
+ FUN local final fun IInvoke.(): kotlin.Int
+ BLOCK_BODY
+ RETURN type=kotlin.Nothing
+ CALL .invoke type=kotlin.Int operator=INVOKE
+ $this: $RECEIVER of: type=IInvoke
+ $receiver: CALL . type=B operator=GET_PROPERTY
+ $this: $RECEIVER of: type=IFoo
+ $receiver: $RECEIVER of: type=A
+ CALLABLE_REFERENCE local final fun IInvoke.(): kotlin.Int type=IInvoke.() -> kotlin.Int
+ CALLABLE_REFERENCE local final fun IFoo.(): kotlin.Int type=IFoo.() -> kotlin.Int
+ CALLABLE_REFERENCE local final fun A.(): kotlin.Int type=A.() -> kotlin.Int
diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java
index 0a91c993a17..1f7daee9b03 100644
--- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java
+++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java
@@ -352,4 +352,31 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
doTest(fileName);
}
}
+
+ @TestMetadata("compiler/testData/ir/irText/lambdas")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class Lambdas extends AbstractIrTextTestCase {
+ public void testAllFilesPresentInLambdas() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/ir/irText/lambdas"), Pattern.compile("^(.+)\\.kt$"), true);
+ }
+
+ @TestMetadata("extensionLambda.kt")
+ public void testExtensionLambda() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/lambdas/extensionLambda.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("justLambda.kt")
+ public void testJustLambda() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/lambdas/justLambda.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("multipleImplicitReceivers.kt")
+ public void testMultipleImplicitReceivers() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.kt");
+ doTest(fileName);
+ }
+ }
}