[FIR] Fix binding return expression to function
This commit is contained in:
+1
-1
@@ -1037,7 +1037,7 @@ class DeclarationsConverter(
|
||||
val parentNode = functionDeclaration.getParent()
|
||||
val isLocal = !(parentNode?.tokenType == KT_FILE || parentNode?.tokenType == CLASS_BODY)
|
||||
val firFunction = if (identifier == null) {
|
||||
FirAnonymousFunctionImpl(null, session, returnType!!, receiverType, FirAnonymousFunctionSymbol())
|
||||
FirAnonymousFunctionImpl(null, session, returnType!!, receiverType, FirAnonymousFunctionSymbol(), isLambda = false)
|
||||
} else {
|
||||
val functionName = identifier.nameAsSafeName()
|
||||
val status = FirDeclarationStatusImpl(
|
||||
|
||||
+1
-1
@@ -127,7 +127,7 @@ class ExpressionsConverter(
|
||||
}
|
||||
}
|
||||
|
||||
return FirAnonymousFunctionImpl(null, session, implicitType, implicitType, FirAnonymousFunctionSymbol()).apply {
|
||||
return FirAnonymousFunctionImpl(null, session, implicitType, implicitType, FirAnonymousFunctionSymbol(), isLambda = true).apply {
|
||||
context.firFunctions += this
|
||||
var destructuringBlock: FirExpression? = null
|
||||
for (valueParameter in valueParameterList) {
|
||||
|
||||
@@ -105,8 +105,8 @@ abstract class BaseFirBuilder<T>(val session: FirSession, val context: Context =
|
||||
this
|
||||
).apply {
|
||||
target = FirFunctionTarget(labelName)
|
||||
val lastFunction = context.firFunctions.lastOrNull()
|
||||
if (labelName == null) {
|
||||
val lastFunction = context.firFunctions.lastOrNull { !(it is FirAnonymousFunction && it.isLambda) }
|
||||
if (lastFunction != null) {
|
||||
target.bind(lastFunction)
|
||||
} else {
|
||||
|
||||
@@ -592,7 +592,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
|
||||
}
|
||||
val receiverType = function.receiverTypeReference.convertSafe<FirTypeRef>()
|
||||
val firFunction = if (function.name == null) {
|
||||
FirAnonymousFunctionImpl(function.toFirSourceElement(), session, returnType, receiverType, FirAnonymousFunctionSymbol())
|
||||
FirAnonymousFunctionImpl(function.toFirSourceElement(), session, returnType, receiverType, FirAnonymousFunctionSymbol(), isLambda = false)
|
||||
} else {
|
||||
val status = FirDeclarationStatusImpl(
|
||||
if (function.isLocal) Visibilities.LOCAL else function.visibility,
|
||||
@@ -636,7 +636,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
|
||||
val literalSource = literal.toFirSourceElement()
|
||||
val returnType = FirImplicitTypeRefImpl(literalSource)
|
||||
val receiverType = FirImplicitTypeRefImpl(literalSource)
|
||||
return FirAnonymousFunctionImpl(literalSource, session, returnType, receiverType, FirAnonymousFunctionSymbol()).apply {
|
||||
return FirAnonymousFunctionImpl(literalSource, session, returnType, receiverType, FirAnonymousFunctionSymbol(), isLambda = true).apply {
|
||||
context.firFunctions += this
|
||||
var destructuringBlock: FirExpression? = null
|
||||
for (valueParameter in literal.valueParameters) {
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
fun <T> run(block: () -> T): T = block()
|
||||
|
||||
fun test_1() {
|
||||
run { return@run }
|
||||
run { return }
|
||||
}
|
||||
|
||||
fun test_2() {
|
||||
run(fun (): Int { return 1 })
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
FILE: lambdaAndAnonymousFunction.kt
|
||||
public? final? fun <T> run(block: ( () -> T )): T {
|
||||
^run block#()
|
||||
}
|
||||
public? final? fun test_1(): R|kotlin/Unit| {
|
||||
run#(<L> = run@fun <implicit>.<anonymous>(): <implicit> {
|
||||
^@run Unit
|
||||
}
|
||||
)
|
||||
run#(<L> = run@fun <implicit>.<anonymous>(): <implicit> {
|
||||
^test_1 Unit
|
||||
}
|
||||
)
|
||||
}
|
||||
public? final? fun test_2(): R|kotlin/Unit| {
|
||||
run#(fun <anonymous>(): Int {
|
||||
^ Int(1)
|
||||
}
|
||||
)
|
||||
}
|
||||
Generated
+5
@@ -223,6 +223,11 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/lambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaAndAnonymousFunction.kt")
|
||||
public void testLambdaAndAnonymousFunction() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/lambdaAndAnonymousFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("locals.kt")
|
||||
public void testLocals() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/locals.kt");
|
||||
|
||||
@@ -62,7 +62,7 @@ fun FirAnonymousFunction.copy(
|
||||
controlFlowGraphReference: FirControlFlowGraphReference = this.controlFlowGraphReference,
|
||||
invocationKind: InvocationKind? = this.invocationKind
|
||||
): FirAnonymousFunction {
|
||||
return FirAnonymousFunctionImpl(source, session, returnTypeRef, receiverTypeRef, symbol).apply {
|
||||
return FirAnonymousFunctionImpl(source, session, returnTypeRef, receiverTypeRef, symbol, isLambda).apply {
|
||||
this.valueParameters.addAll(valueParameters)
|
||||
this.body = body
|
||||
this.annotations.addAll(annotations)
|
||||
|
||||
@@ -120,25 +120,27 @@ digraph returnValuesFromLambda_kt {
|
||||
subgraph cluster_10 {
|
||||
color=blue
|
||||
34 [label="Enter function anonymousFunction"];
|
||||
35 [label="Jump: ^ Unit"];
|
||||
35 [label="Jump: ^test_3 Unit"];
|
||||
36 [label="Stub" style="filled" fillcolor=gray];
|
||||
37 [label="Exit function anonymousFunction"];
|
||||
37 [label="Exit function anonymousFunction" style="filled" fillcolor=gray];
|
||||
}
|
||||
38 [label="Function call: R|kotlin/run|<R|kotlin/Unit|>(<L> = run@fun <anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
^ Unit
|
||||
38 [label="Function call: R|kotlin/run|<R|kotlin/Nothing|>(<L> = run@fun <anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
^test_3 Unit
|
||||
}
|
||||
)"];
|
||||
39 [label="Variable declaration: lval x: R|kotlin/Unit|"];
|
||||
40 [label="Exit function test_3" style="filled" fillcolor=red];
|
||||
)" style="filled" fillcolor=gray];
|
||||
39 [label="Stub" style="filled" fillcolor=gray];
|
||||
40 [label="Variable declaration: lval x: R|kotlin/Nothing|" style="filled" fillcolor=gray];
|
||||
41 [label="Exit function test_3" style="filled" fillcolor=red];
|
||||
}
|
||||
|
||||
33 -> {34};
|
||||
34 -> {35};
|
||||
35 -> {37};
|
||||
35 -> {41};
|
||||
35 -> {36} [style=dotted];
|
||||
36 -> {37} [style=dotted];
|
||||
37 -> {38};
|
||||
38 -> {39};
|
||||
39 -> {40};
|
||||
37 -> {38} [style=dotted];
|
||||
38 -> {41 39} [style=dotted];
|
||||
39 -> {40} [style=dotted];
|
||||
40 -> {41} [style=dotted];
|
||||
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ FILE: returnValuesFromLambda.kt
|
||||
)
|
||||
}
|
||||
public final fun test_3(): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Unit| = R|kotlin/run|<R|kotlin/Unit|>(<L> = run@fun <anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
^ Unit
|
||||
lval x: R|kotlin/Nothing| = R|kotlin/run|<R|kotlin/Nothing|>(<L> = run@fun <anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
^test_3 Unit
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+28
-27
@@ -195,44 +195,45 @@ digraph safeCalls_kt {
|
||||
subgraph cluster_12 {
|
||||
color=blue
|
||||
71 [label="Enter function anonymousFunction"];
|
||||
72 [label="Jump: ^ Unit"];
|
||||
72 [label="Jump: ^test_5 Unit"];
|
||||
73 [label="Stub" style="filled" fillcolor=gray];
|
||||
74 [label="Exit function anonymousFunction"];
|
||||
74 [label="Exit function anonymousFunction" style="filled" fillcolor=gray];
|
||||
}
|
||||
75 [label="Function call: R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Unit|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
^ Unit
|
||||
75 [label="Function call: R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Nothing|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
^test_5 Unit
|
||||
}
|
||||
)"];
|
||||
76 [label="Exit safe call"];
|
||||
77 [label="Enter safe call"];
|
||||
78 [label="Access variable R|<local>/x|"];
|
||||
79 [label="Function call: R|<local>/x|.R|/A.bool|()"];
|
||||
80 [label="Function call: R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Unit|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
^ Unit
|
||||
)" style="filled" fillcolor=gray];
|
||||
76 [label="Exit safe call" style="filled" fillcolor=gray];
|
||||
77 [label="Enter safe call" style="filled" fillcolor=gray];
|
||||
78 [label="Access variable R|<local>/x|" style="filled" fillcolor=gray];
|
||||
79 [label="Function call: R|<local>/x|.R|/A.bool|()" style="filled" fillcolor=gray];
|
||||
80 [label="Function call: R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Nothing|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
^test_5 Unit
|
||||
}
|
||||
)?.R|/boo|(R|<local>/x|.R|/A.bool|())"];
|
||||
81 [label="Exit safe call"];
|
||||
82 [label="Access variable R|<local>/x|"];
|
||||
83 [label="Function call: R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [/A.id]>#()"];
|
||||
)?.R|/boo|(R|<local>/x|.R|/A.bool|())" style="filled" fillcolor=gray];
|
||||
81 [label="Exit safe call" style="filled" fillcolor=gray];
|
||||
82 [label="Access variable R|<local>/x|" style="filled" fillcolor=gray];
|
||||
83 [label="Function call: R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [/A.id]>#()" style="filled" fillcolor=gray];
|
||||
84 [label="Exit function test_5" style="filled" fillcolor=red];
|
||||
}
|
||||
|
||||
68 -> {69};
|
||||
69 -> {70 76};
|
||||
69 -> {70};
|
||||
69 -> {76} [style=dotted];
|
||||
70 -> {71};
|
||||
71 -> {72};
|
||||
72 -> {74};
|
||||
72 -> {84};
|
||||
72 -> {73} [style=dotted];
|
||||
73 -> {74} [style=dotted];
|
||||
74 -> {75};
|
||||
75 -> {76};
|
||||
76 -> {77 81};
|
||||
77 -> {78};
|
||||
78 -> {79};
|
||||
79 -> {80};
|
||||
80 -> {81};
|
||||
81 -> {82};
|
||||
82 -> {83};
|
||||
83 -> {84};
|
||||
74 -> {75} [style=dotted];
|
||||
75 -> {76} [style=dotted];
|
||||
76 -> {77 81} [style=dotted];
|
||||
77 -> {78} [style=dotted];
|
||||
78 -> {79} [style=dotted];
|
||||
79 -> {80} [style=dotted];
|
||||
80 -> {81} [style=dotted];
|
||||
81 -> {82} [style=dotted];
|
||||
82 -> {83} [style=dotted];
|
||||
83 -> {84} [style=dotted];
|
||||
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ FILE: safeCalls.kt
|
||||
}
|
||||
public final fun R|kotlin/Any?|.boo(b: R|kotlin/Boolean|): R|kotlin/Unit|
|
||||
public final fun test_5(x: R|A?|): R|kotlin/Unit| {
|
||||
R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Unit|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
^ Unit
|
||||
R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Nothing|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
^test_5 Unit
|
||||
}
|
||||
)?.R|/boo|(R|<local>/x|.R|/A.bool|())
|
||||
R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [/A.id]>#()
|
||||
|
||||
@@ -38,6 +38,7 @@ abstract class FirAnonymousFunction : FirPureAbstractElement(), FirFunction<FirA
|
||||
abstract override val symbol: FirAnonymousFunctionSymbol
|
||||
abstract val label: FirLabel?
|
||||
abstract val invocationKind: InvocationKind?
|
||||
abstract val isLambda: Boolean
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitAnonymousFunction(this, data)
|
||||
|
||||
|
||||
+2
-1
@@ -33,7 +33,8 @@ class FirAnonymousFunctionImpl(
|
||||
override val session: FirSession,
|
||||
override var returnTypeRef: FirTypeRef,
|
||||
override var receiverTypeRef: FirTypeRef?,
|
||||
override val symbol: FirAnonymousFunctionSymbol
|
||||
override val symbol: FirAnonymousFunctionSymbol,
|
||||
override val isLambda: Boolean
|
||||
) : FirAnonymousFunction(), FirModifiableFunction<FirAnonymousFunction>, FirAbstractAnnotatedElement {
|
||||
override var resolvePhase: FirResolvePhase = FirResolvePhase.DECLARATIONS
|
||||
override val annotations: MutableList<FirAnnotationCall> = mutableListOf()
|
||||
|
||||
+1
@@ -253,6 +253,7 @@ object NodeConfigurator : AbstractFieldConfigurator() {
|
||||
+field(invocationKindType, nullable = true, withReplace = true).apply {
|
||||
isMutable = true
|
||||
}
|
||||
+booleanField("isLambda")
|
||||
}
|
||||
|
||||
typeParameter.configure {
|
||||
|
||||
@@ -5,7 +5,7 @@ FILE fqName:<root> fileName:/nonLocalReturn.kt
|
||||
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Unit declared in <root>.test0'
|
||||
RETURN type=kotlin.Nothing from='public final fun test0 (): kotlin.Unit declared in <root>'
|
||||
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
|
||||
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||
BLOCK_BODY
|
||||
|
||||
+5
@@ -223,6 +223,11 @@ public class FirVisualizerForRawFirDataGenerated extends AbstractFirVisualizer {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/lambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaAndAnonymousFunction.kt")
|
||||
public void testLambdaAndAnonymousFunction() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/lambdaAndAnonymousFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("locals.kt")
|
||||
public void testLocals() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/locals.kt");
|
||||
|
||||
+5
@@ -223,6 +223,11 @@ public class PsiVisualizerForRawFirDataGenerated extends AbstractPsiVisualizer {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/lambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaAndAnonymousFunction.kt")
|
||||
public void testLambdaAndAnonymousFunction() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/lambdaAndAnonymousFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("locals.kt")
|
||||
public void testLocals() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/locals.kt");
|
||||
|
||||
Reference in New Issue
Block a user